-
Notifications
You must be signed in to change notification settings - Fork 15.5k
Description
| Bugzilla Link | 35229 |
| Version | 5.0 |
| OS | Linux |
| Depends On | #33896 |
| Blocks | #39717 |
| CC | @comex,@efriedma-quic,@hfinkel,@jrmuizel,@jplatte,@aqjune,@sunfishcode,@nunoplopes,@regehr,@rnk |
Extended Description
Clang/LLVM currently miscompiles the following program:
// gvnbug.c
#include <stdio.h>
#include <stdint.h>
int foo();
void test(int* gp1, int* gp2)
{
int g = 0;
int a = 0, b = 0;
int x = 7777, y = 6666; // also try swapping these
int* p = &g;
int* q = &g;
int* r = &g;
if (foo()) {
a = 1;
p = &y+1;
q = &x;
}
*gp1 = (uintptr_t)p+1;
if (q == p) {
b = 1;
*gp2 = (uintptr_t)q+1;
r = q;
}
*r = 42;
printf("a = %d, b = %d, x = %d\n", a, b, x);
}
int main() {
int gp1 = 0;
int gp2 = 0;
test(&gp1, &gp2);
return 0;
}
// aux.c
int foo() { return 1; }$ clang-5.0 aux.c gvnbug.c -o gvnbug -O3 && ./gvnbug
a = 1, b = 1, x = 7777This result is not allowed. If a and b are both 1, the branch q == p must have been taken, so r was set to &x (via q), so x cannot be 7777.
I think this issue has already come up in #33896, but so far there was no example showing that the bug arises independent of the incorrect inttoptr-simplification.
What is happening here (if my analysis is correct) is that GVN sees the equality q == p and uses that to replace q by p in the then-branch. Next, LLVM notices that because p is derived from y, writing to r (which will either have value &g or p in the line where the assignment happens) cannot possibly affect x, and hence the initial value of x can be propagated into the printf. GVN is wrong to perform this kind of replacement; just because the bit representations of two pointers are equal, that doesn't mean that their provenance information is equal.
Test case by Gil Hur.