[PATCH] D151644: [InstCombine] Propegating `nocapture` flag to callsites
Noah Goldstein via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Mon May 29 15:27:42 PDT 2023
goldstein.w.n added a comment.
In D151644#4379528 <https://reviews.llvm.org/D151644#4379528>, @goldstein.w.n wrote:
> In D151644#4379353 <https://reviews.llvm.org/D151644#4379353>, @nikic wrote:
>
>> In D151644#4378838 <https://reviews.llvm.org/D151644#4378838>, @goldstein.w.n wrote:
>>
>>> It should still work then in the case that the function doesn't interact with the global state after
>>> the call?
>>> So we could reverse iterate and while the sequence remains `pure`, it should be appliable?
>>
>> I don't think it's quite as simple as that. Here's another example:
>>
>> define void @test(ptr nocapture %p) {
>> %a = alloca ptr
>> call void @store_into_alloca(ptr %a, ptr %p)
>> ret void
>> }
>
> Is this really not safe? The alloca is dead after the `store_into_alloca` call so does `%p` ever really escape? Its like if you had a function return `%p` but the return value was unused would it be unsafe to put `nocapture` at that return site?
>
>> The call-site is not no-capture, even though there are no memory accesses after it.
>>
>>> My motivation is something like: https://godbolt.org/z/b1Pjf4bjP
>>>
>>> where AFAICT there is no way to write a syscall wrapper like that and actually preserve nocapture. Maybe a better approach?
>>
>> So yeah, the case where we're literally calling another function with the exact same arguments is clearly safe -- it's just not entirely obvious to me what the right way to generalize that would be.
Another easy case is a taillcall cannot capture `%p`.
> So any output value used in creating the return value can't be a medium for capture. Working with your example:
>
> define void @test(ptr nocapture %p) {
> %a = alloca ptr
> call void @store_into_alloca(ptr %a, ptr %p)
> ret void
> }
>
> We can't prove this doesn't capture b.c it may go through the dead alloca.
> But if it was slightly different:
>
> define ptr @test(ptr nocapture %p) {
> %a = alloca ptr
> call void @store_into_alloca(ptr %a, ptr %p)
> %x = load ptr, ptr %a
> ret ptr %x
> }
>
> Now we know for certain `%p` can't have been captured in `%a`.
>
> So for any argument if its either non-ptr or its contents are used in creating the return value we can be sure `%p` is not captured through it.
> For a return value its basically the same, if the return value of the callsite is either unused or used in the functions return value then we can be sure `%p` is not captured through it.
>
> If both of the above, then we can propegate no capture.
> This obviously doesn't fit in InstCombine. I was thinking a new pass in Transform/Scalar?
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D151644/new/
https://reviews.llvm.org/D151644
More information about the llvm-commits
mailing list