https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98499
--- Comment #6 from Sergei Trofimovich <slyfox at gcc dot gnu.org> --- (In reply to Richard Biener from comment #5) > Possibly in discovering pure/constness. See uses of > gimple_call_return_slot_opt_p in tree-ssa-structalias.c Aha, that's useful! Trying to understand the problem better myself: `-fdump-tree-all` has seemingly relevant `036t.ealias` that precedes breaking `037t.fre1`. I assume `036t.ealias` analyses individual functions locally and does not take into account other details, thus main() analysis should be enough: ``` ... Points-to sets ANYTHING = { ANYTHING } ESCAPED = { ESCAPED NONLOCAL } NONLOCAL = { ESCAPED NONLOCAL } STOREDANYTHING = { } INTEGER = { ANYTHING } _ZN8ImporterC1Ev = { } imp.0+64 = { ESCAPED NONLOCAL } same as _6 imp.64+8 = { ESCAPED NONLOCAL } __builtin_trap = { } main = { } CALLUSED(9) = { ESCAPED NONLOCAL imp.0+64 imp.64+8 } same as callarg(11) CALLCLOBBERED(10) = { ESCAPED NONLOCAL imp.0+64 imp.64+8 } same as callarg(11) callarg(11) = { ESCAPED NONLOCAL imp.0+64 imp.64+8 } _6 = { ESCAPED NONLOCAL } Alias information for int main() Aliased symbols imp, UID D.2146, struct Importer, is addressable Call clobber information ESCAPED, points-to non-local, points-to vars: { } Flow-insensitive points-to information _6, points-to non-local, points-to escaped, points-to NULL, points-to vars: { } int main () { struct Importer imp; char * _6; <bb 2> : Importer::Importer (&imp); _6 = MEM[(struct string *)&imp]._M_buf; if (&MEM[(struct string *)&imp]._M_local_buf != _6) goto <bb 3>; [0.00%] else goto <bb 4>; [100.00%] <bb 3> [count: 0]: __builtin_trap (); <bb 4> : imp ={v} {CLOBBER}; imp ={v} {CLOBBER}; return 0; } ``` I think this looks correct. As I understand we care about a few things in the analysis here: 1. imp.0+64 and _6 both point to the same flow-insensitive classes (both are ESCAPED NONLOCAL) 2. imp.0+64 and _6 both point to the same field in flow-sensitive analysis (both do according to `imp.0+64 = { ESCAPED NONLOCAL } same as _6`. I don't see problems here. Mechanically looking at incorrect gcc's decision for `imp.0+64 != _6`: ptrs_compare_unequal( ptr1 = &MEM[(struct string *)&imp]._M_local_buf, ptr2 = _6 ) returns `TRUE` because pt_solution_includes( info = ptr2->pt, obj1 = imp ) returns `FALSE`. That seems to be a bug. Do arguments to `pt_solution_includes` look correct so far? Does it try to answer "could _6 point at any field of 'imp' type"?