148fa355eSMircea Trofin //===- InlineAdvisor.cpp - analysis pass implementation -------------------===//
248fa355eSMircea Trofin //
3296e4773SMircea Trofin // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4296e4773SMircea Trofin // See https://llvm.org/LICENSE.txt for license information.
5296e4773SMircea Trofin // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
648fa355eSMircea Trofin //
748fa355eSMircea Trofin //===----------------------------------------------------------------------===//
848fa355eSMircea Trofin //
9d6695e18SMircea Trofin // This file implements InlineAdvisorAnalysis and DefaultInlineAdvisor, and
10d6695e18SMircea Trofin // related types.
1148fa355eSMircea Trofin //
1248fa355eSMircea Trofin //===----------------------------------------------------------------------===//
1348fa355eSMircea Trofin 
1448fa355eSMircea Trofin #include "llvm/Analysis/InlineAdvisor.h"
1548fa355eSMircea Trofin #include "llvm/ADT/Statistic.h"
1671c3a551Sserge-sans-paille #include "llvm/Analysis/AssumptionCache.h"
1748fa355eSMircea Trofin #include "llvm/Analysis/InlineCost.h"
1848fa355eSMircea Trofin #include "llvm/Analysis/OptimizationRemarkEmitter.h"
1948fa355eSMircea Trofin #include "llvm/Analysis/ProfileSummaryInfo.h"
205caad9b5Smodimo #include "llvm/Analysis/ReplayInlineAdvisor.h"
2148fa355eSMircea Trofin #include "llvm/Analysis/TargetLibraryInfo.h"
2248fa355eSMircea Trofin #include "llvm/Analysis/TargetTransformInfo.h"
2371c3a551Sserge-sans-paille #include "llvm/Analysis/Utils/ImportedFunctionsInliningStatistics.h"
247c8a6936SWenlei He #include "llvm/IR/DebugInfoMetadata.h"
253e8553aaSMircea Trofin #include "llvm/IR/PassManager.h"
26cdceef4aSSimon Pilgrim #include "llvm/Support/CommandLine.h"
2748fa355eSMircea Trofin #include "llvm/Support/raw_ostream.h"
2848fa355eSMircea Trofin 
2948fa355eSMircea Trofin using namespace llvm;
3048fa355eSMircea Trofin #define DEBUG_TYPE "inline"
31f29256a6SMircea Trofin #ifdef LLVM_HAVE_TF_AOT_INLINERSIZEMODEL
32f29256a6SMircea Trofin #define LLVM_HAVE_TF_AOT
33f29256a6SMircea Trofin #endif
3448fa355eSMircea Trofin 
3548fa355eSMircea Trofin // This weirdly named statistic tracks the number of times that, when attempting
3648fa355eSMircea Trofin // to inline a function A into B, we analyze the callers of B in order to see
3748fa355eSMircea Trofin // if those would be more profitable and blocked inline steps.
3848fa355eSMircea Trofin STATISTIC(NumCallerCallersAnalyzed, "Number of caller-callers analyzed");
3948fa355eSMircea Trofin 
4048fa355eSMircea Trofin /// Flag to add inline messages as callsite attributes 'inline-remark'.
4148fa355eSMircea Trofin static cl::opt<bool>
4248fa355eSMircea Trofin     InlineRemarkAttribute("inline-remark-attribute", cl::init(false),
4348fa355eSMircea Trofin                           cl::Hidden,
4448fa355eSMircea Trofin                           cl::desc("Enable adding inline-remark attribute to"
4548fa355eSMircea Trofin                                    " callsites processed by inliner but decided"
4648fa355eSMircea Trofin                                    " to be not inlined"));
4748fa355eSMircea Trofin 
48a8c2ba10SNikita Popov static cl::opt<bool> EnableInlineDeferral("inline-deferral", cl::init(false),
497abf299fSNikita Popov                                           cl::Hidden,
507abf299fSNikita Popov                                           cl::desc("Enable deferred inlining"));
517abf299fSNikita Popov 
5248fa355eSMircea Trofin // An integer used to limit the cost of inline deferral.  The default negative
5348fa355eSMircea Trofin // number tells shouldBeDeferred to only take the secondary cost into account.
5448fa355eSMircea Trofin static cl::opt<int>
5548fa355eSMircea Trofin     InlineDeferralScale("inline-deferral-scale",
5648fa355eSMircea Trofin                         cl::desc("Scale to limit the cost of inline deferral"),
57cec20db5SKazu Hirata                         cl::init(2), cl::Hidden);
5848fa355eSMircea Trofin 
59*30d3f56eSKazu Hirata static cl::opt<bool>
60*30d3f56eSKazu Hirata     AnnotateInlinePhase("annotate-inline-phase", cl::Hidden, cl::init(false),
61e0d06959SMingming Liu                         cl::desc("If true, annotate inline advisor remarks "
62e0d06959SMingming Liu                                  "with LTO and pass information."));
63e0d06959SMingming Liu 
64ccec2cf1SMircea Trofin extern cl::opt<InlinerFunctionImportStatsOpts> InlinerFunctionImportStats;
65ccec2cf1SMircea Trofin 
667d541eb4SMircea Trofin namespace {
677d541eb4SMircea Trofin using namespace llvm::ore;
687d541eb4SMircea Trofin class MandatoryInlineAdvice : public InlineAdvice {
697d541eb4SMircea Trofin public:
MandatoryInlineAdvice(InlineAdvisor * Advisor,CallBase & CB,OptimizationRemarkEmitter & ORE,bool IsInliningMandatory)707d541eb4SMircea Trofin   MandatoryInlineAdvice(InlineAdvisor *Advisor, CallBase &CB,
717d541eb4SMircea Trofin                         OptimizationRemarkEmitter &ORE,
727d541eb4SMircea Trofin                         bool IsInliningMandatory)
737d541eb4SMircea Trofin       : InlineAdvice(Advisor, CB, ORE, IsInliningMandatory) {}
747d541eb4SMircea Trofin 
757d541eb4SMircea Trofin private:
recordInliningWithCalleeDeletedImpl()767d541eb4SMircea Trofin   void recordInliningWithCalleeDeletedImpl() override { recordInliningImpl(); }
777d541eb4SMircea Trofin 
recordInliningImpl()787d541eb4SMircea Trofin   void recordInliningImpl() override {
797d541eb4SMircea Trofin     if (IsInliningRecommended)
807d541eb4SMircea Trofin       emitInlinedInto(ORE, DLoc, Block, *Callee, *Caller, IsInliningRecommended,
817d541eb4SMircea Trofin                       [&](OptimizationRemark &Remark) {
827d541eb4SMircea Trofin                         Remark << ": always inline attribute";
837d541eb4SMircea Trofin                       });
847d541eb4SMircea Trofin   }
857d541eb4SMircea Trofin 
recordUnsuccessfulInliningImpl(const InlineResult & Result)867d541eb4SMircea Trofin   void recordUnsuccessfulInliningImpl(const InlineResult &Result) override {
877d541eb4SMircea Trofin     if (IsInliningRecommended)
887d541eb4SMircea Trofin       ORE.emit([&]() {
898601f269SMingming Liu         return OptimizationRemarkMissed(Advisor->getAnnotatedInlinePassName(),
908601f269SMingming Liu                                         "NotInlined", DLoc, Block)
917d541eb4SMircea Trofin                << "'" << NV("Callee", Callee) << "' is not AlwaysInline into '"
927d541eb4SMircea Trofin                << NV("Caller", Caller)
937d541eb4SMircea Trofin                << "': " << NV("Reason", Result.getFailureReason());
947d541eb4SMircea Trofin       });
957d541eb4SMircea Trofin   }
967d541eb4SMircea Trofin 
recordUnattemptedInliningImpl()977d541eb4SMircea Trofin   void recordUnattemptedInliningImpl() override {
987d541eb4SMircea Trofin     assert(!IsInliningRecommended && "Expected to attempt inlining");
997d541eb4SMircea Trofin   }
1007d541eb4SMircea Trofin };
1017d541eb4SMircea Trofin } // namespace
1027d541eb4SMircea Trofin 
recordUnsuccessfulInliningImpl(const InlineResult & Result)1032a49b7c6Smodimo void DefaultInlineAdvice::recordUnsuccessfulInliningImpl(
1042a49b7c6Smodimo     const InlineResult &Result) {
105d6695e18SMircea Trofin   using namespace ore;
106d6695e18SMircea Trofin   llvm::setInlineRemark(*OriginalCB, std::string(Result.getFailureReason()) +
107d6695e18SMircea Trofin                                          "; " + inlineCostStr(*OIC));
108d6695e18SMircea Trofin   ORE.emit([&]() {
1098601f269SMingming Liu     return OptimizationRemarkMissed(Advisor->getAnnotatedInlinePassName(),
1108601f269SMingming Liu                                     "NotInlined", DLoc, Block)
11176093b17SFangrui Song            << "'" << NV("Callee", Callee) << "' is not inlined into '"
1120bb767e7SFangrui Song            << NV("Caller", Caller)
11376093b17SFangrui Song            << "': " << NV("Reason", Result.getFailureReason());
114d6695e18SMircea Trofin   });
115d6695e18SMircea Trofin }
116d6695e18SMircea Trofin 
recordInliningWithCalleeDeletedImpl()1172a49b7c6Smodimo void DefaultInlineAdvice::recordInliningWithCalleeDeletedImpl() {
1182a49b7c6Smodimo   if (EmitRemarks)
1198601f269SMingming Liu     emitInlinedIntoBasedOnCost(ORE, DLoc, Block, *Callee, *Caller, *OIC,
1208601f269SMingming Liu                                /* ForProfileContext= */ false,
1218601f269SMingming Liu                                Advisor->getAnnotatedInlinePassName());
122d6695e18SMircea Trofin }
123d6695e18SMircea Trofin 
recordInliningImpl()1242a49b7c6Smodimo void DefaultInlineAdvice::recordInliningImpl() {
1252a49b7c6Smodimo   if (EmitRemarks)
1268601f269SMingming Liu     emitInlinedIntoBasedOnCost(ORE, DLoc, Block, *Callee, *Caller, *OIC,
1278601f269SMingming Liu                                /* ForProfileContext= */ false,
1288601f269SMingming Liu                                Advisor->getAnnotatedInlinePassName());
129d6695e18SMircea Trofin }
130d6695e18SMircea Trofin 
getDefaultInlineAdvice(CallBase & CB,FunctionAnalysisManager & FAM,const InlineParams & Params)1319a0689e0SBenjamin Kramer llvm::Optional<llvm::InlineCost> static getDefaultInlineAdvice(
1329a0689e0SBenjamin Kramer     CallBase &CB, FunctionAnalysisManager &FAM, const InlineParams &Params) {
1338a2e2a6aSMircea Trofin   Function &Caller = *CB.getCaller();
1348a2e2a6aSMircea Trofin   ProfileSummaryInfo *PSI =
1358a2e2a6aSMircea Trofin       FAM.getResult<ModuleAnalysisManagerFunctionProxy>(Caller)
136d6695e18SMircea Trofin           .getCachedResult<ProfileSummaryAnalysis>(
137d6695e18SMircea Trofin               *CB.getParent()->getParent()->getParent());
138d6695e18SMircea Trofin 
1398a2e2a6aSMircea Trofin   auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(Caller);
14008e2386dSMircea Trofin   auto GetAssumptionCache = [&](Function &F) -> AssumptionCache & {
1418a2e2a6aSMircea Trofin     return FAM.getResult<AssumptionAnalysis>(F);
142d6695e18SMircea Trofin   };
143d6695e18SMircea Trofin   auto GetBFI = [&](Function &F) -> BlockFrequencyInfo & {
144d6695e18SMircea Trofin     return FAM.getResult<BlockFrequencyAnalysis>(F);
145d6695e18SMircea Trofin   };
146d6695e18SMircea Trofin   auto GetTLI = [&](Function &F) -> const TargetLibraryInfo & {
147d6695e18SMircea Trofin     return FAM.getResult<TargetLibraryAnalysis>(F);
148d6695e18SMircea Trofin   };
149d6695e18SMircea Trofin 
150d6695e18SMircea Trofin   auto GetInlineCost = [&](CallBase &CB) {
151d6695e18SMircea Trofin     Function &Callee = *CB.getCalledFunction();
152d6695e18SMircea Trofin     auto &CalleeTTI = FAM.getResult<TargetIRAnalysis>(Callee);
153d6695e18SMircea Trofin     bool RemarksEnabled =
154d6695e18SMircea Trofin         Callee.getContext().getDiagHandlerPtr()->isMissedOptRemarkEnabled(
155d6695e18SMircea Trofin             DEBUG_TYPE);
15608e2386dSMircea Trofin     return getInlineCost(CB, Params, CalleeTTI, GetAssumptionCache, GetTLI,
15708e2386dSMircea Trofin                          GetBFI, PSI, RemarksEnabled ? &ORE : nullptr);
158d6695e18SMircea Trofin   };
1597abf299fSNikita Popov   return llvm::shouldInline(
1607abf299fSNikita Popov       CB, GetInlineCost, ORE,
161129b531cSKazu Hirata       Params.EnableDeferral.value_or(EnableInlineDeferral));
16211046ef6SMircea Trofin }
16311046ef6SMircea Trofin 
164e8049dc3SMircea Trofin std::unique_ptr<InlineAdvice>
getAdviceImpl(CallBase & CB)165e8049dc3SMircea Trofin DefaultInlineAdvisor::getAdviceImpl(CallBase &CB) {
16611046ef6SMircea Trofin   auto OIC = getDefaultInlineAdvice(CB, FAM, Params);
16711046ef6SMircea Trofin   return std::make_unique<DefaultInlineAdvice>(
16811046ef6SMircea Trofin       this, CB, OIC,
16911046ef6SMircea Trofin       FAM.getResult<OptimizationRemarkEmitterAnalysis>(*CB.getCaller()));
170d6695e18SMircea Trofin }
171d6695e18SMircea Trofin 
InlineAdvice(InlineAdvisor * Advisor,CallBase & CB,OptimizationRemarkEmitter & ORE,bool IsInliningRecommended)172d6695e18SMircea Trofin InlineAdvice::InlineAdvice(InlineAdvisor *Advisor, CallBase &CB,
173e82eff7aSMircea Trofin                            OptimizationRemarkEmitter &ORE,
174d6695e18SMircea Trofin                            bool IsInliningRecommended)
175d6695e18SMircea Trofin     : Advisor(Advisor), Caller(CB.getCaller()), Callee(CB.getCalledFunction()),
176e82eff7aSMircea Trofin       DLoc(CB.getDebugLoc()), Block(CB.getParent()), ORE(ORE),
177d6695e18SMircea Trofin       IsInliningRecommended(IsInliningRecommended) {}
178d6695e18SMircea Trofin 
recordInlineStatsIfNeeded()179ccec2cf1SMircea Trofin void InlineAdvice::recordInlineStatsIfNeeded() {
180ccec2cf1SMircea Trofin   if (Advisor->ImportedFunctionsStats)
181ccec2cf1SMircea Trofin     Advisor->ImportedFunctionsStats->recordInline(*Caller, *Callee);
182ccec2cf1SMircea Trofin }
183ccec2cf1SMircea Trofin 
recordInlining()184ccec2cf1SMircea Trofin void InlineAdvice::recordInlining() {
185ccec2cf1SMircea Trofin   markRecorded();
186ccec2cf1SMircea Trofin   recordInlineStatsIfNeeded();
187ccec2cf1SMircea Trofin   recordInliningImpl();
188ccec2cf1SMircea Trofin }
189ccec2cf1SMircea Trofin 
recordInliningWithCalleeDeleted()190d6695e18SMircea Trofin void InlineAdvice::recordInliningWithCalleeDeleted() {
191d6695e18SMircea Trofin   markRecorded();
192ccec2cf1SMircea Trofin   recordInlineStatsIfNeeded();
193d6695e18SMircea Trofin   recordInliningWithCalleeDeletedImpl();
194d6695e18SMircea Trofin }
195d6695e18SMircea Trofin 
196d6695e18SMircea Trofin AnalysisKey InlineAdvisorAnalysis::Key;
197d6695e18SMircea Trofin 
tryCreate(InlineParams Params,InliningAdvisorMode Mode,const ReplayInlinerSettings & ReplaySettings,InlineContext IC)1985caad9b5Smodimo bool InlineAdvisorAnalysis::Result::tryCreate(
1995caad9b5Smodimo     InlineParams Params, InliningAdvisorMode Mode,
200e0d06959SMingming Liu     const ReplayInlinerSettings &ReplaySettings, InlineContext IC) {
201999ea25aSMircea Trofin   auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
202d6695e18SMircea Trofin   switch (Mode) {
203d6695e18SMircea Trofin   case InliningAdvisorMode::Default:
204935dea2cSMircea Trofin     LLVM_DEBUG(dbgs() << "Using default inliner heuristic.\n");
205e0d06959SMingming Liu     Advisor.reset(new DefaultInlineAdvisor(M, FAM, Params, IC));
206ce7f9cdbSmodimo     // Restrict replay to default advisor, ML advisors are stateful so
207ce7f9cdbSmodimo     // replay will need augmentations to interleave with them correctly.
2085caad9b5Smodimo     if (!ReplaySettings.ReplayFile.empty()) {
2095caad9b5Smodimo       Advisor = llvm::getReplayInlineAdvisor(M, FAM, M.getContext(),
2105caad9b5Smodimo                                              std::move(Advisor), ReplaySettings,
211e0d06959SMingming Liu                                              /* EmitRemarks =*/true, IC);
212ce7f9cdbSmodimo     }
213d6695e18SMircea Trofin     break;
214d6695e18SMircea Trofin   case InliningAdvisorMode::Development:
21570f8d0acSMircea Trofin #ifdef LLVM_HAVE_TF_API
216935dea2cSMircea Trofin     LLVM_DEBUG(dbgs() << "Using development-mode inliner policy.\n");
21770f8d0acSMircea Trofin     Advisor =
21870f8d0acSMircea Trofin         llvm::getDevelopmentModeAdvisor(M, MAM, [&FAM, Params](CallBase &CB) {
21970f8d0acSMircea Trofin           auto OIC = getDefaultInlineAdvice(CB, FAM, Params);
22070f8d0acSMircea Trofin           return OIC.hasValue();
22170f8d0acSMircea Trofin         });
22270f8d0acSMircea Trofin #endif
223d6695e18SMircea Trofin     break;
224d6695e18SMircea Trofin   case InliningAdvisorMode::Release:
225bdceefe9SMircea Trofin #ifdef LLVM_HAVE_TF_AOT
226935dea2cSMircea Trofin     LLVM_DEBUG(dbgs() << "Using release-mode inliner policy.\n");
227bdceefe9SMircea Trofin     Advisor = llvm::getReleaseModeAdvisor(M, MAM);
228bdceefe9SMircea Trofin #endif
229d6695e18SMircea Trofin     break;
230d6695e18SMircea Trofin   }
231ce7f9cdbSmodimo 
232d6695e18SMircea Trofin   return !!Advisor;
233d6695e18SMircea Trofin }
234d6695e18SMircea Trofin 
23548fa355eSMircea Trofin /// Return true if inlining of CB can block the caller from being
23648fa355eSMircea Trofin /// inlined which is proved to be more beneficial. \p IC is the
23748fa355eSMircea Trofin /// estimated inline cost associated with callsite \p CB.
23848fa355eSMircea Trofin /// \p TotalSecondaryCost will be set to the estimated cost of inlining the
23948fa355eSMircea Trofin /// caller if \p CB is suppressed for inlining.
2400205fabeSKazu Hirata static bool
shouldBeDeferred(Function * Caller,InlineCost IC,int & TotalSecondaryCost,function_ref<InlineCost (CallBase & CB)> GetInlineCost)2410205fabeSKazu Hirata shouldBeDeferred(Function *Caller, InlineCost IC, int &TotalSecondaryCost,
24248fa355eSMircea Trofin                  function_ref<InlineCost(CallBase &CB)> GetInlineCost) {
24348fa355eSMircea Trofin   // For now we only handle local or inline functions.
24448fa355eSMircea Trofin   if (!Caller->hasLocalLinkage() && !Caller->hasLinkOnceODRLinkage())
24548fa355eSMircea Trofin     return false;
24648fa355eSMircea Trofin   // If the cost of inlining CB is non-positive, it is not going to prevent the
24748fa355eSMircea Trofin   // caller from being inlined into its callers and hence we don't need to
24848fa355eSMircea Trofin   // defer.
24948fa355eSMircea Trofin   if (IC.getCost() <= 0)
25048fa355eSMircea Trofin     return false;
25148fa355eSMircea Trofin   // Try to detect the case where the current inlining candidate caller (call
25248fa355eSMircea Trofin   // it B) is a static or linkonce-ODR function and is an inlining candidate
25348fa355eSMircea Trofin   // elsewhere, and the current candidate callee (call it C) is large enough
25448fa355eSMircea Trofin   // that inlining it into B would make B too big to inline later. In these
25548fa355eSMircea Trofin   // circumstances it may be best not to inline C into B, but to inline B into
25648fa355eSMircea Trofin   // its callers.
25748fa355eSMircea Trofin   //
25848fa355eSMircea Trofin   // This only applies to static and linkonce-ODR functions because those are
25948fa355eSMircea Trofin   // expected to be available for inlining in the translation units where they
26048fa355eSMircea Trofin   // are used. Thus we will always have the opportunity to make local inlining
26148fa355eSMircea Trofin   // decisions. Importantly the linkonce-ODR linkage covers inline functions
26248fa355eSMircea Trofin   // and templates in C++.
26348fa355eSMircea Trofin   //
26448fa355eSMircea Trofin   // FIXME: All of this logic should be sunk into getInlineCost. It relies on
26548fa355eSMircea Trofin   // the internal implementation of the inline cost metrics rather than
26648fa355eSMircea Trofin   // treating them as truly abstract units etc.
26748fa355eSMircea Trofin   TotalSecondaryCost = 0;
26848fa355eSMircea Trofin   // The candidate cost to be imposed upon the current function.
26948fa355eSMircea Trofin   int CandidateCost = IC.getCost() - 1;
27048fa355eSMircea Trofin   // If the caller has local linkage and can be inlined to all its callers, we
27148fa355eSMircea Trofin   // can apply a huge negative bonus to TotalSecondaryCost.
27248fa355eSMircea Trofin   bool ApplyLastCallBonus = Caller->hasLocalLinkage() && !Caller->hasOneUse();
27348fa355eSMircea Trofin   // This bool tracks what happens if we DO inline C into B.
27448fa355eSMircea Trofin   bool InliningPreventsSomeOuterInline = false;
27548fa355eSMircea Trofin   unsigned NumCallerUsers = 0;
27648fa355eSMircea Trofin   for (User *U : Caller->users()) {
27748fa355eSMircea Trofin     CallBase *CS2 = dyn_cast<CallBase>(U);
27848fa355eSMircea Trofin 
27948fa355eSMircea Trofin     // If this isn't a call to Caller (it could be some other sort
28048fa355eSMircea Trofin     // of reference) skip it.  Such references will prevent the caller
28148fa355eSMircea Trofin     // from being removed.
28248fa355eSMircea Trofin     if (!CS2 || CS2->getCalledFunction() != Caller) {
28348fa355eSMircea Trofin       ApplyLastCallBonus = false;
28448fa355eSMircea Trofin       continue;
28548fa355eSMircea Trofin     }
28648fa355eSMircea Trofin 
28748fa355eSMircea Trofin     InlineCost IC2 = GetInlineCost(*CS2);
28848fa355eSMircea Trofin     ++NumCallerCallersAnalyzed;
28948fa355eSMircea Trofin     if (!IC2) {
29048fa355eSMircea Trofin       ApplyLastCallBonus = false;
29148fa355eSMircea Trofin       continue;
29248fa355eSMircea Trofin     }
29348fa355eSMircea Trofin     if (IC2.isAlways())
29448fa355eSMircea Trofin       continue;
29548fa355eSMircea Trofin 
29648fa355eSMircea Trofin     // See if inlining of the original callsite would erase the cost delta of
29748fa355eSMircea Trofin     // this callsite. We subtract off the penalty for the call instruction,
29848fa355eSMircea Trofin     // which we would be deleting.
29948fa355eSMircea Trofin     if (IC2.getCostDelta() <= CandidateCost) {
30048fa355eSMircea Trofin       InliningPreventsSomeOuterInline = true;
30148fa355eSMircea Trofin       TotalSecondaryCost += IC2.getCost();
30248fa355eSMircea Trofin       NumCallerUsers++;
30348fa355eSMircea Trofin     }
30448fa355eSMircea Trofin   }
30548fa355eSMircea Trofin 
30648fa355eSMircea Trofin   if (!InliningPreventsSomeOuterInline)
30748fa355eSMircea Trofin     return false;
30848fa355eSMircea Trofin 
30948fa355eSMircea Trofin   // If all outer calls to Caller would get inlined, the cost for the last
31048fa355eSMircea Trofin   // one is set very low by getInlineCost, in anticipation that Caller will
31148fa355eSMircea Trofin   // be removed entirely.  We did not account for this above unless there
31248fa355eSMircea Trofin   // is only one caller of Caller.
31348fa355eSMircea Trofin   if (ApplyLastCallBonus)
31448fa355eSMircea Trofin     TotalSecondaryCost -= InlineConstants::LastCallToStaticBonus;
31548fa355eSMircea Trofin 
31648fa355eSMircea Trofin   // If InlineDeferralScale is negative, then ignore the cost of primary
31748fa355eSMircea Trofin   // inlining -- IC.getCost() multiplied by the number of callers to Caller.
31848fa355eSMircea Trofin   if (InlineDeferralScale < 0)
31948fa355eSMircea Trofin     return TotalSecondaryCost < IC.getCost();
32048fa355eSMircea Trofin 
32148fa355eSMircea Trofin   int TotalCost = TotalSecondaryCost + IC.getCost() * NumCallerUsers;
32248fa355eSMircea Trofin   int Allowance = IC.getCost() * InlineDeferralScale;
32348fa355eSMircea Trofin   return TotalCost < Allowance;
32448fa355eSMircea Trofin }
32548fa355eSMircea Trofin 
32648fa355eSMircea Trofin namespace llvm {
operator <<(raw_ostream & R,const ore::NV & Arg)3271ce2b584Sserge-sans-paille static raw_ostream &operator<<(raw_ostream &R, const ore::NV &Arg) {
32848fa355eSMircea Trofin   return R << Arg.Val;
32948fa355eSMircea Trofin }
33048fa355eSMircea Trofin 
33148fa355eSMircea Trofin template <class RemarkT>
operator <<(RemarkT && R,const InlineCost & IC)33248fa355eSMircea Trofin RemarkT &operator<<(RemarkT &&R, const InlineCost &IC) {
33348fa355eSMircea Trofin   using namespace ore;
33448fa355eSMircea Trofin   if (IC.isAlways()) {
33548fa355eSMircea Trofin     R << "(cost=always)";
33648fa355eSMircea Trofin   } else if (IC.isNever()) {
33748fa355eSMircea Trofin     R << "(cost=never)";
33848fa355eSMircea Trofin   } else {
33948fa355eSMircea Trofin     R << "(cost=" << ore::NV("Cost", IC.getCost())
34048fa355eSMircea Trofin       << ", threshold=" << ore::NV("Threshold", IC.getThreshold()) << ")";
34148fa355eSMircea Trofin   }
34248fa355eSMircea Trofin   if (const char *Reason = IC.getReason())
34348fa355eSMircea Trofin     R << ": " << ore::NV("Reason", Reason);
34448fa355eSMircea Trofin   return R;
34548fa355eSMircea Trofin }
34648fa355eSMircea Trofin } // namespace llvm
34748fa355eSMircea Trofin 
inlineCostStr(const InlineCost & IC)34848fa355eSMircea Trofin std::string llvm::inlineCostStr(const InlineCost &IC) {
3491ce2b584Sserge-sans-paille   std::string Buffer;
3501ce2b584Sserge-sans-paille   raw_string_ostream Remark(Buffer);
35148fa355eSMircea Trofin   Remark << IC;
35248fa355eSMircea Trofin   return Remark.str();
35348fa355eSMircea Trofin }
35448fa355eSMircea Trofin 
setInlineRemark(CallBase & CB,StringRef Message)35548fa355eSMircea Trofin void llvm::setInlineRemark(CallBase &CB, StringRef Message) {
35648fa355eSMircea Trofin   if (!InlineRemarkAttribute)
35748fa355eSMircea Trofin     return;
35848fa355eSMircea Trofin 
35948fa355eSMircea Trofin   Attribute Attr = Attribute::get(CB.getContext(), "inline-remark", Message);
3603f4d00bcSArthur Eubanks   CB.addFnAttr(Attr);
36148fa355eSMircea Trofin }
36248fa355eSMircea Trofin 
36348fa355eSMircea Trofin /// Return the cost only if the inliner should attempt to inline at the given
36448fa355eSMircea Trofin /// CallSite. If we return the cost, we will emit an optimisation remark later
36548fa355eSMircea Trofin /// using that cost, so we won't do so from this function. Return None if
36648fa355eSMircea Trofin /// inlining should not be attempted.
36748fa355eSMircea Trofin Optional<InlineCost>
shouldInline(CallBase & CB,function_ref<InlineCost (CallBase & CB)> GetInlineCost,OptimizationRemarkEmitter & ORE,bool EnableDeferral)36848fa355eSMircea Trofin llvm::shouldInline(CallBase &CB,
36948fa355eSMircea Trofin                    function_ref<InlineCost(CallBase &CB)> GetInlineCost,
370347a599eSKazu Hirata                    OptimizationRemarkEmitter &ORE, bool EnableDeferral) {
37148fa355eSMircea Trofin   using namespace ore;
37248fa355eSMircea Trofin 
37348fa355eSMircea Trofin   InlineCost IC = GetInlineCost(CB);
37448fa355eSMircea Trofin   Instruction *Call = &CB;
37548fa355eSMircea Trofin   Function *Callee = CB.getCalledFunction();
37648fa355eSMircea Trofin   Function *Caller = CB.getCaller();
37748fa355eSMircea Trofin 
37848fa355eSMircea Trofin   if (IC.isAlways()) {
37948fa355eSMircea Trofin     LLVM_DEBUG(dbgs() << "    Inlining " << inlineCostStr(IC)
38048fa355eSMircea Trofin                       << ", Call: " << CB << "\n");
38148fa355eSMircea Trofin     return IC;
38248fa355eSMircea Trofin   }
38348fa355eSMircea Trofin 
38448fa355eSMircea Trofin   if (!IC) {
38548fa355eSMircea Trofin     LLVM_DEBUG(dbgs() << "    NOT Inlining " << inlineCostStr(IC)
38648fa355eSMircea Trofin                       << ", Call: " << CB << "\n");
38748fa355eSMircea Trofin     if (IC.isNever()) {
38848fa355eSMircea Trofin       ORE.emit([&]() {
38948fa355eSMircea Trofin         return OptimizationRemarkMissed(DEBUG_TYPE, "NeverInline", Call)
39076093b17SFangrui Song                << "'" << NV("Callee", Callee) << "' not inlined into '"
39176093b17SFangrui Song                << NV("Caller", Caller)
39276093b17SFangrui Song                << "' because it should never be inlined " << IC;
39348fa355eSMircea Trofin       });
39448fa355eSMircea Trofin     } else {
39548fa355eSMircea Trofin       ORE.emit([&]() {
39648fa355eSMircea Trofin         return OptimizationRemarkMissed(DEBUG_TYPE, "TooCostly", Call)
39776093b17SFangrui Song                << "'" << NV("Callee", Callee) << "' not inlined into '"
39876093b17SFangrui Song                << NV("Caller", Caller) << "' because too costly to inline "
39948fa355eSMircea Trofin                << IC;
40048fa355eSMircea Trofin       });
40148fa355eSMircea Trofin     }
40248fa355eSMircea Trofin     setInlineRemark(CB, inlineCostStr(IC));
40348fa355eSMircea Trofin     return None;
40448fa355eSMircea Trofin   }
40548fa355eSMircea Trofin 
40648fa355eSMircea Trofin   int TotalSecondaryCost = 0;
407347a599eSKazu Hirata   if (EnableDeferral &&
408347a599eSKazu Hirata       shouldBeDeferred(Caller, IC, TotalSecondaryCost, GetInlineCost)) {
40948fa355eSMircea Trofin     LLVM_DEBUG(dbgs() << "    NOT Inlining: " << CB
41048fa355eSMircea Trofin                       << " Cost = " << IC.getCost()
41148fa355eSMircea Trofin                       << ", outer Cost = " << TotalSecondaryCost << '\n');
41248fa355eSMircea Trofin     ORE.emit([&]() {
41348fa355eSMircea Trofin       return OptimizationRemarkMissed(DEBUG_TYPE, "IncreaseCostInOtherContexts",
41448fa355eSMircea Trofin                                       Call)
41576093b17SFangrui Song              << "Not inlining. Cost of inlining '" << NV("Callee", Callee)
41676093b17SFangrui Song              << "' increases the cost of inlining '" << NV("Caller", Caller)
41776093b17SFangrui Song              << "' in other contexts";
41848fa355eSMircea Trofin     });
41948fa355eSMircea Trofin     setInlineRemark(CB, "deferred");
42048fa355eSMircea Trofin     return None;
42148fa355eSMircea Trofin   }
42248fa355eSMircea Trofin 
42348fa355eSMircea Trofin   LLVM_DEBUG(dbgs() << "    Inlining " << inlineCostStr(IC) << ", Call: " << CB
42448fa355eSMircea Trofin                     << '\n');
42548fa355eSMircea Trofin   return IC;
42648fa355eSMircea Trofin }
42748fa355eSMircea Trofin 
formatCallSiteLocation(DebugLoc DLoc,const CallSiteFormat & Format)4285caad9b5Smodimo std::string llvm::formatCallSiteLocation(DebugLoc DLoc,
4295caad9b5Smodimo                                          const CallSiteFormat &Format) {
4301ce2b584Sserge-sans-paille   std::string Buffer;
4311ce2b584Sserge-sans-paille   raw_string_ostream CallSiteLoc(Buffer);
432577e58bcSWenlei He   bool First = true;
433577e58bcSWenlei He   for (DILocation *DIL = DLoc.get(); DIL; DIL = DIL->getInlinedAt()) {
434577e58bcSWenlei He     if (!First)
435577e58bcSWenlei He       CallSiteLoc << " @ ";
436577e58bcSWenlei He     // Note that negative line offset is actually possible, but we use
437577e58bcSWenlei He     // unsigned int to match line offset representation in remarks so
438577e58bcSWenlei He     // it's directly consumable by relay advisor.
439577e58bcSWenlei He     uint32_t Offset =
440577e58bcSWenlei He         DIL->getLine() - DIL->getScope()->getSubprogram()->getLine();
441577e58bcSWenlei He     uint32_t Discriminator = DIL->getBaseDiscriminator();
442577e58bcSWenlei He     StringRef Name = DIL->getScope()->getSubprogram()->getLinkageName();
443577e58bcSWenlei He     if (Name.empty())
444577e58bcSWenlei He       Name = DIL->getScope()->getSubprogram()->getName();
4455caad9b5Smodimo     CallSiteLoc << Name.str() << ":" << llvm::utostr(Offset);
4465caad9b5Smodimo     if (Format.outputColumn())
4475caad9b5Smodimo       CallSiteLoc << ":" << llvm::utostr(DIL->getColumn());
4485caad9b5Smodimo     if (Format.outputDiscriminator() && Discriminator)
449577e58bcSWenlei He       CallSiteLoc << "." << llvm::utostr(Discriminator);
450577e58bcSWenlei He     First = false;
451577e58bcSWenlei He   }
452577e58bcSWenlei He 
453577e58bcSWenlei He   return CallSiteLoc.str();
454577e58bcSWenlei He }
455577e58bcSWenlei He 
addLocationToRemarks(OptimizationRemark & Remark,DebugLoc DLoc)4567c8a6936SWenlei He void llvm::addLocationToRemarks(OptimizationRemark &Remark, DebugLoc DLoc) {
4579aa52ba5SKazu Hirata   if (!DLoc) {
4587c8a6936SWenlei He     return;
459577e58bcSWenlei He   }
4607c8a6936SWenlei He 
4617c8a6936SWenlei He   bool First = true;
4627c8a6936SWenlei He   Remark << " at callsite ";
4637c8a6936SWenlei He   for (DILocation *DIL = DLoc.get(); DIL; DIL = DIL->getInlinedAt()) {
4647c8a6936SWenlei He     if (!First)
4657c8a6936SWenlei He       Remark << " @ ";
4667c8a6936SWenlei He     unsigned int Offset = DIL->getLine();
4677c8a6936SWenlei He     Offset -= DIL->getScope()->getSubprogram()->getLine();
4687c8a6936SWenlei He     unsigned int Discriminator = DIL->getBaseDiscriminator();
4697c8a6936SWenlei He     StringRef Name = DIL->getScope()->getSubprogram()->getLinkageName();
4707c8a6936SWenlei He     if (Name.empty())
4717c8a6936SWenlei He       Name = DIL->getScope()->getSubprogram()->getName();
4722a49b7c6Smodimo     Remark << Name << ":" << ore::NV("Line", Offset) << ":"
4732a49b7c6Smodimo            << ore::NV("Column", DIL->getColumn());
4747c8a6936SWenlei He     if (Discriminator)
4757c8a6936SWenlei He       Remark << "." << ore::NV("Disc", Discriminator);
4767c8a6936SWenlei He     First = false;
4777c8a6936SWenlei He   }
4782a49b7c6Smodimo 
4792a49b7c6Smodimo   Remark << ";";
4807c8a6936SWenlei He }
4817c8a6936SWenlei He 
emitInlinedInto(OptimizationRemarkEmitter & ORE,DebugLoc DLoc,const BasicBlock * Block,const Function & Callee,const Function & Caller,bool AlwaysInline,function_ref<void (OptimizationRemark &)> ExtraContext,const char * PassName)4827d541eb4SMircea Trofin void llvm::emitInlinedInto(
4837d541eb4SMircea Trofin     OptimizationRemarkEmitter &ORE, DebugLoc DLoc, const BasicBlock *Block,
4847d541eb4SMircea Trofin     const Function &Callee, const Function &Caller, bool AlwaysInline,
4857d541eb4SMircea Trofin     function_ref<void(OptimizationRemark &)> ExtraContext,
4867d541eb4SMircea Trofin     const char *PassName) {
48748fa355eSMircea Trofin   ORE.emit([&]() {
48848fa355eSMircea Trofin     StringRef RemarkName = AlwaysInline ? "AlwaysInline" : "Inlined";
4897c8a6936SWenlei He     OptimizationRemark Remark(PassName ? PassName : DEBUG_TYPE, RemarkName,
4907c8a6936SWenlei He                               DLoc, Block);
49176093b17SFangrui Song     Remark << "'" << ore::NV("Callee", &Callee) << "' inlined into '"
49276093b17SFangrui Song            << ore::NV("Caller", &Caller) << "'";
4937d541eb4SMircea Trofin     if (ExtraContext)
4947d541eb4SMircea Trofin       ExtraContext(Remark);
4957c8a6936SWenlei He     addLocationToRemarks(Remark, DLoc);
4967c8a6936SWenlei He     return Remark;
49748fa355eSMircea Trofin   });
49848fa355eSMircea Trofin }
4995fe10263SMircea Trofin 
emitInlinedIntoBasedOnCost(OptimizationRemarkEmitter & ORE,DebugLoc DLoc,const BasicBlock * Block,const Function & Callee,const Function & Caller,const InlineCost & IC,bool ForProfileContext,const char * PassName)5007d541eb4SMircea Trofin void llvm::emitInlinedIntoBasedOnCost(
5017d541eb4SMircea Trofin     OptimizationRemarkEmitter &ORE, DebugLoc DLoc, const BasicBlock *Block,
5027d541eb4SMircea Trofin     const Function &Callee, const Function &Caller, const InlineCost &IC,
5037d541eb4SMircea Trofin     bool ForProfileContext, const char *PassName) {
5047d541eb4SMircea Trofin   llvm::emitInlinedInto(
5057d541eb4SMircea Trofin       ORE, DLoc, Block, Callee, Caller, IC.isAlways(),
5067d541eb4SMircea Trofin       [&](OptimizationRemark &Remark) {
5077d541eb4SMircea Trofin         if (ForProfileContext)
5087d541eb4SMircea Trofin           Remark << " to match profiling context";
5097d541eb4SMircea Trofin         Remark << " with " << IC;
5107d541eb4SMircea Trofin       },
5117d541eb4SMircea Trofin       PassName);
5127d541eb4SMircea Trofin }
5137d541eb4SMircea Trofin 
InlineAdvisor(Module & M,FunctionAnalysisManager & FAM,Optional<InlineContext> IC)5148601f269SMingming Liu InlineAdvisor::InlineAdvisor(Module &M, FunctionAnalysisManager &FAM,
5158601f269SMingming Liu                              Optional<InlineContext> IC)
516bc856eb3SMingming Liu     : M(M), FAM(FAM), IC(IC),
517*30d3f56eSKazu Hirata       AnnotatedInlinePassName((IC && AnnotateInlinePhase)
518*30d3f56eSKazu Hirata                                   ? llvm::AnnotateInlinePassName(*IC)
519bc856eb3SMingming Liu                                   : DEBUG_TYPE) {
520ccec2cf1SMircea Trofin   if (InlinerFunctionImportStats != InlinerFunctionImportStatsOpts::No) {
521ccec2cf1SMircea Trofin     ImportedFunctionsStats =
522ccec2cf1SMircea Trofin         std::make_unique<ImportedFunctionsInliningStatistics>();
523ccec2cf1SMircea Trofin     ImportedFunctionsStats->setModuleInfo(M);
524ccec2cf1SMircea Trofin   }
525ccec2cf1SMircea Trofin }
526ccec2cf1SMircea Trofin 
~InlineAdvisor()527ccec2cf1SMircea Trofin InlineAdvisor::~InlineAdvisor() {
528ccec2cf1SMircea Trofin   if (ImportedFunctionsStats) {
529ccec2cf1SMircea Trofin     assert(InlinerFunctionImportStats != InlinerFunctionImportStatsOpts::No);
530ccec2cf1SMircea Trofin     ImportedFunctionsStats->dump(InlinerFunctionImportStats ==
531ccec2cf1SMircea Trofin                                  InlinerFunctionImportStatsOpts::Verbose);
532ccec2cf1SMircea Trofin   }
533ccec2cf1SMircea Trofin }
534ccec2cf1SMircea Trofin 
getMandatoryAdvice(CallBase & CB,bool Advice)535e8049dc3SMircea Trofin std::unique_ptr<InlineAdvice> InlineAdvisor::getMandatoryAdvice(CallBase &CB,
536e8049dc3SMircea Trofin                                                                 bool Advice) {
5377d541eb4SMircea Trofin   return std::make_unique<MandatoryInlineAdvice>(this, CB, getCallerORE(CB),
5387d541eb4SMircea Trofin                                                  Advice);
5395fe10263SMircea Trofin }
5405fe10263SMircea Trofin 
getLTOPhase(ThinOrFullLTOPhase LTOPhase)5418601f269SMingming Liu static inline const char *getLTOPhase(ThinOrFullLTOPhase LTOPhase) {
5428601f269SMingming Liu   switch (LTOPhase) {
5438601f269SMingming Liu   case (ThinOrFullLTOPhase::None):
5448601f269SMingming Liu     return "main";
5458601f269SMingming Liu   case (ThinOrFullLTOPhase::ThinLTOPreLink):
5468601f269SMingming Liu   case (ThinOrFullLTOPhase::FullLTOPreLink):
5478601f269SMingming Liu     return "prelink";
5488601f269SMingming Liu   case (ThinOrFullLTOPhase::ThinLTOPostLink):
5498601f269SMingming Liu   case (ThinOrFullLTOPhase::FullLTOPostLink):
5508601f269SMingming Liu     return "postlink";
5518601f269SMingming Liu   }
5528601f269SMingming Liu   llvm_unreachable("unreachable");
5538601f269SMingming Liu }
5548601f269SMingming Liu 
getInlineAdvisorContext(InlinePass IP)5558601f269SMingming Liu static inline const char *getInlineAdvisorContext(InlinePass IP) {
5568601f269SMingming Liu   switch (IP) {
5578601f269SMingming Liu   case (InlinePass::AlwaysInliner):
5588601f269SMingming Liu     return "always-inline";
5598601f269SMingming Liu   case (InlinePass::CGSCCInliner):
5608601f269SMingming Liu     return "cgscc-inline";
5618601f269SMingming Liu   case (InlinePass::EarlyInliner):
5628601f269SMingming Liu     return "early-inline";
5638601f269SMingming Liu   case (InlinePass::MLInliner):
5648601f269SMingming Liu     return "ml-inline";
5658601f269SMingming Liu   case (InlinePass::ModuleInliner):
5668601f269SMingming Liu     return "module-inline";
5678601f269SMingming Liu   case (InlinePass::ReplayCGSCCInliner):
5688601f269SMingming Liu     return "replay-cgscc-inline";
5698601f269SMingming Liu   case (InlinePass::ReplaySampleProfileInliner):
5708601f269SMingming Liu     return "replay-sample-profile-inline";
5718601f269SMingming Liu   case (InlinePass::SampleProfileInliner):
5728601f269SMingming Liu     return "sample-profile-inline";
5738601f269SMingming Liu   }
5748601f269SMingming Liu 
5758601f269SMingming Liu   llvm_unreachable("unreachable");
5768601f269SMingming Liu }
5778601f269SMingming Liu 
AnnotateInlinePassName(InlineContext IC)5788601f269SMingming Liu std::string llvm::AnnotateInlinePassName(InlineContext IC) {
5798601f269SMingming Liu   return std::string(getLTOPhase(IC.LTOPhase)) + "-" +
5808601f269SMingming Liu          std::string(getInlineAdvisorContext(IC.Pass));
5818601f269SMingming Liu }
5828601f269SMingming Liu 
583e8049dc3SMircea Trofin InlineAdvisor::MandatoryInliningKind
getMandatoryKind(CallBase & CB,FunctionAnalysisManager & FAM,OptimizationRemarkEmitter & ORE)584e8049dc3SMircea Trofin InlineAdvisor::getMandatoryKind(CallBase &CB, FunctionAnalysisManager &FAM,
5855fe10263SMircea Trofin                                 OptimizationRemarkEmitter &ORE) {
5865fe10263SMircea Trofin   auto &Callee = *CB.getCalledFunction();
5875fe10263SMircea Trofin 
5885fe10263SMircea Trofin   auto GetTLI = [&](Function &F) -> const TargetLibraryInfo & {
5895fe10263SMircea Trofin     return FAM.getResult<TargetLibraryAnalysis>(F);
5905fe10263SMircea Trofin   };
5915fe10263SMircea Trofin 
5925fe10263SMircea Trofin   auto &TIR = FAM.getResult<TargetIRAnalysis>(Callee);
5935fe10263SMircea Trofin 
5945fe10263SMircea Trofin   auto TrivialDecision =
5955fe10263SMircea Trofin       llvm::getAttributeBasedInliningDecision(CB, &Callee, TIR, GetTLI);
5965fe10263SMircea Trofin 
597e0e687a6SKazu Hirata   if (TrivialDecision) {
5985fe10263SMircea Trofin     if (TrivialDecision->isSuccess())
5995fe10263SMircea Trofin       return MandatoryInliningKind::Always;
6005fe10263SMircea Trofin     else
6015fe10263SMircea Trofin       return MandatoryInliningKind::Never;
6025fe10263SMircea Trofin   }
6035fe10263SMircea Trofin   return MandatoryInliningKind::NotMandatory;
6045fe10263SMircea Trofin }
605e8049dc3SMircea Trofin 
getAdvice(CallBase & CB,bool MandatoryOnly)606e8049dc3SMircea Trofin std::unique_ptr<InlineAdvice> InlineAdvisor::getAdvice(CallBase &CB,
607e8049dc3SMircea Trofin                                                        bool MandatoryOnly) {
608e8049dc3SMircea Trofin   if (!MandatoryOnly)
609e8049dc3SMircea Trofin     return getAdviceImpl(CB);
610e8049dc3SMircea Trofin   bool Advice = CB.getCaller() != CB.getCalledFunction() &&
611e8049dc3SMircea Trofin                 MandatoryInliningKind::Always ==
612e8049dc3SMircea Trofin                     getMandatoryKind(CB, FAM, getCallerORE(CB));
613e8049dc3SMircea Trofin   return getMandatoryAdvice(CB, Advice);
614e8049dc3SMircea Trofin }
615e8049dc3SMircea Trofin 
getCallerORE(CallBase & CB)616e8049dc3SMircea Trofin OptimizationRemarkEmitter &InlineAdvisor::getCallerORE(CallBase &CB) {
617e8049dc3SMircea Trofin   return FAM.getResult<OptimizationRemarkEmitterAnalysis>(*CB.getCaller());
618e8049dc3SMircea Trofin }
6193e8553aaSMircea Trofin 
6203e8553aaSMircea Trofin PreservedAnalyses
run(Module & M,ModuleAnalysisManager & MAM)6213e8553aaSMircea Trofin InlineAdvisorAnalysisPrinterPass::run(Module &M, ModuleAnalysisManager &MAM) {
6223e8553aaSMircea Trofin   const auto *IA = MAM.getCachedResult<InlineAdvisorAnalysis>(M);
6233e8553aaSMircea Trofin   if (!IA)
6243e8553aaSMircea Trofin     OS << "No Inline Advisor\n";
6253e8553aaSMircea Trofin   else
6263e8553aaSMircea Trofin     IA->getAdvisor()->print(OS);
6273e8553aaSMircea Trofin   return PreservedAnalyses::all();
6283e8553aaSMircea Trofin }
6299f2b873aSJin Xin Ng 
run(LazyCallGraph::SCC & InitialC,CGSCCAnalysisManager & AM,LazyCallGraph & CG,CGSCCUpdateResult & UR)6309f2b873aSJin Xin Ng PreservedAnalyses InlineAdvisorAnalysisPrinterPass::run(
6319f2b873aSJin Xin Ng     LazyCallGraph::SCC &InitialC, CGSCCAnalysisManager &AM, LazyCallGraph &CG,
6329f2b873aSJin Xin Ng     CGSCCUpdateResult &UR) {
6339f2b873aSJin Xin Ng   const auto &MAMProxy =
6349f2b873aSJin Xin Ng       AM.getResult<ModuleAnalysisManagerCGSCCProxy>(InitialC, CG);
6359f2b873aSJin Xin Ng 
6369f2b873aSJin Xin Ng   if (InitialC.size() == 0) {
6379f2b873aSJin Xin Ng     OS << "SCC is empty!\n";
6389f2b873aSJin Xin Ng     return PreservedAnalyses::all();
6399f2b873aSJin Xin Ng   }
6409f2b873aSJin Xin Ng   Module &M = *InitialC.begin()->getFunction().getParent();
6419f2b873aSJin Xin Ng   const auto *IA = MAMProxy.getCachedResult<InlineAdvisorAnalysis>(M);
6429f2b873aSJin Xin Ng   if (!IA)
6439f2b873aSJin Xin Ng     OS << "No Inline Advisor\n";
6449f2b873aSJin Xin Ng   else
6459f2b873aSJin Xin Ng     IA->getAdvisor()->print(OS);
6469f2b873aSJin Xin Ng   return PreservedAnalyses::all();
6479f2b873aSJin Xin Ng }
648