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