diff options
Diffstat (limited to 'src/glsl/opt_constant_propagation.cpp')
-rw-r--r-- | src/glsl/opt_constant_propagation.cpp | 21 |
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); |