https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106783
--- Comment #5 from Andrew Pinski <pinskia at gcc dot gnu.org> --- ``` /* To simplify debugging, compare IPA and local solutions. */ if (past_flags_known && summary) { size_t len = summary->arg_flags.length (); if (past_flags.length () > len) len = past_flags.length (); for (size_t i = 0; i < len; i++) { int old_flags = i < past_flags.length () ? past_flags[i] : 0; int new_flags = i < summary->arg_flags.length () ? summary->arg_flags[i] : 0; old_flags = remove_useless_eaf_flags (old_flags, flags_from_decl_or_type (current_function_decl), VOID_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl)))); if (old_flags != new_flags) { if ((old_flags & ~new_flags) == 0 || (new_flags & EAF_UNUSED)) fprintf (dump_file, " Flags for param %i improved:", (int)i); else gcc_unreachable (); dump_eaf_flags (dump_file, old_flags, false); fprintf (dump_file, " -> "); dump_eaf_flags (dump_file, new_flags, true); } } ``` (gdb) p old_flags $1 = 960 (gdb) p new_flags $2 = 828 (gdb) p dump_eaf_flags (dump_file, old_flags, true) not_returned_directly not_returned_indirectly no_direct_read no_indirect_read $4 = void (gdb) p dump_eaf_flags (dump_file, new_flags, true) no_direct_clobber no_indirect_clobber no_direct_escape no_indirect_escape no_direct_read no_indirect_read So what is happening is the `n/=0;` after modref1 is being turned into a __builtin_trap and so basically modref1 and modref2 now disagree but only because of the now it is unconditional trap. Another testcase (fails at `-O1 -fno-tree-fre`): ``` int n; __attribute__ ((noinline,noclone,returns_twice)) static int bar (int) { n = 1; if (n) __builtin_unreachable(); return n; } int foo (int x) { return bar (x); } ``` Same as above, modref1 disagrees with modref2 but only because we go from a conditional __builtin_unreachable to an unconditional one (this is why -fno-tree-fre is needed to get the disagreement happening).