[llvm-dev] sret read after unwind

Nikita Popov via llvm-dev llvm-dev at lists.llvm.org
Fri Jan 7 02:45:40 PST 2022


On Thu, Jan 6, 2022 at 6:47 PM Johannes Doerfert <johannesdoerfert at gmail.com>
wrote:

>
> On 1/5/22 07:41, Nikita Popov wrote:
> >> Maybe I am confused but I thought something like this pseudo-code
> >> could be optimized, readonly_on_return is similar.
> >>
> >> ```
> >> int a = 42;
> >> invoke foo(/* readonly_on_unwind */ &a);
> >> lp:
> >>     return a; // a == 42
> >> cont:
> >>     return a; // a unknown
> >> ```
> >>
> > Okay, I guess there's a possible point of confusion here: The intention
> > here is that the attribute encodes a requirement on accesses *after* the
> > call. readonly_on_unwind would allow only reading "a" in "lp", but does
> not
> > prevent foo() from modifying "a" even if it ultimately unwinds. With that
> > in mind, I don't think the attribute would enable any additional
> > optimization here.
> >
> > So maybe the proposed attribute is better named as "noreadafterunwind"
> > rather than "noreadonunwind".
>
> So I misunderstood the entire idea :D
>
> I am not sure how I feel about such a new "category" of attributes.
> Can we try to throw around some ideas before we commit to it?
>
> One of the weirdest things is that the semantics are somewhat
> described in terms of the caller. Making it callee-centric might
> help, e.g., `poison_on_unwind(%a)` to indicate the value in the
> unwind case is "not read" or rather, replaced with poison.
>

Yeah, the caller-dependent semantics are unusual. poison_on_unwind is an
interesting idea, though also a bit odd in that attributes usually describe
a constraint.


> You noted in the other mail that we don't want to make unwind paths
> explicit (which I agree with, FWIW). However, in the caller we already
> have them explicitly, no? So what materializing the "virtual memset"/
> lifetime.end stuff there? Frontends (like Rust) can do it based on the
> callee type so that should not be a problem.
>

We need the information in the callee though, so that optimizations that
reason about unwinds (DSE, MemCpyOpt, LICM etc) running on the callee can
benefit. They wouldn't have information about what is going on in the
caller (apart from what we can provide via function attributes).

At this point I'm starting to lean towards not introducing a separate
attribute for this, and only tweaking sret semantics to specify it can't be
read on unwind. That's the original motivation, and I'm not sure solving
something more general is really worthwhile, as this turned out to be
trickier than I expected.

For the Rust move arguments, I think that the proper modeling is likely a
stronger form of "noalias" rather than this kind of
noreadafterunwind/noreadafterreturn attributes. Normally, "noalias" only
means that it is noalias for the duration of the call. Rust move arguments
remain "noalias" after the call. That is, even after we return or unwind,
accesses to the memory can only happen through pointers based on the
original noalias argument (which would have to be captured at that point).
I just realized that this is similar (the same?) as the semantics for
"noalias" on return values, which is not the same as "noalias" on
arguments. Not sure what to call this concept though. really_noalias :)

Regards,
Nikita
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20220107/ad650b2c/attachment.html>


More information about the llvm-dev mailing list