aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2010-08-04 23:23:15 -0700
committerEric Anholt <[email protected]>2010-08-05 09:17:45 -0700
commitc5b9cab49900cbcab78911361976a3678d49e853 (patch)
tree31b1e314919911b72ffeb2cc27807ae9adffeec4
parent8f6a0c9ed985267c2d202cf85d17ac04bddfb9d2 (diff)
glsl2: Catch pointless copies in copy propagation.
We wouldn't want to go rewriting dereferences to variables to point at the same variable it did before. While I didn't find a way to trigger that, a shader in Yo Frankie managed to produce a self-assignment by passing a constant to a function doing self assignment like this. Cleans up the IR for glsl-deadcode-self-assign.shader_test
-rw-r--r--src/glsl/ir_copy_propagation.cpp22
1 files changed, 17 insertions, 5 deletions
diff --git a/src/glsl/ir_copy_propagation.cpp b/src/glsl/ir_copy_propagation.cpp
index 26588a352c8..1d28392d7c3 100644
--- a/src/glsl/ir_copy_propagation.cpp
+++ b/src/glsl/ir_copy_propagation.cpp
@@ -213,7 +213,7 @@ kill_invalidated_copies(ir_assignment *ir, exec_list *acp)
* Adds an entry to the available copy list if it's a plain assignment
* of a variable to a variable.
*/
-static void
+static bool
add_copy(void *ctx, ir_assignment *ir, exec_list *acp)
{
acp_entry *entry;
@@ -221,16 +221,28 @@ add_copy(void *ctx, ir_assignment *ir, exec_list *acp)
if (ir->condition) {
ir_constant *condition = ir->condition->as_constant();
if (!condition || !condition->value.b[0])
- return;
+ return false;
}
ir_variable *lhs_var = ir->whole_variable_written();
ir_variable *rhs_var = ir->rhs->whole_variable_referenced();
if ((lhs_var != NULL) && (rhs_var != NULL)) {
- entry = new(ctx) acp_entry(lhs_var, rhs_var);
- acp->push_tail(entry);
+ if (lhs_var == rhs_var) {
+ /* This is a dumb assignment, but we've conveniently noticed
+ * it here. Removing it now would mess up the loop iteration
+ * calling us. Just flag it to not execute, and someone else
+ * will clean up the mess.
+ */
+ ir->condition = new(talloc_parent(ir)) ir_constant(false);
+ return true;
+ } else {
+ entry = new(ctx) acp_entry(lhs_var, rhs_var);
+ acp->push_tail(entry);
+ }
}
+
+ return false;
}
static void
@@ -253,7 +265,7 @@ copy_propagation_basic_block(ir_instruction *first,
if (ir_assign) {
kill_invalidated_copies(ir_assign, &acp);
- add_copy(ctx, ir_assign, &acp);
+ progress = add_copy(ctx, ir_assign, &acp) || progress;
}
if (ir == last)
break;