summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Berry <[email protected]>2012-05-19 08:59:36 -0700
committerPaul Berry <[email protected]>2012-05-23 14:21:48 -0700
commitaa173e16a07566b7549b00946840ea16ac17a380 (patch)
tree068027d556c71e1d4be41b171780a3d971d158fc /src
parentb45052b3f761deb980bcca405f25e543892a93ee (diff)
glsl/constant propagation: kill whole var if LHS involves array indexing.
When considering which components of a variable were killed by an assignment, constant propagation would previously just use the write mask of the assignment. This worked if the LHS of the assignment was simple, e.g.: v.xy = ...; // (assign (xy) (var_ref v) ...) But it did the wrong thing if the LHS of the assignment involved an array indexing operator, since in this case the write mask is always (x): v[i] = ...; // (assign (x) (deref_array (var_ref v) (var_ref i)) ...) In general, we can't predict which vector component will be selected by array indexing, so the only safe thing to do in this case is to kill the entire variable. Fixes piglit tests {fs,vs}-vector-indexing-kills-all-channels.shader_test. Reviewed-by: Ian Romanick <[email protected]> Reviewed-by: Eric Anholt <[email protected]>
Diffstat (limited to 'src')
-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);