[Mesa-dev] [PATCH] glsl: remove redundant function inout assignments

Timothy Arceri t_arceri at yahoo.com.au
Sun Nov 1 01:33:26 PDT 2015


Handles the case with function inout params where array elements
do an assignment to themselves e.g.

 void array_mod(inout int b[2])
 {
    b[0] = int(2);
    b[1] = b[1];
 }

 Fixes assert in nir for:
 ES31-CTS.arrays_of_arrays.InteractionFunctionCalls2

https://bugs.freedesktop.org/show_bug.cgi?id=92588
---
 src/glsl/opt_copy_propagation_elements.cpp | 46 ++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

 Piglit test: https://patchwork.freedesktop.org/patch/63355/

diff --git a/src/glsl/opt_copy_propagation_elements.cpp b/src/glsl/opt_copy_propagation_elements.cpp
index 353a5c6..a62b625 100644
--- a/src/glsl/opt_copy_propagation_elements.cpp
+++ b/src/glsl/opt_copy_propagation_elements.cpp
@@ -439,6 +439,8 @@ ir_copy_propagation_elements_visitor::kill(kill_entry *k)
 /**
  * Adds directly-copied channels between vector variables to the available
  * copy propagation list.
+ *
+ * Also tidy up redundant function inout assignments while we are here.
  */
 void
 ir_copy_propagation_elements_visitor::add_copy(ir_assignment *ir)
@@ -450,6 +452,50 @@ ir_copy_propagation_elements_visitor::add_copy(ir_assignment *ir)
    if (ir->condition)
       return;
 
+   /* Handle a corner case with function inout params where array elements
+    * do an assignment to themselves e.g.
+    *
+    * void array_mod(inout int b[2])
+    * {
+    *    b[0] = int(2);
+    *    b[1] = b[1];
+    * }
+    */
+   ir_rvalue *rhs_array = ir->rhs;
+   ir_rvalue *lhs_array = ir->lhs;
+   if (lhs_array->as_dereference_array() &&
+       rhs_array->as_dereference_array()) {
+      /* Check arrays are indexed by a const and match otherwise return */
+      while (rhs_array->as_dereference_array() &&
+             lhs_array->as_dereference_array()) {
+
+         ir_dereference_array *rhs_deref_array =
+            rhs_array->as_dereference_array();
+         ir_dereference_array *lhs_deref_array =
+            lhs_array->as_dereference_array();
+
+         ir_constant *lhs_ai_const =
+            lhs_deref_array->array_index->as_constant();
+         ir_constant *rhs_ai_const =
+            rhs_deref_array->array_index->as_constant();
+         if (lhs_ai_const == NULL || rhs_ai_const == NULL ||
+             lhs_ai_const->value.i[0] != rhs_ai_const->value.i[0])
+            return;
+         lhs_array = lhs_deref_array->array;
+         rhs_array = rhs_deref_array->array;
+      }
+
+      ir_dereference_variable *lhs_var = lhs_array->as_dereference_variable();
+      ir_dereference_variable *rhs_var = rhs_array->as_dereference_variable();
+      if(lhs_var && rhs_var && lhs_var->var == rhs_var->var){
+	 /* Removing the assignment now would mess up the loop iteration
+	  * calling us.  Just flag it to not execute, and someone else
+	  * will clean up the mess.
+	  */
+	 ir->condition = new(ralloc_parent(ir)) ir_constant(false);
+      }
+   }
+
    ir_dereference_variable *lhs = ir->lhs->as_dereference_variable();
    if (!lhs || !(lhs->type->is_scalar() || lhs->type->is_vector()))
       return;
-- 
2.4.3



More information about the mesa-dev mailing list