glsl2: Move the common optimization passes to a helper function.
authorEric Anholt <eric@anholt.net>
Tue, 10 Aug 2010 20:06:49 +0000 (13:06 -0700)
committerEric Anholt <eric@anholt.net>
Sat, 14 Aug 2010 00:47:00 +0000 (17:47 -0700)
These are passes that we expect all codegen to be happy with.  The
other lowering passes for Mesa IR are moved to the Mesa IR generator.

src/glsl/glsl_parser_extras.cpp
src/glsl/ir_optimization.h
src/glsl/linker.cpp
src/mesa/program/ir_to_mesa.cpp

index dbf6f53156981c6e7dda27ac776df71b5e339ad6..2ed3905abc98e491cc725e64251213b1b45a5ad3 100644 (file)
@@ -33,6 +33,7 @@ extern "C" {
 #include "ast.h"
 #include "glsl_parser_extras.h"
 #include "glsl_parser.h"
+#include "ir_optimization.h"
 
 _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct __GLcontextRec *ctx,
                                               GLenum target, void *mem_ctx)
@@ -705,3 +706,37 @@ ast_struct_specifier::ast_struct_specifier(char *identifier,
    name = identifier;
    this->declarations.push_degenerate_list_at_head(&declarator_list->link);
 }
+
+bool
+do_common_optimization(exec_list *ir, bool linked)
+{
+   GLboolean progress = GL_FALSE;
+
+   progress = do_sub_to_add_neg(ir) || progress;
+
+   if (linked) {
+      progress = do_function_inlining(ir) || progress;
+      progress = do_dead_functions(ir) || progress;
+   }
+   progress = do_structure_splitting(ir) || progress;
+   progress = do_if_simplification(ir) || progress;
+   progress = do_copy_propagation(ir) || progress;
+   if (linked)
+      progress = do_dead_code(ir) || progress;
+   else
+      progress = do_dead_code_unlinked(ir) || progress;
+   progress = do_dead_code_local(ir) || progress;
+   progress = do_tree_grafting(ir) || progress;
+   progress = do_constant_propagation(ir) || progress;
+   if (linked)
+      progress = do_constant_variable(ir) || progress;
+   else
+      progress = do_constant_variable_unlinked(ir) || progress;
+   progress = do_constant_folding(ir) || progress;
+   progress = do_algebraic(ir) || progress;
+   progress = do_if_return(ir) || progress;
+   progress = do_vec_index_to_swizzle(ir) || progress;
+   progress = do_swizzle_swizzle(ir) || progress;
+
+   return progress;
+}
index 5997a30eab3adce530a260fe4e65d16373eed422..0c4e548e44c47b6582a7b65dbe747fe2d1a472f2 100644 (file)
@@ -28,6 +28,8 @@
  * Prototypes for optimization passes to be called by the compiler and drivers.
  */
 
+bool do_common_optimization(exec_list *ir, bool linked);
+
 bool do_algebraic(exec_list *instructions);
 bool do_constant_folding(exec_list *instructions);
 bool do_constant_variable(exec_list *instructions);
index 7bff859d554519322e16de76b1fb8fd83942014b..9931251f404e5c0d8c8eef226fc909f01fa453cd 100644 (file)
@@ -1308,48 +1308,13 @@ link_shaders(struct gl_shader_program *prog)
       prog->LinkStatus = true;
    }
 
-   /* FINISHME: Perform whole-program optimization here. */
+   /* Do common optimization before assigning storage for attributes,
+    * uniforms, and varyings.  Later optimization could possibly make
+    * some of that unused.
+    */
    for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
-      /* Optimization passes */
-      bool progress;
-      exec_list *ir = prog->_LinkedShaders[i]->ir;
-
-      /* Lowering */
-      do_mat_op_to_vec(ir);
-      do_mod_to_fract(ir);
-      do_div_to_mul_rcp(ir);
-      do_explog_to_explog2(ir);
-      do_sub_to_add_neg(ir);
-
-      do {
-        progress = false;
-
-        progress = do_function_inlining(ir) || progress;
-        progress = do_dead_functions(ir) || progress;
-        progress = do_structure_splitting(ir) || progress;
-        progress = do_if_simplification(ir) || progress;
-        progress = do_copy_propagation(ir) || progress;
-        progress = do_dead_code_local(ir) || progress;
-        progress = do_dead_code(ir) || progress;
-        progress = do_tree_grafting(ir) || progress;
-        progress = do_constant_propagation(ir) || progress;
-        progress = do_constant_variable(ir) || progress;
-        progress = do_constant_folding(ir) || progress;
-        progress = do_algebraic(ir) || progress;
-        progress = do_if_return(ir) || progress;
-#if 0
-        if (ctx->Shader.EmitNoIfs)
-           progress = do_if_to_cond_assign(ir) || progress;
-#endif
-
-        progress = do_vec_index_to_swizzle(ir) || progress;
-        /* Do this one after the previous to let the easier pass handle
-         * constant vector indexing.
-         */
-        progress = do_vec_index_to_cond_assign(ir) || progress;
-
-        progress = do_swizzle_swizzle(ir) || progress;
-      } while (progress);
+      while (do_common_optimization(prog->_LinkedShaders[i]->ir, true))
+        ;
    }
 
    assign_uniform_locations(prog);
index ecb13069cb7a3c342c737abfe3d99dcb6082d1b3..c8c655b29675848523f0bb5f9a9a8ffd91ea1812 100644 (file)
@@ -2567,38 +2567,11 @@ _mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *shader)
    if (!state->error && !shader->ir->is_empty()) {
       validate_ir_tree(shader->ir);
 
-      /* Lowering */
-      do_mat_op_to_vec(shader->ir);
-      do_mod_to_fract(shader->ir);
-      do_div_to_mul_rcp(shader->ir);
-      do_sub_to_add_neg(shader->ir);
-
-      /* Optimization passes */
-      bool progress;
-      do {
-        progress = false;
-
-        progress = do_if_simplification(shader->ir) || progress;
-        progress = do_copy_propagation(shader->ir) || progress;
-        progress = do_dead_code_local(shader->ir) || progress;
-        progress = do_dead_code_unlinked(shader->ir) || progress;
-        progress = do_tree_grafting(shader->ir) || progress;
-        progress = do_constant_propagation(shader->ir) || progress;
-        progress = do_constant_variable_unlinked(shader->ir) || progress;
-        progress = do_constant_folding(shader->ir) || progress;
-        progress = do_algebraic(shader->ir) || progress;
-        progress = do_if_return(shader->ir) || progress;
-        if (ctx->Shader.EmitNoIfs)
-           progress = do_if_to_cond_assign(shader->ir) || progress;
-
-        progress = do_vec_index_to_swizzle(shader->ir) || progress;
-        /* Do this one after the previous to let the easier pass handle
-         * constant vector indexing.
-         */
-        progress = do_vec_index_to_cond_assign(shader->ir) || progress;
-
-        progress = do_swizzle_swizzle(shader->ir) || progress;
-      } while (progress);
+      /* Do some optimization at compile time to reduce shader IR size
+       * and reduce later work if the same shader is linked multiple times
+       */
+      while (do_common_optimization(shader->ir, false))
+        ;
 
       validate_ir_tree(shader->ir);
    }
@@ -2665,6 +2638,30 @@ _mesa_glsl_link_shader(GLcontext *ctx, struct gl_shader_program *prog)
       prog->Uniforms = _mesa_new_uniform_list();
    }
 
+   if (prog->LinkStatus) {
+      for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
+        bool progress;
+        exec_list *ir = prog->_LinkedShaders[i]->ir;
+
+        do {
+           progress = false;
+
+           /* Lowering */
+           do_mat_op_to_vec(ir);
+           do_mod_to_fract(ir);
+           do_div_to_mul_rcp(ir);
+           do_explog_to_explog2(ir);
+
+           progress = do_common_optimization(ir, true) || progress;
+
+           if (ctx->Shader.EmitNoIfs)
+              progress = do_if_to_cond_assign(ir) || progress;
+
+           progress = do_vec_index_to_cond_assign(ir) || progress;
+        } while (progress);
+      }
+   }
+
    if (prog->LinkStatus) {
       for (i = 0; i < prog->_NumLinkedShaders; i++) {
         struct gl_program *linked_prog;