diff options
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/nir/nir_opt_copy_prop_vars.c | 45 |
1 files changed, 35 insertions, 10 deletions
diff --git a/src/compiler/nir/nir_opt_copy_prop_vars.c b/src/compiler/nir/nir_opt_copy_prop_vars.c index 7a21ad56c79..48070cd5e31 100644 --- a/src/compiler/nir/nir_opt_copy_prop_vars.c +++ b/src/compiler/nir/nir_opt_copy_prop_vars.c @@ -86,6 +86,21 @@ struct copy_prop_var_state { bool progress; }; +static bool +value_equals_store_src(struct value *value, nir_intrinsic_instr *intrin) +{ + assert(intrin->intrinsic == nir_intrinsic_store_deref); + uintptr_t write_mask = nir_intrinsic_write_mask(intrin); + + for (unsigned i = 0; i < intrin->num_components; i++) { + if ((write_mask & (1 << i)) && + value->ssa[i] != intrin->src[1].ssa) + return false; + } + + return true; +} + static struct vars_written * create_vars_written(struct copy_prop_var_state *state) { @@ -676,18 +691,28 @@ copy_prop_vars_block(struct copy_prop_var_state *state, } case nir_intrinsic_store_deref: { - struct value value = { - .is_ssa = true - }; - - for (unsigned i = 0; i < intrin->num_components; i++) - value.ssa[i] = intrin->src[1].ssa; - nir_deref_instr *dst = nir_src_as_deref(intrin->src[0]); - unsigned wrmask = nir_intrinsic_write_mask(intrin); struct copy_entry *entry = - get_entry_and_kill_aliases(copies, dst, wrmask); - store_to_entry(state, entry, &value, wrmask); + lookup_entry_for_deref(copies, dst, nir_derefs_equal_bit); + if (entry && value_equals_store_src(&entry->src, intrin)) { + /* If we are storing the value from a load of the same var the + * store is redundant so remove it. + */ + nir_instr_remove(instr); + } else { + struct value value = { + .is_ssa = true + }; + + for (unsigned i = 0; i < intrin->num_components; i++) + value.ssa[i] = intrin->src[1].ssa; + + unsigned wrmask = nir_intrinsic_write_mask(intrin); + struct copy_entry *entry = + get_entry_and_kill_aliases(copies, dst, wrmask); + store_to_entry(state, entry, &value, wrmask); + } + break; } |