[Mesa-dev] [PATCH 09/12] glsl: Convert lower_clip_distance_visitor to be an ir_rvalue_visitor

Ian Romanick idr at freedesktop.org
Mon Apr 8 15:24:40 PDT 2013


From: Ian Romanick <ian.d.romanick at intel.com>

Right now the lower_clip_distance_visitor lowers variable indexing into
gl_ClipDistance into variable indexing into both the array
gl_ClipDistanceMESA and the vectors of that array.  For example,

    gl_ClipDistance[i] = f;

becomes

    gl_ClipDistanceMESA[i/4][i%4] = f;

However, variable indexing into vectors using ir_dereference_array is
being removed.  Instead, ir_expression with ir_triop_vector_insert will
be used.  The above code will become

    gl_ClipDistanceMESA[i/4] = vector_insert(gl_ClipDistanceMESA[i/4],
                                             i % 4,
                                             f);

In order to do this, an ir_rvalue_visitor will need to be used.  This
commit is really just a refactor to get ready for that.

Signed-off-by: Ian Romanick <ian.d.romanick at intel.com>
Cc: Paul Berry <stereotype441 at gmail.com>
---
 src/glsl/lower_clip_distance.cpp | 136 +++++++++++++++++++++++++--------------
 1 file changed, 86 insertions(+), 50 deletions(-)

diff --git a/src/glsl/lower_clip_distance.cpp b/src/glsl/lower_clip_distance.cpp
index 643807d..26a0feb 100644
--- a/src/glsl/lower_clip_distance.cpp
+++ b/src/glsl/lower_clip_distance.cpp
@@ -46,10 +46,10 @@
  */
 
 #include "glsl_symbol_table.h"
-#include "ir_hierarchical_visitor.h"
+#include "ir_rvalue_visitor.h"
 #include "ir.h"
 
-class lower_clip_distance_visitor : public ir_hierarchical_visitor {
+class lower_clip_distance_visitor : public ir_rvalue_visitor {
 public:
    lower_clip_distance_visitor()
       : progress(false), old_clip_distance_var(NULL),
@@ -59,11 +59,12 @@ public:
 
    virtual ir_visitor_status visit(ir_variable *);
    void create_indices(ir_rvalue*, ir_rvalue *&, ir_rvalue *&);
-   virtual ir_visitor_status visit_leave(ir_dereference_array *);
    virtual ir_visitor_status visit_leave(ir_assignment *);
    void visit_new_assignment(ir_assignment *ir);
    virtual ir_visitor_status visit_leave(ir_call *);
 
+   virtual void handle_rvalue(ir_rvalue **rvalue);
+
    bool progress;
 
    /**
@@ -173,33 +174,35 @@ lower_clip_distance_visitor::create_indices(ir_rvalue *old_index,
 }
 
 
-/**
- * Replace any expression that indexes into the gl_ClipDistance array with an
- * expression that indexes into one of the vec4's in gl_ClipDistanceMESA and
- * accesses the appropriate component.
- */
-ir_visitor_status
-lower_clip_distance_visitor::visit_leave(ir_dereference_array *ir)
+void
+lower_clip_distance_visitor::handle_rvalue(ir_rvalue **rv)
 {
    /* If the gl_ClipDistance var hasn't been declared yet, then
     * there's no way this deref can refer to it.
     */
-   if (!this->old_clip_distance_var)
-      return visit_continue;
-
-   ir_dereference_variable *old_var_ref = ir->array->as_dereference_variable();
-   if (old_var_ref && old_var_ref->var == this->old_clip_distance_var) {
-      this->progress = true;
-      ir_rvalue *array_index;
-      ir_rvalue *swizzle_index;
-      this->create_indices(ir->array_index, array_index, swizzle_index);
-      void *mem_ctx = ralloc_parent(ir);
-      ir->array = new(mem_ctx) ir_dereference_array(
-         this->new_clip_distance_var, array_index);
-      ir->array_index = swizzle_index;
+   if (!this->old_clip_distance_var || *rv == NULL)
+      return;
+
+   ir_dereference_array *const array = (*rv)->as_dereference_array();
+   if (array != NULL) {
+      /* Replace any expression that indexes into the gl_ClipDistance array
+       * with an expression that indexes into one of the vec4's in
+       * gl_ClipDistanceMESA and accesses the appropriate component.
+       */
+      ir_dereference_variable *old_var_ref =
+	 array->array->as_dereference_variable();
+      if (old_var_ref && old_var_ref->var == this->old_clip_distance_var) {
+	 this->progress = true;
+	 ir_rvalue *array_index;
+	 ir_rvalue *swizzle_index;
+	 this->create_indices(array->array_index, array_index, swizzle_index);
+	 void *mem_ctx = ralloc_parent(array);
+	 array->array =
+	    new(mem_ctx) ir_dereference_array(this->new_clip_distance_var,
+					      array_index);
+	 array->array_index = swizzle_index;
+      }
    }
-
-   return visit_continue;
 }
 
 
@@ -214,38 +217,71 @@ lower_clip_distance_visitor::visit_leave(ir_assignment *ir)
 {
    ir_dereference_variable *lhs_var = ir->lhs->as_dereference_variable();
    ir_dereference_variable *rhs_var = ir->rhs->as_dereference_variable();
-   if ((lhs_var && lhs_var->var == this->old_clip_distance_var)
-       || (rhs_var && rhs_var->var == this->old_clip_distance_var)) {
-      /* LHS or RHS of the assignment is the entire gl_ClipDistance array.
-       * Since we are reshaping gl_ClipDistance from an array of floats to an
-       * array of vec4's, this isn't going to work as a bulk assignment
-       * anymore, so unroll it to element-by-element assignments and lower
-       * each of them.
-       *
-       * Note: to unroll into element-by-element assignments, we need to make
-       * clones of the LHS and RHS.  This is only safe if the LHS and RHS are
-       * side-effect free.  Fortunately, we know that they are, because the
-       * only kind of rvalue that can have side effects is an ir_call, and
-       * ir_calls only appear (a) as a statement on their own, or (b) as the
-       * RHS of an assignment that stores the result of the call in a
-       * temporary variable.
-       */
-      void *ctx = ralloc_parent(ir);
+   void *ctx = ralloc_parent(ir);
+
+   /* LHS or RHS of the assignment is the entire gl_ClipDistance array.
+    * Since we are reshaping gl_ClipDistance from an array of floats to an
+    * array of vec4's, this isn't going to work as a bulk assignment
+    * anymore, so unroll it to element-by-element assignments and lower
+    * each of them.
+    *
+    * Note: to unroll into element-by-element assignments, we need to make
+    * clones of the LHS and RHS.  This is only safe if the LHS and RHS are
+    * side-effect free.  Fortunately, we know that they are, because the
+    * only kind of rvalue that can have side effects is an ir_call, and
+    * ir_calls only appear (a) as a statement on their own, or (b) as the
+    * RHS of an assignment that stores the result of the call in a
+    * temporary variable.
+    */
+   if (lhs_var && lhs_var->var == this->old_clip_distance_var) {
       int array_size = this->old_clip_distance_var->type->array_size();
       for (int i = 0; i < array_size; ++i) {
-         ir_dereference_array *new_lhs = new(ctx) ir_dereference_array(
-            ir->lhs->clone(ctx, NULL), new(ctx) ir_constant(i));
-         new_lhs->accept(this);
+	 ir_dereference_variable *const new_deref =
+	    new(ctx) ir_dereference_variable(new_clip_distance_var);
+
+         ir_dereference_array *const new_lhs =
+	    new(ctx) ir_dereference_array(new_deref,
+					  new(ctx) ir_constant(i / 4));
+
          ir_dereference_array *new_rhs = new(ctx) ir_dereference_array(
             ir->rhs->clone(ctx, NULL), new(ctx) ir_constant(i));
-         new_rhs->accept(this);
-         this->base_ir->insert_before(
-            new(ctx) ir_assignment(new_lhs, new_rhs));
+
+	 const int mask = 1 << (i % 4);
+
+	 ir_assignment *const assign =
+	    new(ctx) ir_assignment(new_lhs, new_rhs, NULL, mask);
+
+	 this->base_ir->insert_before(assign);
       }
       ir->remove();
+
+      return visit_continue;
+   } else if (rhs_var && rhs_var->var == this->old_clip_distance_var) {
+      int array_size = this->old_clip_distance_var->type->array_size();
+      for (int i = 0; i < array_size; ++i) {
+         ir_dereference_array *new_lhs = new(ctx) ir_dereference_array(
+            ir->lhs->clone(ctx, NULL), new(ctx) ir_constant(i));
+
+	 ir_dereference_variable *const new_deref =
+	    new(ctx) ir_dereference_variable(new_clip_distance_var);
+
+         ir_rvalue *const new_rhs =
+	    new(ctx) ir_swizzle(new(ctx) ir_dereference_array(new_deref,
+							      new(ctx) ir_constant(i / 4)),
+				i % 4, 0, 0, 0, 1);
+
+	 ir_assignment *const assign =
+	    new(ctx) ir_assignment(new_lhs, new_rhs);
+
+	 this->base_ir->insert_before(assign);
+      }
+      ir->remove();
+
+      return visit_continue;
    }
 
-   return visit_continue;
+   handle_rvalue((ir_rvalue **)&ir->lhs);
+   return rvalue_visit(ir);
 }
 
 
@@ -330,7 +366,7 @@ lower_clip_distance_visitor::visit_leave(ir_call *ir)
       }
    }
 
-   return visit_continue;
+   return rvalue_visit(ir);
 }
 
 
-- 
1.8.1.4



More information about the mesa-dev mailing list