glsl2: Fix copy propagation in the presence of derefs in array indexes.
authorEric Anholt <eric@anholt.net>
Mon, 12 Jul 2010 22:32:37 +0000 (15:32 -0700)
committerEric Anholt <eric@anholt.net>
Mon, 12 Jul 2010 23:07:02 +0000 (16:07 -0700)
We would clear the in_lhs flag early, avoiding copy propagation on the
array index variable (oops) and then copy propagating on the array
variable (ouch).  Just avoid all copy propagation on the LHS instead.

src/glsl/ir_copy_propagation.cpp

index f502f5e0b0693d72a44bd3fad0808a584ff54111..57123987322f15b807d7cbb8419d5c1b663ccd05 100644 (file)
@@ -96,9 +96,29 @@ ir_copy_propagation_visitor::visit_enter(ir_function_signature *ir)
 ir_visitor_status
 ir_copy_propagation_visitor::visit_enter(ir_assignment *ir)
 {
-   (void) ir;
+   ir_visitor_status s;
+
+   /* Inline the rest of ir_assignment::accept(ir_hv *v), wrapping the
+    * LHS part with setting in_lhs so that we can avoid copy
+    * propagating into the LHS.
+    *
+    * Note that this means we won't copy propagate into the derefs of
+    * an array index.  Oh well.
+    */
    this->in_lhs = true;
-   return visit_continue;
+   s = ir->lhs->accept(this);
+   this->in_lhs = false;
+   if (s != visit_continue)
+      return (s == visit_continue_with_parent) ? visit_continue : s;
+
+   s = ir->rhs->accept(this);
+   if (s != visit_continue)
+      return (s == visit_continue_with_parent) ? visit_continue : s;
+
+   if (ir->condition)
+      s = ir->condition->accept(this);
+
+   return (s == visit_stop) ? s : visit_continue_with_parent;
 }
 
 ir_visitor_status
@@ -122,7 +142,6 @@ ir_copy_propagation_visitor::visit(ir_dereference_variable *ir)
     * other storage!
     */
    if (this->in_lhs) {
-      this->in_lhs = false;
       return visit_continue;
    }