https://gcc.gnu.org/bugzilla/show_bug.cgi?id=38534
--- Comment #12 from Lukas Grätz <lukas.gra...@tu-darmstadt.de> --- (In reply to H.J. Lu from comment #10) > The C++ test issue is caused by missing callee-saved registers for > exception supports in noreturn functions in libstdc++. I fixed it by > keeping callee-saved registers when exception is enabled. I guess that exception throwing needs callee-saved registers, because it uses stack unwinding to do something very similar to a return. void f1(void) { CODE, compiler translation uses callee-saved %r12 f2(); CODE, compiler translation uses callee-saved %r12 } void f2(void) { f3(); } void f3(void) { CODE, compiler translation uses callee-saved %r12 f4(); while(1); } void f4(void) { CODE, uses loop unwinding functions a) restores all callee-saved registers in f3(), f2() b) restores %rsp and %rip from stack of f2() unreachable(); } In effect, b) is a return from the call f2() in f1(), although it happens in f4(). %r12 needs only to be saved in f1() and f3(). Gcc with -O2 would do that. However, with your patch, %r12 would not be saved in f3() anymore. This can lead to crashing in the second CODE block in f1(). The solution should require __attribute__((nothrow)) in addition to noreturn in your optimization patch. The b) in f4() should/would be treated as a throw. So none of f1(), f2(), f3() should have the attribute nothrow. So in the example of this report, the signature of value() should be modified to: extern __attribute__((nothrow)) unsigned value(int i, int j, int k); Only then it is safe to skip saving callee-saved registers. "nothrow" should also be added to bar() and fn() in your test case pr38534-2.c.