ir_copy_propagation: Handle swizzles and array derefs on LHS of assign.
authorEric Anholt <eric@anholt.net>
Wed, 5 May 2010 16:26:46 +0000 (09:26 -0700)
committerEric Anholt <eric@anholt.net>
Wed, 5 May 2010 16:27:50 +0000 (09:27 -0700)
This improves the ACP to not get cleared when more complicated assignments
occur, cleaning up more redundant copies in programs.

ir_copy_propagation.cpp

index 8eb1ebde38c5e6aca0daf873bdcd43ea4fb48806..526ff96e6236c171ccee0f3c564980a52b371422 100644 (file)
@@ -30,6 +30,7 @@
 #include <stdio.h>
 #include "ir.h"
 #include "ir_visitor.h"
+#include "ir_print_visitor.h"
 #include "ir_basic_block.h"
 #include "ir_copy_propagation.h"
 #include "glsl_types.h"
@@ -226,23 +227,33 @@ propagate_copies(ir_instruction *ir, exec_list *acp)
 static void
 kill_invalidated_copies(ir_assignment *ir, exec_list *acp)
 {
-   ir_dereference *lhs_deref = ir->lhs->as_dereference();
-
-   /* Only handle simple dereferences for now. */
-   if (lhs_deref &&
-       lhs_deref->mode == ir_dereference::ir_reference_variable) {
-      ir_variable *var = lhs_deref->var->as_variable();
-
-      foreach_iter(exec_list_iterator, iter, *acp) {
-        acp_entry *entry = (acp_entry *)iter.get();
+   ir_instruction *current = ir->lhs;
 
-        if (entry->lhs == var || entry->rhs == var) {
-           entry->remove();
+   /* Walk down the dereference chain to find the variable at the end
+    * of it that we're actually modifying.
+    */
+   while (current != NULL) {
+      ir_swizzle *swiz;
+      ir_dereference *deref;
+
+      if ((swiz = current->as_swizzle())) {
+        current = swiz->val;
+      } else if ((deref = current->as_dereference())) {
+        current = deref->var;
+      } else {
+        ir_variable *var = current->as_variable();
+        assert(var);
+
+        foreach_iter(exec_list_iterator, iter, *acp) {
+           acp_entry *entry = (acp_entry *)iter.get();
+
+           if (entry->lhs == var || entry->rhs == var) {
+              entry->remove();
+           }
         }
+        current = NULL;
+        break;
       }
-   } else {
-      /* FINISHME: Only clear out the entries we overwrote here. */
-      acp->make_empty();
    }
 }