diff options
author | Jason Ekstrand <[email protected]> | 2018-03-20 17:32:07 -0700 |
---|---|---|
committer | Jason Ekstrand <[email protected]> | 2018-06-22 20:15:53 -0700 |
commit | 8b7aa66169f9d675f83c483b3c7af38007e7e056 (patch) | |
tree | 881cb6611af8ebc4c57215b49873cba746ecfafb /src | |
parent | a80fa2766ec1e3e6575d06254e42da5868f43885 (diff) |
nir/deref: Add some deref cleanup functions
Sometimes it's useful for a pass to be able to clean up its own derefs
instead of waiting for DCE. This little helper makes it very easy.
Reviewed-by: Caio Marcelo de Oliveira Filho <[email protected]>
Acked-by: Rob Clark <[email protected]>
Acked-by: Bas Nieuwenhuizen <[email protected]>
Acked-by: Dave Airlie <[email protected]>
Reviewed-by: Kenneth Graunke <[email protected]>
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/nir/nir.h | 4 | ||||
-rw-r--r-- | src/compiler/nir/nir_deref.c | 53 |
2 files changed, 57 insertions, 0 deletions
diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index bec5f99ba78..d25aa7491ed 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -1032,6 +1032,8 @@ nir_deref_instr_get_variable(const nir_deref_instr *instr) return instr->var; } +bool nir_deref_instr_remove_if_unused(nir_deref_instr *instr); + nir_deref_var * nir_deref_instr_to_deref(nir_deref_instr *instr, void *mem_ctx); @@ -2728,6 +2730,8 @@ bool nir_lower_regs_to_ssa_impl(nir_function_impl *impl); bool nir_lower_regs_to_ssa(nir_shader *shader); bool nir_lower_vars_to_ssa(nir_shader *shader); +bool nir_remove_dead_derefs(nir_shader *shader); +bool nir_remove_dead_derefs_impl(nir_function_impl *impl); bool nir_remove_dead_variables(nir_shader *shader, nir_variable_mode modes); bool nir_lower_constant_initializers(nir_shader *shader, nir_variable_mode modes); diff --git a/src/compiler/nir/nir_deref.c b/src/compiler/nir/nir_deref.c index 87a81925c40..0e8699aa6e6 100644 --- a/src/compiler/nir/nir_deref.c +++ b/src/compiler/nir/nir_deref.c @@ -24,6 +24,59 @@ #include "nir.h" #include "nir_builder.h" +/** + * Recursively removes unused deref instructions + */ +bool +nir_deref_instr_remove_if_unused(nir_deref_instr *instr) +{ + bool progress = false; + + for (nir_deref_instr *d = instr; d; d = nir_deref_instr_parent(d)) { + /* If anyone is using this deref, leave it alone */ + assert(d->dest.is_ssa); + if (!list_empty(&d->dest.ssa.uses)) + break; + + nir_instr_remove(&d->instr); + progress = true; + } + + return progress; +} + +bool +nir_remove_dead_derefs_impl(nir_function_impl *impl) +{ + bool progress = false; + + nir_foreach_block(block, impl) { + nir_foreach_instr_safe(instr, block) { + if (instr->type == nir_instr_type_deref && + nir_deref_instr_remove_if_unused(nir_instr_as_deref(instr))) + progress = true; + } + } + + if (progress) + nir_metadata_preserve(impl, nir_metadata_block_index | + nir_metadata_dominance); + + return progress; +} + +bool +nir_remove_dead_derefs(nir_shader *shader) +{ + bool progress = false; + nir_foreach_function(function, shader) { + if (function->impl && nir_remove_dead_derefs_impl(function->impl)) + progress = true; + } + + return progress; +} + nir_deref_var * nir_deref_instr_to_deref(nir_deref_instr *instr, void *mem_ctx) { |