aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2010-07-12 15:32:37 -0700
committerEric Anholt <eric@anholt.net>2010-07-12 16:07:02 -0700
commitb87259d3efeadf05556e2daf688935a038097bba (patch)
tree4fb8db72174bc2f8cb6e9407bc5d9e47803a8255
parent8258a6a2c36c9769428f4525415d6c0d565e588c (diff)
glsl2: Fix copy propagation in the presence of derefs in array indexes.
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.
-rw-r--r--src/glsl/ir_copy_propagation.cpp25
1 files changed, 22 insertions, 3 deletions
diff --git a/src/glsl/ir_copy_propagation.cpp b/src/glsl/ir_copy_propagation.cpp
index f502f5e0b06..57123987322 100644
--- a/src/glsl/ir_copy_propagation.cpp
+++ b/src/glsl/ir_copy_propagation.cpp
@@ -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;
}