]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/llvm/lib/Analysis/InlineAdvisor.cpp
Merge llvm-project main llvmorg-14-init-10186-gff7f2cfa959b
[FreeBSD/FreeBSD.git] / contrib / llvm-project / llvm / lib / Analysis / InlineAdvisor.cpp
1 //===- InlineAdvisor.cpp - analysis pass implementation -------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements InlineAdvisorAnalysis and DefaultInlineAdvisor, and
10 // related types.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/Analysis/InlineAdvisor.h"
15 #include "llvm/ADT/Statistic.h"
16 #include "llvm/Analysis/InlineCost.h"
17 #include "llvm/Analysis/OptimizationRemarkEmitter.h"
18 #include "llvm/Analysis/ProfileSummaryInfo.h"
19 #include "llvm/Analysis/ReplayInlineAdvisor.h"
20 #include "llvm/Analysis/TargetLibraryInfo.h"
21 #include "llvm/Analysis/TargetTransformInfo.h"
22 #include "llvm/IR/DebugInfoMetadata.h"
23 #include "llvm/IR/Instructions.h"
24 #include "llvm/Support/CommandLine.h"
25 #include "llvm/Support/raw_ostream.h"
26
27 using namespace llvm;
28 #define DEBUG_TYPE "inline"
29
30 // This weirdly named statistic tracks the number of times that, when attempting
31 // to inline a function A into B, we analyze the callers of B in order to see
32 // if those would be more profitable and blocked inline steps.
33 STATISTIC(NumCallerCallersAnalyzed, "Number of caller-callers analyzed");
34
35 /// Flag to add inline messages as callsite attributes 'inline-remark'.
36 static cl::opt<bool>
37     InlineRemarkAttribute("inline-remark-attribute", cl::init(false),
38                           cl::Hidden,
39                           cl::desc("Enable adding inline-remark attribute to"
40                                    " callsites processed by inliner but decided"
41                                    " to be not inlined"));
42
43 // An integer used to limit the cost of inline deferral.  The default negative
44 // number tells shouldBeDeferred to only take the secondary cost into account.
45 static cl::opt<int>
46     InlineDeferralScale("inline-deferral-scale",
47                         cl::desc("Scale to limit the cost of inline deferral"),
48                         cl::init(2), cl::Hidden);
49
50 extern cl::opt<InlinerFunctionImportStatsOpts> InlinerFunctionImportStats;
51
52 namespace {
53 using namespace llvm::ore;
54 class MandatoryInlineAdvice : public InlineAdvice {
55 public:
56   MandatoryInlineAdvice(InlineAdvisor *Advisor, CallBase &CB,
57                         OptimizationRemarkEmitter &ORE,
58                         bool IsInliningMandatory)
59       : InlineAdvice(Advisor, CB, ORE, IsInliningMandatory) {}
60
61 private:
62   void recordInliningWithCalleeDeletedImpl() override { recordInliningImpl(); }
63
64   void recordInliningImpl() override {
65     if (IsInliningRecommended)
66       emitInlinedInto(ORE, DLoc, Block, *Callee, *Caller, IsInliningRecommended,
67                       [&](OptimizationRemark &Remark) {
68                         Remark << ": always inline attribute";
69                       });
70   }
71
72   void recordUnsuccessfulInliningImpl(const InlineResult &Result) override {
73     if (IsInliningRecommended)
74       ORE.emit([&]() {
75         return OptimizationRemarkMissed(DEBUG_TYPE, "NotInlined", DLoc, Block)
76                << "'" << NV("Callee", Callee) << "' is not AlwaysInline into '"
77                << NV("Caller", Caller)
78                << "': " << NV("Reason", Result.getFailureReason());
79       });
80   }
81
82   void recordUnattemptedInliningImpl() override {
83     assert(!IsInliningRecommended && "Expected to attempt inlining");
84   }
85 };
86 } // namespace
87
88 void DefaultInlineAdvice::recordUnsuccessfulInliningImpl(
89     const InlineResult &Result) {
90   using namespace ore;
91   llvm::setInlineRemark(*OriginalCB, std::string(Result.getFailureReason()) +
92                                          "; " + inlineCostStr(*OIC));
93   ORE.emit([&]() {
94     return OptimizationRemarkMissed(DEBUG_TYPE, "NotInlined", DLoc, Block)
95            << "'" << NV("Callee", Callee) << "' is not inlined into '"
96            << NV("Caller", Caller)
97            << "': " << NV("Reason", Result.getFailureReason());
98   });
99 }
100
101 void DefaultInlineAdvice::recordInliningWithCalleeDeletedImpl() {
102   if (EmitRemarks)
103     emitInlinedIntoBasedOnCost(ORE, DLoc, Block, *Callee, *Caller, *OIC);
104 }
105
106 void DefaultInlineAdvice::recordInliningImpl() {
107   if (EmitRemarks)
108     emitInlinedIntoBasedOnCost(ORE, DLoc, Block, *Callee, *Caller, *OIC);
109 }
110
111 llvm::Optional<llvm::InlineCost> static getDefaultInlineAdvice(
112     CallBase &CB, FunctionAnalysisManager &FAM, const InlineParams &Params) {
113   Function &Caller = *CB.getCaller();
114   ProfileSummaryInfo *PSI =
115       FAM.getResult<ModuleAnalysisManagerFunctionProxy>(Caller)
116           .getCachedResult<ProfileSummaryAnalysis>(
117               *CB.getParent()->getParent()->getParent());
118
119   auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(Caller);
120   auto GetAssumptionCache = [&](Function &F) -> AssumptionCache & {
121     return FAM.getResult<AssumptionAnalysis>(F);
122   };
123   auto GetBFI = [&](Function &F) -> BlockFrequencyInfo & {
124     return FAM.getResult<BlockFrequencyAnalysis>(F);
125   };
126   auto GetTLI = [&](Function &F) -> const TargetLibraryInfo & {
127     return FAM.getResult<TargetLibraryAnalysis>(F);
128   };
129
130   auto GetInlineCost = [&](CallBase &CB) {
131     Function &Callee = *CB.getCalledFunction();
132     auto &CalleeTTI = FAM.getResult<TargetIRAnalysis>(Callee);
133     bool RemarksEnabled =
134         Callee.getContext().getDiagHandlerPtr()->isMissedOptRemarkEnabled(
135             DEBUG_TYPE);
136     return getInlineCost(CB, Params, CalleeTTI, GetAssumptionCache, GetTLI,
137                          GetBFI, PSI, RemarksEnabled ? &ORE : nullptr);
138   };
139   return llvm::shouldInline(CB, GetInlineCost, ORE,
140                             Params.EnableDeferral.getValueOr(false));
141 }
142
143 std::unique_ptr<InlineAdvice>
144 DefaultInlineAdvisor::getAdviceImpl(CallBase &CB) {
145   auto OIC = getDefaultInlineAdvice(CB, FAM, Params);
146   return std::make_unique<DefaultInlineAdvice>(
147       this, CB, OIC,
148       FAM.getResult<OptimizationRemarkEmitterAnalysis>(*CB.getCaller()));
149 }
150
151 InlineAdvice::InlineAdvice(InlineAdvisor *Advisor, CallBase &CB,
152                            OptimizationRemarkEmitter &ORE,
153                            bool IsInliningRecommended)
154     : Advisor(Advisor), Caller(CB.getCaller()), Callee(CB.getCalledFunction()),
155       DLoc(CB.getDebugLoc()), Block(CB.getParent()), ORE(ORE),
156       IsInliningRecommended(IsInliningRecommended) {}
157
158 void InlineAdvisor::markFunctionAsDeleted(Function *F) {
159   assert((!DeletedFunctions.count(F)) &&
160          "Cannot put cause a function to become dead twice!");
161   DeletedFunctions.insert(F);
162 }
163
164 void InlineAdvisor::freeDeletedFunctions() {
165   for (auto *F : DeletedFunctions)
166     delete F;
167   DeletedFunctions.clear();
168 }
169
170 void InlineAdvice::recordInlineStatsIfNeeded() {
171   if (Advisor->ImportedFunctionsStats)
172     Advisor->ImportedFunctionsStats->recordInline(*Caller, *Callee);
173 }
174
175 void InlineAdvice::recordInlining() {
176   markRecorded();
177   recordInlineStatsIfNeeded();
178   recordInliningImpl();
179 }
180
181 void InlineAdvice::recordInliningWithCalleeDeleted() {
182   markRecorded();
183   recordInlineStatsIfNeeded();
184   Advisor->markFunctionAsDeleted(Callee);
185   recordInliningWithCalleeDeletedImpl();
186 }
187
188 AnalysisKey InlineAdvisorAnalysis::Key;
189
190 bool InlineAdvisorAnalysis::Result::tryCreate(
191     InlineParams Params, InliningAdvisorMode Mode,
192     const ReplayInlinerSettings &ReplaySettings) {
193   auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
194   switch (Mode) {
195   case InliningAdvisorMode::Default:
196     LLVM_DEBUG(dbgs() << "Using default inliner heuristic.\n");
197     Advisor.reset(new DefaultInlineAdvisor(M, FAM, Params));
198     // Restrict replay to default advisor, ML advisors are stateful so
199     // replay will need augmentations to interleave with them correctly.
200     if (!ReplaySettings.ReplayFile.empty()) {
201       Advisor = llvm::getReplayInlineAdvisor(M, FAM, M.getContext(),
202                                              std::move(Advisor), ReplaySettings,
203                                              /* EmitRemarks =*/true);
204     }
205     break;
206   case InliningAdvisorMode::Development:
207 #ifdef LLVM_HAVE_TF_API
208     LLVM_DEBUG(dbgs() << "Using development-mode inliner policy.\n");
209     Advisor =
210         llvm::getDevelopmentModeAdvisor(M, MAM, [&FAM, Params](CallBase &CB) {
211           auto OIC = getDefaultInlineAdvice(CB, FAM, Params);
212           return OIC.hasValue();
213         });
214 #endif
215     break;
216   case InliningAdvisorMode::Release:
217 #ifdef LLVM_HAVE_TF_AOT
218     LLVM_DEBUG(dbgs() << "Using release-mode inliner policy.\n");
219     Advisor = llvm::getReleaseModeAdvisor(M, MAM);
220 #endif
221     break;
222   }
223
224   return !!Advisor;
225 }
226
227 /// Return true if inlining of CB can block the caller from being
228 /// inlined which is proved to be more beneficial. \p IC is the
229 /// estimated inline cost associated with callsite \p CB.
230 /// \p TotalSecondaryCost will be set to the estimated cost of inlining the
231 /// caller if \p CB is suppressed for inlining.
232 static bool
233 shouldBeDeferred(Function *Caller, InlineCost IC, int &TotalSecondaryCost,
234                  function_ref<InlineCost(CallBase &CB)> GetInlineCost) {
235   // For now we only handle local or inline functions.
236   if (!Caller->hasLocalLinkage() && !Caller->hasLinkOnceODRLinkage())
237     return false;
238   // If the cost of inlining CB is non-positive, it is not going to prevent the
239   // caller from being inlined into its callers and hence we don't need to
240   // defer.
241   if (IC.getCost() <= 0)
242     return false;
243   // Try to detect the case where the current inlining candidate caller (call
244   // it B) is a static or linkonce-ODR function and is an inlining candidate
245   // elsewhere, and the current candidate callee (call it C) is large enough
246   // that inlining it into B would make B too big to inline later. In these
247   // circumstances it may be best not to inline C into B, but to inline B into
248   // its callers.
249   //
250   // This only applies to static and linkonce-ODR functions because those are
251   // expected to be available for inlining in the translation units where they
252   // are used. Thus we will always have the opportunity to make local inlining
253   // decisions. Importantly the linkonce-ODR linkage covers inline functions
254   // and templates in C++.
255   //
256   // FIXME: All of this logic should be sunk into getInlineCost. It relies on
257   // the internal implementation of the inline cost metrics rather than
258   // treating them as truly abstract units etc.
259   TotalSecondaryCost = 0;
260   // The candidate cost to be imposed upon the current function.
261   int CandidateCost = IC.getCost() - 1;
262   // If the caller has local linkage and can be inlined to all its callers, we
263   // can apply a huge negative bonus to TotalSecondaryCost.
264   bool ApplyLastCallBonus = Caller->hasLocalLinkage() && !Caller->hasOneUse();
265   // This bool tracks what happens if we DO inline C into B.
266   bool InliningPreventsSomeOuterInline = false;
267   unsigned NumCallerUsers = 0;
268   for (User *U : Caller->users()) {
269     CallBase *CS2 = dyn_cast<CallBase>(U);
270
271     // If this isn't a call to Caller (it could be some other sort
272     // of reference) skip it.  Such references will prevent the caller
273     // from being removed.
274     if (!CS2 || CS2->getCalledFunction() != Caller) {
275       ApplyLastCallBonus = false;
276       continue;
277     }
278
279     InlineCost IC2 = GetInlineCost(*CS2);
280     ++NumCallerCallersAnalyzed;
281     if (!IC2) {
282       ApplyLastCallBonus = false;
283       continue;
284     }
285     if (IC2.isAlways())
286       continue;
287
288     // See if inlining of the original callsite would erase the cost delta of
289     // this callsite. We subtract off the penalty for the call instruction,
290     // which we would be deleting.
291     if (IC2.getCostDelta() <= CandidateCost) {
292       InliningPreventsSomeOuterInline = true;
293       TotalSecondaryCost += IC2.getCost();
294       NumCallerUsers++;
295     }
296   }
297
298   if (!InliningPreventsSomeOuterInline)
299     return false;
300
301   // If all outer calls to Caller would get inlined, the cost for the last
302   // one is set very low by getInlineCost, in anticipation that Caller will
303   // be removed entirely.  We did not account for this above unless there
304   // is only one caller of Caller.
305   if (ApplyLastCallBonus)
306     TotalSecondaryCost -= InlineConstants::LastCallToStaticBonus;
307
308   // If InlineDeferralScale is negative, then ignore the cost of primary
309   // inlining -- IC.getCost() multiplied by the number of callers to Caller.
310   if (InlineDeferralScale < 0)
311     return TotalSecondaryCost < IC.getCost();
312
313   int TotalCost = TotalSecondaryCost + IC.getCost() * NumCallerUsers;
314   int Allowance = IC.getCost() * InlineDeferralScale;
315   return TotalCost < Allowance;
316 }
317
318 namespace llvm {
319 static raw_ostream &operator<<(raw_ostream &R, const ore::NV &Arg) {
320   return R << Arg.Val;
321 }
322
323 template <class RemarkT>
324 RemarkT &operator<<(RemarkT &&R, const InlineCost &IC) {
325   using namespace ore;
326   if (IC.isAlways()) {
327     R << "(cost=always)";
328   } else if (IC.isNever()) {
329     R << "(cost=never)";
330   } else {
331     R << "(cost=" << ore::NV("Cost", IC.getCost())
332       << ", threshold=" << ore::NV("Threshold", IC.getThreshold()) << ")";
333   }
334   if (const char *Reason = IC.getReason())
335     R << ": " << ore::NV("Reason", Reason);
336   return R;
337 }
338 } // namespace llvm
339
340 std::string llvm::inlineCostStr(const InlineCost &IC) {
341   std::string Buffer;
342   raw_string_ostream Remark(Buffer);
343   Remark << IC;
344   return Remark.str();
345 }
346
347 void llvm::setInlineRemark(CallBase &CB, StringRef Message) {
348   if (!InlineRemarkAttribute)
349     return;
350
351   Attribute Attr = Attribute::get(CB.getContext(), "inline-remark", Message);
352   CB.addFnAttr(Attr);
353 }
354
355 /// Return the cost only if the inliner should attempt to inline at the given
356 /// CallSite. If we return the cost, we will emit an optimisation remark later
357 /// using that cost, so we won't do so from this function. Return None if
358 /// inlining should not be attempted.
359 Optional<InlineCost>
360 llvm::shouldInline(CallBase &CB,
361                    function_ref<InlineCost(CallBase &CB)> GetInlineCost,
362                    OptimizationRemarkEmitter &ORE, bool EnableDeferral) {
363   using namespace ore;
364
365   InlineCost IC = GetInlineCost(CB);
366   Instruction *Call = &CB;
367   Function *Callee = CB.getCalledFunction();
368   Function *Caller = CB.getCaller();
369
370   if (IC.isAlways()) {
371     LLVM_DEBUG(dbgs() << "    Inlining " << inlineCostStr(IC)
372                       << ", Call: " << CB << "\n");
373     return IC;
374   }
375
376   if (!IC) {
377     LLVM_DEBUG(dbgs() << "    NOT Inlining " << inlineCostStr(IC)
378                       << ", Call: " << CB << "\n");
379     if (IC.isNever()) {
380       ORE.emit([&]() {
381         return OptimizationRemarkMissed(DEBUG_TYPE, "NeverInline", Call)
382                << "'" << NV("Callee", Callee) << "' not inlined into '"
383                << NV("Caller", Caller)
384                << "' because it should never be inlined " << IC;
385       });
386     } else {
387       ORE.emit([&]() {
388         return OptimizationRemarkMissed(DEBUG_TYPE, "TooCostly", Call)
389                << "'" << NV("Callee", Callee) << "' not inlined into '"
390                << NV("Caller", Caller) << "' because too costly to inline "
391                << IC;
392       });
393     }
394     setInlineRemark(CB, inlineCostStr(IC));
395     return None;
396   }
397
398   int TotalSecondaryCost = 0;
399   if (EnableDeferral &&
400       shouldBeDeferred(Caller, IC, TotalSecondaryCost, GetInlineCost)) {
401     LLVM_DEBUG(dbgs() << "    NOT Inlining: " << CB
402                       << " Cost = " << IC.getCost()
403                       << ", outer Cost = " << TotalSecondaryCost << '\n');
404     ORE.emit([&]() {
405       return OptimizationRemarkMissed(DEBUG_TYPE, "IncreaseCostInOtherContexts",
406                                       Call)
407              << "Not inlining. Cost of inlining '" << NV("Callee", Callee)
408              << "' increases the cost of inlining '" << NV("Caller", Caller)
409              << "' in other contexts";
410     });
411     setInlineRemark(CB, "deferred");
412     // IC does not bool() to false, so get an InlineCost that will.
413     // This will not be inspected to make an error message.
414     return None;
415   }
416
417   LLVM_DEBUG(dbgs() << "    Inlining " << inlineCostStr(IC) << ", Call: " << CB
418                     << '\n');
419   return IC;
420 }
421
422 std::string llvm::formatCallSiteLocation(DebugLoc DLoc,
423                                          const CallSiteFormat &Format) {
424   std::string Buffer;
425   raw_string_ostream CallSiteLoc(Buffer);
426   bool First = true;
427   for (DILocation *DIL = DLoc.get(); DIL; DIL = DIL->getInlinedAt()) {
428     if (!First)
429       CallSiteLoc << " @ ";
430     // Note that negative line offset is actually possible, but we use
431     // unsigned int to match line offset representation in remarks so
432     // it's directly consumable by relay advisor.
433     uint32_t Offset =
434         DIL->getLine() - DIL->getScope()->getSubprogram()->getLine();
435     uint32_t Discriminator = DIL->getBaseDiscriminator();
436     StringRef Name = DIL->getScope()->getSubprogram()->getLinkageName();
437     if (Name.empty())
438       Name = DIL->getScope()->getSubprogram()->getName();
439     CallSiteLoc << Name.str() << ":" << llvm::utostr(Offset);
440     if (Format.outputColumn())
441       CallSiteLoc << ":" << llvm::utostr(DIL->getColumn());
442     if (Format.outputDiscriminator() && Discriminator)
443       CallSiteLoc << "." << llvm::utostr(Discriminator);
444     First = false;
445   }
446
447   return CallSiteLoc.str();
448 }
449
450 void llvm::addLocationToRemarks(OptimizationRemark &Remark, DebugLoc DLoc) {
451   if (!DLoc.get()) {
452     return;
453   }
454
455   bool First = true;
456   Remark << " at callsite ";
457   for (DILocation *DIL = DLoc.get(); DIL; DIL = DIL->getInlinedAt()) {
458     if (!First)
459       Remark << " @ ";
460     unsigned int Offset = DIL->getLine();
461     Offset -= DIL->getScope()->getSubprogram()->getLine();
462     unsigned int Discriminator = DIL->getBaseDiscriminator();
463     StringRef Name = DIL->getScope()->getSubprogram()->getLinkageName();
464     if (Name.empty())
465       Name = DIL->getScope()->getSubprogram()->getName();
466     Remark << Name << ":" << ore::NV("Line", Offset) << ":"
467            << ore::NV("Column", DIL->getColumn());
468     if (Discriminator)
469       Remark << "." << ore::NV("Disc", Discriminator);
470     First = false;
471   }
472
473   Remark << ";";
474 }
475
476 void llvm::emitInlinedInto(
477     OptimizationRemarkEmitter &ORE, DebugLoc DLoc, const BasicBlock *Block,
478     const Function &Callee, const Function &Caller, bool AlwaysInline,
479     function_ref<void(OptimizationRemark &)> ExtraContext,
480     const char *PassName) {
481   ORE.emit([&]() {
482     StringRef RemarkName = AlwaysInline ? "AlwaysInline" : "Inlined";
483     OptimizationRemark Remark(PassName ? PassName : DEBUG_TYPE, RemarkName,
484                               DLoc, Block);
485     Remark << "'" << ore::NV("Callee", &Callee) << "' inlined into '"
486            << ore::NV("Caller", &Caller) << "'";
487     if (ExtraContext)
488       ExtraContext(Remark);
489     addLocationToRemarks(Remark, DLoc);
490     return Remark;
491   });
492 }
493
494 void llvm::emitInlinedIntoBasedOnCost(
495     OptimizationRemarkEmitter &ORE, DebugLoc DLoc, const BasicBlock *Block,
496     const Function &Callee, const Function &Caller, const InlineCost &IC,
497     bool ForProfileContext, const char *PassName) {
498   llvm::emitInlinedInto(
499       ORE, DLoc, Block, Callee, Caller, IC.isAlways(),
500       [&](OptimizationRemark &Remark) {
501         if (ForProfileContext)
502           Remark << " to match profiling context";
503         Remark << " with " << IC;
504       },
505       PassName);
506 }
507
508 InlineAdvisor::InlineAdvisor(Module &M, FunctionAnalysisManager &FAM)
509     : M(M), FAM(FAM) {
510   if (InlinerFunctionImportStats != InlinerFunctionImportStatsOpts::No) {
511     ImportedFunctionsStats =
512         std::make_unique<ImportedFunctionsInliningStatistics>();
513     ImportedFunctionsStats->setModuleInfo(M);
514   }
515 }
516
517 InlineAdvisor::~InlineAdvisor() {
518   if (ImportedFunctionsStats) {
519     assert(InlinerFunctionImportStats != InlinerFunctionImportStatsOpts::No);
520     ImportedFunctionsStats->dump(InlinerFunctionImportStats ==
521                                  InlinerFunctionImportStatsOpts::Verbose);
522   }
523
524   freeDeletedFunctions();
525 }
526
527 std::unique_ptr<InlineAdvice> InlineAdvisor::getMandatoryAdvice(CallBase &CB,
528                                                                 bool Advice) {
529   return std::make_unique<MandatoryInlineAdvice>(this, CB, getCallerORE(CB),
530                                                  Advice);
531 }
532
533 InlineAdvisor::MandatoryInliningKind
534 InlineAdvisor::getMandatoryKind(CallBase &CB, FunctionAnalysisManager &FAM,
535                                 OptimizationRemarkEmitter &ORE) {
536   auto &Callee = *CB.getCalledFunction();
537
538   auto GetTLI = [&](Function &F) -> const TargetLibraryInfo & {
539     return FAM.getResult<TargetLibraryAnalysis>(F);
540   };
541
542   auto &TIR = FAM.getResult<TargetIRAnalysis>(Callee);
543
544   auto TrivialDecision =
545       llvm::getAttributeBasedInliningDecision(CB, &Callee, TIR, GetTLI);
546
547   if (TrivialDecision.hasValue()) {
548     if (TrivialDecision->isSuccess())
549       return MandatoryInliningKind::Always;
550     else
551       return MandatoryInliningKind::Never;
552   }
553   return MandatoryInliningKind::NotMandatory;
554 }
555
556 std::unique_ptr<InlineAdvice> InlineAdvisor::getAdvice(CallBase &CB,
557                                                        bool MandatoryOnly) {
558   if (!MandatoryOnly)
559     return getAdviceImpl(CB);
560   bool Advice = CB.getCaller() != CB.getCalledFunction() &&
561                 MandatoryInliningKind::Always ==
562                     getMandatoryKind(CB, FAM, getCallerORE(CB));
563   return getMandatoryAdvice(CB, Advice);
564 }
565
566 OptimizationRemarkEmitter &InlineAdvisor::getCallerORE(CallBase &CB) {
567   return FAM.getResult<OptimizationRemarkEmitterAnalysis>(*CB.getCaller());
568 }