[llvm-dev] sret read after unwind

Johannes Doerfert via llvm-dev llvm-dev at lists.llvm.org
Fri Jan 7 13:06:16 PST 2022


On 1/7/22 04:45, Nikita Popov wrote:
> 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).

Or we lift these things into the inter-procedural space ;)


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

Making sret imply this seems fine to me.


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

noalias on args becomes restrict, and noalias on return value
semantics will become noalias?

Anyway, we should keep this in mind for later.

~ Johannes


> Regards,
> Nikita
>


More information about the llvm-dev mailing list