[PATCH] Clarify wording in the LangRef around !invariant.load

Andrew Trick atrick at apple.com
Thu Nov 20 22:07:11 PST 2014


> On Nov 20, 2014, at 4:25 PM, Philip Reames <listmail at philipreames.com> wrote:
> 
> 
> On 11/20/2014 04:14 PM, Sanjoy Das wrote:
>>> To clarify that the invariant nature of a given pointer does not preclude the modification of that location through a pointer which is unrelated to the load operand. In particular, initializing a location and then passing a pointer through an opaque intrinsic which produces a new unrelated pointer, should behave as expected provided that the intrinsic is memory dependent on the initializing store.
>> Does this mean you cannot common loads for escaped memory over calls?  The call could have modified the pointed-to location using another pointer.
> No, it does not.  The optimizer is free to assume that the location as seen through *this* pointer is invariant.  Whether another copy of the pointer escaped is irrelevant to that assumption.  The call may contain a "potentially aliasing store" in my proposed wording.
> 
> The scheme I was trying to describe in my clarification (not LangRef wording!) was this:
> %p = ...
> store i32 5, i32* %p
> %p2 = call i32* @opaque_call(i32* %p)
> %v = load i32* %p2, !invariant !{}
> 
> The fact that %p and %p2 might happen to be the same location is irrelevant to the fact that the location as seen by %p2 is invariant and the location as seen by %p is not.  In this case, I would expect the load from %p2 to see the value stored to %p, but that's only because the optimizer can't provide that %p == %p2.  If it could, then the value of the load is unclear.  (5, or whatever value that field had beforeā€¦)

The confusing semantics crop up with this apparently contradictory IR:

%raw = ...
store i32 5, i32* %raw
%obj = call i32* @opaque_call(i32* %raw)
%z = cmp eq i8* %raw, %obj
call @llvm.assume(%z)
%v = load i32* %obj, !invariant !{}

This IR impies that the load's address can be substituted:

%v = load i32* %raw, !invariant.load !{}

That's wrong! The frontend can't allow this. The object initialization and dereference must appear at IR level to be different objects. i.e. opaque_call must be treated like a potential object allocation, returning a new object. Comparing pointers of different objects should be considered illegal in LLVM, although I'm not sure where that's spelled out.

-Andy





More information about the llvm-commits mailing list