[Mesa-dev] [PATCH 2/9] nir: Export deref comparison functions

Jason Ekstrand jason at jlekstrand.net
Wed Aug 22 17:31:27 UTC 2018


Thanks!  I've been wanting to do this ever since I added that function.  I
just didn't have a second consumer.

Reviewed-by: Jason Ekstrand <jason at jlekstrand.net>

On Wed, Aug 15, 2018 at 4:57 PM Caio Marcelo de Oliveira Filho <
caio.oliveira at intel.com> wrote:

> Reviewed-by: Timothy Arceri <tarceri at itsqueeze.com>
> ---
>  src/compiler/nir/nir_deref.c              | 109 ++++++++++++++++
>  src/compiler/nir/nir_deref.h              |  10 ++
>  src/compiler/nir/nir_opt_copy_prop_vars.c | 145 ++--------------------
>  3 files changed, 132 insertions(+), 132 deletions(-)
>
> diff --git a/src/compiler/nir/nir_deref.c b/src/compiler/nir/nir_deref.c
> index c03acf83597..d013b423a8b 100644
> --- a/src/compiler/nir/nir_deref.c
> +++ b/src/compiler/nir/nir_deref.c
> @@ -270,3 +270,112 @@ nir_fixup_deref_modes(nir_shader *shader)
>        }
>     }
>  }
> +
> +/** Returns true if the storage referrenced to by deref completely
> contains
> + * the storage referenced by sub.
> + */
> +nir_deref_compare_result
> +nir_compare_deref_paths(nir_deref_path *a_path,
> +                        nir_deref_path *b_path)
> +{
> +   if (a_path->path[0]->var != b_path->path[0]->var)
> +      return 0;
> +
> +   /* Start off assuming they fully compare.  We ignore equality for
> now.  In
> +    * the end, we'll determine that by containment.
> +    */
> +   nir_deref_compare_result result = nir_derefs_may_alias_bit |
> +                                     nir_derefs_a_contains_b_bit |
> +                                     nir_derefs_b_contains_a_bit;
> +
> +   nir_deref_instr **a_p = &a_path->path[1];
> +   nir_deref_instr **b_p = &b_path->path[1];
> +   while (*a_p != NULL && *b_p != NULL) {
> +      nir_deref_instr *a_tail = *(a_p++);
> +      nir_deref_instr *b_tail = *(b_p++);
> +
> +      switch (a_tail->deref_type) {
> +      case nir_deref_type_array:
> +      case nir_deref_type_array_wildcard: {
> +         assert(b_tail->deref_type == nir_deref_type_array ||
> +                b_tail->deref_type == nir_deref_type_array_wildcard);
> +
> +         if (a_tail->deref_type == nir_deref_type_array_wildcard) {
> +            if (b_tail->deref_type != nir_deref_type_array_wildcard)
> +               result &= ~nir_derefs_b_contains_a_bit;
> +         } else if (b_tail->deref_type == nir_deref_type_array_wildcard) {
> +            if (a_tail->deref_type != nir_deref_type_array_wildcard)
> +               result &= ~nir_derefs_a_contains_b_bit;
> +         } else {
> +            assert(a_tail->deref_type == nir_deref_type_array &&
> +                   b_tail->deref_type == nir_deref_type_array);
> +            assert(a_tail->arr.index.is_ssa && b_tail->arr.index.is_ssa);
> +
> +            nir_const_value *a_index_const =
> +               nir_src_as_const_value(a_tail->arr.index);
> +            nir_const_value *b_index_const =
> +               nir_src_as_const_value(b_tail->arr.index);
> +            if (a_index_const && b_index_const) {
> +               /* If they're both direct and have different offsets, they
> +                * don't even alias much less anything else.
> +                */
> +               if (a_index_const->u32[0] != b_index_const->u32[0])
> +                  return 0;
> +            } else if (a_tail->arr.index.ssa == b_tail->arr.index.ssa) {
> +               /* They're the same indirect, continue on */
> +            } else {
> +               /* They're not the same index so we can't prove anything
> about
> +                * containment.
> +                */
> +               result &= ~(nir_derefs_a_contains_b_bit |
> nir_derefs_b_contains_a_bit);
> +            }
> +         }
> +         break;
> +      }
> +
> +      case nir_deref_type_struct: {
> +         /* If they're different struct members, they don't even alias */
> +         if (a_tail->strct.index != b_tail->strct.index)
> +            return 0;
> +         break;
> +      }
> +
> +      default:
> +         unreachable("Invalid deref type");
> +      }
> +   }
> +
> +   /* If a is longer than b, then it can't contain b */
> +   if (*a_p != NULL)
> +      result &= ~nir_derefs_a_contains_b_bit;
> +   if (*b_p != NULL)
> +      result &= ~nir_derefs_b_contains_a_bit;
> +
> +   /* If a contains b and b contains a they must be equal. */
> +   if ((result & nir_derefs_a_contains_b_bit) && (result &
> nir_derefs_b_contains_a_bit))
> +      result |= nir_derefs_equal_bit;
> +
> +   return result;
> +}
> +
> +nir_deref_compare_result
> +nir_compare_derefs(nir_deref_instr *a, nir_deref_instr *b)
> +{
> +   if (a == b) {
> +      return nir_derefs_equal_bit | nir_derefs_may_alias_bit |
> +             nir_derefs_a_contains_b_bit | nir_derefs_b_contains_a_bit;
> +   }
> +
> +   nir_deref_path a_path, b_path;
> +   nir_deref_path_init(&a_path, a, NULL);
> +   nir_deref_path_init(&b_path, b, NULL);
> +   assert(a_path.path[0]->deref_type == nir_deref_type_var);
> +   assert(b_path.path[0]->deref_type == nir_deref_type_var);
> +
> +   nir_deref_compare_result result = nir_compare_deref_paths(&a_path,
> &b_path);
> +
> +   nir_deref_path_finish(&a_path);
> +   nir_deref_path_finish(&b_path);
> +
> +   return result;
> +}
> diff --git a/src/compiler/nir/nir_deref.h b/src/compiler/nir/nir_deref.h
> index 6f4141aaf82..c61c3f9366f 100644
> --- a/src/compiler/nir/nir_deref.h
> +++ b/src/compiler/nir/nir_deref.h
> @@ -54,6 +54,16 @@ unsigned
> nir_deref_instr_get_const_offset(nir_deref_instr *deref,
>  nir_ssa_def *nir_build_deref_offset(nir_builder *b, nir_deref_instr
> *deref,
>                                      glsl_type_size_align_func size_align);
>
> +typedef enum {
> +   nir_derefs_equal_bit        = (1 << 0),
> +   nir_derefs_may_alias_bit    = (1 << 1),
> +   nir_derefs_a_contains_b_bit = (1 << 2),
> +   nir_derefs_b_contains_a_bit = (1 << 3),
> +} nir_deref_compare_result;
> +
> +nir_deref_compare_result nir_compare_deref_paths(nir_deref_path *a_path,
> nir_deref_path *b_path);
> +nir_deref_compare_result nir_compare_derefs(nir_deref_instr *a,
> nir_deref_instr *b);
> +
>  #ifdef __cplusplus
>  } /* extern "C" */
>  #endif
> diff --git a/src/compiler/nir/nir_opt_copy_prop_vars.c
> b/src/compiler/nir/nir_opt_copy_prop_vars.c
> index d8c4cab34d7..9fecaf0eeec 100644
> --- a/src/compiler/nir/nir_opt_copy_prop_vars.c
> +++ b/src/compiler/nir/nir_opt_copy_prop_vars.c
> @@ -114,125 +114,6 @@ copy_entry_remove(struct copy_prop_var_state *state,
> struct copy_entry *entry)
>     list_add(&entry->link, &state->copy_free_list);
>  }
>
> -enum deref_compare_result {
> -   derefs_equal_bit = (1 << 0),
> -   derefs_may_alias_bit = (1 << 1),
> -   derefs_a_contains_b_bit = (1 << 2),
> -   derefs_b_contains_a_bit = (1 << 3),
> -};
> -
> -/** Returns true if the storage referrenced to by deref completely
> contains
> - * the storage referenced by sub.
> - *
> - * NOTE: This is fairly general and could be moved to core NIR if someone
> else
> - * ever needs it.
> - */
> -static enum deref_compare_result
> -compare_deref_paths(nir_deref_path *a_path,
> -                    nir_deref_path *b_path)
> -{
> -   if (a_path->path[0]->var != b_path->path[0]->var)
> -      return 0;
> -
> -   /* Start off assuming they fully compare.  We ignore equality for
> now.  In
> -    * the end, we'll determine that by containment.
> -    */
> -   enum deref_compare_result result = derefs_may_alias_bit |
> -                                      derefs_a_contains_b_bit |
> -                                      derefs_b_contains_a_bit;
> -
> -   nir_deref_instr **a_p = &a_path->path[1];
> -   nir_deref_instr **b_p = &b_path->path[1];
> -   while (*a_p != NULL && *b_p != NULL) {
> -      nir_deref_instr *a_tail = *(a_p++);
> -      nir_deref_instr *b_tail = *(b_p++);
> -
> -      switch (a_tail->deref_type) {
> -      case nir_deref_type_array:
> -      case nir_deref_type_array_wildcard: {
> -         assert(b_tail->deref_type == nir_deref_type_array ||
> -                b_tail->deref_type == nir_deref_type_array_wildcard);
> -
> -         if (a_tail->deref_type == nir_deref_type_array_wildcard) {
> -            if (b_tail->deref_type != nir_deref_type_array_wildcard)
> -               result &= ~derefs_b_contains_a_bit;
> -         } else if (b_tail->deref_type == nir_deref_type_array_wildcard) {
> -            if (a_tail->deref_type != nir_deref_type_array_wildcard)
> -               result &= ~derefs_a_contains_b_bit;
> -         } else {
> -            assert(a_tail->deref_type == nir_deref_type_array &&
> -                   b_tail->deref_type == nir_deref_type_array);
> -            assert(a_tail->arr.index.is_ssa && b_tail->arr.index.is_ssa);
> -
> -            nir_const_value *a_index_const =
> -               nir_src_as_const_value(a_tail->arr.index);
> -            nir_const_value *b_index_const =
> -               nir_src_as_const_value(b_tail->arr.index);
> -            if (a_index_const && b_index_const) {
> -               /* If they're both direct and have different offsets, they
> -                * don't even alias much less anything else.
> -                */
> -               if (a_index_const->u32[0] != b_index_const->u32[0])
> -                  return 0;
> -            } else if (a_tail->arr.index.ssa == b_tail->arr.index.ssa) {
> -               /* They're the same indirect, continue on */
> -            } else {
> -               /* They're not the same index so we can't prove anything
> about
> -                * containment.
> -                */
> -               result &= ~(derefs_a_contains_b_bit |
> derefs_b_contains_a_bit);
> -            }
> -         }
> -         break;
> -      }
> -
> -      case nir_deref_type_struct: {
> -         /* If they're different struct members, they don't even alias */
> -         if (a_tail->strct.index != b_tail->strct.index)
> -            return 0;
> -         break;
> -      }
> -
> -      default:
> -         unreachable("Invalid deref type");
> -      }
> -   }
> -
> -   /* If a is longer than b, then it can't contain b */
> -   if (*a_p != NULL)
> -      result &= ~derefs_a_contains_b_bit;
> -   if (*b_p != NULL)
> -      result &= ~derefs_b_contains_a_bit;
> -
> -   /* If a contains b and b contains a they must be equal. */
> -   if ((result & derefs_a_contains_b_bit) && (result &
> derefs_b_contains_a_bit))
> -      result |= derefs_equal_bit;
> -
> -   return result;
> -}
> -
> -static enum deref_compare_result
> -compare_derefs(nir_deref_instr *a, nir_deref_instr *b)
> -{
> -   if (a == b) {
> -      return derefs_equal_bit | derefs_may_alias_bit |
> -             derefs_a_contains_b_bit | derefs_b_contains_a_bit;
> -   }
> -
> -   nir_deref_path a_path, b_path;
> -   nir_deref_path_init(&a_path, a, NULL);
> -   nir_deref_path_init(&b_path, b, NULL);
> -   assert(a_path.path[0]->deref_type == nir_deref_type_var);
> -   assert(b_path.path[0]->deref_type == nir_deref_type_var);
> -
> -   enum deref_compare_result result = compare_deref_paths(&a_path,
> &b_path);
> -
> -   nir_deref_path_finish(&a_path);
> -   nir_deref_path_finish(&b_path);
> -
> -   return result;
> -}
> -
>  static void
>  remove_dead_writes(struct copy_prop_var_state *state,
>                     struct copy_entry *entry, unsigned write_mask)
> @@ -274,10 +155,10 @@ remove_dead_writes(struct copy_prop_var_state *state,
>  static struct copy_entry *
>  lookup_entry_for_deref(struct copy_prop_var_state *state,
>                         nir_deref_instr *deref,
> -                       enum deref_compare_result allowed_comparisons)
> +                       nir_deref_compare_result allowed_comparisons)
>  {
>     list_for_each_entry(struct copy_entry, iter, &state->copies, link) {
> -      if (compare_derefs(iter->dst, deref) & allowed_comparisons)
> +      if (nir_compare_derefs(iter->dst, deref) & allowed_comparisons)
>           return iter;
>     }
>
> @@ -289,7 +170,7 @@ mark_aliased_entries_as_read(struct
> copy_prop_var_state *state,
>                               nir_deref_instr *deref, unsigned components)
>  {
>     list_for_each_entry(struct copy_entry, iter, &state->copies, link) {
> -      if (compare_derefs(iter->dst, deref) & derefs_may_alias_bit)
> +      if (nir_compare_derefs(iter->dst, deref) & nir_derefs_may_alias_bit)
>           iter->comps_may_be_read |= components;
>     }
>  }
> @@ -303,23 +184,23 @@ get_entry_and_kill_aliases(struct
> copy_prop_var_state *state,
>     list_for_each_entry_safe(struct copy_entry, iter, &state->copies,
> link) {
>        if (!iter->src.is_ssa) {
>           /* If this write aliases the source of some entry, get rid of it
> */
> -         if (compare_derefs(iter->src.deref, deref) &
> derefs_may_alias_bit) {
> +         if (nir_compare_derefs(iter->src.deref, deref) &
> nir_derefs_may_alias_bit) {
>              copy_entry_remove(state, iter);
>              continue;
>           }
>        }
>
> -      enum deref_compare_result comp = compare_derefs(iter->dst, deref);
> +      nir_deref_compare_result comp = nir_compare_derefs(iter->dst,
> deref);
>        /* This is a store operation.  If we completely overwrite some
> value, we
>         * want to delete any dead writes that may be present.
>         */
> -      if (comp & derefs_b_contains_a_bit)
> +      if (comp & nir_derefs_b_contains_a_bit)
>           remove_dead_writes(state, iter, write_mask);
>
> -      if (comp & derefs_equal_bit) {
> +      if (comp & nir_derefs_equal_bit) {
>           assert(entry == NULL);
>           entry = iter;
> -      } else if (comp & derefs_may_alias_bit) {
> +      } else if (comp & nir_derefs_may_alias_bit) {
>           copy_entry_remove(state, iter);
>        }
>     }
> @@ -613,7 +494,7 @@ copy_prop_vars_block(struct copy_prop_var_state *state,
>           mark_aliased_entries_as_read(state, src, comps_read);
>
>           struct copy_entry *src_entry =
> -            lookup_entry_for_deref(state, src, derefs_a_contains_b_bit);
> +            lookup_entry_for_deref(state, src,
> nir_derefs_a_contains_b_bit);
>           struct value value;
>           if (try_load_from_entry(state, src_entry, b, intrin, src,
> &value)) {
>              if (value.is_ssa) {
> @@ -658,7 +539,7 @@ copy_prop_vars_block(struct copy_prop_var_state *state,
>            * contains what we're looking for.
>            */
>           struct copy_entry *store_entry =
> -            lookup_entry_for_deref(state, src, derefs_equal_bit);
> +            lookup_entry_for_deref(state, src, nir_derefs_equal_bit);
>           if (!store_entry)
>              store_entry = copy_entry_create(state, src);
>
> @@ -692,7 +573,7 @@ copy_prop_vars_block(struct copy_prop_var_state *state,
>           nir_deref_instr *dst = nir_src_as_deref(intrin->src[0]);
>           nir_deref_instr *src = nir_src_as_deref(intrin->src[1]);
>
> -         if (compare_derefs(src, dst) & derefs_equal_bit) {
> +         if (nir_compare_derefs(src, dst) & nir_derefs_equal_bit) {
>              /* This is a no-op self-copy.  Get rid of it */
>              nir_instr_remove(instr);
>              continue;
> @@ -701,7 +582,7 @@ copy_prop_vars_block(struct copy_prop_var_state *state,
>           mark_aliased_entries_as_read(state, src, 0xf);
>
>           struct copy_entry *src_entry =
> -            lookup_entry_for_deref(state, src, derefs_a_contains_b_bit);
> +            lookup_entry_for_deref(state, src,
> nir_derefs_a_contains_b_bit);
>           struct value value;
>           if (try_load_from_entry(state, src_entry, b, intrin, src,
> &value)) {
>              if (value.is_ssa) {
> @@ -709,7 +590,7 @@ copy_prop_vars_block(struct copy_prop_var_state *state,
>                 intrin = nir_instr_as_intrinsic(nir_builder_last_instr(b));
>              } else {
>                 /* If this would be a no-op self-copy, don't bother. */
> -               if (compare_derefs(value.deref, dst) & derefs_equal_bit)
> +               if (nir_compare_derefs(value.deref, dst) &
> nir_derefs_equal_bit)
>                    continue;
>
>                 /* Just turn it into a copy of a different deref */
> --
> 2.18.0
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20180822/b5211c75/attachment-0001.html>


More information about the mesa-dev mailing list