This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug tree-optimization/65752] Too strong optimizations int -> pointer casts


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.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]