opt_constant_folding is supposed to fold trees of constants into a
single constant. Surprisingly, it was also propagating constant values
from variables into expression trees - even when the result couldn't be
folded together. This is opt_constant_propagation's job.
The ir_dereference_variable::constant_expression_value() method returns
a clone of var->constant_value. So we would replace the dereference
with a constant, propagating it into the tree.
Skip over ir_dereference_variable to avoid this surprising behavior.
However, add code to explicitly continue doing it in the constant
propagation pass, as it's useful to do so.
shader-db statistics on Broadwell:
total instructions in shared programs:
8905349 ->
8905126 (-0.00%)
instructions in affected programs: 30100 -> 29877 (-0.74%)
helped: 93
HURT: 20
total cycles in shared programs:
71017030 ->
71015944 (-0.00%)
cycles in affected programs: 132456 -> 131370 (-0.82%)
helped: 54
HURT: 45
The only hurt programs are by a single instruction, while the helped
ones are helped by 1-4 instructions.
Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
!array_ref->array_index->as_constant()))
return false;
+ /* No constant folding can be performed on variable dereferences. We need
+ * to explicitly avoid them, as calling constant_expression_value() on a
+ * variable dereference will return a clone of var->constant_value. This
+ * would make us propagate the value into the tree, which isn't our job.
+ */
+ ir_dereference_variable *var_ref = (*rvalue)->as_dereference_variable();
+ if (var_ref)
+ return false;
+
ir_constant *constant = (*rvalue)->constant_expression_value();
if (constant) {
*rvalue = constant;
void
ir_constant_propagation_visitor::constant_folding(ir_rvalue **rvalue)
{
+ if (*rvalue == NULL)
+ return;
+
if (ir_constant_fold(rvalue))
this->progress = true;
+
+ ir_dereference_variable *var_ref = (*rvalue)->as_dereference_variable();
+ if (var_ref) {
+ ir_constant *constant = var_ref->constant_expression_value();
+ if (constant) {
+ *rvalue = constant;
+ this->progress = true;
+ }
+ }
}
void