From 4f5d83034351af798f2e668616be9a535ccd5df0 Mon Sep 17 00:00:00 2001 From: Dehao Chen Date: Sat, 30 Sep 2017 20:46:15 +0000 Subject: [PATCH] Refactor the SamplePGO profile annotation logic to extract inlineCallInstruction. (NFC) llvm-svn: 314601 --- llvm/lib/Transforms/IPO/SampleProfile.cpp | 123 ++++++++++++---------- 1 file changed, 65 insertions(+), 58 deletions(-) diff --git a/llvm/lib/Transforms/IPO/SampleProfile.cpp b/llvm/lib/Transforms/IPO/SampleProfile.cpp index 5258746dbb9c..93e697c9a7eb 100644 --- a/llvm/lib/Transforms/IPO/SampleProfile.cpp +++ b/llvm/lib/Transforms/IPO/SampleProfile.cpp @@ -172,6 +172,7 @@ protected: std::vector findIndirectCallFunctionSamples(const Instruction &I) const; const FunctionSamples *findFunctionSamples(const Instruction &I) const; + bool inlineCallInstruction(Instruction *I); bool inlineHotFunctions(Function &F, DenseSet &ImportGUIDs); void printEdgeWeight(raw_ostream &OS, Edge E); @@ -676,6 +677,39 @@ SampleProfileLoader::findFunctionSamples(const Instruction &Inst) const { return FS; } +bool SampleProfileLoader::inlineCallInstruction(Instruction *I) { + assert(isa(I) || isa(I)); + CallSite CS(I); + Function *CalledFunction = CS.getCalledFunction(); + assert(CalledFunction); + DebugLoc DLoc = I->getDebugLoc(); + BasicBlock *BB = I->getParent(); + InlineParams Params = getInlineParams(); + Params.ComputeFullInlineCost = true; + // Checks if there is anything in the reachable portion of the callee at + // this callsite that makes this inlining potentially illegal. Need to + // set ComputeFullInlineCost, otherwise getInlineCost may return early + // when cost exceeds threshold without checking all IRs in the callee. + // The acutal cost does not matter because we only checks isNever() to + // see if it is legal to inline the callsite. + InlineCost Cost = getInlineCost(CS, Params, GetTTI(*CalledFunction), GetAC, + None, nullptr, nullptr); + if (Cost.isNever()) { + ORE->emit(OptimizationRemark(DEBUG_TYPE, "Not inline", DLoc, BB) + << "incompatible inlining"); + return false; + } + InlineFunctionInfo IFI(nullptr, &GetAC); + if (InlineFunction(CS, IFI)) { + // The call to InlineFunction erases I, so we can't pass it here. + ORE->emit(OptimizationRemark(DEBUG_TYPE, "HotInline", DLoc, BB) + << "inlined hot callee '" << ore::NV("Callee", CalledFunction) + << "' into '" << ore::NV("Caller", BB->getParent()) << "'"); + return true; + } + return false; +} + /// \brief Iteratively inline hot callsites of a function. /// /// Iteratively traverse all callsites of the function \p F, and find if @@ -713,82 +747,55 @@ bool SampleProfileLoader::inlineHotFunctions( } } for (auto I : CIS) { - InlineFunctionInfo IFI(nullptr, &GetAC); Function *CalledFunction = CallSite(I).getCalledFunction(); // Do not inline recursive calls. if (CalledFunction == &F) continue; - Instruction *DI = I; - if (!CalledFunction && !PromotedInsns.count(I) && - CallSite(I).isIndirectCall()) { + if (CallSite(I).isIndirectCall()) { + if (PromotedInsns.count(I)) + continue; for (const auto *FS : findIndirectCallFunctionSamples(*I)) { auto CalleeFunctionName = FS->getName(); // If it is a recursive call, we do not inline it as it could bloat // the code exponentially. There is way to better handle this, e.g. // clone the caller first, and inline the cloned caller if it is - // recursive. As llvm does not inline recursive calls, we will simply - // ignore it instead of handling it explicitly. + // recursive. As llvm does not inline recursive calls, we will + // simply ignore it instead of handling it explicitly. if (CalleeFunctionName == F.getName()) continue; + const char *Reason = "Callee function not available"; auto R = SymbolMap.find(CalleeFunctionName); - if (R == SymbolMap.end()) - continue; - CalledFunction = R->getValue(); - if (CalledFunction && isLegalToPromote(I, CalledFunction, &Reason)) { - // The indirect target was promoted and inlined in the profile, as a - // result, we do not have profile info for the branch probability. - // We set the probability to 80% taken to indicate that the static - // call is likely taken. - DI = dyn_cast( - promoteIndirectCall(I, CalledFunction, 80, 100, false, ORE) + if (R != SymbolMap.end() && R->getValue() && + !R->getValue()->isDeclaration() && + R->getValue()->getSubprogram() && + isLegalToPromote(I, R->getValue(), &Reason)) { + // The indirect target was promoted and inlined in the profile, + // as a result, we do not have profile info for the branch + // probability. We set the probability to 80% taken to indicate + // that the static call is likely taken. + Instruction *DI = dyn_cast( + promoteIndirectCall(I, R->getValue(), 80, 100, false, ORE) ->stripPointerCasts()); PromotedInsns.insert(I); + // If profile mismatches, we should not attempt to inline DI. + if ((isa(DI) || isa(DI)) && + inlineCallInstruction(DI)) + LocalChanged = true; } else { - DEBUG(dbgs() << "\nFailed to promote indirect call to " - << CalleeFunctionName << " because " << Reason - << "\n"); - continue; + FS->findImportedFunctions(ImportGUIDs, F.getParent(), + Samples->getTotalSamples() * + SampleProfileHotThreshold / 100); } } - // If there is profile mismatch, we should not attempt to inline DI. - if (!isa(DI) && !isa(DI)) - continue; - } - if (!CalledFunction || !CalledFunction->getSubprogram()) { - // Handles functions that are imported from other modules. - for (const FunctionSamples *FS : findIndirectCallFunctionSamples(*I)) - FS->findImportedFunctions( - ImportGUIDs, F.getParent(), - Samples->getTotalSamples() * SampleProfileHotThreshold / 100); - continue; - } - assert(isa(DI) || isa(DI)); - CallSite CS(DI); - DebugLoc DLoc = I->getDebugLoc(); - BasicBlock *BB = I->getParent(); - InlineParams Params = getInlineParams(); - Params.ComputeFullInlineCost = true; - // Checks if there is anything in the reachable portion of the callee at - // this callsite that makes this inlining potentially illegal. Need to - // set ComputeFullInlineCost, otherwise getInlineCost may return early - // when cost exceeds threshold without checking all IRs in the callee. - // The acutal cost does not matter because we only checks isNever() to - // see if it is legal to inline the callsite. - InlineCost Cost = getInlineCost(CS, Params, GetTTI(*CalledFunction), GetAC, - None, nullptr, nullptr); - if (Cost.isNever()) { - ORE->emit(OptimizationRemark(DEBUG_TYPE, "Not inline", DLoc, BB) - << "incompatible inlining"); - continue; - } - if (InlineFunction(CS, IFI)) { - LocalChanged = true; - // The call to InlineFunction erases DI, so we can't pass it here. - ORE->emit(OptimizationRemark(DEBUG_TYPE, "HotInline", DLoc, BB) - << "inlined hot callee '" - << ore::NV("Callee", CalledFunction) << "' into '" - << ore::NV("Caller", &F) << "'"); + } else if (CalledFunction && CalledFunction->getSubprogram() && + !CalledFunction->isDeclaration()) { + if (inlineCallInstruction(I)) + LocalChanged = true; + } else { + findCalleeFunctionSamples(*I)->findImportedFunctions( + ImportGUIDs, F.getParent(), + Samples->getTotalSamples() * SampleProfileHotThreshold / 100); } } if (LocalChanged) {