[Mesa-dev] [PATCH v3 003/104] nir/builder: Add deref building helpers

Rob Clark robdclark at gmail.com
Sun Apr 8 18:07:58 UTC 2018


On Sun, Apr 8, 2018 at 7:21 AM, Rob Clark <robdclark at gmail.com> wrote:
> On Tue, Apr 3, 2018 at 2:32 PM, Jason Ekstrand <jason at jlekstrand.net> wrote:
>> ---
>>  src/compiler/nir/nir_builder.h | 106 +++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 106 insertions(+)
>>
>> diff --git a/src/compiler/nir/nir_builder.h b/src/compiler/nir/nir_builder.h
>> index 8f7ddf1..69c7261 100644
>> --- a/src/compiler/nir/nir_builder.h
>> +++ b/src/compiler/nir/nir_builder.h
>> @@ -525,6 +525,112 @@ nir_ssa_for_alu_src(nir_builder *build, nir_alu_instr *instr, unsigned srcn)
>>     return nir_imov_alu(build, *src, num_components);
>>  }
>>
>> +static inline nir_deref_instr *
>> +nir_build_deref_var(nir_builder *build, nir_variable *var)
>> +{
>> +   nir_deref_instr *deref =
>> +      nir_deref_instr_create(build->shader, nir_deref_type_var);
>> +
>> +   deref->mode = var->data.mode;
>> +   deref->type = var->type;
>> +   deref->var = var;
>> +
>> +   nir_ssa_dest_init(&deref->instr, &deref->dest, 1, 32, NULL);
>> +
>> +   nir_builder_instr_insert(build, &deref->instr);
>> +
>> +   return deref;
>> +}
>> +
>> +static inline nir_deref_instr *
>> +nir_build_deref_array(nir_builder *build, nir_deref_instr *parent,
>> +                      nir_ssa_def *index)
>> +{
>> +   assert(glsl_type_is_array(parent->type) ||
>> +          glsl_type_is_matrix(parent->type) ||
>> +          glsl_type_is_vector(parent->type));
>> +
>> +   nir_deref_instr *deref =
>> +      nir_deref_instr_create(build->shader, nir_deref_type_array);
>> +
>> +   deref->mode = parent->mode;
>> +   deref->type = glsl_get_array_element(parent->type);
>> +   deref->parent = nir_src_for_ssa(&parent->dest.ssa);
>> +   deref->arr.index = nir_src_for_ssa(index);
>> +
>> +   nir_ssa_dest_init(&deref->instr, &deref->dest,
>> +                     parent->dest.ssa.num_components,
>> +                     parent->dest.ssa.bit_size, NULL);
>> +
>> +   nir_builder_instr_insert(build, &deref->instr);
>> +
>> +   return deref;
>> +}
>> +
>> +static inline nir_deref_instr *
>> +nir_build_deref_array_wildcard(nir_builder *build, nir_deref_instr *parent)
>> +{
>> +   assert(glsl_type_is_array(parent->type) ||
>> +          glsl_type_is_matrix(parent->type));
>> +
>> +   nir_deref_instr *deref =
>> +      nir_deref_instr_create(build->shader, nir_deref_type_array_wildcard);
>> +
>> +   deref->mode = parent->mode;
>> +   deref->type = glsl_get_array_element(parent->type);
>> +   deref->parent = nir_src_for_ssa(&parent->dest.ssa);
>> +
>> +   nir_ssa_dest_init(&deref->instr, &deref->dest,
>> +                     parent->dest.ssa.num_components,
>> +                     parent->dest.ssa.bit_size, NULL);
>> +
>> +   nir_builder_instr_insert(build, &deref->instr);
>> +
>> +   return deref;
>> +}
>> +
>> +static inline nir_deref_instr *
>> +nir_build_deref_struct(nir_builder *build, nir_deref_instr *parent,
>> +                       unsigned index)
>> +{
>> +   assert(glsl_type_is_struct(parent->type));
>> +
>> +   nir_deref_instr *deref =
>> +      nir_deref_instr_create(build->shader, nir_deref_type_struct);
>> +
>> +   deref->mode = parent->mode;
>> +   deref->type = glsl_get_struct_field(parent->type, index);
>> +   deref->parent = nir_src_for_ssa(&parent->dest.ssa);
>> +   deref->strct.index = index;
>> +
>> +   nir_ssa_dest_init(&deref->instr, &deref->dest,
>> +                     parent->dest.ssa.num_components,
>> +                     parent->dest.ssa.bit_size, NULL);
>> +
>> +   nir_builder_instr_insert(build, &deref->instr);
>> +
>> +   return deref;
>> +}
>> +
>> +static inline nir_deref_instr *
>> +nir_build_deref_cast(nir_builder *build, nir_ssa_def *parent,
>> +                     nir_variable_mode mode, const struct glsl_type *type)
>
> so a couple small differences between deref_cast and what I had in
> mind for deref_ptr:
>
> 1) deref_ptr took two ssa src's, one is the input pointer (a vec2),
> and the 2nd an array idx (which can be zero), which matches the
> 'Element' parameter in the Op*PtrAccessChain instructions.  Ie. a ptr
> is dereferenced as ptrval[Element].foo.bar (where ptr->foo.bar or
> (*ptr).foo.bar is just a nice way to write ptr[0].foo.bar)
>
> 2) not sure nir_variable_mode makes sense with pointers.. well maybe
> we need to add some nir_variable_mode values to differentiate between
> global/local/const memory spaces (I couldn't think of a good name for
> global since nir_var_global is already taken but has a different
> meaning).  But in any case, the variable mode comes from the pointer
> value itself.
>
> Other random thought, I don't think we should allow a deref_cast (if
> that is what we use for pointers) to have a src instruction that is a
> deref instruction.  We probably instead want an intrinsic that
> evaluates to the address of a deref chain.  So something like:
>
>    ptr2 = &ptr1->foo;
>    ptr2++;
>    result_val = ptr2->bar;
>
> becomes something like:
>
>    vec1 64 ssa_0 = ... ptr1 address ...
>    vec1 64 ssa_1 = ... ptr1 address space, ie. global/shared/const ...
>    vec2 64 ssa_2 = vec2 ssa_0, ssa_1
>    vec1 32 ssa_3 = deref_cast (struct.SomeStruct *)&ssa_2[0]
>    vec1 32 ssa_4 = deref_struct () &ssa_3->foo
>    vec2 64 ssa_5 = intrinsic address_deref (ssa_4) ()
>    vec1 32 ssa_6 = deref_cast (struct.OtherStruct *)&ssa_5[1]
>    vec2 64 ssa_7 = intrinsic address_deref (ssa_6) ()
>    vec1 32 ssa_8 = deref_cast (struct.OtherStruct *)&ssa_7[0]
>    vec1 32 ssa_9 = deref_struct () &ssa_8->bar
>    vec1 32 ssa_10 = intrinsic load_deref (ssa_9) ()   /* load 'result_val' */
>

fwiw, this is what I have in mind for tweaking deref_cast to be more
like what we need for generic pointers:

  https://github.com/freedreno/mesa/commit/ce8a8adc5d0f0e6eaa8090d8aba92651668b7b51

I have something working(ish), which I'll cleanup further and rebase
the rest of the clover/vtn/ir3 patches for compute support on tomorrow
(or perhaps later today):

  https://github.com/freedreno/mesa/commits/wip-spirv-v4

which generates something like:

  https://hastebin.com/iyutozuduk.c

it still needs a bit more work to utilize the address_from_deref
intrinisc when we have something that would currently try to handle
things like:

         %18 = OpInBoundsPtrAccessChain %_ptr_CrossWorkgroup_uchar %12
%uint_0 %uint_2 %uint_1
         %19 = OpInBoundsPtrAccessChain %_ptr_CrossWorkgroup_uchar %18 %uint_1

(I guess we *could* try to allow deref_cast mid deref-chain for that,
but vtn isn't really setup for that and address_from_deref intrinsic
is pretty easy to implement and seems like the cleaner solution)

BR,
-R


> BR,
> -R
>
>
>> +{
>> +   nir_deref_instr *deref =
>> +      nir_deref_instr_create(build->shader, nir_deref_type_cast);
>> +
>> +   deref->mode = mode;
>> +   deref->type = type;
>> +   deref->parent = nir_src_for_ssa(parent);
>> +
>> +   nir_ssa_dest_init(&deref->instr, &deref->dest,
>> +                     parent->num_components, parent->bit_size, NULL);
>> +
>> +   nir_builder_instr_insert(build, &deref->instr);
>> +
>> +   return deref;
>> +}
>> +
>>  static inline nir_ssa_def *
>>  nir_load_var(nir_builder *build, nir_variable *var)
>>  {
>> --
>> 2.5.0.400.gff86faf
>>
>> _______________________________________________
>> mesa-dev mailing list
>> mesa-dev at lists.freedesktop.org
>> https://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list