<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <p><br>
    </p>
    <div class="moz-cite-prefix">On 12/7/21 12:29 AM, Nikita Popov
      wrote:<br>
    </div>
    <blockquote type="cite"
cite="mid:CAF+90c-=yc12i_Wj2rQW4NVtFtihtwVWovyrNxJHCHYF2PBYwQ@mail.gmail.com">
      <meta http-equiv="content-type" content="text/html; charset=UTF-8">
      <div dir="ltr">
        <div class="gmail_quote">
          <div dir="ltr" class="gmail_attr">On Mon, Dec 6, 2021 at 10:51
            PM Philip Reames <<a
              href="mailto:listmail@philipreames.com"
              moz-do-not-send="true">listmail@philipreames.com</a>>
            wrote:<br>
          </div>
          <blockquote class="gmail_quote" style="margin:0px 0px 0px
            0.8ex;border-left:1px solid
            rgb(204,204,204);padding-left:1ex">
            <div>
              <p>I think this is an interesting problem.</p>
              <p>I'd probably lean towards the use of a separate
                attribute, but not strongly so.</p>
              <p>The example which makes me prefer the separate
                attribute would be a function with an out-param.  It's
                very unlikely that an out-param will be read on the
                exception path.  Being able to perform DSE for such out
                params seems quite interesting.</p>
            </div>
          </blockquote>
          <div>Right. I think it's mainly a question of whether we'd be
            able to infer the attribute in practice, in cases where it's
            not annotated by the frontend (which it should do in the
            sret case). I think this is possible at least for the case
            where all calls to the function pass in an alloca to this
            parameter (or another argument with nounwindread I guess)
            and don't use a landingpad for the call. However, I believe
            we do inference in this direction (RPO rather than PO) only
            in the module optimization pipeline, which means that
            DSE/MemCpyOpt might not be able to make use of the inferred
            information.<br>
          </div>
        </div>
      </div>
    </blockquote>
    <p>A couple of points here:</p>
    <ol>
      <li>I often see attributes for which inference isn't a goal as
        being under specified.  It's too easy not to think about all the
        corner cases up front, and that bites us later.  I think it's
        important to have specified the valid inference rules as part of
        the initial definition discussion, even if we don't implement
        them.  It forces us to think through the subtleties.  <br>
      </li>
      <li>I think you're alloc rule can be extended to any unescaped
        allocation for which we can indentify all accesses and that none
        are reachable on the exceptional path.  The trivial call rule
        (there is no exceptional path) is one sub-case of that.  This
        backwards walk may seem expensive, but I think we already do it
        in DSE, and could leave converting callsite attributes to
        functions attributes to a later RPO phase.</li>
      <li>You're right that we don't really do RPO today.  See point
        (1).  I wouldn't want to add such just for this.  <br>
      </li>
    </ol>
    <p>Aside: sret has the under-specified problem today.  I have no
      idea when it would be legal to infer sret.  <br>
    </p>
    <blockquote type="cite"
cite="mid:CAF+90c-=yc12i_Wj2rQW4NVtFtihtwVWovyrNxJHCHYF2PBYwQ@mail.gmail.com">
      <div dir="ltr">
        <div class="gmail_quote">
          <blockquote class="gmail_quote" style="margin:0px 0px 0px
            0.8ex;border-left:1px solid
            rgb(204,204,204);padding-left:1ex">
            <div>
              <p>However, I'll note that the same problem can be framed
                as an escape problem.  That is, we have an annotation
                not that a value is dead on the exception path, but that
                it hasn't been captured on entry to the routine.  Then,
                we can apply local reasoning to show that the first
                store can't be visible to may_unwind, and eliminate it.<br>
              </p>
            </div>
          </blockquote>
          <div>I don't think this would solve the same problem. In the
            given examples the pointer is already not visible to
            @may_unwind because it is noalias. "noalias" here is a
            weaker version of "not captured before": The pointer may be
            captured, but it's illegal to write through the captured
            pointer, which is sufficient for alias analysis. The problem
            with unwinding is that after the unwind, the calling
            function may read the stored value in a landingpad, which
            does not require any capture of the pointer.</div>
        </div>
      </div>
    </blockquote>
    You are completely correct, particularly on that last point.  Don't
    know what I was thinking when I first responded.  <br>
    <blockquote type="cite"
cite="mid:CAF+90c-=yc12i_Wj2rQW4NVtFtihtwVWovyrNxJHCHYF2PBYwQ@mail.gmail.com">
      <div dir="ltr">
        <div class="gmail_quote">
          <div><br>
          </div>
          <div>Regards,</div>
          <div>Nikita<br>
          </div>
          <blockquote class="gmail_quote" style="margin:0px 0px 0px
            0.8ex;border-left:1px solid
            rgb(204,204,204);padding-left:1ex">
            <div>
              <p> </p>
              <p>I'd want to give the escape framing more thought as
                that seems potentially more general.  Does knowing that
                an argument does not point to escaped memory on entry
                help on all of your motivating examples?</p>
              <p>Philip<br>
              </p>
              <div>On 12/4/21 2:39 AM, Nikita Popov via llvm-dev wrote:<br>
              </div>
              <blockquote type="cite">
                <div dir="ltr">
                  <div>Hi,</div>
                  <div><br>
                  </div>
                  <div>Consider the following IR:</div>
                  <div><br>
                  </div>
                  <div>declare void <a class="gmail_plusreply"
                      id="gmail-m_7533167157008207913plusReplyChip-4"
                      moz-do-not-send="true">@may_unwind()</a><br>
                  </div>
                  <div>define void @test(i32* noalias sret(i32) %out) {</div>
                  <div>    store i32 0, i32* %out</div>
                  <div>    call void <a class="gmail_plusreply"
                      id="gmail-m_7533167157008207913plusReplyChip-3"
                      moz-do-not-send="true">@may_unwind()<br>
                    </a>
                    <div>    store i32 1, i32* %out</div>
                  </div>
                  <div>    ret void<br>
                  </div>
                  <div>}</div>
                  <div><br>
                  </div>
                  <div>Currently, we can't remove the first store as
                    dead, because the @may_unwind() call may unwind, and
                    the caller might read %out at that point, making the
                    first store visible.</div>
                  <div><br>
                  </div>
                  <div>Similarly, it prevents call slot optimization in
                    the following example, because the call may unwind
                    and make an early write to the sret argument
                    visible:<br>
                  </div>
                  <br>
                  declare void @may_unwind(i32*)<br>
                  declare void @llvm.memcpy.p0i8.p0i8.i64(i8*, i8*, i64,
                  i1)<br>
                  define void @test(i32* noalias sret(i32) %arg) {<br>
                      %tmp = alloca i32<br>
                      call void @may_unwind(i32* nocapture %tmp)<br>
                      %tmp.8 = bitcast i32* %tmp to i8*<br>
                      %arg.8 = bitcast i32* %arg to i8*<br>
                      call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4
                  %arg.8, i8* align 4 %tmp.8, i64 4, i1 false)<br>
                      ret void<br>
                  <div>}</div>
                  <div><br>
                  </div>
                  <div>I would like to address this in some form. The
                    easiest way would be to change LangRef to specify
                    that sret arguments cannot be read on unwind paths.
                    I think that matches how sret arguments are
                    generally used.</div>
                  <div><br>
                  </div>
                  <div>Alternatively, this could be handled using a
                    separate attribute that can be applied to any
                    argument, something along the lines of "i32*
                    nounwindread sret(i32) %arg". The benefit would be
                    that this is decoupled from sret ABI semantics and
                    could potentially be inferred (e.g. if the function
                    is only ever used with call and not invoke, this
                    should be a given).</div>
                  <div><br>
                  </div>
                  <div>Any thoughts on this? Is this a problem worth
                    solving, and if yes, would a new attribute be
                    preferred over restricting sret semantics?<br>
                  </div>
                  <div><br>
                  </div>
                  <div>Regards,</div>
                  <div>Nikita<br>
                  </div>
                </div>
                <br>
                <fieldset></fieldset>
                <pre>_______________________________________________
LLVM Developers mailing list
<a href="mailto:llvm-dev@lists.llvm.org" target="_blank" moz-do-not-send="true">llvm-dev@lists.llvm.org</a>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" target="_blank" moz-do-not-send="true">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a>
</pre>
              </blockquote>
            </div>
          </blockquote>
        </div>
      </div>
    </blockquote>
  </body>
</html>