From: Eric Anholt Date: Thu, 5 Aug 2010 06:23:15 +0000 (-0700) Subject: glsl2: Catch pointless copies in copy propagation. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=c5b9cab49900cbcab78911361976a3678d49e853;p=mesa.git 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 --- 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;