summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/glsl/opt_copy_propagation_elements.cpp15
1 files changed, 14 insertions, 1 deletions
diff --git a/src/glsl/opt_copy_propagation_elements.cpp b/src/glsl/opt_copy_propagation_elements.cpp
index be446bc08ba..ebfd4fd3fe1 100644
--- a/src/glsl/opt_copy_propagation_elements.cpp
+++ b/src/glsl/opt_copy_propagation_elements.cpp
@@ -461,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);
}