glsl2: Add constant propagation.
[mesa.git] / src / glsl / linker.cpp
index 9b47e4788fcde7934ed096e43c88be11cb3f6eec..52c932278885d39a501a99ff2eec74e1bbaa7452 100644 (file)
@@ -78,7 +78,7 @@ extern "C" {
 #include "glsl_symbol_table.h"
 #include "ir.h"
 #include "program.h"
-#include "hash_table.h"
+#include "program/hash_table.h"
 #include "linker.h"
 #include "ir_optimization.h"
 
@@ -323,7 +323,8 @@ cross_validate_globals(struct gl_shader_program *prog,
                   * FINISHME: modify the shader, and linking with the second
                   * FINISHME: will fail.
                   */
-                 existing->constant_value = var->constant_value->clone(NULL);
+                 existing->constant_value =
+                    var->constant_value->clone(talloc_parent(existing), NULL);
            }
         } else
            variables.add_variable(var->name, var);
@@ -488,16 +489,17 @@ populate_symbol_table(gl_shader *sh)
  *                     should be added.
  */
 void
-remap_variables(ir_instruction *inst, glsl_symbol_table *symbols,
-               exec_list *instructions, hash_table *temps)
+remap_variables(ir_instruction *inst, struct gl_shader *target,
+               hash_table *temps)
 {
    class remap_visitor : public ir_hierarchical_visitor {
    public:
-      remap_visitor(glsl_symbol_table *symbols, exec_list *instructions,
+        remap_visitor(struct gl_shader *target,
                    hash_table *temps)
       {
-        this->symbols = symbols;
-        this->instructions = instructions;
+        this->target = target;
+        this->symbols = target->symbols;
+        this->instructions = target->ir;
         this->temps = temps;
       }
 
@@ -516,7 +518,7 @@ remap_variables(ir_instruction *inst, glsl_symbol_table *symbols,
         if (existing != NULL)
            ir->var = existing;
         else {
-           ir_variable *copy = ir->var->clone(NULL);
+           ir_variable *copy = ir->var->clone(this->target, NULL);
 
            this->symbols->add_variable(copy->name, copy);
            this->instructions->push_head(copy);
@@ -527,12 +529,13 @@ remap_variables(ir_instruction *inst, glsl_symbol_table *symbols,
       }
 
    private:
+      struct gl_shader *target;
       glsl_symbol_table *symbols;
       exec_list *instructions;
       hash_table *temps;
    };
 
-   remap_visitor v(symbols, instructions, temps);
+   remap_visitor v(target, temps);
 
    inst->accept(&v);
 }
@@ -583,12 +586,12 @@ move_non_declarations(exec_list *instructions, exec_node *last,
             || ((var != NULL) && (var->mode == ir_var_temporary)));
 
       if (make_copies) {
-        inst = inst->clone(NULL);
+        inst = inst->clone(target, NULL);
 
         if (var != NULL)
            hash_table_insert(temps, inst, var);
         else
-           remap_variables(inst, target->symbols, target->ir, temps);
+           remap_variables(inst, target, temps);
       } else {
         inst->remove();
       }
@@ -713,7 +716,7 @@ link_intrastage_shaders(struct gl_shader_program *prog,
 
    gl_shader *const linked = _mesa_new_shader(NULL, 0, main->Type);
    linked->ir = new(linked) exec_list;
-   clone_ir_list(linked->ir, main->ir);
+   clone_ir_list(linked, linked->ir, main->ir);
 
    populate_symbol_table(linked);
 
@@ -791,7 +794,12 @@ assign_uniform_locations(struct gl_shader_program *prog)
            continue;
 
         const unsigned vec4_slots = (var->component_slots() + 3) / 4;
-        assert(vec4_slots != 0);
+        if (vec4_slots == 0) {
+           /* If we've got a sampler or an aggregate of them, the size can
+            * end up zero.  Don't allocate any space.
+            */
+           continue;
+        }
 
         uniform_node *n = (uniform_node *) hash_table_find(ht, var->name);
         if (n == NULL) {
@@ -1118,7 +1126,6 @@ assign_varying_locations(struct gl_shader_program *prog,
        * by the following stage.
        */
       if (var->location == -1) {
-        var->shader_out = false;
         var->mode = ir_var_auto;
       }
    }
@@ -1152,7 +1159,6 @@ assign_varying_locations(struct gl_shader_program *prog,
         /* An 'in' variable is only really a shader input if its
          * value is written by the previous stage.
          */
-        var->shader_in = false;
         var->mode = ir_var_auto;
       }
    }
@@ -1277,18 +1283,23 @@ link_shaders(struct gl_shader_program *prog)
       do_mat_op_to_vec(ir);
       do_mod_to_fract(ir);
       do_div_to_mul_rcp(ir);
+      do_explog_to_explog2(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_variable_unlinked(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)