[llvm-dev] [RFC] Introduce the `!nocapture` metadata and "nocapture_use" operand bundle

Artur Pilipenko via llvm-dev llvm-dev at lists.llvm.org
Mon Jan 11 14:25:05 PST 2021


I'm a bit confused with nocapture_use. I guess you need this because without it BasicAA would assume that the pointer is not accessed by the call at all. So, as a workaround you introduce a use which implicitly reads and writes. But this might be a more general problem. For example:

a = new ...
store a, ptr, !nocapture
a' = load ptr
; Now you have 2 pointers to the same object (a' and a ) which BasicAA considers as no aliasing. 
v1 = load a
store 5, a' 
v2 = load a 

We would happily replace v2 with v1 even though the memory was clobbered by the store through a’.

Artur

> On Jan 7, 2021, at 4:20 PM, Johannes Doerfert via llvm-dev <llvm-dev at lists.llvm.org> wrote:
> 
> TL;DR: A pointer stored in memory is not necessarily captured, let's add a way to express this.
> 
> Phab: https://reviews.llvm.org/D93189
> 
> --- Commit Message / Rational ---
> 
> Runtime functions, as well as regular functions, might require a pointer
> to be passed in memory even though the memory is simply a means to pass
> (multiple) arguments. That is, the indirection through memory is only
> used on the call edge and not otherwise relevant. However, such pointers
> are currently assumed to escape as soon as they are stored in memory
> even if the callee only reloads them and use them in a "non-escaping" way.
> Generally, storing a pointer might not cause it to escape if all "uses of
> the memory" it is stored to all have the "nocapture" property.
> 
> To allow optimizations in the presence of pointers stored to memory we
> introduce two new IR extensions. `!nocapture` metadata on stores and
> "nocapture_use" operand bundles for call(base) instructions. The former
> ensures that the store can be ignored for the purpose of escape
> analysis. The latter indicates that a call is using a pointer value
> but not capturing it. This is important as the call might still read
> or write the pointer and since the passing of the pointer through
> memory is not considered "capturing" with the "nocapture" metadata,
> we need to otherwise indicate the potential read/write.
> 
> As an example use case where we can deduce `!nocapture` metadata,
> consider the following code:
> 
> ```
> struct Payload {
>  int *a;
>  double *b;
> };
> 
> int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
>                    void *(*start_routine) (void *), void *arg);
> 
> int use(double);
> 
> void fn(void *v) {
>  Payload *p = (Payload*)(v);
>  // Load the pointers from the payload and then dereference them,
>  // this will not capture the pointers.
>  int *a = p->a;
>  double *b = p->b;
>  *a = use(*b);
> }
> 
> void foo(int *a, double *b) {
>  Payload p = {a, b};
>  pthread_create(..., &fn, &p);
> }
> ```
> 
> Given the usage of the payload struct in `fn` we can conclude neither
> `a` nor `b` in are captured in `foo`, however we could not express this
> fact "locally" before. That is, we can deduce and annotate it for the
> arguments `a` and `b` but only since there is no other use (later on).
> Similarly, if the callee would not be known, we were not able to
> describe the "nocapture" behavior of the API.
> 
> A follow up patch will introduce `!nocapture` metadata to stores
> generated during OpenMP lowering. This will, among other things, fix
> PR48475. I generally expect us to find more APIs that could benefit from
> the annotation in addition to the deduction we can do if we see the callee.
> 
> ---
> 
> As always, feedback is welcome. Feel free to look at the phab patch as well.
> 
> Thanks,
>  Johannes
> 
> 
> -- 
> ──────────
> ∽ Johannes
> 
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev



More information about the llvm-dev mailing list