[Mesa-dev] [PATCH 1/4] nir: Add a small pass to rematerialize derefs per-block

Iago Toral itoral at igalia.com
Wed Sep 19 05:48:12 UTC 2018


On Tue, 2018-09-18 at 07:27 -0500, Jason Ekstrand wrote:
> On Tue, Sep 18, 2018 at 4:11 AM Iago Toral <itoral at igalia.com> wrote:
> > Hi Jason,
> > 
> > 
> > 
> > I left a few comments in patches 1 and 4, feel free to ignore them
> > if
> > 
> > you think they are not relevant. Either way the series is:
> 
> I would like to back-port this to 18.2 if you don't mind.  I think
> it's far more accurate than what we were doing before to try and
> avoid derefs in phis.

Sure, sounds good to me.
Iago
> --Jason
>  
> > Reviewed-by: Iago Toral Quiroga <itoral at igalia.com>
> > 
> > 
> > 
> > On Mon, 2018-09-17 at 09:43 -0500, Jason Ekstrand wrote:
> > 
> > > This pass re-materializes deref instructions on a per-block basis
> > to
> > 
> > > ensure that every use of a deref occurs in the same block as the
> > 
> > > instruction which uses it.
> > 
> > > ---
> > 
> > >  src/compiler/nir/nir.h       |   1 +
> > 
> > >  src/compiler/nir/nir_deref.c | 132
> > 
> > > +++++++++++++++++++++++++++++++++++
> > 
> > >  2 files changed, 133 insertions(+)
> > 
> > > 
> > 
> > > diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
> > 
> > > index 599f469a714..e0df95c391c 100644
> > 
> > > --- a/src/compiler/nir/nir.h
> > 
> > > +++ b/src/compiler/nir/nir.h
> > 
> > > @@ -3012,6 +3012,7 @@ bool nir_convert_from_ssa(nir_shader
> > *shader,
> > 
> > > bool phi_webs_only);
> > 
> > >  
> > 
> > >  bool nir_lower_phis_to_regs_block(nir_block *block);
> > 
> > >  bool nir_lower_ssa_defs_to_regs_block(nir_block *block);
> > 
> > > +bool
> > nir_rematerialize_derefs_in_use_blocks_impl(nir_function_impl
> > 
> > > *impl);
> > 
> > >  
> > 
> > >  bool nir_opt_algebraic(nir_shader *shader);
> > 
> > >  bool nir_opt_algebraic_before_ffma(nir_shader *shader);
> > 
> > > diff --git a/src/compiler/nir/nir_deref.c
> > 
> > > b/src/compiler/nir/nir_deref.c
> > 
> > > index 097ea8f1046..87a54790c95 100644
> > 
> > > --- a/src/compiler/nir/nir_deref.c
> > 
> > > +++ b/src/compiler/nir/nir_deref.c
> > 
> > > @@ -24,6 +24,7 @@
> > 
> > >  #include "nir.h"
> > 
> > >  #include "nir_builder.h"
> > 
> > >  #include "nir_deref.h"
> > 
> > > +#include "util/hash_table.h"
> > 
> > >  
> > 
> > >  void
> > 
> > >  nir_deref_path_init(nir_deref_path *path,
> > 
> > > @@ -379,3 +380,134 @@ nir_compare_derefs(nir_deref_instr *a,
> > 
> > > nir_deref_instr *b)
> > 
> > >  
> > 
> > >     return result;
> > 
> > >  }
> > 
> > > +
> > 
> > > +struct rematerialize_deref_state {
> > 
> > > +   bool progress;
> > 
> > > +   nir_builder builder;
> > 
> > > +   nir_block *block;
> > 
> > > +   struct hash_table *cache;
> > 
> > > +};
> > 
> > > +
> > 
> > > +static nir_deref_instr *
> > 
> > > +rematerialize_deref_in_block(nir_deref_instr *deref,
> > 
> > > +                             struct rematerialize_deref_state
> > 
> > > *state)
> > 
> > > +{
> > 
> > > +   if (deref->instr.block == state->block)
> > 
> > > +      return deref;
> > 
> > > +
> > 
> > > +   if (!state->cache) {
> > 
> > > +      state->cache= _mesa_hash_table_create(NULL,
> > 
> > > _mesa_hash_pointer,
> > 
> > > +                                           
> > _mesa_key_pointer_equal)
> > 
> > > ;
> > 
> > > +   }
> > 
> > > +
> > 
> > > +   struct hash_entry *cached = _mesa_hash_table_search(state-
> > >cache, 
> > 
> > > deref);
> > 
> > > +   if (cached)
> > 
> > > +      return cached->data;
> > 
> > > +
> > 
> > > +   nir_builder *b = &state->builder;
> > 
> > > +   nir_deref_instr *new_deref =
> > 
> > > +      nir_deref_instr_create(b->shader, deref->deref_type);
> > 
> > > +   new_deref->mode = deref->mode;
> > 
> > > +   new_deref->type = deref->type;
> > 
> > > +
> > 
> > > +   if (deref->deref_type == nir_deref_type_var) {
> > 
> > > +      new_deref->var = deref->var;
> > 
> > > +   } else {
> > 
> > > +      nir_deref_instr *parent = nir_src_as_deref(deref->parent);
> > 
> > > +      if (parent) {
> > 
> > > +         parent = rematerialize_deref_in_block(parent, state);
> > 
> > > +         new_deref->parent = nir_src_for_ssa(&parent->dest.ssa);
> > 
> > > +      } else {
> > 
> > > +         nir_src_copy(&new_deref->parent, &deref->parent,
> > 
> > > new_deref);
> > 
> > > +      }
> > 
> > > +   }
> > 
> > > +
> > 
> > > +   switch (deref->deref_type) {
> > 
> > > +   case nir_deref_type_var:
> > 
> > > +   case nir_deref_type_array_wildcard:
> > 
> > > +   case nir_deref_type_cast:
> > 
> > > +      /* Nothing more to do */
> > 
> > > +      break;
> > 
> > > +
> > 
> > > +   case nir_deref_type_array:
> > 
> > > +      assert(!nir_src_as_deref(deref->arr.index));
> > 
> > > +      nir_src_copy(&new_deref->arr.index, &deref->arr.index,
> > 
> > > new_deref);
> > 
> > > +      break;
> > 
> > > +
> > 
> > > +   case nir_deref_type_struct:
> > 
> > > +      new_deref->strct.index = deref->strct.index;
> > 
> > > +      break;
> > 
> > > +
> > 
> > > +   default:
> > 
> > > +      unreachable("Invalid deref instruction type");
> > 
> > > +   }
> > 
> > > +
> > 
> > > +   nir_ssa_dest_init(&new_deref->instr, &new_deref->dest,
> > 
> > > +                     deref->dest.ssa.num_components,
> > 
> > > +                     deref->dest.ssa.bit_size,
> > 
> > > +                     deref->dest.ssa.name);
> > 
> > > +   nir_builder_instr_insert(b, &new_deref->instr);
> > 
> > > +
> > 
> > > +   return new_deref;
> > 
> > > +}
> > 
> > > +
> > 
> > > +static bool
> > 
> > > +rematerialize_deref_src(nir_src *src, void *_state)
> > 
> > > +{
> > 
> > > +   struct rematerialize_deref_state *state = _state;
> > 
> > > +
> > 
> > > +   nir_deref_instr *deref = nir_src_as_deref(*src);
> > 
> > > +   if (!deref)
> > 
> > > +      return true;
> > 
> > > +
> > 
> > > +   nir_deref_instr *block_deref =
> > 
> > > rematerialize_deref_in_block(deref, state);
> > 
> > > +
> > 
> > > +   nir_instr_rewrite_src(src->parent_instr, src,
> > 
> > > +                         nir_src_for_ssa(&block_deref-
> > >dest.ssa));
> > 
> > > +   nir_deref_instr_remove_if_unused(deref);
> > 
> > > +   state->progress = true;
> > 
> > > +
> > 
> > > +   return true;
> > 
> > > +}
> > 
> > > +
> > 
> > > +/** Re-materialize derefs in every block
> > 
> > > + *
> > 
> > > + * This pass re-materializes deref instructions in every block
> > in
> > 
> > > which it is
> > 
> > > + * used.  After this pass has been run, every use of a deref
> > will be
> > 
> > > of a
> > 
> > > + * deref in the same block as the use.  Also, all unused derefs
> > will
> > 
> > > be
> > 
> > > + * deleted as a side-effect.
> > 
> > > + */
> > 
> > > +bool
> > 
> > > +nir_rematerialize_derefs_in_use_blocks_impl(nir_function_impl
> > *impl)
> > 
> > > +{
> > 
> > > +   struct rematerialize_deref_state state = { };
> > 
> > > +   nir_builder_init(&state.builder, impl);
> > 
> > > +
> > 
> > > +   nir_foreach_block(block, impl) {
> > 
> > > +      state.block = block;
> > 
> > > +
> > 
> > > +      /* Start each block with a fresh cache */
> > 
> > > +      if (state.cache)
> > 
> > > +         _mesa_hash_table_clear(state.cache, NULL);
> > 
> > > +
> > 
> > > +      nir_foreach_instr_safe(instr, block) {
> > 
> > > +         if (instr->type == nir_instr_type_deref) {
> > 
> > > +           
> > nir_deref_instr_remove_if_unused(nir_instr_as_deref(inst
> > 
> > > r));
> > 
> > > +            continue;
> > 
> > > +         }
> > 
> > > +
> > 
> > > +         state.builder.cursor = nir_before_instr(instr);
> > 
> > > +         nir_foreach_src(instr, rematerialize_deref_src,
> > &state);
> > 
> > > +      }
> > 
> > > +
> > 
> > > +#ifndef NDEBUG
> > 
> > > +      nir_if *following_if = nir_block_get_following_if(block);
> > 
> > > +      if (following_if)
> > 
> > > +         assert(!nir_src_as_deref(following_if->condition));
> > 
> > > +#endif
> > 
> > > +   }
> > 
> > > +
> > 
> > > +   _mesa_hash_table_destroy(state.cache, NULL);
> > 
> > > +
> > 
> > > +   return state.progress;
> > 
> > > +}
> > 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20180919/9d37f1af/attachment-0001.html>


More information about the mesa-dev mailing list