Try to resolv compares by checking the possible variable range. --- src/glsl/opt_minmax.cpp | 101 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+)
diff --git a/src/glsl/opt_minmax.cpp b/src/glsl/opt_minmax.cpp index 07d3d53..8cf0fe5 100644 --- a/src/glsl/opt_minmax.cpp +++ b/src/glsl/opt_minmax.cpp @@ -78,6 +78,8 @@ public: ir_rvalue *opt_saturate(ir_expression *expr, minmax_range baserange); + ir_rvalue *opt_compare(ir_expression *expr, minmax_range baserange); + ir_rvalue *opt_undefined_behaviour(ir_expression *expr, minmax_range baserange); void handle_rvalue(ir_rvalue **rvalue); @@ -332,6 +334,19 @@ resolv_mul_range(minmax_range r0, minmax_range r1) return minmax_range(low, high); } +/* Checks if two ranges can possibly intersect + * The function is NULL-tolerant + */ +static bool +does_range_intersect(minmax_range r0, minmax_range r1) +{ + if ((r0.high && r1.low && compare_components(r0.high, r1.low) == LESS) || + (r0.low && r1.high && compare_components(r0.low, r1.high) == GREATER)) + return false; + + return true; +} + static minmax_range get_range(ir_rvalue *rval) { @@ -611,6 +626,84 @@ ir_minmax_visitor::opt_saturate(ir_expression *expr, minmax_range baserange) } /** + * Solves a compare by using what we know about bounds + * + * @param baserange the range of this expression that will be used by its + * parents, if this is applicable + */ +ir_rvalue * +ir_minmax_visitor::opt_compare(ir_expression *expr, minmax_range baserange) +{ + void *mem_ctx = ralloc_parent(expr); + + // Get the range for the operand + minmax_range r0 = get_range(expr->operands[0]); + minmax_range r1 = get_range(expr->operands[1]); + + switch(expr->operation) { + + case ir_binop_equal: + if (!does_range_intersect(r0, r1)) + return new(mem_ctx) ir_constant(false); + break; + + case ir_binop_nequal: + if (!does_range_intersect(r0, r1)) + return new(mem_ctx) ir_constant(true); + break; + + case ir_binop_lequal: + if (r0.high && r1.low && + compare_components(r0.high, r1.low) == LESS_OR_EQUAL) + return new(mem_ctx) ir_constant(true); + + if (r0.low && r1.high && + compare_components(r0.low, r1.high) == GREATER) + return new(mem_ctx) ir_constant(false); + + break; + + case ir_binop_gequal: + if (r0.high && r1.low && + compare_components(r0.high, r1.low) == LESS) + return new(mem_ctx) ir_constant(false); + + if (r0.low && r1.high && + compare_components(r0.low, r1.high) == GREATER_OR_EQUAL) + return new(mem_ctx) ir_constant(true); + + break; + + case ir_binop_less: + if (r0.high && r1.low && + compare_components(r0.high, r1.low) == LESS) + return new(mem_ctx) ir_constant(true); + + if (r0.low && r1.high && + compare_components(r0.low, r1.high) == GREATER_OR_EQUAL) + return new(mem_ctx) ir_constant(false); + + break; + + case ir_binop_greater: + if (r0.high && r1.low && + compare_components(r0.high, r1.low) == LESS_OR_EQUAL) + return new(mem_ctx) ir_constant(false); + + if (r0.low && r1.high && + compare_components(r0.low, r1.high) == GREATER) + return new(mem_ctx) ir_constant(true); + + break; + + default: + break; + } + + return expr; +} + +/** * Prunes a min/max expression considering the base range of the parent * min/max expression. * @@ -770,6 +863,14 @@ ir_minmax_visitor::handle_rvalue(ir_rvalue **rvalue) if (expr->operation == ir_unop_saturate) new_rvalue = opt_saturate(expr, minmax_range()); + if (expr->operation == ir_binop_equal || + expr->operation == ir_binop_lequal || + expr->operation == ir_binop_gequal || + expr->operation == ir_binop_less || + expr->operation == ir_binop_greater || + expr->operation == ir_binop_nequal) + new_rvalue = opt_compare(expr, minmax_range()); + if (expr->operation == ir_unop_sqrt || expr->operation == ir_unop_rsq || expr->operation == ir_binop_pow || -- 2.2.1 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev