diff --git a/lib/Transforms/IPO/HotColdSplitting.cpp b/lib/Transforms/IPO/HotColdSplitting.cpp index 2bd3df3add7..5e690714bfd 100644 --- a/lib/Transforms/IPO/HotColdSplitting.cpp +++ b/lib/Transforms/IPO/HotColdSplitting.cpp @@ -207,6 +207,11 @@ bool HotColdSplitting::shouldOutlineFrom(const Function &F) const { if (F.hasFnAttribute(Attribute::NoInline)) return false; + // A function marked `noreturn` may contain unreachable terminators: these + // should not be considered cold, as the function may be a trampoline. + if (F.hasFnAttribute(Attribute::NoReturn)) + return false; + if (F.hasFnAttribute(Attribute::SanitizeAddress) || F.hasFnAttribute(Attribute::SanitizeHWAddress) || F.hasFnAttribute(Attribute::SanitizeThread) || diff --git a/test/Transforms/HotColdSplit/noreturn.ll b/test/Transforms/HotColdSplit/noreturn.ll index ca0f58815bf..74f4cb18c7f 100644 --- a/test/Transforms/HotColdSplit/noreturn.ll +++ b/test/Transforms/HotColdSplit/noreturn.ll @@ -23,6 +23,24 @@ define void @foo(i32, %struct.__jmp_buf_tag*) { ret void } +; Don't outline within a noreturn function. + +; CHECK: define {{.*}}@xpc_objc_main(i32 {{.*}}) [[XPC_OBJC_MAIN_ATTRS:#[0-9]+]] +; CHECK-NOT: xpc_objc_main.cold.1 +define void @xpc_objc_main(i32) noreturn { + %2 = icmp eq i32 %0, 0 + tail call void @_Z10sideeffectv() + br i1 %2, label %4, label %3 + +;