diff options
author | Eric Anholt <eric@anholt.net> | 2010-05-05 09:26:46 -0700 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2010-05-05 09:27:50 -0700 |
commit | 4e2c0b99d932577d082b95d54e4ed1ba1d5d686b (patch) | |
tree | a1ff541ce329eabf29e6175ede1ccb6ef7444206 | |
parent | 5c89f0ecb9581cbe83442ab3f41f2f3701fffab0 (diff) |
ir_copy_propagation: Handle swizzles and array derefs on LHS of assign.
This improves the ACP to not get cleared when more complicated assignments
occur, cleaning up more redundant copies in programs.
-rw-r--r-- | ir_copy_propagation.cpp | 39 |
1 files changed, 25 insertions, 14 deletions
diff --git a/ir_copy_propagation.cpp b/ir_copy_propagation.cpp index 8eb1ebd..526ff96 100644 --- a/ir_copy_propagation.cpp +++ b/ir_copy_propagation.cpp @@ -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(); } } |