diff options
Diffstat (limited to 'lib/Transforms/IPO/Inliner.cpp')
-rw-r--r-- | lib/Transforms/IPO/Inliner.cpp | 95 |
1 files changed, 65 insertions, 30 deletions
diff --git a/lib/Transforms/IPO/Inliner.cpp b/lib/Transforms/IPO/Inliner.cpp index 4449c87ddefa..3da0c2e83eb8 100644 --- a/lib/Transforms/IPO/Inliner.cpp +++ b/lib/Transforms/IPO/Inliner.cpp @@ -35,6 +35,7 @@ #include "llvm/Analysis/ProfileSummaryInfo.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/Transforms/Utils/Local.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/CallSite.h" @@ -59,7 +60,6 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Utils/Cloning.h" #include "llvm/Transforms/Utils/ImportedFunctionsInliningStatistics.h" -#include "llvm/Transforms/Utils/Local.h" #include "llvm/Transforms/Utils/ModuleUtils.h" #include <algorithm> #include <cassert> @@ -208,8 +208,8 @@ static void mergeInlinedArrayAllocas( // Otherwise, we *can* reuse it, RAUW AI into AvailableAlloca and declare // success! - DEBUG(dbgs() << " ***MERGED ALLOCA: " << *AI - << "\n\t\tINTO: " << *AvailableAlloca << '\n'); + LLVM_DEBUG(dbgs() << " ***MERGED ALLOCA: " << *AI + << "\n\t\tINTO: " << *AvailableAlloca << '\n'); // Move affected dbg.declare calls immediately after the new alloca to // avoid the situation when a dbg.declare precedes its alloca. @@ -379,14 +379,14 @@ shouldInline(CallSite CS, function_ref<InlineCost(CallSite CS)> GetInlineCost, Function *Caller = CS.getCaller(); if (IC.isAlways()) { - DEBUG(dbgs() << " Inlining: cost=always" - << ", Call: " << *CS.getInstruction() << "\n"); + LLVM_DEBUG(dbgs() << " Inlining: cost=always" + << ", Call: " << *CS.getInstruction() << "\n"); return IC; } if (IC.isNever()) { - DEBUG(dbgs() << " NOT Inlining: cost=never" - << ", Call: " << *CS.getInstruction() << "\n"); + LLVM_DEBUG(dbgs() << " NOT Inlining: cost=never" + << ", Call: " << *CS.getInstruction() << "\n"); ORE.emit([&]() { return OptimizationRemarkMissed(DEBUG_TYPE, "NeverInline", Call) << NV("Callee", Callee) << " not inlined into " @@ -397,9 +397,9 @@ shouldInline(CallSite CS, function_ref<InlineCost(CallSite CS)> GetInlineCost, } if (!IC) { - DEBUG(dbgs() << " NOT Inlining: cost=" << IC.getCost() - << ", thres=" << IC.getThreshold() - << ", Call: " << *CS.getInstruction() << "\n"); + LLVM_DEBUG(dbgs() << " NOT Inlining: cost=" << IC.getCost() + << ", thres=" << IC.getThreshold() + << ", Call: " << *CS.getInstruction() << "\n"); ORE.emit([&]() { return OptimizationRemarkMissed(DEBUG_TYPE, "TooCostly", Call) << NV("Callee", Callee) << " not inlined into " @@ -412,9 +412,9 @@ shouldInline(CallSite CS, function_ref<InlineCost(CallSite CS)> GetInlineCost, int TotalSecondaryCost = 0; if (shouldBeDeferred(Caller, CS, IC, TotalSecondaryCost, GetInlineCost)) { - DEBUG(dbgs() << " NOT Inlining: " << *CS.getInstruction() - << " Cost = " << IC.getCost() - << ", outer Cost = " << TotalSecondaryCost << '\n'); + LLVM_DEBUG(dbgs() << " NOT Inlining: " << *CS.getInstruction() + << " Cost = " << IC.getCost() + << ", outer Cost = " << TotalSecondaryCost << '\n'); ORE.emit([&]() { return OptimizationRemarkMissed(DEBUG_TYPE, "IncreaseCostInOtherContexts", Call) @@ -428,9 +428,9 @@ shouldInline(CallSite CS, function_ref<InlineCost(CallSite CS)> GetInlineCost, return None; } - DEBUG(dbgs() << " Inlining: cost=" << IC.getCost() - << ", thres=" << IC.getThreshold() - << ", Call: " << *CS.getInstruction() << '\n'); + LLVM_DEBUG(dbgs() << " Inlining: cost=" << IC.getCost() + << ", thres=" << IC.getThreshold() + << ", Call: " << *CS.getInstruction() << '\n'); return IC; } @@ -470,12 +470,12 @@ inlineCallsImpl(CallGraphSCC &SCC, CallGraph &CG, function_ref<AAResults &(Function &)> AARGetter, ImportedFunctionsInliningStatistics &ImportedFunctionsStats) { SmallPtrSet<Function *, 8> SCCFunctions; - DEBUG(dbgs() << "Inliner visiting SCC:"); + LLVM_DEBUG(dbgs() << "Inliner visiting SCC:"); for (CallGraphNode *Node : SCC) { Function *F = Node->getFunction(); if (F) SCCFunctions.insert(F); - DEBUG(dbgs() << " " << (F ? F->getName() : "INDIRECTNODE")); + LLVM_DEBUG(dbgs() << " " << (F ? F->getName() : "INDIRECTNODE")); } // Scan through and identify all call sites ahead of time so that we only @@ -524,7 +524,7 @@ inlineCallsImpl(CallGraphSCC &SCC, CallGraph &CG, } } - DEBUG(dbgs() << ": " << CallSites.size() << " call sites.\n"); + LLVM_DEBUG(dbgs() << ": " << CallSites.size() << " call sites.\n"); // If there are no calls in this function, exit early. if (CallSites.empty()) @@ -593,7 +593,7 @@ inlineCallsImpl(CallGraphSCC &SCC, CallGraph &CG, // size. This happens because IPSCCP propagates the result out of the // call and then we're left with the dead call. if (IsTriviallyDead) { - DEBUG(dbgs() << " -> Deleting dead call: " << *Instr << "\n"); + LLVM_DEBUG(dbgs() << " -> Deleting dead call: " << *Instr << "\n"); // Update the call graph by deleting the edge from Callee to Caller. CG[Caller]->removeCallEdgeFor(CS); Instr->eraseFromParent(); @@ -657,8 +657,8 @@ inlineCallsImpl(CallGraphSCC &SCC, CallGraph &CG, // callgraph references to the node, we cannot delete it yet, this // could invalidate the CGSCC iterator. CG[Callee]->getNumReferences() == 0) { - DEBUG(dbgs() << " -> Deleting dead function: " << Callee->getName() - << "\n"); + LLVM_DEBUG(dbgs() << " -> Deleting dead function: " + << Callee->getName() << "\n"); CallGraphNode *CalleeNode = CG[Callee]; // Remove any call graph edges from the callee to its callees. @@ -793,6 +793,14 @@ bool LegacyInlinerBase::removeDeadFunctions(CallGraph &CG, return true; } +InlinerPass::~InlinerPass() { + if (ImportedFunctionsStats) { + assert(InlinerFunctionImportStats != InlinerFunctionImportStatsOpts::No); + ImportedFunctionsStats->dump(InlinerFunctionImportStats == + InlinerFunctionImportStatsOpts::Verbose); + } +} + PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR) { @@ -804,6 +812,13 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC, Module &M = *InitialC.begin()->getFunction().getParent(); ProfileSummaryInfo *PSI = MAM.getCachedResult<ProfileSummaryAnalysis>(M); + if (!ImportedFunctionsStats && + InlinerFunctionImportStats != InlinerFunctionImportStatsOpts::No) { + ImportedFunctionsStats = + llvm::make_unique<ImportedFunctionsInliningStatistics>(); + ImportedFunctionsStats->setModuleInfo(M); + } + // We use a single common worklist for calls across the entire SCC. We // process these in-order and append new calls introduced during inlining to // the end. @@ -830,8 +845,14 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC, // incrementally maknig a single function grow in a super linear fashion. SmallVector<std::pair<CallSite, int>, 16> Calls; + FunctionAnalysisManager &FAM = + AM.getResult<FunctionAnalysisManagerCGSCCProxy>(InitialC, CG) + .getManager(); + // Populate the initial list of calls in this SCC. for (auto &N : InitialC) { + auto &ORE = + FAM.getResult<OptimizationRemarkEmitterAnalysis>(N.getFunction()); // We want to generally process call sites top-down in order for // simplifications stemming from replacing the call with the returned value // after inlining to be visible to subsequent inlining decisions. @@ -839,9 +860,20 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC, // Instead we should do an actual RPO walk of the function body. for (Instruction &I : instructions(N.getFunction())) if (auto CS = CallSite(&I)) - if (Function *Callee = CS.getCalledFunction()) + if (Function *Callee = CS.getCalledFunction()) { if (!Callee->isDeclaration()) Calls.push_back({CS, -1}); + else if (!isa<IntrinsicInst>(I)) { + using namespace ore; + ORE.emit([&]() { + return OptimizationRemarkMissed(DEBUG_TYPE, "NoDefinition", &I) + << NV("Callee", Callee) << " will not be inlined into " + << NV("Caller", CS.getCaller()) + << " because its definition is unavailable" + << setIsVerbose(); + }); + } + } } if (Calls.empty()) return PreservedAnalyses::all(); @@ -879,7 +911,7 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC, if (F.hasFnAttribute(Attribute::OptimizeNone)) continue; - DEBUG(dbgs() << "Inlining calls in: " << F.getName() << "\n"); + LLVM_DEBUG(dbgs() << "Inlining calls in: " << F.getName() << "\n"); // Get a FunctionAnalysisManager via a proxy for this particular node. We // do this each time we visit a node as the SCC may have changed and as @@ -931,9 +963,9 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC, // and thus hidden from the full inline history. if (CG.lookupSCC(*CG.lookup(Callee)) == C && UR.InlinedInternalEdges.count({&N, C})) { - DEBUG(dbgs() << "Skipping inlining internal SCC edge from a node " - "previously split out of this SCC by inlining: " - << F.getName() << " -> " << Callee.getName() << "\n"); + LLVM_DEBUG(dbgs() << "Skipping inlining internal SCC edge from a node " + "previously split out of this SCC by inlining: " + << F.getName() << " -> " << Callee.getName() << "\n"); continue; } @@ -992,6 +1024,9 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC, Calls.push_back({CS, NewHistoryID}); } + if (InlinerFunctionImportStats != InlinerFunctionImportStatsOpts::No) + ImportedFunctionsStats->recordInline(F, Callee); + // Merge the attributes based on the inlining. AttributeFuncs::mergeAttributesForInlining(F, Callee); @@ -1052,7 +1087,7 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC, // change. LazyCallGraph::SCC *OldC = C; C = &updateCGAndAnalysisManagerForFunctionPass(CG, *C, N, AM, UR); - DEBUG(dbgs() << "Updated inlining SCC: " << *C << "\n"); + LLVM_DEBUG(dbgs() << "Updated inlining SCC: " << *C << "\n"); RC = &C->getOuterRefSCC(); // If this causes an SCC to split apart into multiple smaller SCCs, there @@ -1070,8 +1105,8 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC, if (C != OldC && llvm::any_of(InlinedCallees, [&](Function *Callee) { return CG.lookupSCC(*CG.lookup(*Callee)) == OldC; })) { - DEBUG(dbgs() << "Inlined an internal call edge and split an SCC, " - "retaining this to avoid infinite inlining.\n"); + LLVM_DEBUG(dbgs() << "Inlined an internal call edge and split an SCC, " + "retaining this to avoid infinite inlining.\n"); UR.InlinedInternalEdges.insert({&N, OldC}); } InlinedCallees.clear(); |