summaryrefslogtreecommitdiff
path: root/src/glsl/ir_copy_propagation.cpp
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 /src/glsl/ir_copy_propagation.cpp
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.
Diffstat (limited to 'src/glsl/ir_copy_propagation.cpp')
-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 f502f5e0b0..5712398732 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;
}