10b57cec5SDimitry Andric //===- Inliner.cpp - Code common to all inliners --------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements the mechanics required to implement inlining without 100b57cec5SDimitry Andric // missing any calls and updating the call graph. The decisions of which calls 110b57cec5SDimitry Andric // are profitable to inline are implemented elsewhere. 120b57cec5SDimitry Andric // 130b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric #include "llvm/Transforms/IPO/Inliner.h" 1681ad6265SDimitry Andric #include "llvm/ADT/PriorityWorklist.h" 170b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 185ffd83dbSDimitry Andric #include "llvm/ADT/ScopeExit.h" 190b57cec5SDimitry Andric #include "llvm/ADT/SetVector.h" 200b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 210b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 220b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 23fb03ea46SDimitry Andric #include "llvm/ADT/StringExtras.h" 240b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 250b57cec5SDimitry Andric #include "llvm/Analysis/AssumptionCache.h" 260b57cec5SDimitry Andric #include "llvm/Analysis/BasicAliasAnalysis.h" 270b57cec5SDimitry Andric #include "llvm/Analysis/BlockFrequencyInfo.h" 280b57cec5SDimitry Andric #include "llvm/Analysis/CGSCCPassManager.h" 295ffd83dbSDimitry Andric #include "llvm/Analysis/InlineAdvisor.h" 300b57cec5SDimitry Andric #include "llvm/Analysis/InlineCost.h" 310b57cec5SDimitry Andric #include "llvm/Analysis/LazyCallGraph.h" 320b57cec5SDimitry Andric #include "llvm/Analysis/OptimizationRemarkEmitter.h" 330b57cec5SDimitry Andric #include "llvm/Analysis/ProfileSummaryInfo.h" 34349cc55cSDimitry Andric #include "llvm/Analysis/ReplayInlineAdvisor.h" 350b57cec5SDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h" 36e8d8bef9SDimitry Andric #include "llvm/Analysis/Utils/ImportedFunctionsInliningStatistics.h" 370b57cec5SDimitry Andric #include "llvm/IR/Attributes.h" 380b57cec5SDimitry Andric #include "llvm/IR/BasicBlock.h" 390b57cec5SDimitry Andric #include "llvm/IR/DebugLoc.h" 400b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h" 410b57cec5SDimitry Andric #include "llvm/IR/DiagnosticInfo.h" 420b57cec5SDimitry Andric #include "llvm/IR/Function.h" 430b57cec5SDimitry Andric #include "llvm/IR/InstIterator.h" 440b57cec5SDimitry Andric #include "llvm/IR/Instruction.h" 450b57cec5SDimitry Andric #include "llvm/IR/Instructions.h" 460b57cec5SDimitry Andric #include "llvm/IR/IntrinsicInst.h" 470b57cec5SDimitry Andric #include "llvm/IR/Metadata.h" 480b57cec5SDimitry Andric #include "llvm/IR/Module.h" 490b57cec5SDimitry Andric #include "llvm/IR/PassManager.h" 500b57cec5SDimitry Andric #include "llvm/IR/User.h" 510b57cec5SDimitry Andric #include "llvm/IR/Value.h" 520b57cec5SDimitry Andric #include "llvm/Pass.h" 530b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 540b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 550b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 560b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 575ffd83dbSDimitry Andric #include "llvm/Transforms/Utils/CallPromotionUtils.h" 580b57cec5SDimitry Andric #include "llvm/Transforms/Utils/Cloning.h" 595ffd83dbSDimitry Andric #include "llvm/Transforms/Utils/Local.h" 600b57cec5SDimitry Andric #include "llvm/Transforms/Utils/ModuleUtils.h" 610b57cec5SDimitry Andric #include <algorithm> 620b57cec5SDimitry Andric #include <cassert> 630b57cec5SDimitry Andric #include <functional> 640b57cec5SDimitry Andric #include <utility> 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric using namespace llvm; 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric #define DEBUG_TYPE "inline" 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric STATISTIC(NumInlined, "Number of functions inlined"); 710b57cec5SDimitry Andric STATISTIC(NumDeleted, "Number of functions deleted because all callers found"); 720b57cec5SDimitry Andric 73fb03ea46SDimitry Andric static cl::opt<int> IntraSCCCostMultiplier( 74fb03ea46SDimitry Andric "intra-scc-cost-multiplier", cl::init(2), cl::Hidden, 75fb03ea46SDimitry Andric cl::desc( 76fb03ea46SDimitry Andric "Cost multiplier to multiply onto inlined call sites where the " 77fb03ea46SDimitry Andric "new call was previously an intra-SCC call (not relevant when the " 78fb03ea46SDimitry Andric "original call was already intra-SCC). This can accumulate over " 79fb03ea46SDimitry Andric "multiple inlinings (e.g. if a call site already had a cost " 80fb03ea46SDimitry Andric "multiplier and one of its inlined calls was also subject to " 81fb03ea46SDimitry Andric "this, the inlined call would have the original multiplier " 82fb03ea46SDimitry Andric "multiplied by intra-scc-cost-multiplier). This is to prevent tons of " 83fb03ea46SDimitry Andric "inlining through a child SCC which can cause terrible compile times")); 84fb03ea46SDimitry Andric 8504eeddc0SDimitry Andric /// A flag for test, so we can print the content of the advisor when running it 8604eeddc0SDimitry Andric /// as part of the default (e.g. -O3) pipeline. 8704eeddc0SDimitry Andric static cl::opt<bool> KeepAdvisorForPrinting("keep-inline-advisor-for-printing", 8804eeddc0SDimitry Andric cl::init(false), cl::Hidden); 8904eeddc0SDimitry Andric 9081ad6265SDimitry Andric /// Allows printing the contents of the advisor after each SCC inliner pass. 9181ad6265SDimitry Andric static cl::opt<bool> 9281ad6265SDimitry Andric EnablePostSCCAdvisorPrinting("enable-scc-inline-advisor-printing", 9381ad6265SDimitry Andric cl::init(false), cl::Hidden); 9481ad6265SDimitry Andric 950b57cec5SDimitry Andric 96e8d8bef9SDimitry Andric static cl::opt<std::string> CGSCCInlineReplayFile( 97e8d8bef9SDimitry Andric "cgscc-inline-replay", cl::init(""), cl::value_desc("filename"), 98e8d8bef9SDimitry Andric cl::desc( 99e8d8bef9SDimitry Andric "Optimization remarks file containing inline remarks to be replayed " 100349cc55cSDimitry Andric "by cgscc inlining."), 101e8d8bef9SDimitry Andric cl::Hidden); 1020b57cec5SDimitry Andric 103349cc55cSDimitry Andric static cl::opt<ReplayInlinerSettings::Scope> CGSCCInlineReplayScope( 104349cc55cSDimitry Andric "cgscc-inline-replay-scope", 105349cc55cSDimitry Andric cl::init(ReplayInlinerSettings::Scope::Function), 106349cc55cSDimitry Andric cl::values(clEnumValN(ReplayInlinerSettings::Scope::Function, "Function", 107349cc55cSDimitry Andric "Replay on functions that have remarks associated " 108349cc55cSDimitry Andric "with them (default)"), 109349cc55cSDimitry Andric clEnumValN(ReplayInlinerSettings::Scope::Module, "Module", 110349cc55cSDimitry Andric "Replay on the entire module")), 111349cc55cSDimitry Andric cl::desc("Whether inline replay should be applied to the entire " 112349cc55cSDimitry Andric "Module or just the Functions (default) that are present as " 113349cc55cSDimitry Andric "callers in remarks during cgscc inlining."), 114349cc55cSDimitry Andric cl::Hidden); 115349cc55cSDimitry Andric 116349cc55cSDimitry Andric static cl::opt<ReplayInlinerSettings::Fallback> CGSCCInlineReplayFallback( 117349cc55cSDimitry Andric "cgscc-inline-replay-fallback", 118349cc55cSDimitry Andric cl::init(ReplayInlinerSettings::Fallback::Original), 119349cc55cSDimitry Andric cl::values( 120349cc55cSDimitry Andric clEnumValN( 121349cc55cSDimitry Andric ReplayInlinerSettings::Fallback::Original, "Original", 122349cc55cSDimitry Andric "All decisions not in replay send to original advisor (default)"), 123349cc55cSDimitry Andric clEnumValN(ReplayInlinerSettings::Fallback::AlwaysInline, 124349cc55cSDimitry Andric "AlwaysInline", "All decisions not in replay are inlined"), 125349cc55cSDimitry Andric clEnumValN(ReplayInlinerSettings::Fallback::NeverInline, "NeverInline", 126349cc55cSDimitry Andric "All decisions not in replay are not inlined")), 127349cc55cSDimitry Andric cl::desc( 128349cc55cSDimitry Andric "How cgscc inline replay treats sites that don't come from the replay. " 129349cc55cSDimitry Andric "Original: defers to original advisor, AlwaysInline: inline all sites " 130349cc55cSDimitry Andric "not in replay, NeverInline: inline no sites not in replay"), 131349cc55cSDimitry Andric cl::Hidden); 132349cc55cSDimitry Andric 133349cc55cSDimitry Andric static cl::opt<CallSiteFormat::Format> CGSCCInlineReplayFormat( 134349cc55cSDimitry Andric "cgscc-inline-replay-format", 135349cc55cSDimitry Andric cl::init(CallSiteFormat::Format::LineColumnDiscriminator), 136349cc55cSDimitry Andric cl::values( 137349cc55cSDimitry Andric clEnumValN(CallSiteFormat::Format::Line, "Line", "<Line Number>"), 138349cc55cSDimitry Andric clEnumValN(CallSiteFormat::Format::LineColumn, "LineColumn", 139349cc55cSDimitry Andric "<Line Number>:<Column Number>"), 140349cc55cSDimitry Andric clEnumValN(CallSiteFormat::Format::LineDiscriminator, 141349cc55cSDimitry Andric "LineDiscriminator", "<Line Number>.<Discriminator>"), 142349cc55cSDimitry Andric clEnumValN(CallSiteFormat::Format::LineColumnDiscriminator, 143349cc55cSDimitry Andric "LineColumnDiscriminator", 144349cc55cSDimitry Andric "<Line Number>:<Column Number>.<Discriminator> (default)")), 145349cc55cSDimitry Andric cl::desc("How cgscc inline replay file is formatted"), cl::Hidden); 146349cc55cSDimitry Andric 1470b57cec5SDimitry Andric /// Return true if the specified inline history ID 1480b57cec5SDimitry Andric /// indicates an inline history that includes the specified function. 1495ffd83dbSDimitry Andric static bool inlineHistoryIncludes( 1500b57cec5SDimitry Andric Function *F, int InlineHistoryID, 1510b57cec5SDimitry Andric const SmallVectorImpl<std::pair<Function *, int>> &InlineHistory) { 1520b57cec5SDimitry Andric while (InlineHistoryID != -1) { 1530b57cec5SDimitry Andric assert(unsigned(InlineHistoryID) < InlineHistory.size() && 1540b57cec5SDimitry Andric "Invalid inline history ID"); 1550b57cec5SDimitry Andric if (InlineHistory[InlineHistoryID].first == F) 1560b57cec5SDimitry Andric return true; 1570b57cec5SDimitry Andric InlineHistoryID = InlineHistory[InlineHistoryID].second; 1580b57cec5SDimitry Andric } 1590b57cec5SDimitry Andric return false; 1600b57cec5SDimitry Andric } 1610b57cec5SDimitry Andric 1625ffd83dbSDimitry Andric InlineAdvisor & 1635ffd83dbSDimitry Andric InlinerPass::getAdvisor(const ModuleAnalysisManagerCGSCCProxy::Result &MAM, 1645ffd83dbSDimitry Andric FunctionAnalysisManager &FAM, Module &M) { 165e8d8bef9SDimitry Andric if (OwnedAdvisor) 166e8d8bef9SDimitry Andric return *OwnedAdvisor; 167e8d8bef9SDimitry Andric 1685ffd83dbSDimitry Andric auto *IAA = MAM.getCachedResult<InlineAdvisorAnalysis>(M); 1695ffd83dbSDimitry Andric if (!IAA) { 1705ffd83dbSDimitry Andric // It should still be possible to run the inliner as a stand-alone SCC pass, 1715ffd83dbSDimitry Andric // for test scenarios. In that case, we default to the 1725ffd83dbSDimitry Andric // DefaultInlineAdvisor, which doesn't need to keep state between SCC pass 1735ffd83dbSDimitry Andric // runs. It also uses just the default InlineParams. 1745ffd83dbSDimitry Andric // In this case, we need to use the provided FAM, which is valid for the 1755ffd83dbSDimitry Andric // duration of the inliner pass, and thus the lifetime of the owned advisor. 1765ffd83dbSDimitry Andric // The one we would get from the MAM can be invalidated as a result of the 1775ffd83dbSDimitry Andric // inliner's activity. 17881ad6265SDimitry Andric OwnedAdvisor = std::make_unique<DefaultInlineAdvisor>( 17981ad6265SDimitry Andric M, FAM, getInlineParams(), 18081ad6265SDimitry Andric InlineContext{LTOPhase, InlinePass::CGSCCInliner}); 181e8d8bef9SDimitry Andric 182e8d8bef9SDimitry Andric if (!CGSCCInlineReplayFile.empty()) 183349cc55cSDimitry Andric OwnedAdvisor = getReplayInlineAdvisor( 184e8d8bef9SDimitry Andric M, FAM, M.getContext(), std::move(OwnedAdvisor), 185349cc55cSDimitry Andric ReplayInlinerSettings{CGSCCInlineReplayFile, 186349cc55cSDimitry Andric CGSCCInlineReplayScope, 187349cc55cSDimitry Andric CGSCCInlineReplayFallback, 188349cc55cSDimitry Andric {CGSCCInlineReplayFormat}}, 18981ad6265SDimitry Andric /*EmitRemarks=*/true, 19006c3fb27SDimitry Andric InlineContext{LTOPhase, InlinePass::ReplayCGSCCInliner}); 191e8d8bef9SDimitry Andric 192e8d8bef9SDimitry Andric return *OwnedAdvisor; 1935ffd83dbSDimitry Andric } 1945ffd83dbSDimitry Andric assert(IAA->getAdvisor() && 1955ffd83dbSDimitry Andric "Expected a present InlineAdvisorAnalysis also have an " 1965ffd83dbSDimitry Andric "InlineAdvisor initialized"); 1975ffd83dbSDimitry Andric return *IAA->getAdvisor(); 1985ffd83dbSDimitry Andric } 1995ffd83dbSDimitry Andric 200*0fca6ea1SDimitry Andric void makeFunctionBodyUnreachable(Function &F) { 201*0fca6ea1SDimitry Andric F.dropAllReferences(); 202*0fca6ea1SDimitry Andric for (BasicBlock &BB : make_early_inc_range(F)) 203*0fca6ea1SDimitry Andric BB.eraseFromParent(); 204*0fca6ea1SDimitry Andric BasicBlock *BB = BasicBlock::Create(F.getContext(), "", &F); 205*0fca6ea1SDimitry Andric new UnreachableInst(F.getContext(), BB); 206*0fca6ea1SDimitry Andric } 207*0fca6ea1SDimitry Andric 2080b57cec5SDimitry Andric PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC, 2090b57cec5SDimitry Andric CGSCCAnalysisManager &AM, LazyCallGraph &CG, 2100b57cec5SDimitry Andric CGSCCUpdateResult &UR) { 2115ffd83dbSDimitry Andric const auto &MAMProxy = 2125ffd83dbSDimitry Andric AM.getResult<ModuleAnalysisManagerCGSCCProxy>(InitialC, CG); 2130b57cec5SDimitry Andric bool Changed = false; 2140b57cec5SDimitry Andric 2150b57cec5SDimitry Andric assert(InitialC.size() > 0 && "Cannot handle an empty SCC!"); 2160b57cec5SDimitry Andric Module &M = *InitialC.begin()->getFunction().getParent(); 2175ffd83dbSDimitry Andric ProfileSummaryInfo *PSI = MAMProxy.getCachedResult<ProfileSummaryAnalysis>(M); 2185ffd83dbSDimitry Andric 2195ffd83dbSDimitry Andric FunctionAnalysisManager &FAM = 2205ffd83dbSDimitry Andric AM.getResult<FunctionAnalysisManagerCGSCCProxy>(InitialC, CG) 2215ffd83dbSDimitry Andric .getManager(); 2225ffd83dbSDimitry Andric 2235ffd83dbSDimitry Andric InlineAdvisor &Advisor = getAdvisor(MAMProxy, FAM, M); 22481ad6265SDimitry Andric Advisor.onPassEntry(&InitialC); 2255ffd83dbSDimitry Andric 2260b57cec5SDimitry Andric // We use a single common worklist for calls across the entire SCC. We 2270b57cec5SDimitry Andric // process these in-order and append new calls introduced during inlining to 228fe6060f1SDimitry Andric // the end. The PriorityInlineOrder is optional here, in which the smaller 229fe6060f1SDimitry Andric // callee would have a higher priority to inline. 2300b57cec5SDimitry Andric // 2310b57cec5SDimitry Andric // Note that this particular order of processing is actually critical to 2320b57cec5SDimitry Andric // avoid very bad behaviors. Consider *highly connected* call graphs where 233e8d8bef9SDimitry Andric // each function contains a small amount of code and a couple of calls to 2340b57cec5SDimitry Andric // other functions. Because the LLVM inliner is fundamentally a bottom-up 2350b57cec5SDimitry Andric // inliner, it can handle gracefully the fact that these all appear to be 2360b57cec5SDimitry Andric // reasonable inlining candidates as it will flatten things until they become 2370b57cec5SDimitry Andric // too big to inline, and then move on and flatten another batch. 2380b57cec5SDimitry Andric // 2390b57cec5SDimitry Andric // However, when processing call edges *within* an SCC we cannot rely on this 2400b57cec5SDimitry Andric // bottom-up behavior. As a consequence, with heavily connected *SCCs* of 2410b57cec5SDimitry Andric // functions we can end up incrementally inlining N calls into each of 2420b57cec5SDimitry Andric // N functions because each incremental inlining decision looks good and we 2430b57cec5SDimitry Andric // don't have a topological ordering to prevent explosions. 2440b57cec5SDimitry Andric // 2450b57cec5SDimitry Andric // To compensate for this, we don't process transitive edges made immediate 2460b57cec5SDimitry Andric // by inlining until we've done one pass of inlining across the entire SCC. 2470b57cec5SDimitry Andric // Large, highly connected SCCs still lead to some amount of code bloat in 2480b57cec5SDimitry Andric // this model, but it is uniformly spread across all the functions in the SCC 2490b57cec5SDimitry Andric // and eventually they all become too large to inline, rather than 2500b57cec5SDimitry Andric // incrementally maknig a single function grow in a super linear fashion. 251bdd1243dSDimitry Andric SmallVector<std::pair<CallBase *, int>, 16> Calls; 2520b57cec5SDimitry Andric 2530b57cec5SDimitry Andric // Populate the initial list of calls in this SCC. 2540b57cec5SDimitry Andric for (auto &N : InitialC) { 2550b57cec5SDimitry Andric auto &ORE = 2560b57cec5SDimitry Andric FAM.getResult<OptimizationRemarkEmitterAnalysis>(N.getFunction()); 2570b57cec5SDimitry Andric // We want to generally process call sites top-down in order for 2580b57cec5SDimitry Andric // simplifications stemming from replacing the call with the returned value 2590b57cec5SDimitry Andric // after inlining to be visible to subsequent inlining decisions. 2600b57cec5SDimitry Andric // FIXME: Using instructions sequence is a really bad way to do this. 2610b57cec5SDimitry Andric // Instead we should do an actual RPO walk of the function body. 2620b57cec5SDimitry Andric for (Instruction &I : instructions(N.getFunction())) 2635ffd83dbSDimitry Andric if (auto *CB = dyn_cast<CallBase>(&I)) 2645ffd83dbSDimitry Andric if (Function *Callee = CB->getCalledFunction()) { 2650b57cec5SDimitry Andric if (!Callee->isDeclaration()) 266bdd1243dSDimitry Andric Calls.push_back({CB, -1}); 2670b57cec5SDimitry Andric else if (!isa<IntrinsicInst>(I)) { 2680b57cec5SDimitry Andric using namespace ore; 2695ffd83dbSDimitry Andric setInlineRemark(*CB, "unavailable definition"); 2700b57cec5SDimitry Andric ORE.emit([&]() { 2710b57cec5SDimitry Andric return OptimizationRemarkMissed(DEBUG_TYPE, "NoDefinition", &I) 2720b57cec5SDimitry Andric << NV("Callee", Callee) << " will not be inlined into " 2735ffd83dbSDimitry Andric << NV("Caller", CB->getCaller()) 2740b57cec5SDimitry Andric << " because its definition is unavailable" 2750b57cec5SDimitry Andric << setIsVerbose(); 2760b57cec5SDimitry Andric }); 2770b57cec5SDimitry Andric } 2780b57cec5SDimitry Andric } 2790b57cec5SDimitry Andric } 2800b57cec5SDimitry Andric 281e8d8bef9SDimitry Andric // Capture updatable variable for the current SCC. 2820b57cec5SDimitry Andric auto *C = &InitialC; 2830b57cec5SDimitry Andric 284*0fca6ea1SDimitry Andric auto AdvisorOnExit = make_scope_exit([&] { Advisor.onPassExit(C); }); 285*0fca6ea1SDimitry Andric 286*0fca6ea1SDimitry Andric if (Calls.empty()) 287*0fca6ea1SDimitry Andric return PreservedAnalyses::all(); 288*0fca6ea1SDimitry Andric 2890b57cec5SDimitry Andric // When inlining a callee produces new call sites, we want to keep track of 2900b57cec5SDimitry Andric // the fact that they were inlined from the callee. This allows us to avoid 2910b57cec5SDimitry Andric // infinite inlining in some obscure cases. To represent this, we use an 2920b57cec5SDimitry Andric // index into the InlineHistory vector. 2930b57cec5SDimitry Andric SmallVector<std::pair<Function *, int>, 16> InlineHistory; 2940b57cec5SDimitry Andric 2950b57cec5SDimitry Andric // Track a set vector of inlined callees so that we can augment the caller 2960b57cec5SDimitry Andric // with all of their edges in the call graph before pruning out the ones that 2970b57cec5SDimitry Andric // got simplified away. 2980b57cec5SDimitry Andric SmallSetVector<Function *, 4> InlinedCallees; 2990b57cec5SDimitry Andric 3000b57cec5SDimitry Andric // Track the dead functions to delete once finished with inlining calls. We 3010b57cec5SDimitry Andric // defer deleting these to make it easier to handle the call graph updates. 3020b57cec5SDimitry Andric SmallVector<Function *, 4> DeadFunctions; 3030b57cec5SDimitry Andric 30404eeddc0SDimitry Andric // Track potentially dead non-local functions with comdats to see if they can 30504eeddc0SDimitry Andric // be deleted as a batch after inlining. 30604eeddc0SDimitry Andric SmallVector<Function *, 4> DeadFunctionsInComdats; 30704eeddc0SDimitry Andric 308bdd1243dSDimitry Andric // Loop forward over all of the calls. Note that we cannot cache the size as 309bdd1243dSDimitry Andric // inlining can introduce new calls that need to be processed. 310bdd1243dSDimitry Andric for (int I = 0; I < (int)Calls.size(); ++I) { 3110b57cec5SDimitry Andric // We expect the calls to typically be batched with sequences of calls that 3120b57cec5SDimitry Andric // have the same caller, so we first set up some shared infrastructure for 3130b57cec5SDimitry Andric // this caller. We also do any pruning we can at this layer on the caller 3140b57cec5SDimitry Andric // alone. 315bdd1243dSDimitry Andric Function &F = *Calls[I].first->getCaller(); 3160b57cec5SDimitry Andric LazyCallGraph::Node &N = *CG.lookup(F); 317bdd1243dSDimitry Andric if (CG.lookupSCC(N) != C) 3180b57cec5SDimitry Andric continue; 3190b57cec5SDimitry Andric 320fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "Inlining calls in: " << F.getName() << "\n" 321fe6060f1SDimitry Andric << " Function size: " << F.getInstructionCount() 322fe6060f1SDimitry Andric << "\n"); 3230b57cec5SDimitry Andric 3245ffd83dbSDimitry Andric auto GetAssumptionCache = [&](Function &F) -> AssumptionCache & { 3250b57cec5SDimitry Andric return FAM.getResult<AssumptionAnalysis>(F); 3260b57cec5SDimitry Andric }; 3270b57cec5SDimitry Andric 3285ffd83dbSDimitry Andric // Now process as many calls as we have within this caller in the sequence. 3290b57cec5SDimitry Andric // We bail out as soon as the caller has to change so we can update the 3300b57cec5SDimitry Andric // call graph and prepare the context of that new caller. 3310b57cec5SDimitry Andric bool DidInline = false; 332bdd1243dSDimitry Andric for (; I < (int)Calls.size() && Calls[I].first->getCaller() == &F; ++I) { 333bdd1243dSDimitry Andric auto &P = Calls[I]; 3345ffd83dbSDimitry Andric CallBase *CB = P.first; 3355ffd83dbSDimitry Andric const int InlineHistoryID = P.second; 3365ffd83dbSDimitry Andric Function &Callee = *CB->getCalledFunction(); 3370b57cec5SDimitry Andric 3380b57cec5SDimitry Andric if (InlineHistoryID != -1 && 3395ffd83dbSDimitry Andric inlineHistoryIncludes(&Callee, InlineHistoryID, InlineHistory)) { 34006c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << "Skipping inlining due to history: " << F.getName() 34106c3fb27SDimitry Andric << " -> " << Callee.getName() << "\n"); 3425ffd83dbSDimitry Andric setInlineRemark(*CB, "recursive"); 34306c3fb27SDimitry Andric // Set noinline so that we don't forget this decision across CGSCC 34406c3fb27SDimitry Andric // iterations. 34506c3fb27SDimitry Andric CB->setIsNoInline(); 3460b57cec5SDimitry Andric continue; 3470b57cec5SDimitry Andric } 3480b57cec5SDimitry Andric 3490b57cec5SDimitry Andric // Check if this inlining may repeat breaking an SCC apart that has 3500b57cec5SDimitry Andric // already been split once before. In that case, inlining here may 3510b57cec5SDimitry Andric // trigger infinite inlining, much like is prevented within the inliner 3520b57cec5SDimitry Andric // itself by the InlineHistory above, but spread across CGSCC iterations 3530b57cec5SDimitry Andric // and thus hidden from the full inline history. 354fb03ea46SDimitry Andric LazyCallGraph::SCC *CalleeSCC = CG.lookupSCC(*CG.lookup(Callee)); 355fb03ea46SDimitry Andric if (CalleeSCC == C && UR.InlinedInternalEdges.count({&N, C})) { 3560b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Skipping inlining internal SCC edge from a node " 3570b57cec5SDimitry Andric "previously split out of this SCC by inlining: " 3580b57cec5SDimitry Andric << F.getName() << " -> " << Callee.getName() << "\n"); 3595ffd83dbSDimitry Andric setInlineRemark(*CB, "recursive SCC split"); 3600b57cec5SDimitry Andric continue; 3610b57cec5SDimitry Andric } 3620b57cec5SDimitry Andric 363349cc55cSDimitry Andric std::unique_ptr<InlineAdvice> Advice = 364349cc55cSDimitry Andric Advisor.getAdvice(*CB, OnlyMandatory); 365349cc55cSDimitry Andric 3660b57cec5SDimitry Andric // Check whether we want to inline this callsite. 367349cc55cSDimitry Andric if (!Advice) 368349cc55cSDimitry Andric continue; 369349cc55cSDimitry Andric 3705ffd83dbSDimitry Andric if (!Advice->isInliningRecommended()) { 3715ffd83dbSDimitry Andric Advice->recordUnattemptedInlining(); 3720b57cec5SDimitry Andric continue; 3730b57cec5SDimitry Andric } 3740b57cec5SDimitry Andric 375fb03ea46SDimitry Andric int CBCostMult = 376fb03ea46SDimitry Andric getStringFnAttrAsInt( 377fb03ea46SDimitry Andric *CB, InlineConstants::FunctionInlineCostMultiplierAttributeName) 37881ad6265SDimitry Andric .value_or(1); 379fb03ea46SDimitry Andric 3800b57cec5SDimitry Andric // Setup the data structure used to plumb customization into the 3810b57cec5SDimitry Andric // `InlineFunction` routine. 3820b57cec5SDimitry Andric InlineFunctionInfo IFI( 38306c3fb27SDimitry Andric GetAssumptionCache, PSI, 3845ffd83dbSDimitry Andric &FAM.getResult<BlockFrequencyAnalysis>(*(CB->getCaller())), 3850b57cec5SDimitry Andric &FAM.getResult<BlockFrequencyAnalysis>(Callee)); 3860b57cec5SDimitry Andric 387e8d8bef9SDimitry Andric InlineResult IR = 388bdd1243dSDimitry Andric InlineFunction(*CB, IFI, /*MergeAttributes=*/true, 389bdd1243dSDimitry Andric &FAM.getResult<AAManager>(*CB->getCaller())); 3905ffd83dbSDimitry Andric if (!IR.isSuccess()) { 3915ffd83dbSDimitry Andric Advice->recordUnsuccessfulInlining(IR); 3920b57cec5SDimitry Andric continue; 3930b57cec5SDimitry Andric } 3945ffd83dbSDimitry Andric 3950b57cec5SDimitry Andric DidInline = true; 3960b57cec5SDimitry Andric InlinedCallees.insert(&Callee); 3970b57cec5SDimitry Andric ++NumInlined; 3980b57cec5SDimitry Andric 399fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << " Size after inlining: " 400fe6060f1SDimitry Andric << F.getInstructionCount() << "\n"); 401fe6060f1SDimitry Andric 4020b57cec5SDimitry Andric // Add any new callsites to defined functions to the worklist. 4030b57cec5SDimitry Andric if (!IFI.InlinedCallSites.empty()) { 4040b57cec5SDimitry Andric int NewHistoryID = InlineHistory.size(); 4050b57cec5SDimitry Andric InlineHistory.push_back({&Callee, InlineHistoryID}); 4065ffd83dbSDimitry Andric 4075ffd83dbSDimitry Andric for (CallBase *ICB : reverse(IFI.InlinedCallSites)) { 4085ffd83dbSDimitry Andric Function *NewCallee = ICB->getCalledFunction(); 409fe6060f1SDimitry Andric assert(!(NewCallee && NewCallee->isIntrinsic()) && 410fe6060f1SDimitry Andric "Intrinsic calls should not be tracked."); 4115ffd83dbSDimitry Andric if (!NewCallee) { 4125ffd83dbSDimitry Andric // Try to promote an indirect (virtual) call without waiting for 4135ffd83dbSDimitry Andric // the post-inline cleanup and the next DevirtSCCRepeatedPass 4145ffd83dbSDimitry Andric // iteration because the next iteration may not happen and we may 4155ffd83dbSDimitry Andric // miss inlining it. 4165ffd83dbSDimitry Andric if (tryPromoteCall(*ICB)) 4175ffd83dbSDimitry Andric NewCallee = ICB->getCalledFunction(); 4185ffd83dbSDimitry Andric } 419fb03ea46SDimitry Andric if (NewCallee) { 420fb03ea46SDimitry Andric if (!NewCallee->isDeclaration()) { 421bdd1243dSDimitry Andric Calls.push_back({ICB, NewHistoryID}); 422fb03ea46SDimitry Andric // Continually inlining through an SCC can result in huge compile 423fb03ea46SDimitry Andric // times and bloated code since we arbitrarily stop at some point 424fb03ea46SDimitry Andric // when the inliner decides it's not profitable to inline anymore. 425fb03ea46SDimitry Andric // We attempt to mitigate this by making these calls exponentially 426fb03ea46SDimitry Andric // more expensive. 427fb03ea46SDimitry Andric // This doesn't apply to calls in the same SCC since if we do 428fb03ea46SDimitry Andric // inline through the SCC the function will end up being 429fb03ea46SDimitry Andric // self-recursive which the inliner bails out on, and inlining 430fb03ea46SDimitry Andric // within an SCC is necessary for performance. 431fb03ea46SDimitry Andric if (CalleeSCC != C && 432fb03ea46SDimitry Andric CalleeSCC == CG.lookupSCC(CG.get(*NewCallee))) { 433fb03ea46SDimitry Andric Attribute NewCBCostMult = Attribute::get( 434fb03ea46SDimitry Andric M.getContext(), 435fb03ea46SDimitry Andric InlineConstants::FunctionInlineCostMultiplierAttributeName, 436fb03ea46SDimitry Andric itostr(CBCostMult * IntraSCCCostMultiplier)); 437fb03ea46SDimitry Andric ICB->addFnAttr(NewCBCostMult); 438fb03ea46SDimitry Andric } 439fb03ea46SDimitry Andric } 440fb03ea46SDimitry Andric } 4415ffd83dbSDimitry Andric } 4420b57cec5SDimitry Andric } 4430b57cec5SDimitry Andric 44404eeddc0SDimitry Andric // For local functions or discardable functions without comdats, check 44504eeddc0SDimitry Andric // whether this makes the callee trivially dead. In that case, we can drop 44604eeddc0SDimitry Andric // the body of the function eagerly which may reduce the number of callers 44704eeddc0SDimitry Andric // of other functions to one, changing inline cost thresholds. Non-local 44804eeddc0SDimitry Andric // discardable functions with comdats are checked later on. 4495ffd83dbSDimitry Andric bool CalleeWasDeleted = false; 45004eeddc0SDimitry Andric if (Callee.isDiscardableIfUnused() && Callee.hasZeroLiveUses() && 45104eeddc0SDimitry Andric !CG.isLibFunction(Callee)) { 45204eeddc0SDimitry Andric if (Callee.hasLocalLinkage() || !Callee.hasComdat()) { 453bdd1243dSDimitry Andric Calls.erase( 454bdd1243dSDimitry Andric std::remove_if(Calls.begin() + I + 1, Calls.end(), 455bdd1243dSDimitry Andric [&](const std::pair<CallBase *, int> &Call) { 4565ffd83dbSDimitry Andric return Call.first->getCaller() == &Callee; 457bdd1243dSDimitry Andric }), 458bdd1243dSDimitry Andric Calls.end()); 459bdd1243dSDimitry Andric 460*0fca6ea1SDimitry Andric // Clear the body and queue the function itself for call graph 461*0fca6ea1SDimitry Andric // updating when we finish inlining. 462*0fca6ea1SDimitry Andric makeFunctionBodyUnreachable(Callee); 463e8d8bef9SDimitry Andric assert(!is_contained(DeadFunctions, &Callee) && 4640b57cec5SDimitry Andric "Cannot put cause a function to become dead twice!"); 4650b57cec5SDimitry Andric DeadFunctions.push_back(&Callee); 4665ffd83dbSDimitry Andric CalleeWasDeleted = true; 46704eeddc0SDimitry Andric } else { 46804eeddc0SDimitry Andric DeadFunctionsInComdats.push_back(&Callee); 4690b57cec5SDimitry Andric } 4700b57cec5SDimitry Andric } 4715ffd83dbSDimitry Andric if (CalleeWasDeleted) 4725ffd83dbSDimitry Andric Advice->recordInliningWithCalleeDeleted(); 4735ffd83dbSDimitry Andric else 4745ffd83dbSDimitry Andric Advice->recordInlining(); 4750b57cec5SDimitry Andric } 4760b57cec5SDimitry Andric 477bdd1243dSDimitry Andric // Back the call index up by one to put us in a good position to go around 478bdd1243dSDimitry Andric // the outer loop. 479bdd1243dSDimitry Andric --I; 480bdd1243dSDimitry Andric 4810b57cec5SDimitry Andric if (!DidInline) 4820b57cec5SDimitry Andric continue; 4830b57cec5SDimitry Andric Changed = true; 4840b57cec5SDimitry Andric 4850b57cec5SDimitry Andric // At this point, since we have made changes we have at least removed 4860b57cec5SDimitry Andric // a call instruction. However, in the process we do some incremental 4870b57cec5SDimitry Andric // simplification of the surrounding code. This simplification can 4880b57cec5SDimitry Andric // essentially do all of the same things as a function pass and we can 4890b57cec5SDimitry Andric // re-use the exact same logic for updating the call graph to reflect the 4900b57cec5SDimitry Andric // change. 4915ffd83dbSDimitry Andric 4925ffd83dbSDimitry Andric // Inside the update, we also update the FunctionAnalysisManager in the 4935ffd83dbSDimitry Andric // proxy for this particular SCC. We do this as the SCC may have changed and 4945ffd83dbSDimitry Andric // as we're going to mutate this particular function we want to make sure 4955ffd83dbSDimitry Andric // the proxy is in place to forward any invalidation events. 4960b57cec5SDimitry Andric LazyCallGraph::SCC *OldC = C; 497e8d8bef9SDimitry Andric C = &updateCGAndAnalysisManagerForCGSCCPass(CG, *C, N, AM, UR, FAM); 4980b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Updated inlining SCC: " << *C << "\n"); 4990b57cec5SDimitry Andric 5000b57cec5SDimitry Andric // If this causes an SCC to split apart into multiple smaller SCCs, there 5010b57cec5SDimitry Andric // is a subtle risk we need to prepare for. Other transformations may 5020b57cec5SDimitry Andric // expose an "infinite inlining" opportunity later, and because of the SCC 5030b57cec5SDimitry Andric // mutation, we will revisit this function and potentially re-inline. If we 5040b57cec5SDimitry Andric // do, and that re-inlining also has the potentially to mutate the SCC 5050b57cec5SDimitry Andric // structure, the infinite inlining problem can manifest through infinite 5060b57cec5SDimitry Andric // SCC splits and merges. To avoid this, we capture the originating caller 5070b57cec5SDimitry Andric // node and the SCC containing the call edge. This is a slight over 5080b57cec5SDimitry Andric // approximation of the possible inlining decisions that must be avoided, 5090b57cec5SDimitry Andric // but is relatively efficient to store. We use C != OldC to know when 5100b57cec5SDimitry Andric // a new SCC is generated and the original SCC may be generated via merge 5110b57cec5SDimitry Andric // in later iterations. 5120b57cec5SDimitry Andric // 5130b57cec5SDimitry Andric // It is also possible that even if no new SCC is generated 5140b57cec5SDimitry Andric // (i.e., C == OldC), the original SCC could be split and then merged 5150b57cec5SDimitry Andric // into the same one as itself. and the original SCC will be added into 5160b57cec5SDimitry Andric // UR.CWorklist again, we want to catch such cases too. 5170b57cec5SDimitry Andric // 5180b57cec5SDimitry Andric // FIXME: This seems like a very heavyweight way of retaining the inline 5190b57cec5SDimitry Andric // history, we should look for a more efficient way of tracking it. 5200b57cec5SDimitry Andric if ((C != OldC || UR.CWorklist.count(OldC)) && 5210b57cec5SDimitry Andric llvm::any_of(InlinedCallees, [&](Function *Callee) { 5220b57cec5SDimitry Andric return CG.lookupSCC(*CG.lookup(*Callee)) == OldC; 5230b57cec5SDimitry Andric })) { 5240b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Inlined an internal call edge and split an SCC, " 5250b57cec5SDimitry Andric "retaining this to avoid infinite inlining.\n"); 5260b57cec5SDimitry Andric UR.InlinedInternalEdges.insert({&N, OldC}); 5270b57cec5SDimitry Andric } 5280b57cec5SDimitry Andric InlinedCallees.clear(); 529349cc55cSDimitry Andric 530349cc55cSDimitry Andric // Invalidate analyses for this function now so that we don't have to 531349cc55cSDimitry Andric // invalidate analyses for all functions in this SCC later. 532349cc55cSDimitry Andric FAM.invalidate(F, PreservedAnalyses::none()); 5330b57cec5SDimitry Andric } 5340b57cec5SDimitry Andric 53504eeddc0SDimitry Andric // We must ensure that we only delete functions with comdats if every function 53604eeddc0SDimitry Andric // in the comdat is going to be deleted. 53704eeddc0SDimitry Andric if (!DeadFunctionsInComdats.empty()) { 53804eeddc0SDimitry Andric filterDeadComdatFunctions(DeadFunctionsInComdats); 53904eeddc0SDimitry Andric for (auto *Callee : DeadFunctionsInComdats) 540*0fca6ea1SDimitry Andric makeFunctionBodyUnreachable(*Callee); 54104eeddc0SDimitry Andric DeadFunctions.append(DeadFunctionsInComdats); 54204eeddc0SDimitry Andric } 54304eeddc0SDimitry Andric 5440b57cec5SDimitry Andric // Now that we've finished inlining all of the calls across this SCC, delete 5450b57cec5SDimitry Andric // all of the trivially dead functions, updating the call graph and the CGSCC 5460b57cec5SDimitry Andric // pass manager in the process. 5470b57cec5SDimitry Andric // 5480b57cec5SDimitry Andric // Note that this walks a pointer set which has non-deterministic order but 5490b57cec5SDimitry Andric // that is OK as all we do is delete things and add pointers to unordered 5500b57cec5SDimitry Andric // sets. 5510b57cec5SDimitry Andric for (Function *DeadF : DeadFunctions) { 552*0fca6ea1SDimitry Andric CG.markDeadFunction(*DeadF); 5530b57cec5SDimitry Andric // Get the necessary information out of the call graph and nuke the 5545ffd83dbSDimitry Andric // function there. Also, clear out any cached analyses. 5550b57cec5SDimitry Andric auto &DeadC = *CG.lookupSCC(*CG.lookup(*DeadF)); 5560b57cec5SDimitry Andric FAM.clear(*DeadF, DeadF->getName()); 5570b57cec5SDimitry Andric AM.clear(DeadC, DeadC.getName()); 5580b57cec5SDimitry Andric 5590b57cec5SDimitry Andric // Mark the relevant parts of the call graph as invalid so we don't visit 5600b57cec5SDimitry Andric // them. 5610b57cec5SDimitry Andric UR.InvalidatedSCCs.insert(&DeadC); 5620b57cec5SDimitry Andric 563*0fca6ea1SDimitry Andric UR.DeadFunctions.push_back(DeadF); 5645ffd83dbSDimitry Andric 5650b57cec5SDimitry Andric ++NumDeleted; 5660b57cec5SDimitry Andric } 5670b57cec5SDimitry Andric 5680b57cec5SDimitry Andric if (!Changed) 5690b57cec5SDimitry Andric return PreservedAnalyses::all(); 5700b57cec5SDimitry Andric 571349cc55cSDimitry Andric PreservedAnalyses PA; 5720b57cec5SDimitry Andric // Even if we change the IR, we update the core CGSCC data structures and so 5730b57cec5SDimitry Andric // can preserve the proxy to the function analysis manager. 5740b57cec5SDimitry Andric PA.preserve<FunctionAnalysisManagerCGSCCProxy>(); 575349cc55cSDimitry Andric // We have already invalidated all analyses on modified functions. 576349cc55cSDimitry Andric PA.preserveSet<AllAnalysesOn<Function>>(); 5770b57cec5SDimitry Andric return PA; 5780b57cec5SDimitry Andric } 5795ffd83dbSDimitry Andric 5805ffd83dbSDimitry Andric ModuleInlinerWrapperPass::ModuleInlinerWrapperPass(InlineParams Params, 581e8d8bef9SDimitry Andric bool MandatoryFirst, 58281ad6265SDimitry Andric InlineContext IC, 5835ffd83dbSDimitry Andric InliningAdvisorMode Mode, 5845ffd83dbSDimitry Andric unsigned MaxDevirtIterations) 58581ad6265SDimitry Andric : Params(Params), IC(IC), Mode(Mode), 58681ad6265SDimitry Andric MaxDevirtIterations(MaxDevirtIterations) { 5875ffd83dbSDimitry Andric // Run the inliner first. The theory is that we are walking bottom-up and so 5885ffd83dbSDimitry Andric // the callees have already been fully optimized, and we want to inline them 5895ffd83dbSDimitry Andric // into the callers so that our optimizations can reflect that. 5905ffd83dbSDimitry Andric // For PreLinkThinLTO pass, we disable hot-caller heuristic for sample PGO 5915ffd83dbSDimitry Andric // because it makes profile annotation in the backend inaccurate. 59281ad6265SDimitry Andric if (MandatoryFirst) { 593e8d8bef9SDimitry Andric PM.addPass(InlinerPass(/*OnlyMandatory*/ true)); 59481ad6265SDimitry Andric if (EnablePostSCCAdvisorPrinting) 59581ad6265SDimitry Andric PM.addPass(InlineAdvisorAnalysisPrinterPass(dbgs())); 59681ad6265SDimitry Andric } 5975ffd83dbSDimitry Andric PM.addPass(InlinerPass()); 59881ad6265SDimitry Andric if (EnablePostSCCAdvisorPrinting) 59981ad6265SDimitry Andric PM.addPass(InlineAdvisorAnalysisPrinterPass(dbgs())); 6005ffd83dbSDimitry Andric } 6015ffd83dbSDimitry Andric 6025ffd83dbSDimitry Andric PreservedAnalyses ModuleInlinerWrapperPass::run(Module &M, 6035ffd83dbSDimitry Andric ModuleAnalysisManager &MAM) { 6045ffd83dbSDimitry Andric auto &IAA = MAM.getResult<InlineAdvisorAnalysis>(M); 605349cc55cSDimitry Andric if (!IAA.tryCreate(Params, Mode, 606349cc55cSDimitry Andric {CGSCCInlineReplayFile, 607349cc55cSDimitry Andric CGSCCInlineReplayScope, 608349cc55cSDimitry Andric CGSCCInlineReplayFallback, 60981ad6265SDimitry Andric {CGSCCInlineReplayFormat}}, 61081ad6265SDimitry Andric IC)) { 6115ffd83dbSDimitry Andric M.getContext().emitError( 6125ffd83dbSDimitry Andric "Could not setup Inlining Advisor for the requested " 6135ffd83dbSDimitry Andric "mode and/or options"); 6145ffd83dbSDimitry Andric return PreservedAnalyses::all(); 6155ffd83dbSDimitry Andric } 6165ffd83dbSDimitry Andric 6175ffd83dbSDimitry Andric // We wrap the CGSCC pipeline in a devirtualization repeater. This will try 6185ffd83dbSDimitry Andric // to detect when we devirtualize indirect calls and iterate the SCC passes 6195ffd83dbSDimitry Andric // in that case to try and catch knock-on inlining or function attrs 6205ffd83dbSDimitry Andric // opportunities. Then we add it to the module pipeline by walking the SCCs 6215ffd83dbSDimitry Andric // in postorder (or bottom-up). 6225ffd83dbSDimitry Andric // If MaxDevirtIterations is 0, we just don't use the devirtualization 6235ffd83dbSDimitry Andric // wrapper. 6245ffd83dbSDimitry Andric if (MaxDevirtIterations == 0) 6255ffd83dbSDimitry Andric MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(PM))); 6265ffd83dbSDimitry Andric else 6275ffd83dbSDimitry Andric MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor( 6285ffd83dbSDimitry Andric createDevirtSCCRepeatedPass(std::move(PM), MaxDevirtIterations))); 629349cc55cSDimitry Andric 630349cc55cSDimitry Andric MPM.addPass(std::move(AfterCGMPM)); 631fe6060f1SDimitry Andric MPM.run(M, MAM); 6325ffd83dbSDimitry Andric 633349cc55cSDimitry Andric // Discard the InlineAdvisor, a subsequent inlining session should construct 634349cc55cSDimitry Andric // its own. 635349cc55cSDimitry Andric auto PA = PreservedAnalyses::all(); 63604eeddc0SDimitry Andric if (!KeepAdvisorForPrinting) 637349cc55cSDimitry Andric PA.abandon<InlineAdvisorAnalysis>(); 638349cc55cSDimitry Andric return PA; 639349cc55cSDimitry Andric } 640fe6060f1SDimitry Andric 641349cc55cSDimitry Andric void InlinerPass::printPipeline( 642349cc55cSDimitry Andric raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) { 643349cc55cSDimitry Andric static_cast<PassInfoMixin<InlinerPass> *>(this)->printPipeline( 644349cc55cSDimitry Andric OS, MapClassName2PassName); 645349cc55cSDimitry Andric if (OnlyMandatory) 646349cc55cSDimitry Andric OS << "<only-mandatory>"; 647349cc55cSDimitry Andric } 648349cc55cSDimitry Andric 649349cc55cSDimitry Andric void ModuleInlinerWrapperPass::printPipeline( 650349cc55cSDimitry Andric raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) { 651349cc55cSDimitry Andric // Print some info about passes added to the wrapper. This is however 652349cc55cSDimitry Andric // incomplete as InlineAdvisorAnalysis part isn't included (which also depends 653349cc55cSDimitry Andric // on Params and Mode). 654349cc55cSDimitry Andric if (!MPM.isEmpty()) { 655349cc55cSDimitry Andric MPM.printPipeline(OS, MapClassName2PassName); 65606c3fb27SDimitry Andric OS << ','; 657349cc55cSDimitry Andric } 658349cc55cSDimitry Andric OS << "cgscc("; 659349cc55cSDimitry Andric if (MaxDevirtIterations != 0) 660349cc55cSDimitry Andric OS << "devirt<" << MaxDevirtIterations << ">("; 661349cc55cSDimitry Andric PM.printPipeline(OS, MapClassName2PassName); 662349cc55cSDimitry Andric if (MaxDevirtIterations != 0) 66306c3fb27SDimitry Andric OS << ')'; 66406c3fb27SDimitry Andric OS << ')'; 6655ffd83dbSDimitry Andric } 666