[PATCH] D151644: [InstCombine] Propegating `nocapture` flag to callsites

Noah Goldstein via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed May 31 11:12:54 PDT 2023


goldstein.w.n added a comment.

In D151644#4384102 <https://reviews.llvm.org/D151644#4384102>, @nikic wrote:

> propegate -> propagate everywhere
>
> You're really playing with fire here when it comes to "it's captured, but it doesn't really matter" reasoning. Consider something like this:
>
>   define i32 @test(ptr noalias nocapture %p) {
>     %a = alloca ptr
>     store i32 0, ptr %p 
>     call void @store_into_alloca(ptr %a, ptr %p)
>     %p2 = load ptr, ptr %a
>     %v = load i32, ptr %p2
>     ret i32 %v
>   }
>   
>   declare void @store_into_alloca(ptr, ptr)
>
> This call is clearly capturing, in a way that will affect alias analysis results (`load i32, ptr %p2` cannot ref `%p` with that `nocapture` attribute in place, which will be materialized with invalid alias scope metadata during inlining).

Alright fair enough. I think this can only occur for allocas as any other type of store with no more may-write instructions would actually capture.
I guess we also need to handle returns in a similiar way. You could do:

  > define i32 @test(ptr noalias nocapture %p) {
  >   %p2 = call ptr @return_ptr(ptr %p)
  >   %v = load i32, ptr %p2
  >   ret i32 %v
  > }

where `p2` captures and it would also be an alias analysis issue.
So the rule needs to update.
I don't think we need so go so far as "any load after makes it unsafe"
although maybe that does need to be case. How about the following case:

>   define i32 @test(ptr noalias nocapture %p, ptr noalias nocapture %q) {
>     %a = alloca ptr
>     store ptr %a, ptr %q 
>     call void @store_p_into_alloca_in_q(ptr %q, ptr %p)
>     %p3 = load ptr, ptr %q
>     %p2 = load ptr, ptr %p3
>     %v = load i32, ptr %p2
>     ret i32 %v
>   }

so `%p` is stored into `%a` through `%q` that is obviously a capture, but does that
violate the `nocapture` in `@test` or because the temporary pointer that capture
`%p` is no longer accesible after `@test` is it safe?

I was also thinking something like:

  > define void @test(ptr noalias nocapture %p) {
  >   %p_i64 = call ptr @return_ptr_as_i64(ptr %p)
  >   %p2 = ptrtoint ptr %p to i64
  >   %d = sub i64 %p_64, %p2
  >   %unused = udiv i64 %n, %d
  >   ret void
  > }

Might be an issue as was thinking if `@return_ptr_as_i64` can't capture then the return
value must != `%p` so the `udiv` is speculatable. But I think its safe to return random
from a function that has a nocapture argument so its possible to get the exact bit pattern
of the pointer, it just cant be derived from the pointer itself.


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