Also handle undefined behaviour for sqrt(x) where x < 0 and rsq(x) where x <= 0.
This gives us some reduction in instruction count on three Dungeon Defenders shaders as they are doing: max(exp(x), 0) v2: Change to use new IS_CONSTANT() macro Fix high unintenionally not being returned Add some air for readability Comment on the exploit of undefined behavior Constify mem_ctx --- src/glsl/opt_minmax.cpp | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/glsl/opt_minmax.cpp b/src/glsl/opt_minmax.cpp index 56805c0..2faa3c3 100644 --- a/src/glsl/opt_minmax.cpp +++ b/src/glsl/opt_minmax.cpp @@ -274,9 +274,40 @@ get_range(ir_rvalue *rval) minmax_range r0; minmax_range r1; + void *const mem_ctx = ralloc_parent(rval); + + ir_constant *low = NULL; + ir_constant *high = NULL; + if (expr) { switch (expr->operation) { + case ir_unop_exp: + case ir_unop_exp2: + case ir_unop_sqrt: + case ir_unop_rsq: + r0 = get_range(expr->operands[0]); + + /* The spec says sqrt is undefined if x < 0 + * We can use this to set the range to whatever we want + */ + if (expr->operation == ir_unop_sqrt && + IS_CONSTANT(r0.high, <, 0.0f)) + high = new(mem_ctx) ir_constant(0.0f); + + /* The spec says rsq is undefined if x <= 0 + * We can use this to set the range to whatever we want + */ + if (expr->operation == ir_unop_rsq && + IS_CONSTANT(r0.high, <=, 0.0f)) + high = new(mem_ctx) ir_constant(0.0f); + + /* TODO: If we know, i.e, the lower range of the operand + * we can calculate the lower range + */ + low = new(mem_ctx) ir_constant(0.0f); + return minmax_range(low, high); + case ir_binop_min: case ir_binop_max: r0 = get_range(expr->operands[0]); -- 2.2.1 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev