summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJason Ekstrand <[email protected]>2018-03-20 17:32:07 -0700
committerJason Ekstrand <[email protected]>2018-06-22 20:15:53 -0700
commit8b7aa66169f9d675f83c483b3c7af38007e7e056 (patch)
tree881cb6611af8ebc4c57215b49873cba746ecfafb /src
parenta80fa2766ec1e3e6575d06254e42da5868f43885 (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.h4
-rw-r--r--src/compiler/nir/nir_deref.c53
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)
{