[PATCH] D18738: Add new !unconditionally_dereferenceable load instruction metadata

Hal Finkel via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 10 13:58:43 PST 2016


hfinkel added a comment.

In https://reviews.llvm.org/D18738#592113, @sanjoy wrote:

> In https://reviews.llvm.org/D18738#592084, @hfinkel wrote:
>
> > >   void bar(int* ptr) {
> > >     int* k1 = foo1(ptr, true);
> > >     // inlined int* k2 = foo_common(alloca(...), false);
> > >     t = alloca(...)
> > >     int* val;
> > >     if (false) {
> > >       val = *t, unconditionally_dereferenceable
> > >     } else {
> > >       val = *ptr
> > >     }
> > >   }
> >
> > The assumption is placed on the return value, and val would not unconditionally have the assumption, and so never will really, so there's not a problem here (AFAIKT).
>
>
> Sure, but isn't that the same as `!dereferenceable` then?
>
> I thought the idea here was to be able to hoist the load of `val` out of the never-taken branch and still preserve the `!unconditionally_dereferenceable` attribute.  That would mean if the example was a bit more complicated:
>
>   void bar(int* ptr) {
>     int* k1 = foo1(ptr, true);
>     // inlined int* k2 = foo_common(alloca(...), false);
>     t = alloca(...)
>     int* val;
>     if (false) {
>       val = *t, unconditionally_dereferenceable
>       int k = *val;
>       print(k)
>     } else {
>       val = *ptr
>     }
>   }
>
>
> (hoisting)
>
>   void bar(int* ptr) {
>     int* k1 = foo1(ptr, true);
>     // inlined int* k2 = foo_common(alloca(...), false);
>     t = alloca(...)
>     int* val;
>     val = *t, unconditionally_dereferenceable
>     if (false) {
>       int k = *val;
>       print(k)
>     } else {
>       val = *ptr
>     }
>   }
>
>
> (hoisting, since `k` is a load from a known dereferenceable pointer)
>
>   void bar(int* ptr) {
>     int* k1 = foo1(ptr, true);
>     // inlined int* k2 = foo_common(alloca(...), false);
>     t = alloca(...)
>     int* val;
>     val = *t, unconditionally_dereferenceable
>     int k = *val; // FAULT / UB
>     if (false) {
>       print(k)
>     } else {
>       val = *ptr
>     }
>   }
>


Good point. I think that the merging in your example needs to be invalid. I think the relevant restrictions here seems very much like the restrictions on what can be done for the convergent attribute. The difference being that, for convergent, it only matters if we introduce new control dependencies that might be non-constant (or non-uniform more specifically). Here, we can't introduce any new control dependencies, even if they're trivial.


Repository:
  rL LLVM

https://reviews.llvm.org/D18738





More information about the llvm-commits mailing list