diff options
author | Eric Anholt <eric@anholt.net> | 2010-08-04 23:23:15 -0700 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2010-08-05 09:17:45 -0700 |
commit | c5b9cab49900cbcab78911361976a3678d49e853 (patch) | |
tree | 31b1e314919911b72ffeb2cc27807ae9adffeec4 /src/glsl | |
parent | 8f6a0c9ed985267c2d202cf85d17ac04bddfb9d2 (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
Diffstat (limited to 'src/glsl')
-rw-r--r-- | src/glsl/ir_copy_propagation.cpp | 22 |
1 files changed, 17 insertions, 5 deletions
diff --git a/src/glsl/ir_copy_propagation.cpp b/src/glsl/ir_copy_propagation.cpp index 26588a352c..1d28392d7c 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; |