[PATCH] Clarify wording in the LangRef around !invariant.load
Sanjoy Das
sanjoy at playingwithpointers.com
Mon Dec 1 21:47:37 PST 2014
> I think this is completely legal for the current optimizer. Here's my
> argument:
> - !invariant.load describes the constant-ness of the *pointer value*. Once
> the pointer *value* is known dereferenceable, it is always invariant.
> - The store implies dereferenceability.
> - The store must (by assumption) be not changing the value of the location.
> (Otherwise, the invariant.load marker lied originally.)
> - Given the store can be completely omitted, combining the two loads becomes
> 'obviously' okay.
If I understand this correctly, the above argument allows cases like
this:
int **p = calloc(sizeof(int*))
store calloc(sizeof(int)) to p
int *l = load(p)
print *l // prints zero
==>
int **p = calloc(sizeof(int*))
store calloc(sizeof(int)) to p
if (false) {
int *s = load (p) !invariant
}
int *l = load(p)
print *l // prints zero
==>
int **p = calloc(sizeof(int*))
int *s = load (p) !invariant
store calloc(sizeof(int)) to p
if (false) {
}
int *l = load(p)
print *l // prints zero
==>
int **p = calloc(sizeof(int*))
int *s = load (p) !invariant
store calloc(sizeof(int)) to p
if (false) {
}
int *l = load(s)
print *l
==>
int **p = calloc(sizeof(int*))
int *s = load (p) !invariant
store calloc(sizeof(int)) to p
if (false) {
}
int *l = load(s) // UB, since it now dereferences null
print *l
We started from a well-defined program, and ended in UB.
-- Sanjoy
More information about the llvm-commits
mailing list