This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug tree-optimization/65752] Too strong optimizations int -> pointer casts
- From: "rguenth at gcc dot gnu.org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Fri, 22 May 2015 08:52:05 +0000
- Subject: [Bug tree-optimization/65752] Too strong optimizations int -> pointer casts
- Auto-submitted: auto-generated
- References: <bug-65752-4 at http dot gcc dot gnu dot org/bugzilla/>
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65752
Richard Biener <rguenth at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |law at gcc dot gnu.org
--- Comment #32 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to Chung-Kil Hur from comment #29)
> Dear Richard,
>
> This time, I think I constructed a real bug.
> Please have a look and correct me if I am wrong.
>
> =====================
> #include <stdio.h>
>
> int main() {
> int x = 0;
> uintptr_t xp = (uintptr_t) &x;
> uintptr_t i;
>
> for (i = 0; i < xp; i++) { }
>
> *(int*)xp = 15;
>
> printf("%d\n", x);
> }
> =====================
>
> This program prints "15" and I do not think this raises UB.
>
> Now I add an if-statement to the program.
>
> =====================
> #include <stdio.h>
>
> int main() {
> int x = 0;
> uintptr_t xp = (uintptr_t) &x;
> uintptr_t i;
>
> for (i = 0; i < xp; i++) { }
>
> /*** begin ***/
> if (xp != i) {
> printf("hello\n");
> xp = i;
> }
> /*** end ***/
>
> *(int*)xp = 15;
>
> printf("%d\n", x);
> }
> =====================
>
> This program just prints "0".
>
> Since "hello" is not printed, the if-statement is not executed.
> However, it prints a different result than before, which I think is a bug.
It indeed is a more unfortunate case but you are still breaking the dependency
chain in the if (xp != i) code by assigning i to xp. The code is never
executed (which is why this is unfortunate) and I am less than 100% sure
it still invokes undefined behavior.
The unfortunate thing is that the equivalence you build on the 'else'
path (xp == i) is used by the compiler to replace xp by i on the
*(int*)xp = 15 line getting us into the very same situation as in all
other cases. That is, we have
if (xp != i)
...
# xp = PHI <xp, i>
*(int *)xp = 15;
because of the conditional and in this case our phiopt pass optimizes that
to
# xp = PHI <i, i>
instead of the equally valid
# xp = PHI <xp, xp>
other passes (dom) may end up doing a similar thing (at least for GCC 5 and
the particular testcase we are lucky here though), but for GCC 5
-fdisable-tree-phiopt1 -fdisable-tree-phiopt2 avoids the issue.
Generally there is no good way to determine which choice is better.
What the PTA code does is sensible btw. For
# xp_20 = PHI <0(2), xp_7(7)>
xp_7 = xp_20 + 1;
if (xp_6 > xp_7)
goto <bb 7>;
else
goto <bb 4>;
<bb 7>:
goto <bb 3>;
the PTA constraints are
xp_6 = &x
xp_20 = &NULL
xp_20 = xp_7
xp_7 = xp_20
xp_7 = &NONLOCAL
which means PTA considers that all pointers coming from integer constants
point to global memory only (that's to support fixed address objects).
That helps to avoid false aliasing to stack objects and avoids the need
to make all locals escaped when you have code passing an integer to a
function (that integer, converted to a pointer _could_ point to a stack
slot in the caller, no?!).
So 'i' is considered to eventually point to arbitrary global memory.
But _not_ to arbitrary address-taken locals.