<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>