V2: Add some air for readability Use the new IS_CONSTANT macro Combine if-blocks for reduced code-duplication Split out into separate function for reuse later
V3: Fix flawed logic (Spotted by Bruno) --- src/glsl/opt_minmax.cpp | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/glsl/opt_minmax.cpp b/src/glsl/opt_minmax.cpp index 4153a48..373ba26 100644 --- a/src/glsl/opt_minmax.cpp +++ b/src/glsl/opt_minmax.cpp @@ -300,6 +300,46 @@ resolv_add_range(minmax_range r0, minmax_range r1) return minmax_range(low, high); } +/* Takes the range of the operands in a mul-operation as parameters + * and uses this to solve the range of the mul-operation itself. + */ +static minmax_range +resolv_mul_range(minmax_range r0, minmax_range r1) +{ + ir_constant *low = NULL; + ir_constant *high = NULL; + + // Both are positive, result is positive + if (IS_CONSTANT(r0.low, >=, 0.0f) && IS_CONSTANT(r1.low, >=, 0.0f)) { + low = mul(r0.low, r1.low)->constant_expression_value(); + if (r0.high && r1.high) + high = mul(r0.high, r1.high)->constant_expression_value(); + } + + // Both are negative, result is positive + if (IS_CONSTANT(r0.high, <=, 0.0f) && IS_CONSTANT(r1.high, <=, 0.0f)) { + low = mul(r0.high, r1.high)->constant_expression_value(); + if (r0.low && r1.low) + high = mul(r0.low, r1.low)->constant_expression_value(); + } + + // r0 pos and r1 neg, result is negative + if (IS_CONSTANT(r0.low, >=, 0.0f) && IS_CONSTANT(r1.high, <=, 0.0f)) { + high = mul(r0.low, r1.high)->constant_expression_value(); + if (r0.high && r1.low) + low = mul(r0.high, r1.low)->constant_expression_value(); + } + + // r0 neg and r1 pos, result is negative + if (IS_CONSTANT(r1.low, >=, 0.0f) && IS_CONSTANT(r0.high, <=, 0.0f)) { + high = mul(r1.low, r0.high)->constant_expression_value(); + if (r1.high && r0.low) + low = mul(r1.high, r0.low)->constant_expression_value(); + } + + return minmax_range(low, high); +} + static minmax_range get_range(ir_rvalue *rval) { @@ -389,6 +429,11 @@ get_range(ir_rvalue *rval) r1 = get_range(expr->operands[1]); return combine_range(r0, r1, expr->operation == ir_binop_min); + case ir_binop_mul: + r0 = get_range(expr->operands[0]); + r1 = get_range(expr->operands[1]); + return resolv_mul_range(r0, r1); + default: break; } -- 2.2.1 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev