[llvm-dev] Potential issue with noalias @malloc and @realloc
Sanjoy Das via llvm-dev
llvm-dev at lists.llvm.org
Tue Apr 11 15:32:16 PDT 2017
Hi all,
I think I've spotted a semantic issue with marking @malloc and
@realloc as noalias. Say we have the program:
int f() {
int* p0 = malloc(size of(int));
free(p0);
int* p1 = malloc(sizeof(int));
if (!p1) return 20;
int value = 0;
for (int i = 0; i < 1; i++) {
*p1 = 20;
value = *p1;
if (false) // "false" is obscured in a way the compiler can't fathom
if (p0 == p1)
a();
else
b();
}
return result;
}
The program above is well defined, and will always return 20.
However, if we first unswitch loops:
int f() {
int* p0 = malloc(size of(int));
free(p0);
int* p1 = malloc(sizeof(int));
if (!p1) return 20;
int value = 0;
if (p0 == p1) {
for (int i = 0; i < 1; i++) {
*p1 = 20;
value = *p1;
if (false)
a();
}
} else {
// Other copy of the loop that calls b() in dead code
}
return result;
}
and then run GVN::propgateEquality that replaces one use of p1 with p0
but not the other (for some reason, say the other use was obscured
behind a function call):
int f() {
int* p0 = malloc(size of(int));
free(p0);
int* p1 = malloc(sizeof(int));
if (!p1) return 20;
int value = 0;
if (p0 == p1) {
for (int i = 0; i < 1; i++) {
*p0 = 20; // S0
value = *p1; // L0
if (false)
a();
}
} else {
// Other copy of the loop that calls b() in dead code
}
return result;
}
Now we have a problem -- since p0 NoAlias p1 (distinct @malloc()
calls), we can reorder S0 and L0 (or LICM L0):
int f() {
int* p0 = malloc(size of(int));
free(p0);
int* p1 = malloc(sizeof(int));
if (!p1) return 20;
int value = 0;
if (p0 == p1) {
for (int i = 0; i < 1; i++) {
value = *p1; // L0
*p0 = 20; // S0
if (false)
a();
}
} else {
// Other copy of the loop that calls b() in dead code
}
return result;
}
and we'll now return garbage if p0 == p1 (likely) and p1 is not null
(also likely).
I do not yet have a solution for this. Let me know what you think!
Thanks,
-- Sanjoy
More information about the llvm-dev
mailing list