[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