nir: Move propagation of cast derefs to a new nir_opt_deref pass
authorJason Ekstrand <jason.ekstrand@intel.com>
Thu, 13 Dec 2018 17:08:13 +0000 (11:08 -0600)
committerJason Ekstrand <jason@jlekstrand.net>
Tue, 8 Jan 2019 00:38:30 +0000 (00:38 +0000)
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 <apinheiro@igalia.com>
Reviewed-by: Caio Marcelo de Oliveira Filho <caio.oliveira@intel.com>
src/amd/vulkan/radv_shader.c
src/compiler/nir/nir.h
src/compiler/nir/nir_deref.c
src/compiler/nir/nir_inline_functions.c
src/compiler/nir/nir_opt_copy_propagate.c
src/intel/vulkan/anv_pipeline.c
src/mesa/main/glspirv.c

index 7ad9abe8df8a2a946d74e7fa2c608fc9f693f85e..34bfa44793082ba8f7b13ef8f8a701d8c53dd2a6 100644 (file)
@@ -265,7 +265,7 @@ radv_shader_compile_to_nir(struct radv_device *device,
                NIR_PASS_V(nir, nir_lower_constant_initializers, nir_var_local);
                NIR_PASS_V(nir, nir_lower_returns);
                NIR_PASS_V(nir, nir_inline_functions);
-               NIR_PASS_V(nir, nir_copy_prop);
+               NIR_PASS_V(nir, nir_opt_deref);
 
                /* Pick off the single entrypoint that we want */
                foreach_list_typed_safe(nir_function, func, node, &nir->functions) {
index e72585000d40b09f2c9f44842899529741f2807d..e991c625536e8f06d253ec9ed231b7e4c714985d 100644 (file)
@@ -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);
index 7a625bcf92bb16706dc1baf2355b7367e28fe693..1dffa2850379a81284c3a95121c96fe7bd121d90 100644 (file)
@@ -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;
+}
index 29474bb417b6cba9108e2854f44107f66cef8244..864638d23154b9405bdbaf4a29d7840075c92998 100644 (file)
@@ -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.
  *
index 189d544979b179256e08bf00348b734d1f68e9e6..7673e9b62ddf58aa9c44865455e181a5b2cb0bfc 100644 (file)
@@ -98,22 +98,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;
    }
index 6db9945e0d4b094692ed82cea0907d2bb9990556..10afe0825abfb9c501a0eacd88a5b3b9778d1f29 100644 (file)
@@ -184,7 +184,7 @@ anv_shader_compile_to_nir(struct anv_pipeline *pipeline,
    NIR_PASS_V(nir, nir_lower_constant_initializers, nir_var_local);
    NIR_PASS_V(nir, nir_lower_returns);
    NIR_PASS_V(nir, nir_inline_functions);
-   NIR_PASS_V(nir, nir_copy_prop);
+   NIR_PASS_V(nir, nir_opt_deref);
 
    /* Pick off the single entrypoint that we want */
    foreach_list_typed_safe(nir_function, func, node, &nir->functions) {
index 04e46ba571e237698995250ceb3d78a4949a5889..ec1edf11cfa013713e189ef41e9ae6fa282f9e12 100644 (file)
@@ -245,7 +245,7 @@ _mesa_spirv_to_nir(struct gl_context *ctx,
    NIR_PASS_V(nir, nir_lower_constant_initializers, nir_var_local);
    NIR_PASS_V(nir, nir_lower_returns);
    NIR_PASS_V(nir, nir_inline_functions);
-   NIR_PASS_V(nir, nir_copy_prop);
+   NIR_PASS_V(nir, nir_opt_deref);
 
    /* Pick off the single entrypoint that we want */
    foreach_list_typed_safe(nir_function, func, node, &nir->functions) {