summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2010-05-05 09:26:46 -0700
committerEric Anholt <eric@anholt.net>2010-05-05 09:27:50 -0700
commit4e2c0b99d932577d082b95d54e4ed1ba1d5d686b (patch)
treea1ff541ce329eabf29e6175ede1ccb6ef7444206
parent5c89f0ecb9581cbe83442ab3f41f2f3701fffab0 (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.cpp39
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();
}
}