https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111515
--- Comment #7 from Richard Biener <rguenth at gcc dot gnu.org> --- So like the following which disables threading ending in a if (..) __builtin_unreachable (); branch when we thread to the _reachable_ side of it. We keep threading to the __builtin_unreachable () side as that might result in resolving earlier branches on the path. It's going to be interesting to argue that __builtin_abort () shouldn't be treated this way (but I think __builtin_unreachable and __builtin_unreachable_trap should not differ for QOI reasons?) diff --git a/gcc/tree-ssa-threadbackward.cc b/gcc/tree-ssa-threadbackward.cc index c45f4b261ad..22f6254cf98 100644 --- a/gcc/tree-ssa-threadbackward.cc +++ b/gcc/tree-ssa-threadbackward.cc @@ -878,6 +878,26 @@ back_threader_profitability::profitable_path_p (const vec<basic_block> &m_path, "non-empty latch\n"); return false; } + + /* We don't want to duplicate a path when the branch we resolve is + going to be elided anyway unless we figure the path is unreachable + itself. */ + edge_iterator ei; + edge e; + gcall *call; + FOR_EACH_EDGE (e, ei, taken_edge->src->succs) + if (e != taken_edge + && (call = safe_as_a <gcall *> (*gsi_last_bb (e->dest))) + && (gimple_call_builtin_p (call, BUILT_IN_UNREACHABLE) + || gimple_call_builtin_p (call, BUILT_IN_UNREACHABLE_TRAP))) + { + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, + " FAIL: Thread ends on the reachable side of a branch " + "to unreachable\n"); + return false; + } + if (dump_file && (dump_flags & TDF_DETAILS)) fputc ('\n', dump_file); return true;