--- src/compiler/nir/nir_remove_dead_variables.c | 92 ++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+)
diff --git a/src/compiler/nir/nir_remove_dead_variables.c b/src/compiler/nir/nir_remove_dead_variables.c index eff66f9..88c4a62 100644 --- a/src/compiler/nir/nir_remove_dead_variables.c +++ b/src/compiler/nir/nir_remove_dead_variables.c @@ -27,6 +27,55 @@ #include "nir.h" +static bool +deref_used_for_not_store(nir_deref_instr *deref) +{ + nir_foreach_use(src, &deref->dest.ssa) { + switch (src->parent_instr->type) { + case nir_instr_type_deref: + if (deref_used_for_not_store(nir_instr_as_deref(src->parent_instr))) + return true; + break; + + case nir_instr_type_intrinsic: { + nir_intrinsic_instr *intrin = + nir_instr_as_intrinsic(src->parent_instr); + /* The first source of copy and store intrinsics is the deref to + * write. Don't record those. + */ + if ((intrin->intrinsic != nir_intrinsic_store_deref && + intrin->intrinsic != nir_intrinsic_copy_deref) || + src != &intrin->src[0]) + return true; + break; + } + + default: + /* If it's used by any other instruction type (most likely a texture + * instruction), consider it used. + */ + return true; + } + } + + return false; +} + +static void +add_var_use_deref(nir_deref_instr *deref, struct set *live) +{ + if (deref->deref_type != nir_deref_type_var) + return; + + /* If it's not a local that never escapes the shader, then any access at + * all means we need to keep it alive. + */ + assert(deref->mode == deref->var->data.mode); + if (!(deref->mode & (nir_var_local | nir_var_global | nir_var_shared)) || + deref_used_for_not_store(deref)) + _mesa_set_add(live, deref->var); +} + static void add_var_use_intrinsic(nir_intrinsic_instr *instr, struct set *live, nir_variable_mode modes) @@ -100,6 +149,10 @@ add_var_use_shader(nir_shader *shader, struct set *live, nir_variable_mode modes nir_foreach_block(block, function->impl) { nir_foreach_instr(instr, block) { switch(instr->type) { + case nir_instr_type_deref: + add_var_use_deref(nir_instr_as_deref(instr), live); + break; + case nir_instr_type_intrinsic: add_var_use_intrinsic(nir_instr_as_intrinsic(instr), live, modes); @@ -144,6 +197,45 @@ remove_dead_var_writes(nir_shader *shader, struct set *live) nir_instr_remove(instr); } } + + /* We walk the list of instructions backwards because we're going to + * delete a deref and all of it's uses and we don't want to end up + * deleting stuff ahead of us. + */ + nir_foreach_block(block, function->impl) { + nir_foreach_instr_safe(instr, block) { + switch (instr->type) { + case nir_instr_type_deref: { + /* For deref instructions, propagate modes */ + nir_deref_instr *deref = nir_instr_as_deref(instr); + if (deref->deref_type == nir_deref_type_var) { + deref->mode = deref->var->data.mode; + } else { + nir_deref_instr *parent = nir_deref_instr_parent(deref); + deref->mode = parent->mode; + } + break; + } + + case nir_instr_type_intrinsic: { + nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr); + if (intrin->intrinsic != nir_intrinsic_copy_deref && + intrin->intrinsic != nir_intrinsic_store_deref) + break; + + nir_deref_instr *dst = nir_src_as_deref(intrin->src[0]); + if (dst->mode == 0) { + nir_instr_remove(instr); + nir_deref_instr_cleanup(dst); + } + break; + } + + default: + break; /* Nothing to do */ + } + } + } } } -- 2.5.0.400.gff86faf _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev