[patch] Change llvm_unreachable to use __builtin_unreachable() in -asserts

This patch implements the current consensus of PR8973:

The macro llvm_unreachable is used in LLVM to indicate that
a particular place in a function is not supposed to be reachable
during execution. Like an assert macro, it takes a string
argument. In +Asserts builds, this string argument, together with
some location information, is passed to a function which prints
the information and calls abort(). In -Asserts builds, this string
argument is dropped (to minimize code size impact), and
instead a bunch of zero arguments are passed to the same

The problem is that that’s still not very good for code size, as it
leaves a somewhat bulky function call in the emitted code. It
also doesn’t let give the compiler any opportunity to optimize
based on our assertion that the code is unreachable. A much
better alternative is to use an intrinsic, provided by Clang and
GCC 4.5, called __builtin_unreachable; it has the semantics
of being undefined behavior if reached, much like LLVM’s own
“unreachable” instruction, which incidentally is what Clang
generates for it.

This patch keeps the old behavior of llvm_unreachable in
+Asserts (!defined(NDEBUG)) builds, but changes the behavior
in -Asserts builds to call __builtin_unreachable() (in GCC 4.5
and Clang) or abort() (in everything else).

This is effectively a change in the practical semantics of
llvm_unreachable: if the call is actually reachable, then you
will get some really crazy behavior in -Asserts builds. If you’ve
been using this macro in places that can logically be reached —
e.g., after you’ve tested for all the instructions you’ve actually
implemented in your backend — then you’ve been violating the
spirit of this macro, as communicated by its name, and you
should change your code to handle unexpected patterns
more responsibly.


unreachable.patch.txt (1.25 KB)

Hi John,

The patch looks great to me!