summaryrefslogtreecommitdiffstats
path: root/src/glsl/opt_constant_propagation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/glsl/opt_constant_propagation.cpp')
-rw-r--r--src/glsl/opt_constant_propagation.cpp21
1 files changed, 20 insertions, 1 deletions
diff --git a/src/glsl/opt_constant_propagation.cpp b/src/glsl/opt_constant_propagation.cpp
index d3812637df0..2601b52f6d3 100644
--- a/src/glsl/opt_constant_propagation.cpp
+++ b/src/glsl/opt_constant_propagation.cpp
@@ -241,7 +241,26 @@ ir_constant_propagation_visitor::visit_leave(ir_assignment *ir)
if (this->in_assignee)
return visit_continue;
- kill(ir->lhs->variable_referenced(), ir->write_mask);
+ unsigned kill_mask = ir->write_mask;
+ if (ir->lhs->as_dereference_array()) {
+ /* The LHS of the assignment uses an array indexing operator (e.g. v[i]
+ * = ...;). Since we only try to constant propagate vectors and
+ * scalars, this means that either (a) array indexing is being used to
+ * select a vector component, or (b) the variable in question is neither
+ * a scalar or a vector, so we don't care about it. In the former case,
+ * we want to kill the whole vector, since in general we can't predict
+ * which vector component will be selected by array indexing. In the
+ * latter case, it doesn't matter what we do, so go ahead and kill the
+ * whole variable anyway.
+ *
+ * Note that if the array index is constant (e.g. v[2] = ...;), we could
+ * in principle be smarter, but we don't need to, because a future
+ * optimization pass will convert it to a simple assignment with the
+ * correct mask.
+ */
+ kill_mask = ~0;
+ }
+ kill(ir->lhs->variable_referenced(), kill_mask);
add_constant(ir);