https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82282
--- Comment #3 from rguenther at suse dot de <rguenther at suse dot de> --- On Fri, 22 Sep 2017, nunoplopes at sapo dot pt wrote: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82282 > > --- Comment #2 from Nuno Lopes <nunoplopes at sapo dot pt> --- > This is different from PR82177. That bug is in AA, this one is not. > > See the C source: > uintptr_t u = (uintptr_t) (x + 1); > uintptr_t v = (uintptr_t) y; > > // if b1 true, then b2 must be true as well > int b1 = u != v; > int b2 = u+1 != v+1; > > if (b1) { > v = u; > } > // glb = y if b1 false, glb = u if b1 true > glb = (int*) v; > > if (b2) { > // glb = x > glb = x; > } > > // glb = y if b1/b2 false, glb = x if b1/b2 true > > So at this point, glb can alias either x or y. There's not UB. The cast is > from > a legitimate value. > The problem is that gcc replaces > if (u != v) { > v = u; > } > > simply with: > v = u; > > Which is a correct integer transformation. The deal is that it breaks the > data-flow dependency on 'y'. When the int2ptr cast is removed from "glb = > (int*)v", we get "glb = x + 1", which is wrong. This behavior couldn't ever > happen in the C program. You say that deriving from the equivalency v == u the equivalency &x + 1 == &y is wrong, correct? But you are writing an obfuscated u = (uintptr_t) (x + 1); glb = (int *)u; and expect glb now magically point to y as well. Note that the points-to run after phiopt (it re-runs right from before PRE) produces: glb.2_3, points-to non-local, points-to escaped, points-to NULL, points-to vars: { D.2337 } (escaped) because there we already have the # v_1 = PHI <u_14(2), u_14(3)> v.0_19 = (int *) v_1; glb = v.0_19; and thus it sees v_1 only pointing to what u points to. So this is the same as the other PR - it is about an alias derived from the u == v equivalency.