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

Andrew Trick atrick at apple.com
Mon Nov 24 13:00:20 PST 2014


> On Nov 24, 2014, at 12:34 AM, Sanjoy Das <sanjoy at playingwithpointers.com> wrote:
> 
>> I would actually be fine with more conservative semantics - the load is only invariant with respect to its original uses - because it won't affect optimization in practice.
> 
> I was under the impression that one of motivations for invariant loads
> was to be able to hoist them out of arbitrary control flow.
> 
> Thanks,
> -- Sanjoy

I think hoisting invariant loads is typically a goal, but "dereferenceable" doesn't have to be implied by "invariant". I now agree with Philip's clarification of the semantics:

"Being invariant does not imply that a location is dereferenceable, but it does imply that once the location is known dereferenceable it's value is henceforth unchanging."

Given:

int *p = <known dereferenceable>
store(q)
if (something)
  m1 = load(p) !invariant
  foo(m1)
else 
  m2 = load(p)
  bar(m2)

This is definitely valid:

int *p = <known dereferenceable>
m1 = load(p) !invariant
store(q)
m2 = load(p)
if (something)
  foo(m1)
else 
  bar(m2)

But is this valid?

int *p = <known dereferenceable>
m = load(p) !invariant
store(q)
if (something)
  foo(m)
else 
  bar(m)

I would like to claim that it is valid, because that would make the original code interchangeable with:

int *p = <known dereferenceable>
assume_invariant(p)
store(q)
if (something)
  m1 = load(p)
  foo(m1)
else 
  m2 = load(p)
  bar(m2)

If it is not valid to infer invariance of the memory at ‘p', then the assume_invariant limits optimization vs. the invariant.load metadata. You would be forced to do this, which I think would prevent reordering store(q) and m1 = load(p):

int *p = <known dereferenceable>
store(q)
if (something)
  assume_invariant(p)
  m1 = load(p)
  foo(m1)
else 
  m2 = load(p)
  bar(m2)

-Andy



More information about the llvm-commits mailing list