Index: llvm/lib/Transforms/IPO/HotColdSplitting.cpp =================================================================== --- llvm/lib/Transforms/IPO/HotColdSplitting.cpp +++ llvm/lib/Transforms/IPO/HotColdSplitting.cpp @@ -26,6 +26,7 @@ #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/CFG.h" +#include "llvm/IR/CallSite.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/Dominators.h" @@ -98,36 +99,27 @@ return !(isa(I) || isa(I)); } -static bool exceptionHandlingFunctions(const CallInst *CI) { - auto F = CI->getCalledFunction(); - if (!F) - return false; - auto FName = F->getName(); - return FName == "__cxa_begin_catch" || - FName == "__cxa_free_exception" || - FName == "__cxa_allocate_exception" || - FName == "__cxa_begin_catch" || - FName == "__cxa_end_catch"; -} - -static bool unlikelyExecuted(const BasicBlock &BB) { - if (blockEndsInUnreachable(BB)) - return true; +bool unlikelyExecuted(BasicBlock &BB) { // Exception handling blocks are unlikely executed. if (BB.isEHPad()) return true; - for (const Instruction &I : BB) - if (const CallInst *CI = dyn_cast(&I)) { - // The block is cold if it calls functions tagged as cold or noreturn. - if (CI->hasFnAttr(Attribute::Cold) || - CI->hasFnAttr(Attribute::NoReturn) || - exceptionHandlingFunctions(CI)) + + // The block is cold if it calls/invokes a cold function. + for (Instruction &I : BB) + if (auto CS = CallSite(&I)) + if (CS.hasFnAttr(Attribute::Cold)) return true; - // Assume that inline assembly is hot code. - if (isa(CI->getCalledValue())) + // The block is cold if it has an unreachable terminator, unless it's + // preceded by a call to a (possibly warm) noreturn call (e.g. longjmp). + if (blockEndsInUnreachable(BB)) { + if (auto *CI = + dyn_cast_or_null(BB.getTerminator()->getPrevNode())) + if (CI->hasFnAttr(Attribute::NoReturn)) return false; - } + return true; + } + return false; } Index: llvm/test/Transforms/HotColdSplit/eh-pads.ll =================================================================== --- llvm/test/Transforms/HotColdSplit/eh-pads.ll +++ llvm/test/Transforms/HotColdSplit/eh-pads.ll @@ -6,12 +6,6 @@ ; CHECK-LABEL: define {{.*}}@foo( ; CHECK: landingpad ; CHECK: sideeffect(i32 2) - -; CHECK-LABEL: define {{.*}}@foo.cold.1( -; CHECK: sideeffect(i32 0) -; CHECK: sideeffect(i32 1) -; CHECK: sink - define void @foo(i32 %cond) personality i8 0 { entry: invoke void @llvm.donothing() to label %normal unwind label %exception @@ -32,6 +26,38 @@ ret void } +; CHECK-LABEL: define {{.*}}@bar( +; CHECK-NOT: landingpad +define void @bar(i32 %cond) personality i8 0 { +entry: + br i1 undef, label %exit, label %continue + +exit: + ret void + +continue: + invoke void @sink() to label %normal unwind label %exception + +exception: + ; Note: EH pads are not candidates for region entry points. + %cleanup = landingpad i8 cleanup + ret void + +normal: + call void @sideeffect(i32 0) + call void @sideeffect(i32 1) + ret void +} + +; CHECK-LABEL: define {{.*}}@foo.cold.1( +; CHECK: sideeffect(i32 0) +; CHECK: sideeffect(i32 1) +; CHECK: sink + +; CHECK-LABEL: define {{.*}}@bar.cold.1( +; CHECK: sideeffect(i32 0) +; CHECK: sideeffect(i32 1) + declare void @sideeffect(i32) declare void @sink() cold Index: llvm/test/Transforms/HotColdSplit/noreturn.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/HotColdSplit/noreturn.ll @@ -0,0 +1,73 @@ +; RUN: opt -hotcoldsplit -S < %s | FileCheck %s + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.14.0" + +%struct.__jmp_buf_tag = type { [8 x i64], i32, %struct.__sigset_t } +%struct.__sigset_t = type { [16 x i64] } + +; Don't outline noreturn calls which aren't explicitly marked cold. + +; CHECK-LABEL: define {{.*}}@foo( +; CHECK-NOT: foo.cold.1 +define void @foo(i32, %struct.__jmp_buf_tag*) { + %3 = icmp eq i32 %0, 0 + tail call void @_Z10sideeffectv() + br i1 %3, label %5, label %4 + +;