Note: this will round differently for x.5 where x is even. total instructions in shared programs: 5953897 -> 5948654 (-0.09%) instructions in affected programs: 88619 -> 83376 (-5.92%) helped: 696 --- If we implemented round() differently from roundEven(), we should use it instead.
(mul (floor (add (abs x) 0.5) (sign x))) is 6 i965 instructions. (roundEven x) is 1 instruction. Most shaders with this pattern wrap it in int(...), which increases the counts by one, to 7 and 2 respectively. Alternatively, we could optimize this as (trunc (add f (mul 0.5 (sign f)))), which would be 6 instructions, and the int() conversion would be free. We could also apply f's sign to 0.5 in two instructions, cutting the total to 4. What do you think? Should we do precisely as they say? All but two of the affected shaders seem to be translated from DX. src/glsl/opt_algebraic.cpp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/glsl/opt_algebraic.cpp b/src/glsl/opt_algebraic.cpp index c6f4a9c..eaa5f47 100644 --- a/src/glsl/opt_algebraic.cpp +++ b/src/glsl/opt_algebraic.cpp @@ -514,6 +514,38 @@ ir_algebraic_visitor::handle_expression(ir_expression *ir) if (op_const[1] && !op_const[0]) reassociate_constant(ir, 1, op_const[1], op_expr[0]); + /* Optimizes + * + * (mul (floor (add (abs x) 0.5) (sign x))) + * + * into + * + * (roundEven x) + */ + for (int i = 0; i < 2; i++) { + ir_expression *sign = ir->operands[i]->as_expression(); + ir_expression *floor = ir->operands[1 - i]->as_expression(); + + if (!sign || sign->operation != ir_unop_sign || + !floor || floor->operation != ir_unop_floor) + continue; + + ir_expression *add = floor->operands[0]->as_expression(); + + for (int j = 0; j < 2; j++) { + ir_expression *abs_expr = add->operands[j]->as_expression(); + if (!abs_expr || abs_expr->operation != ir_unop_abs) + continue; + + ir_constant *point_five = add->operands[1 - j]->as_constant(); + if (!point_five->is_value(0.5, 0)) + continue; + + if (abs_expr->operands[0]->equals(sign->operands[0])) { + return round_even(abs_expr->operands[0]); + } + } + } break; case ir_binop_div: -- 2.0.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev