On 01/28/2015 10:31 AM, Matt Turner wrote: > 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)))
If I'm not mistaken, this isn't round-to-even. Doesn't this round 4.5 to 5? roundEven(4.5) should be 4. This looks like "half-up" rounding. Which is very different. See http://userguide.icu-project.org/formatparse/numbers/rounding-modes If we're going to make any clever change here, we really should have a thorough test case first. > + * > + * 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: > _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev