<p dir="ltr"><br>
On Sep 18, 2015 10:12 AM, "Alejandro Piñeiro" <<a href="mailto:apinheiro@igalia.com">apinheiro@igalia.com</a>> wrote:<br>
><br>
> SEL and MOV instructions, as long as they don't have source modifiers, are<br>
> just copying bits around.  So those kind of instruction could be propagated<br>
> even if there are type mismatches. This is needed because NIR generates<br>
> integer SEL and MOV instructions whenever it doesn't know what else to<br>
> generate.<br>
><br>
> This commit adds support for copy propagation using previous instruction<br>
> as reference.<br>
><br>
> v2: using 'arg' index to get the from inst was wrong, as pointed<br>
>     by Jason Ekstrand<br>
> v3: rebased against last change on the previous patch of theh series<br>
> ---<br>
><br>
> v3 is just a rebase against the first patch on the series. I also<br>
> realized that yesterday I did a mess when I sent the v2 of this<br>
> patch (answering to the wrong email, not including v3 on the subject),<br>
> so I will copy the text I had on that email here. Sorry for the noise.<br>
><br>
> From the review:<br>
> >>     if (has_source_modifiers &&<br>
> >>         value.type != inst->src[arg].type &&<br>
> >> -       !can_change_source_types(inst))<br>
> >> +       !can_change_source_types(inst) &&<br>
> >> +       !can_change_source_types(entry->inst[arg]))<br>
><br>
> > This isn't right.  The entry->inst array is indexed on vec4 component<br>
> > but arg is the argument of the instruction.  I think what you want to<br>
> > do is add something to the loop above to loop over 0...3 and check<br>
> > them all.<br>
><br>
> Yes you are right. At that moment I misunderstood 'arg' as the channel<br>
> being used at that moment, and as piglit didn't correct me with a<br>
> regression I never realized that I was wrong. This v2 computes<br>
> the instruction we are looking for corrrectly, with the a loop<br>
> as suggested.<br>
><br>
> >  Also, how this is different from has_source_modifiers?<br>
><br>
> It is different because at that moment has_source_modifiers has<br>
> been computed using the src_reg value that had their modifiers<br>
> changed to the ones at the current string:<br>
><br>
>    if (inst->src[arg].abs) {<br>
>       value.negate = false;<br>
>       value.abs = true;<br>
>    }<br>
>    if (inst->src[arg].negate)<br>
>       value.negate = !value.negate;<br>
><br>
>    bool has_source_modifiers = value.negate || value.abs;<br>
><br>
> While can_change_source_types with the from instruction is<br>
> using the original ones, and checking that is a mov, so "safe"<br>
> to going on with the propagation.<br>
><br>
> That means that there is an alternative to track the instructions<br>
> at copy_entry. I could maintain a copy of value without being<br>
> modified, or compute has_source_modifiers (ie: original_has_source_modifiers).</p>
<p dir="ltr">I think I would prefer that if we can make it work.</p>
<p dir="ltr">> But I would still need to check if the opcode is a MOV on the from<br>
> instruction, so I would need to track opcode on the copy_entry struct.<br>
> Tracking inst also have the advantage that I can reuse the<br>
> function can_change_source_types.</p>
<p dir="ltr">The copy_entry struct shouldn't get filled out.  In particular, we only set the source if is_direct_copy() returns true.</p>
<p dir="ltr">><br>
> > Obviously, it is (the shader-db numbers say so) but I'm not seeing it.<br>
> > Could you please provide an example.<br>
><br>
> Ok. On a shader like this:<br>
><br>
>    uniform vec4 inData;<br>
><br>
>    void main(void)<br>
>    {<br>
>      gl_Position = gl_Vertex - inData;<br>
>    }<br>
><br>
> VS-0001-00-start is like this:<br>
>    0: mov vgrf0.0:F, attr0.xyzw:F<br>
>    1: mov vgrf1.0:UD, u0.xyzw:UD<br>
>    2: add vgrf2.0:F, vgrf0.xyzw:F, -vgrf1.xyzw:F<br>
>    3: mov m2:D, 0D<br>
>    4: mov m3:F, vgrf2.xyzw:F<br>
>    5: vs_urb_write (null):UD<br>
><br>
> When we are at instruction #2, has_source_modifiers is true<br>
> even for the value u0 because as I mentioned, it is copying the<br>
> modifiers at the same instruction (the modifiers of<br>
> vgrf1 at #2). But in any case, it is "safe" to do the copy<br>
> propagation from instruction #1 to instruction #2.</p>
<p dir="ltr">Thanks, that makes sense.<br>
--Jason</p>
<p dir="ltr">><br>
>  .../drivers/dri/i965/brw_vec4_copy_propagation.cpp | 47 ++++++++++++++++------<br>
>  1 file changed, 35 insertions(+), 12 deletions(-)<br>
><br>
> diff --git a/src/mesa/drivers/dri/i965/brw_vec4_copy_propagation.cpp b/src/mesa/drivers/dri/i965/brw_vec4_copy_propagation.cpp<br>
> index 1522eea..dabc25f 100644<br>
> --- a/src/mesa/drivers/dri/i965/brw_vec4_copy_propagation.cpp<br>
> +++ b/src/mesa/drivers/dri/i965/brw_vec4_copy_propagation.cpp<br>
> @@ -39,6 +39,7 @@ namespace brw {<br>
><br>
>  struct copy_entry {<br>
>     src_reg *value[4];<br>
> +   vec4_instruction *inst[4];<br>
>     int saturatemask;<br>
>  };<br>
><br>
> @@ -251,7 +252,8 @@ try_constant_propagate(const struct brw_device_info *devinfo,<br>
>  static bool<br>
>  can_change_source_types(vec4_instruction *inst)<br>
>  {<br>
> -   return inst->dst.type == inst->src[0].type &&<br>
> +   return inst != NULL &&<br>
> +      inst->dst.type == inst->src[0].type &&<br>
>        !inst->src[0].abs && !inst->src[0].negate && !inst->saturate &&<br>
>        (inst->opcode == BRW_OPCODE_MOV ||<br>
>         (inst->opcode == BRW_OPCODE_SEL &&<br>
> @@ -271,6 +273,8 @@ try_copy_propagate(const struct brw_device_info *devinfo,<br>
>      * vectors better.<br>
>      */<br>
>     src_reg value = *entry->value[0];<br>
> +   vec4_instruction *from_inst = entry->inst[0];<br>
> +<br>
>     for (int i = 1; i < 4; i++) {<br>
>        /* This is equals() except we don't care about the swizzle. */<br>
>        if (value.file != entry->value[i]->file ||<br>
> @@ -283,6 +287,13 @@ try_copy_propagate(const struct brw_device_info *devinfo,<br>
>        }<br>
>     }<br>
><br>
> +   for (int i = 1; i < 4; i++) {<br>
> +      if (from_inst != entry->inst[i]) {<br>
> +         from_inst = NULL;<br>
> +         break;<br>
> +      }<br>
> +   }<br>
> +<br>
>     /* Compute the swizzle of the original register by swizzling the<br>
>      * component loaded from each value according to the swizzle of<br>
>      * operand we're going to change.<br>
> @@ -322,7 +333,8 @@ try_copy_propagate(const struct brw_device_info *devinfo,<br>
><br>
>     if (has_source_modifiers &&<br>
>         value.type != inst->src[arg].type &&<br>
> -       !can_change_source_types(inst))<br>
> +       !can_change_source_types(inst) &&<br>
> +       !can_change_source_types(from_inst))<br>
>        return false;<br>
><br>
>     if (has_source_modifiers &&<br>
> @@ -340,7 +352,8 @@ try_copy_propagate(const struct brw_device_info *devinfo,<br>
>      * instead. See also resolve_ud_negate().<br>
>      */<br>
>     if (value.negate &&<br>
> -       value.type == BRW_REGISTER_TYPE_UD)<br>
> +       value.type == BRW_REGISTER_TYPE_UD &&<br>
> +       !can_change_source_types(from_inst))<br>
>        return false;<br>
><br>
>     /* Don't report progress if this is a noop. */<br>
> @@ -378,17 +391,25 @@ try_copy_propagate(const struct brw_device_info *devinfo,<br>
><br>
>     if (has_source_modifiers &&<br>
>         value.type != inst->src[arg].type) {<br>
> -      /* We are propagating source modifiers from a MOV with a different<br>
> -       * type.  If we got here, then we can just change the source and<br>
> -       * destination types of the instruction and keep going.<br>
> +      /* We are propagating source modifiers from a safe instruction with a<br>
> +       * different type. If we got here, then we can just change the source<br>
> +       * and destination types of the current instruction or the instruction<br>
> +       * from we are propagating.<br>
>         */<br>
> -      assert(can_change_source_types(inst));<br>
> -      for (int i = 0; i < 3; i++) {<br>
> -         inst->src[i].type = value.type;<br>
> +      assert(can_change_source_types(inst) ||<br>
> +             can_change_source_types(from_inst));<br>
> +<br>
> +      if (can_change_source_types(inst)) {<br>
> +         for (int i = 0; i < 3; i++) {<br>
> +            inst->src[i].type = value.type;<br>
> +         }<br>
> +         inst->dst.type = value.type;<br>
> +      } else {<br>
> +         value.type = inst->src[arg].type;<br>
>        }<br>
> -      inst->dst.type = value.type;<br>
> -   } else<br>
> +   } else {<br>
>        value.type = inst->src[arg].type;<br>
> +   }<br>
>     inst->src[arg] = value;<br>
>     return true;<br>
>  }<br>
> @@ -441,7 +462,7 @@ vec4_visitor::opt_copy_propagation(bool do_constant_prop)<br>
>          for (c = 0; c < 4; c++) {<br>
>              int channel = BRW_GET_SWZ(inst->src[i].swizzle, c);<br>
>              entry.value[c] = entries[reg].value[channel];<br>
> -<br>
> +            entry.inst[c] = entries[reg].inst[channel];<br>
>             /* If there's no available copy for this channel, bail.<br>
>              * We could be more aggressive here -- some channels might<br>
>              * not get used based on the destination writemask.<br>
> @@ -486,6 +507,7 @@ vec4_visitor::opt_copy_propagation(bool do_constant_prop)<br>
>                 entries[reg].value[i] = direct_copy ? &inst->src[0] : NULL;<br>
>                 entries[reg].saturatemask |=<br>
>                    inst->saturate && direct_copy ? 1 << i : 0;<br>
> +               entries[reg].inst[i] = direct_copy ? inst : NULL;<br>
>              }<br>
>          }<br>
><br>
> @@ -500,6 +522,7 @@ vec4_visitor::opt_copy_propagation(bool do_constant_prop)<br>
>                   if (is_channel_updated(inst, entries[i].value, j)) {<br>
>                      entries[i].value[j] = NULL;<br>
>                      entries[i].saturatemask &= ~(1 << j);<br>
> +                     entries[i].inst[j] = NULL;<br>
>                    }<br>
>                }<br>
>             }<br>
> --<br>
> 2.1.4<br>
><br>
> _______________________________________________<br>
> mesa-dev mailing list<br>
> <a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
> <a href="http://lists.freedesktop.org/mailman/listinfo/mesa-dev">http://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
</p>