[PATCH] D151644: [InstCombine] Propegating `nocapture` flag to callsites
Noah Goldstein via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Mon May 29 14:40:54 PDT 2023
goldstein.w.n added a comment.
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.
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