[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