[Mesa-dev] [PATCH 90.1/133] SQUASH/nir: Add documentation for nir_split_var_copies

Connor Abbott cwabbott0 at gmail.com
Wed Jan 14 13:40:12 PST 2015


With this squashed in, patch 90 is

Reviewed-by: Connor Abbott <cwabbott0 at gmail.com>

On Wed, Jan 14, 2015 at 2:57 PM, Jason Ekstrand <jason at jlekstrand.net> wrote:
> ---
>  src/glsl/nir/nir_split_var_copies.c | 96 ++++++++++++++++++++++++++++++-------
>  1 file changed, 78 insertions(+), 18 deletions(-)
>
> diff --git a/src/glsl/nir/nir_split_var_copies.c b/src/glsl/nir/nir_split_var_copies.c
> index 70ce30a..4d663b5 100644
> --- a/src/glsl/nir/nir_split_var_copies.c
> +++ b/src/glsl/nir/nir_split_var_copies.c
> @@ -74,40 +74,81 @@ get_deref_tail(nir_deref *deref)
>     return deref;
>  }
>
> +/* Recursively constructs deref chains to split a copy instruction into
> + * multiple (if needed) copy instructions with full-length deref chains.
> + * External callers of this function should pass the tail and head of the
> + * deref chains found as the source and destination of the copy instruction
> + * into this function.
> + *
> + * \param  old_copy  The copy instruction we are splitting
> + * \param  dest_head The head of the destination deref chain we are building
> + * \param  src_head  The head of the source deref chain we are building
> + * \param  dest_tail The tail of the destination deref chain we are building
> + * \param  src_tail  The tail of the source deref chain we are building
> + * \param  state     The current split_var_copies_state object
> + */
>  static void
> -nir_split_var_copy_instr(nir_intrinsic_instr *old_copy,
> -                         nir_deref *dest_head, nir_deref *src_head,
> -                         nir_deref *dest_tail, nir_deref *src_tail,
> -                         struct split_var_copies_state *state)
> +split_var_copy_instr(nir_intrinsic_instr *old_copy,
> +                     nir_deref *dest_head, nir_deref *src_head,
> +                     nir_deref *dest_tail, nir_deref *src_tail,
> +                     struct split_var_copies_state *state)
>  {
>     assert(src_tail->type == dest_tail->type);
>
> +   /* Make sure these really are the tails of the deref chains */
> +   assert(dest_tail->child == NULL);
> +   assert(src_tail->child == NULL);
> +
>     switch (glsl_get_base_type(src_tail->type)) {
>     case GLSL_TYPE_ARRAY: {
> +      /* Make a wildcard dereference */
>        nir_deref_array *deref = nir_deref_array_create(state->dead_ctx);
>        deref->deref.type = glsl_get_array_element(src_tail->type);
>        deref->deref_array_type = nir_deref_array_type_wildcard;
>
> +      /* Set the tail of both as the newly created wildcard deref.  It is
> +       * safe to use the same wildcard in both places because a) we will be
> +       * copying it before we put it in an actual instruction and b)
> +       * everything that will potentially add another link in the deref
> +       * chain will also add the same thing to both chains.
> +       */
>        src_tail->child = &deref->deref;
>        dest_tail->child = &deref->deref;
> -      nir_split_var_copy_instr(old_copy, dest_head, src_head,
> -                               dest_tail->child, src_tail->child, state);
> +
> +      split_var_copy_instr(old_copy, dest_head, src_head,
> +                           dest_tail->child, src_tail->child, state);
> +
> +      /* Set it back to the way we found it */
>        src_tail->child = NULL;
>        dest_tail->child = NULL;
>        break;
>     }
>
>     case GLSL_TYPE_STRUCT:
> +      /* This is the only part that actually does any interesting
> +       * splitting.  For array types, we just use wildcards and resolve
> +       * them later.  For structure types, we need to emit one copy
> +       * instruction for every structure element.  Because we may have
> +       * structs inside structs, we just recurse and let the next level
> +       * take care of any additional structures.
> +       */
>        for (unsigned i = 0; i < glsl_get_length(src_tail->type); i++) {
>           nir_deref_struct *deref = nir_deref_struct_create(state->dead_ctx, i);
>           deref->deref.type = glsl_get_struct_field(src_tail->type, i);
>
> +         /* Set the tail of both as the newly created structure deref.  It
> +          * is safe to use the same wildcard in both places because a) we
> +          * will be copying it before we put it in an actual instruction
> +          * and b) everything that will potentially add another link in the
> +          * deref chain will also add the same thing to both chains.
> +          */
>           src_tail->child = &deref->deref;
>           dest_tail->child = &deref->deref;
>
> -         nir_split_var_copy_instr(old_copy, dest_head, src_head,
> -                                  dest_tail->child, src_tail->child, state);
> +         split_var_copy_instr(old_copy, dest_head, src_head,
> +                              dest_tail->child, src_tail->child, state);
>        }
> +      /* Set it back to the way we found it */
>        src_tail->child = NULL;
>        dest_tail->child = NULL;
>        break;
> @@ -121,22 +162,41 @@ nir_split_var_copy_instr(nir_intrinsic_instr *old_copy,
>           deref->deref.type = glsl_get_column_type(src_tail->type);
>           deref->deref_array_type = nir_deref_array_type_wildcard;
>
> +         /* Set the tail of both as the newly created wildcard deref.  It
> +          * is safe to use the same wildcard in both places because a) we
> +          * will be copying it before we put it in an actual instruction
> +          * and b) everything that will potentially add another link in the
> +          * deref chain will also add the same thing to both chains.
> +          */
>           src_tail->child = &deref->deref;
>           dest_tail->child = &deref->deref;
> -         nir_split_var_copy_instr(old_copy, dest_head, src_head,
> -                                  dest_tail->child, src_tail->child, state);
> +
> +         split_var_copy_instr(old_copy, dest_head, src_head,
> +                              dest_tail->child, src_tail->child, state);
> +
> +         /* Set it back to the way we found it */
>           src_tail->child = NULL;
>           dest_tail->child = NULL;
>        } else {
> +         /* At this point, we have fully built our deref chains and can
> +          * actually add the new copy instruction.
> +          */
>           nir_intrinsic_instr *new_copy =
>              nir_intrinsic_instr_create(state->mem_ctx, nir_intrinsic_copy_var);
>
> +         /* We need to make copies because a) this deref chain actually
> +          * belongs to the copy instruction and b) the deref chains may
> +          * have some of the same links due to the way we constructed them
> +          */
>           nir_deref *src = nir_copy_deref(state->mem_ctx, src_head);
>           nir_deref *dest = nir_copy_deref(state->mem_ctx, dest_head);
>
>           new_copy->variables[0] = nir_deref_as_var(dest);
>           new_copy->variables[1] = nir_deref_as_var(src);
>
> +         /* Emit the copy instruction after the old instruction.  We'll
> +          * remove the old one later.
> +          */
>           nir_instr_insert_after(&old_copy->instr, &new_copy->instr);
>        }
>        break;
> @@ -151,7 +211,7 @@ nir_split_var_copy_instr(nir_intrinsic_instr *old_copy,
>  }
>
>  static bool
> -nir_split_var_copies_block(nir_block *block, void *void_state)
> +split_var_copies_block(nir_block *block, void *void_state)
>  {
>     struct split_var_copies_state *state = void_state;
>
> @@ -171,8 +231,8 @@ nir_split_var_copies_block(nir_block *block, void *void_state)
>        switch (glsl_get_base_type(src_tail->type)) {
>        case GLSL_TYPE_ARRAY:
>        case GLSL_TYPE_STRUCT:
> -         nir_split_var_copy_instr(intrinsic, dest_head, src_head,
> -                                  dest_tail, src_tail, state);
> +         split_var_copy_instr(intrinsic, dest_head, src_head,
> +                              dest_tail, src_tail, state);
>           nir_instr_remove(&intrinsic->instr);
>           ralloc_steal(state->dead_ctx, instr);
>           break;
> @@ -181,8 +241,8 @@ nir_split_var_copies_block(nir_block *block, void *void_state)
>        case GLSL_TYPE_UINT:
>        case GLSL_TYPE_BOOL:
>           if (glsl_type_is_matrix(src_tail->type)) {
> -            nir_split_var_copy_instr(intrinsic, dest_head, src_head,
> -                                     dest_tail, src_tail, state);
> +            split_var_copy_instr(intrinsic, dest_head, src_head,
> +                                 dest_tail, src_tail, state);
>              nir_instr_remove(&intrinsic->instr);
>              ralloc_steal(state->dead_ctx, instr);
>           }
> @@ -197,14 +257,14 @@ nir_split_var_copies_block(nir_block *block, void *void_state)
>  }
>
>  static void
> -nir_split_var_copies_impl(nir_function_impl *impl)
> +split_var_copies_impl(nir_function_impl *impl)
>  {
>     struct split_var_copies_state state;
>
>     state.mem_ctx = ralloc_parent(impl);
>     state.dead_ctx = ralloc_context(NULL);
>
> -   nir_foreach_block(impl, nir_split_var_copies_block, &state);
> +   nir_foreach_block(impl, split_var_copies_block, &state);
>
>     ralloc_free(state.dead_ctx);
>  }
> @@ -214,6 +274,6 @@ nir_split_var_copies(nir_shader *shader)
>  {
>     nir_foreach_overload(shader, overload) {
>        if (overload->impl)
> -         nir_split_var_copies_impl(overload->impl);
> +         split_var_copies_impl(overload->impl);
>     }
>  }
> --
> 2.2.1
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list