<html>
  <head>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <br>
    <br>
    <div class="moz-cite-prefix">On 19/09/15 16:34, Jason Ekstrand
      wrote:<br>
    </div>
    <blockquote
cite="mid:CAOFGe94CQh090N2KpAorLPkN78Uk9RdmTzEN3048BmTHRr9GvA@mail.gmail.com"
      type="cite">
      <p dir="ltr"><br>
        On Sep 18, 2015 10:12 AM, "Alejandro Piñeiro" <<a
          moz-do-not-send="true" href="mailto:apinheiro@igalia.com"><a class="moz-txt-link-abbreviated" href="mailto:apinheiro@igalia.com">apinheiro@igalia.com</a></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>
    </blockquote>
    <br>
    Ok.<br>
    <br>
    <blockquote
cite="mid:CAOFGe94CQh090N2KpAorLPkN78Uk9RdmTzEN3048BmTHRr9GvA@mail.gmail.com"
      type="cite">
      <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>
    </blockquote>
    <br>
    Oh true, if I have a source, that means that it came from a MOV.
    Good catch.<br>
    <br>
    Thanks for the hints.<br>
    <br>
    <blockquote
cite="mid:CAOFGe94CQh090N2KpAorLPkN78Uk9RdmTzEN3048BmTHRr9GvA@mail.gmail.com"
      type="cite">
      <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 moz-do-not-send="true"
          href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
        > <a moz-do-not-send="true"
          href="http://lists.freedesktop.org/mailman/listinfo/mesa-dev">http://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
      </p>
    </blockquote>
    <br>
    <pre class="moz-signature" cols="72">-- 
Alejandro Piñeiro (<a class="moz-txt-link-abbreviated" href="mailto:apinheiro@igalia.com">apinheiro@igalia.com</a>)</pre>
  </body>
</html>