[Mesa-dev] [PATCH 21/22] glsl: Add a range based comparison opt-pass
Thomas Helland
thomashelland90 at gmail.com
Sat Jan 3 11:18:26 PST 2015
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
More information about the mesa-dev
mailing list