This will allow us to optimize code such as:
int f(int *p) { int x; return p == &x; }
as well as:
int *allocate(void); int f() { int x; int *p = allocate(); return p == &x; }
The folding can only be done under certain circumstances. Even though p and &x cannot alias, the comparison must still return true if the pointer representations are equal. If a user successfully generates a p that's a correct guess for &x, comparison should return true even though p is an invalid pointer.
This patch argues that if the address of the alloca isn't observable outside the function, the function can act as-if the address is impossible to guess from the outside. The tricky part is keeping the act consistent: if we fold p == &x to false in one place, we must make sure to fold any other comparisons based on those pointers similarly. To ensure that, we only fold when &x is involved exactly once in comparison instructions.
Let me know what you think.
I have a question about this second bit -- do we have to ensure that we only *fold* such comparisons consistently, or do we have to ensure that they also evaluate consistently? IOW, say I have
such that complex_xform(x) == x always, but the compiler cannot prove that. Consequently we fold %t0 to false, but don't fold complex_xform(x) == x at all, and it ends up evaluating to true at runtime.
Are you relying on the fact that a complex_xform cannot be formed out of the operators you look through in CanTrackAlluses? I'd be more comfortable if you folded *all* comparisons based off of %alloca in one go.