summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/glsl/opt_tree_grafting.cpp39
1 files changed, 28 insertions, 11 deletions
diff --git a/src/glsl/opt_tree_grafting.cpp b/src/glsl/opt_tree_grafting.cpp
index 22a1749b9dd..d32d14e88a9 100644
--- a/src/glsl/opt_tree_grafting.cpp
+++ b/src/glsl/opt_tree_grafting.cpp
@@ -76,6 +76,8 @@ public:
virtual ir_visitor_status visit_enter(class ir_swizzle *);
virtual ir_visitor_status visit_enter(class ir_texture *);
+ ir_visitor_status check_graft(ir_instruction *ir, ir_variable *var);
+
bool do_graft(ir_rvalue **rvalue);
bool progress;
@@ -148,18 +150,17 @@ ir_tree_grafting_visitor::visit_enter(ir_loop *ir)
return visit_stop;
}
+/**
+ * Check if we can continue grafting after writing to a variable. If the
+ * expression we're trying to graft references the variable, we must stop.
+ *
+ * \param ir An instruction that writes to a variable.
+ * \param var The variable being updated.
+ */
ir_visitor_status
-ir_tree_grafting_visitor::visit_leave(ir_assignment *ir)
+ir_tree_grafting_visitor::check_graft(ir_instruction *ir, ir_variable *var)
{
- if (do_graft(&ir->rhs) ||
- do_graft(&ir->condition))
- return visit_stop;
-
- /* If this assignment updates a variable used in the assignment
- * we're trying to graft, then we're done.
- */
- if (dereferences_variable(this->graft_assign->rhs,
- ir->lhs->variable_referenced())) {
+ if (dereferences_variable(this->graft_assign->rhs, var)) {
if (debug) {
printf("graft killed by: ");
ir->print();
@@ -172,6 +173,19 @@ ir_tree_grafting_visitor::visit_leave(ir_assignment *ir)
}
ir_visitor_status
+ir_tree_grafting_visitor::visit_leave(ir_assignment *ir)
+{
+ if (do_graft(&ir->rhs) ||
+ do_graft(&ir->condition))
+ return visit_stop;
+
+ /* If this assignment updates a variable used in the assignment
+ * we're trying to graft, then we're done.
+ */
+ return check_graft(ir, ir->lhs->variable_referenced());
+}
+
+ir_visitor_status
ir_tree_grafting_visitor::visit_enter(ir_function *ir)
{
(void) ir;
@@ -195,8 +209,11 @@ ir_tree_grafting_visitor::visit_enter(ir_call *ir)
ir_rvalue *ir = (ir_rvalue *)iter.get();
ir_rvalue *new_ir = ir;
- if (sig_param->mode != ir_var_in && sig_param->mode != ir_var_const_in)
+ if (sig_param->mode != ir_var_in && sig_param->mode != ir_var_const_in) {
+ if (check_graft(ir, sig_param) == visit_stop)
+ return visit_stop;
continue;
+ }
if (do_graft(&new_ir)) {
ir->replace_with(new_ir);