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