This algebraic optimization recognizes an series of adds and multiplies with a particular pattern within the ir which is equivalent to a lrp.
shader-db results: total instructions in shared programs: 1729161 -> 1718321 (-0.63%) instructions in affected programs: 743700 -> 732860 (-1.46%) GAINED: 4 LOST: 41 Signed-off-by: Jordan Justen <jordan.l.jus...@intel.com> Cc: Eric Anholt <e...@anholt.net> --- This requires Eric's "glsl: Move the CSE equality functions to the ir class." src/glsl/opt_algebraic.cpp | 53 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/glsl/opt_algebraic.cpp b/src/glsl/opt_algebraic.cpp index a07e153..8b87146 100644 --- a/src/glsl/opt_algebraic.cpp +++ b/src/glsl/opt_algebraic.cpp @@ -279,6 +279,59 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) reassociate_constant(ir, 0, op_const[0], op_expr[1]); if (op_const[1] && !op_const[0]) reassociate_constant(ir, 1, op_const[1], op_expr[0]); + + /* Find Add(Mult(Add(Neg(x), y), a), x) and commutative variations. + * + * Replace with lrp(x, y, a). + * + * ((-x + y)*a) + x => -a*x + a*y + x => + * a*y + x + x*(-a) => a*y + (1 - a)*x => lrp(x, y, a) + */ + for (int mul_pos = 0; mul_pos < 2; mul_pos++) { + ir_expression *mul = op_expr[mul_pos]; + + if (!mul || mul->operation != ir_binop_mul) + continue; + + /* Multiply found on one of the operands. Now check for an + * inner Addition operation. + */ + for (int inner_add_pos = 0; inner_add_pos < 2; inner_add_pos++) { + ir_expression *inner_add = + mul->operands[inner_add_pos]->as_expression(); + + if (!inner_add || inner_add->operation != ir_binop_add) + continue; + + /* Inner addition found on one of the operands. Now check for + * one of the operands of the inner addition to be the negative + * of x_operand. + */ + for (int neg_pos = 0; neg_pos < 2; neg_pos++) { + ir_expression *neg = + inner_add->operands[neg_pos]->as_expression(); + + if (!neg || neg->operation != ir_unop_neg) + continue; + + ir_rvalue *x_operand = ir->operands[(mul_pos + 1) % 2]; + + if (!neg->operands[0]->equals(x_operand)) + continue; + + /* The pattern was matched, so replace with a lrp */ + ir_rvalue *y_operand = inner_add->operands[(neg_pos + 1) % 2]; + ir_rvalue *a_operand = mul->operands[(inner_add_pos + 1) % 2]; + + if (x_operand->type != y_operand->type || + x_operand->type != a_operand->type) + continue; + + return lrp(x_operand, y_operand, a_operand); + } + } + } + break; case ir_binop_sub: -- 1.7.10.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev