https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82282

            Bug ID: 82282
           Summary: PRE cannot blindly fold
                    integer-to-pointer/pointer-to-integer round-trips
           Product: gcc
           Version: 6.4.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: nunoplopes at sapo dot pt
                CC: gil.hur at sf dot snu.ac.kr, jeehoon.kang at sf dot 
snu.ac.kr,
                    juneyoung.lee at sf dot snu.ac.kr, regehr at cs dot 
utah.edu,
                    sanjoy at playingwithpointers dot com
  Target Milestone: ---

The following program gets miscompiled by gcc:

$ cat foo.c
#include <stdio.h>
#include <stdint.h>

int* glb;
int* tmp[10];

void main(int argc, char* argv) {
  int x[1] = { 555 }, y[1] = { 777 };
  uintptr_t u = (uintptr_t) (x + 1);
  uintptr_t v = (uintptr_t) y;
  uintptr_t w;

  int b1 = u != v;
  int b2 = u+1 != v+1;

  int* z;

  if (b1) {
    printf("b1 TRUE.\n");
    v = u;
  }
  glb = (int*) v;

  for (int i=0; i < 10; i++)
    tmp[i] = (int*) v;

  if (b2) {
    printf("b2 TRUE.\n");
    glb = x;
  }

  w = u;
  for (int i = 0; i < 100; ++i) {
    if (w < v) {
      w += 1;
    }
  }

  if (v == w) {
    z = x;
  } else {
    printf("IMPOSSIBLE!\n");
    z = y;
  }
  *z = 555;

  *glb = 1;

  printf("x=%d y=%d\n", x[0], y[0]);
}

$ gcc -O3 -fdump-tree-all foo.c
$ ./a
x=555 y=777


We start with:
  u_14 = (uintptr_t) &MEM[(void *)&x + 4B];
  v_15 = (uintptr_t) &y;

  if (u_14 != v_15)
    goto <bb 3>;
  else
    goto <bb 4>;

  <bb 4>:
  # v_1 = PHI <v_15(2), u_14(3)>
  v.0_19 = (int *) v_1
  glb = v.0_19;


Which is then (correctly) transformed by phiopt2 to:
  if (u_14 != v_15)
    goto <bb 3>;
  else
    goto <bb 4>;

  <bb 4>:
  # v_1 = PHI <u_14(2), u_14(3)>
  v.0_19 = (int *) v_1;
  glb = v.0_19;


Then PRE incorrectly removes the pointer-to-integer/integer-to-point cast
round-trip through the PHI node:
  glb = &MEM[(void *)&x + 4B];

This is wrong because we've now lost the information that glb may also alias
with y, as seen by the alias analysis report:
glb = { ESCAPED NONLOCAL x }


After a few more rounds of copy propagation and "dom3", "777" is constant
propagated to the printf call, since the store to glb cannot possibly alias 'y'
anymore.
All the subsequent transformations are correct. The bug is that PRE cannot
blindly do a transformation of "int2ptr(ptr2int(x)) -> x".

Test case by Gil Hur.

Reply via email to