<div dir="ltr"><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Jan 3, 2022 at 6:33 PM Johannes Doerfert <<a href="mailto:johannesdoerfert@gmail.com">johannesdoerfert@gmail.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">I somewhat missed this thread and while I should maybe respond<br>
to a few of the other mails too I figured I start with a conceptual<br>
question I have reading this:<br>
<br>
Who and when is the attribute added? If it is implied by sret that's<br>
a good start. For the non-sret deduction it seems very specialized.<br>
I mean, now we have something for the unwind case but not a different<br>
"early exit" or if it is read/writeonly rather than readnone.<br></blockquote><div><br></div><div class="gmail_quote">I'm mainly interested in frontend-annotated cases here, rather than deduced ones. The primary use case there is adding it to sret arguments (and only changing sret semantics would be "good enough" for me, I guess). However, there is another frontend-annotated case I have my eyes on, which is move arguments in rust. These could be modeled by a combination of noreadonunwind and noreadonreturn to indicate that the value will not be used after the call at all, regardless of how it exits. (This would be kind of similar to a byval argument, just without the ABI implication that an actual copy gets inserted.)</div><div class="gmail_quote"><br></div><div class="gmail_quote">Note that as proposed, the noreadonunwind attribute would be the "writeonly on unwind" combination (and noreadonreturn the "writeonly on return" combination). I can see that there are conjugated "readonly on unwind" and "readonly on return" attributes that could be defined here, but I can't think of any circumstances under which these would actually be useful for optimization purposes. How would the presence or absence of later writes impact optimization in the current function?<br></div><div class="gmail_quote"><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

The argument about invoke vs. call instruction call sites only holds for<br>
sret args anyway, so maybe what you are designing here is too sret specific.<br></blockquote><div><br></div><div>Not sure I follow, why would that argument only hold for sret?</div><div><br></div><div>Regards,<br></div><div>Nikita<br></div><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Long term I'd like us to have a proper "side-effect" encoding with values<br>
and that could include conditions, e.g.,<br>
<br>
```<br>
sideeffects(       write(_unknown_, %arg), read(_unknown_),<br>
             unwind{write(_unknown_), read(_unknown_)},<br>
             cond(load %arg eq 0, {read($arg)})<br>
            )<br>
```<br>
<br>
While this is still long away (probably), I'm not convinced an attribute<br>
that is specific to unwind *and* readnone is the right intermediate step.<br>
It should compose better with readonly/writeonly/readnone at least.<br>
<br>
All that said, would your deduction strategy alone solve the problem?<br>
So, the cases you care about could they be optimized by looking at the<br>
call sites and determining if none is an invoke?<br>
<br>
~ Johannes<br>
<br>
<br>
On 12/4/21 04:39, Nikita Popov via llvm-dev wrote:<br>
> Hi,<br>
><br>
> Consider the following IR:<br>
><br>
> declare void @may_unwind()<br>
> define void @test(i32* noalias sret(i32) %out) {<br>
>      store i32 0, i32* %out<br>
>      call void @may_unwind()<br>
>      store i32 1, i32* %out<br>
>      ret void<br>
> }<br>
><br>
> Currently, we can't remove the first store as dead, because the<br>
> @may_unwind() call may unwind, and the caller might read %out at that<br>
> point, making the first store visible.<br>
><br>
> Similarly, it prevents call slot optimization in the following example,<br>
> because the call may unwind and make an early write to the sret argument<br>
> visible:<br>
><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<br>
> %tmp.8, i64 4, i1 false)<br>
>      ret void<br>
> }<br>
><br>
> I would like to address this in some form. The easiest way would be to<br>
> change LangRef to specify that sret arguments cannot be read on unwind<br>
> paths. I think that matches how sret arguments are generally used.<br>
><br>
> Alternatively, this could be handled using a separate attribute that can be<br>
> applied to any argument, something along the lines of "i32* nounwindread<br>
> sret(i32) %arg". The benefit would be that this is decoupled from sret ABI<br>
> semantics and could potentially be inferred (e.g. if the function is only<br>
> ever used with call and not invoke, this should be a given).<br>
><br>
> Any thoughts on this? Is this a problem worth solving, and if yes, would a<br>
> new attribute be preferred over restricting sret semantics?<br>
><br>
> Regards,<br>
> Nikita<br>
><br>
><br>
> _______________________________________________<br>
> LLVM Developers mailing list<br>
> <a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a><br>
> <a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
</blockquote></div></div></div>