Compiling the attached test case with -O2 using the trunk compiler, the compiler will ICE. The proposed patch is also attached. The test is under going, but I like to have discussion on the right fix first.
thanks, David Analysis: ------------- Here is what is happening: BB6 : (Successor: BB8) MEM_19 = phi(MEM_24, MEM_25) t_9 = operator new (100)@MEM_19 (--> MEM_26) mem_ref(pp_6, -16).x@MEM_26 = t_9 (-->MEM_27) --> (1) BB8: ... MEM_20 = PHI(MEM_27, MEM_24) .... d.2348_15 = mem_ref(pp_6, -16).x@MEM_20 In the loop header BB3 (which dominates BB6 and BB8), BB3: .. pp_31 = phi (pp_6, 0); ... pp_6 = pp_31 + 16 In PRE, ANTIC_IN(BB8) includes mem_ref(pp_31,0),x@MEM_20. After phi translate, ANTIC_OUT(BB6) gets mem_ref(pp_31,0).x@MEM_27. However this expression gets propagated into ANTIC_IN(BB6) even though the memory expression is killed by (1). The root cause is that the alias oracle reports that mem_ref(pp_6, -16) and mem_ref(pp_31, 0) are not aliased as their points-to set do not intersect. As as consequence of the bad aliasing, the operator new calls gets transformed into an gimple assignment -- this gimple assignment becomes the defining statement for MEM_26. In a later UD chain walk, the memory chain stops (and triggers the assert) at this new assignment statement because there is no associated vuse for it. Test case -------------- The case is synthesized -- the real world examples involve lots of inlining etc. int g, *gp[100]; struct V { int* x; int y; }; void foo (V **p, V* end, int i) { *p = 0; V* pp = *p; int s = 100; for (; pp < end; ) { pp++; (pp-1)->x = &g; if (g) { if (g>10) g++; int *t = (int*) operator new (100); (pp-1)->x = t; } else s--; gp[end-pp] = (pp-1)->x + s; } } Patch --------- Index: tree-ssa-structalias.c =================================================================== --- tree-ssa-structalias.c (revision 186600) +++ tree-ssa-structalias.c (working copy) @@ -6137,6 +6137,9 @@ pt_solutions_intersect_1 (struct pt_solu if (pt1->anything || pt2->anything) return true; + if (pt1->null && pt2->null) + return true; + /* If either points to unknown global memory and the other points to any global memory they alias. */ if ((pt1->nonlocal