Index: lib/Analysis/InlineCost.cpp =================================================================== --- lib/Analysis/InlineCost.cpp +++ lib/Analysis/InlineCost.cpp @@ -153,6 +153,8 @@ /// passed to support analyzing indirect calls whose target is inferred by /// analysis. void updateThreshold(CallSite CS, Function &Callee); + /// Return true if size growth is allowed when inlining the callee at CS. + bool allowSizeGrowth(CallSite CS); // Custom analysis routines. bool analyzeBlock(BasicBlock *BB, SmallPtrSetImpl &EphValues); @@ -572,7 +574,39 @@ return false; } +bool CallAnalyzer::allowSizeGrowth(CallSite CS) { + // If the normal destination of the invoke or the parent block of the call + // site is unreachable-terminated, there is little point in inlining this + // unless there is literally zero cost. + // FIXME: Note that it is possible that an unreachable-terminated block has a + // hot entry. For example, in below scenario inlining hot_call_X() may be + // beneficial : + // main() { + // hot_call_1(); + // ... + // hot_call_N() + // exit(0); + // } + // For now, we are not handling this corner case here as it is rare in real + // code. In future, we should elaborate this based on BPI and BFI in more + // general threshold adjusting heuristics in updateThreshold(). + Instruction *Instr = CS.getInstruction(); + if (InvokeInst *II = dyn_cast(Instr)) { + if (isa(II->getNormalDest()->getTerminator())) + return false; + } else if (isa(Instr->getParent()->getTerminator())) + return false; + + return true; +} + void CallAnalyzer::updateThreshold(CallSite CS, Function &Callee) { + // If no size growth is allowed for this inlining, set Threshold to 0. + if (!allowSizeGrowth(CS)) { + Threshold = 0; + return; + } + // If -inline-threshold is not given, listen to the optsize and minsize // attributes when they would decrease the threshold. Function *Caller = CS.getCaller(); @@ -1214,28 +1248,6 @@ if (OnlyOneCallAndLocalLinkage) Cost += InlineConstants::LastCallToStaticBonus; - // If the normal destination of the invoke or the parent block of the call - // site is unreachable-terminated, there is little point in inlining this - // unless there is literally zero cost. - // FIXME: Note that it is possible that an unreachable-terminated block has a - // hot entry. For example, in below scenario inlining hot_call_X() may be - // beneficial : - // main() { - // hot_call_1(); - // ... - // hot_call_N() - // exit(0); - // } - // For now, we are not handling this corner case here as it is rare in real - // code. In future, we should elaborate this based on BPI and BFI in more - // general threshold adjusting heuristics in updateThreshold(). - Instruction *Instr = CS.getInstruction(); - if (InvokeInst *II = dyn_cast(Instr)) { - if (isa(II->getNormalDest()->getTerminator())) - Threshold = 0; - } else if (isa(Instr->getParent()->getTerminator())) - Threshold = 0; - // If this function uses the coldcc calling convention, prefer not to inline // it. if (F.getCallingConv() == CallingConv::Cold) @@ -1307,7 +1319,7 @@ // Bail out the moment we cross the threshold. This means we'll under-count // the cost, but only when undercounting doesn't matter. if (Cost > Threshold) - break; + return false; BasicBlock *BB = BBWorklist[Idx]; if (BB->empty()) @@ -1324,20 +1336,8 @@ // Analyze the cost of this block. If we blow through the threshold, this // returns false, and we can bail on out. - if (!analyzeBlock(BB, EphValues)) { - if (IsRecursiveCall || ExposesReturnsTwice || HasDynamicAlloca || - HasIndirectBr || HasFrameEscape) - return false; - - // If the caller is a recursive function then we don't want to inline - // functions which allocate a lot of stack space because it would increase - // the caller stack usage dramatically. - if (IsCallerRecursive && - AllocatedSize > InlineConstants::TotalAllocaSizeRecursiveCaller) - return false; - - break; - } + if (!analyzeBlock(BB, EphValues)) + return false; TerminatorInst *TI = BB->getTerminator(); @@ -1373,7 +1373,7 @@ // inlining. if (SingleBB && TI->getNumSuccessors() > 1) { // Take off the bonus we applied to the threshold. - Threshold -= SingleBBBonus; + Threshold = std::max(Threshold - SingleBBBonus, 0); SingleBB = false; } } @@ -1388,10 +1388,12 @@ // subtract the excess bonus, if any, from the Threshold before // comparing against Cost. if (NumVectorInstructions <= NumInstructions / 10) - Threshold -= FiftyPercentVectorBonus; + Threshold = std::max(Threshold - FiftyPercentVectorBonus, 0); else if (NumVectorInstructions <= NumInstructions / 2) - Threshold -= (FiftyPercentVectorBonus - TenPercentVectorBonus); + Threshold = std::max( + Threshold - (FiftyPercentVectorBonus - TenPercentVectorBonus), 0); + assert(Threshold >= 0 && "Inlinining threshold must be non-negative"); return Cost < std::max(1, Threshold); } Index: test/Transforms/Inline/inline_unreachable-2.ll =================================================================== --- /dev/null +++ test/Transforms/Inline/inline_unreachable-2.ll @@ -0,0 +1,19 @@ +; RUN: opt < %s -inline -S | FileCheck %s + +; CHECK-LABEL: caller +; CHECK: call void @callee +define void @caller(i32 %a, i1 %b) #0 { + call void @callee(i32 %a, i1 %b) + unreachable +} + +define void @callee(i32 %a, i1 %b) { + call void asm sideeffect "", ""() + br i1 %b, label %bb1, label %bb2 +bb1: + call void asm sideeffect "", ""() + ret void +bb2: + call void asm sideeffect "", ""() + ret void +}