summaryrefslogtreecommitdiffstats
path: root/src/compiler/nir
diff options
context:
space:
mode:
authorJason Ekstrand <[email protected]>2018-12-13 11:08:13 -0600
committerJason Ekstrand <[email protected]>2019-01-08 00:38:30 +0000
commitfc9c4f89b85c0116c0dc22a3eaf25f5df88ad657 (patch)
treed66f7211155d2ba45fb2fd269233a9249092b9cd /src/compiler/nir
parentbf1a1eed882980a1cd08482386e3a001ce64a5a4 (diff)
nir: Move propagation of cast derefs to a new nir_opt_deref pass
We're going to want to do more deref optimizations going forward and this gives us a central place to do them. Also, cast propagation will get a bit more complicated with the addition of ptr_as_array derefs. Reviewed-by: Alejandro PiƱeiro <[email protected]> Reviewed-by: Caio Marcelo de Oliveira Filho <[email protected]>
Diffstat (limited to 'src/compiler/nir')
-rw-r--r--src/compiler/nir/nir.h2
-rw-r--r--src/compiler/nir/nir_deref.c63
-rw-r--r--src/compiler/nir/nir_inline_functions.c12
-rw-r--r--src/compiler/nir/nir_opt_copy_propagate.c22
4 files changed, 72 insertions, 27 deletions
diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
index e72585000d4..e991c625536 100644
--- a/src/compiler/nir/nir.h
+++ b/src/compiler/nir/nir.h
@@ -3196,6 +3196,8 @@ bool nir_opt_dead_cf(nir_shader *shader);
bool nir_opt_dead_write_vars(nir_shader *shader);
+bool nir_opt_deref(nir_shader *shader);
+
bool nir_opt_find_array_copies(nir_shader *shader);
bool nir_opt_gcm(nir_shader *shader, bool value_number);
diff --git a/src/compiler/nir/nir_deref.c b/src/compiler/nir/nir_deref.c
index 7a625bcf92b..1dffa285037 100644
--- a/src/compiler/nir/nir_deref.c
+++ b/src/compiler/nir/nir_deref.c
@@ -510,3 +510,66 @@ nir_rematerialize_derefs_in_use_blocks_impl(nir_function_impl *impl)
return state.progress;
}
+
+static bool
+is_trivial_deref_cast(nir_deref_instr *cast)
+{
+ nir_deref_instr *parent = nir_src_as_deref(cast->parent);
+ if (!parent)
+ return false;
+
+ return cast->mode == parent->mode &&
+ cast->type == parent->type &&
+ cast->dest.ssa.num_components == parent->dest.ssa.num_components &&
+ cast->dest.ssa.bit_size == parent->dest.ssa.bit_size;
+}
+
+static bool
+nir_opt_deref_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)
+ continue;
+
+ nir_deref_instr *deref = nir_instr_as_deref(instr);
+ switch (deref->deref_type) {
+ case nir_deref_type_cast:
+ if (is_trivial_deref_cast(deref)) {
+ assert(deref->parent.is_ssa);
+ nir_ssa_def_rewrite_uses(&deref->dest.ssa,
+ nir_src_for_ssa(deref->parent.ssa));
+ nir_instr_remove(&deref->instr);
+ progress = true;
+ }
+ break;
+
+ default:
+ /* Do nothing */
+ break;
+ }
+ }
+ }
+
+ if (progress) {
+ nir_metadata_preserve(impl, nir_metadata_block_index |
+ nir_metadata_dominance);
+ }
+
+ return progress;
+}
+
+bool
+nir_opt_deref(nir_shader *shader)
+{
+ bool progress = false;
+
+ nir_foreach_function(func, shader) {
+ if (func->impl && nir_opt_deref_impl(func->impl))
+ progress = true;
+ }
+
+ return progress;
+}
diff --git a/src/compiler/nir/nir_inline_functions.c b/src/compiler/nir/nir_inline_functions.c
index 29474bb417b..864638d2315 100644
--- a/src/compiler/nir/nir_inline_functions.c
+++ b/src/compiler/nir/nir_inline_functions.c
@@ -164,14 +164,16 @@ inline_function_impl(nir_function_impl *impl, struct set *inlined)
* This does the actual function inlining and the resulting shader will
* contain no call instructions.
*
- * 4. nir_copy_prop(shader)
+ * 4. nir_opt_deref(shader)
*
* Most functions contain pointer parameters where the result of a deref
* instruction is passed in as a parameter, loaded via a load_param
- * intrinsic, and then turned back into a deref via a cast. Running copy
- * propagation gets rid of the intermediate steps and results in a whole
- * deref chain again. This is currently required by a number of
- * optimizations and lowering passes at least for certain variable modes.
+ * intrinsic, and then turned back into a deref via a cast. Function
+ * inlining will get rid of the load_param but we are still left with a
+ * cast. Running nir_opt_deref gets rid of the intermediate cast and
+ * results in a whole deref chain again. This is currently required by a
+ * number of optimizations and lowering passes at least for certain
+ * variable modes.
*
* 5. Loop over the functions and delete all but the main entrypoint.
*
diff --git a/src/compiler/nir/nir_opt_copy_propagate.c b/src/compiler/nir/nir_opt_copy_propagate.c
index 189d544979b..7673e9b62dd 100644
--- a/src/compiler/nir/nir_opt_copy_propagate.c
+++ b/src/compiler/nir/nir_opt_copy_propagate.c
@@ -99,22 +99,6 @@ is_swizzleless_move(nir_alu_instr *instr)
}
static bool
-is_trivial_deref_cast(nir_deref_instr *cast)
-{
- if (cast->deref_type != nir_deref_type_cast)
- return false;
-
- nir_deref_instr *parent = nir_src_as_deref(cast->parent);
- if (!parent)
- return false;
-
- return cast->mode == parent->mode &&
- cast->type == parent->type &&
- cast->dest.ssa.num_components == parent->dest.ssa.num_components &&
- cast->dest.ssa.bit_size == parent->dest.ssa.bit_size;
-}
-
-static bool
copy_prop_src(nir_src *src, nir_instr *parent_instr, nir_if *parent_if,
unsigned num_components)
{
@@ -135,12 +119,6 @@ copy_prop_src(nir_src *src, nir_instr *parent_instr, nir_if *parent_if,
return false;
copy_def= alu_instr->src[0].src.ssa;
- } else if (src_instr->type == nir_instr_type_deref) {
- nir_deref_instr *deref_instr = nir_instr_as_deref(src_instr);
- if (!is_trivial_deref_cast(deref_instr))
- return false;
-
- copy_def = deref_instr->parent.ssa;
} else {
return false;
}