<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">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><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><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">@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">@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">llvm-dev@lists.llvm.org</a>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a>
</pre>
    </blockquote>
  </div>

</blockquote></div></div>