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

Andrew Trick atrick at apple.com
Mon Nov 24 13:01:58 PST 2014


> On Nov 24, 2014, at 2:06 AM, Nick Lewycky <nicholas at mxc.ca> wrote:
> 
> Andrew Trick wrote:
> Comparing pointers of different objects should be considered illegal in LLVM, although I'm not sure where that's spelled out.
> 
> "If the operands are pointer typed, the pointer values are compared as if they were integers." - http://llvm.org/docs/LangRef.html#id251
> 
> I disagree, and think llvm's current model is right. There used to be (still are?) some interesting rules on the inbounds gep instruction, but nothing that applies to pointers in general.
> 
> We do end up with weird cases such as %ptr1 noalias %ptr2 while %ptr1 == %ptr2, but that only comes up because we recognize C functions and graciously handle C's aliasing rules for things like freed pointers and such. It's not actually part of llvm's execution semantics, nor does it need to be. It might hurt support for other languages if we did, and it would make %p eq %q different from ptrtoint %p eq ptrtoint %q, which in turn means you can't do transforms which that a given i64 in memory is always used as a pointer and replace the type loads and stores referring to it.
> 
> Nick

Absolutely. My "comparing pointers" statement reads wrong out of context.

The frontend can generate pointer comparisons wherever it is semantically valid to do so by language rules. Allowing LLVM passes to arbitrarily introduce comparisons on unrelated pointers, or similarly to introduce inttoptr, would limit what we can do with memory attributes. I'm primarily concerned with supporting non-C languages.

The immediate issue is the semantics of !invariant.

Given:

m1 = load %p, !invariant
free(%p)
%q = init()
m2 = load %q
foo(m2)

Can the optimizer do this?

m1 = load %p, !invariant
free(%p)
%q = init()
if %p == %q
  m2 = load %p
  foo(m2)
...

Which, if we give !invariant semantics that I like, would allow this:

m1 = load %p, !invariant
free(%p)
%q = init()
if %p == %q
  foo(m1)
...

Even if we solve this problem, what would it mean for attributes that we associate with pointer values? For uniformity and expressiveness, we want to treat "invariant" as an attribute, the way we currently treat dereferenceable and nonnull.

So we have something like:

assume_invariant(%p)
m1 = load %p
free(%p)
%q = init()
m2 = load %p
foo(m2)

Now semantics are broken the moment we introduce pointer comparison.

assume_invariant(%p)
m1 = load %p
free(%p)
%q = init()
if %p == %q
  m2 = load %p
  foo(m2)

It would be nice if the frontend could generally associate memory attributes with a particular object without needing to prove that the object has process lifetime. Do you think this is reasonable?

-Andy



More information about the llvm-commits mailing list