diff options
author | Matt Turner <[email protected]> | 2015-01-28 10:09:14 -0800 |
---|---|---|
committer | Matt Turner <[email protected]> | 2015-02-11 13:50:19 -0800 |
commit | c262b2b582798f389601b8198b1dbf3c7ba7a187 (patch) | |
tree | eba510689fefddb77dec0d706dbc5c5a6a47ace3 /src/glsl/opt_algebraic.cpp | |
parent | a5455ab1cae85dbe40c12ada9030bc4b4537ced7 (diff) |
glsl: Optimize round-half-up pattern.
Hurts some Psychonauts shaders, but after the next patch (which this
enables) they're fewer instructions than before this patch.
Diffstat (limited to 'src/glsl/opt_algebraic.cpp')
-rw-r--r-- | src/glsl/opt_algebraic.cpp | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/src/glsl/opt_algebraic.cpp b/src/glsl/opt_algebraic.cpp index 616ed37b952..588228c9ec2 100644 --- a/src/glsl/opt_algebraic.cpp +++ b/src/glsl/opt_algebraic.cpp @@ -514,6 +514,39 @@ 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 + * + * (trunc (add x (mul (sign x) 0.5))) + */ + for (int i = 0; i < 2; i++) { + ir_expression *sign_expr = ir->operands[i]->as_expression(); + ir_expression *floor_expr = ir->operands[1 - i]->as_expression(); + + if (!sign_expr || sign_expr->operation != ir_unop_sign || + !floor_expr || floor_expr->operation != ir_unop_floor) + continue; + + ir_expression *add_expr = floor_expr->operands[0]->as_expression(); + + for (int j = 0; j < 2; j++) { + ir_expression *abs_expr = add_expr->operands[j]->as_expression(); + if (!abs_expr || abs_expr->operation != ir_unop_abs) + continue; + + ir_constant *point_five = add_expr->operands[1 - j]->as_constant(); + if (!point_five->is_value(0.5, 0)) + continue; + + if (abs_expr->operands[0]->equals(sign_expr->operands[0])) { + return trunc(add(abs_expr->operands[0], + mul(sign_expr, point_five))); + } + } + } break; case ir_binop_div: |