aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/glsl/opt_copy_propagation_elements.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/glsl/opt_copy_propagation_elements.cpp')
-rw-r--r--mesalib/src/glsl/opt_copy_propagation_elements.cpp25
1 files changed, 24 insertions, 1 deletions
diff --git a/mesalib/src/glsl/opt_copy_propagation_elements.cpp b/mesalib/src/glsl/opt_copy_propagation_elements.cpp
index a91e624cb..ebfd4fd3f 100644
--- a/mesalib/src/glsl/opt_copy_propagation_elements.cpp
+++ b/mesalib/src/glsl/opt_copy_propagation_elements.cpp
@@ -108,6 +108,7 @@ public:
virtual ir_visitor_status visit_leave(class ir_assignment *);
virtual ir_visitor_status visit_enter(class ir_call *);
virtual ir_visitor_status visit_enter(class ir_if *);
+ virtual ir_visitor_status visit_leave(class ir_swizzle *);
void handle_rvalue(ir_rvalue **rvalue);
@@ -179,6 +180,15 @@ ir_copy_propagation_elements_visitor::visit_leave(ir_assignment *ir)
return visit_continue;
}
+ir_visitor_status
+ir_copy_propagation_elements_visitor::visit_leave(ir_swizzle *ir)
+{
+ /* Don't visit the values of swizzles since they are handled while
+ * visiting the swizzle itself.
+ */
+ return visit_continue;
+}
+
/**
* Replaces dereferences of ACP RHS variables with ACP LHS variables.
*
@@ -451,7 +461,20 @@ ir_copy_propagation_elements_visitor::add_copy(ir_assignment *ir)
swizzle[i] = orig_swizzle[j++];
}
- entry = new(this->mem_ctx) acp_entry(lhs->var, rhs->var, ir->write_mask,
+ int write_mask = ir->write_mask;
+ if (lhs->var == rhs->var) {
+ /* If this is a copy from the variable to itself, then we need
+ * to be sure not to include the updated channels from this
+ * instruction in the set of new source channels to be
+ * copy-propagated from.
+ */
+ for (int i = 0; i < 4; i++) {
+ if (ir->write_mask & (1 << orig_swizzle[i]))
+ write_mask &= ~(1 << i);
+ }
+ }
+
+ entry = new(this->mem_ctx) acp_entry(lhs->var, rhs->var, write_mask,
swizzle);
this->acp->push_tail(entry);
}