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 /ir_copy_propagation.cpp | |
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.
Diffstat (limited to 'ir_copy_propagation.cpp')
-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(); } } |