glsl: Fix broken LRP algebraic optimization.
authorKenneth Graunke <kenneth@whitecape.org>
Sat, 1 Mar 2014 07:15:49 +0000 (23:15 -0800)
committerKenneth Graunke <kenneth@whitecape.org>
Sun, 2 Mar 2014 21:35:03 +0000 (13:35 -0800)
opt_algebraic was translating lrp(x, 0, a) into add(x, -mul(x, a)).

Unfortunately, this references "x" twice, which is invalid in the IR,
leading to assertion failures in the validator.

Normally, cloning IR solves this.  However, "x" could actually be an
arbitrary expression tree, so copying it could result in huge piles
of wasted computation.  This is why we avoid reusing subexpressions.

Instead, transform it into mul(x, add(1.0, -a)), which is equivalent
but doesn't need two references to "x".

Fixes a regression since d5fa8a95621169, which isn't in any stable
branches.  Fixes 18 shaders in shader-db (bastion and yofrankie).

Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
src/glsl/opt_algebraic.cpp

index 778638cf261ee13bedb3e35db70917ebc0c57e4a..5c49a785ccd6f1f1e873469aabb4e49f9530febb 100644 (file)
@@ -571,7 +571,9 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir)
       } else if (is_vec_zero(op_const[0])) {
          return mul(ir->operands[1], ir->operands[2]);
       } else if (is_vec_zero(op_const[1])) {
-         return add(ir->operands[0], neg(mul(ir->operands[0], ir->operands[2])));
+         unsigned op2_components = ir->operands[2]->type->vector_elements;
+         ir_constant *one = new(mem_ctx) ir_constant(1.0f, op2_components);
+         return mul(ir->operands[0], add(one, neg(ir->operands[2])));
       }
       break;