https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68871
Bug ID: 68871 Summary: fipa-pta tracks function-level nonlocal Product: gcc Version: 6.0 Status: UNCONFIRMED Severity: enhancement Priority: P3 Component: ipa Assignee: unassigned at gcc dot gnu.org Reporter: vries at gcc dot gnu.org Target Milestone: --- I. one function, ealias Consider testcase ealias.c: ... void foo (int *a) { int b; int *c = a; int *d = &b; *c = 1; *d = 2; *c = *c + 1; } ... compiled with ... $ gcc ealias.c -O2 -S -fno-tree-ccp -fno-tree-forwprop -fno-tree-fre ... At ealias, we have: ... intD.6 bD.1758; # PT = nonlocal c_2 = a_1(D); # PT = { D.1758 } d_3 = &bD.1758; ... So: - c_2 points-to something nonlocal, and - d_3 points to local b. This allows disambiguation of the store '*d = 2' with the load in '*c = *c + 1', and dse removes the store: ... Deleted dead store *d_3 = 2; ... II. two functions, ealias Now, consider example ealias-2.c: ... static void __attribute__((noinline, noclone)) bar (int *c, int *d) { *c = 1; *d = 2; *c = *c + 1; } void foo (int *a) { int b; bar (a, &b); } ... When compiled at -O2, at ealias we have (using the patch at https://gcc.gnu.org/ml/gcc-patches/2015-12/msg01282.html to get ssa-name info for default defs): ... __attribute__((noclone, noinline)) bar (intD.6 * cD.1755, intD.6 * dD.1756) # PT = nonlocal # DEFAULT_DEF c_2(D) # PT = nonlocal # DEFAULT_DEF d_4(D) ... So both pointers point to a non-local, and cannot be disambiguated. III. two functions, fipa-pta Now, consider example ipa-pta.c (the same as ealias-2.c, but with &b assigned to a pointer, to expose the points-to info). ... static void __attribute__((noinline, noclone)) bar (int *c, int *d) { *c = 1; *d = 2; *c = *c + 1; } void foo (int *a) { int b; int *bp = &b; bar (a, bp); } ... When compiled at -O2 -fipa-pta-fno-tree-ccp -fno-tree-forwprop -fno-tree-fre -fno-tree-pre, at pta we have: ... __attribute__((noclone, noinline)) bar (intD.6 * cD.1755, intD.6 * dD.1756) # PT = nonlocal # DEFAULT_DEF c_2(D) # PT = { D.1762 } (nonlocal) # ALIGN = 4, MISALIGN = 0 # DEFAULT_DEF d_4(D) ... c_2 points to a nonlocal. d_4 points to D.1762, which is b in foo: ... foo (intD.6 * aD.1759) # PT = nonlocal # DEFAULT_DEF a_2(D) { intD.6 bD.1762; ... The disambiguation of the memory references relative to the two pointers does not take place, because: - b is nonlocal in bar, and - the nonlocal of c_2 refers to nonlocal to bar. Still: - c_2 has the same value as a_3, which is nonlocal to foo, and - d_2 has the same value as bp_1, which is local to foo as we can see here: ... foo (intD.6 * aD.1759) # PT = nonlocal # DEFAULT_DEF a_3(D) { intD.6 * bpD.1763; intD.6 bD.1762; # PT = { D.1762 } bp_1 = &bD.1762; ... So it seems the information to make the disambiguation is there in principle. A more precise analysis could give something along the lines of: ... __attribute__((noclone, noinline)) bar (intD.6 * cD.1755, intD.6 * dD.1756) # PT = nonlocal(bar, foo) # DEFAULT_DEF c_2(D) # PT = { D.1762 } (local(foo)) # ALIGN = 4, MISALIGN = 0 # DEFAULT_DEF d_4(D) ... And we could disambiguate c_2 and d_4 because: - c_2 is nonlocal(foo), and - d_4 is local(foo).