LLVM 22.0.0git
InlineAdvisor.cpp
Go to the documentation of this file.
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
15#include "llvm/ADT/Statistic.h"
28#include "llvm/IR/Module.h"
29#include "llvm/IR/PassManager.h"
32
33using namespace llvm;
34#define DEBUG_TYPE "inline"
35#ifdef LLVM_HAVE_TF_AOT_INLINERSIZEMODEL
36#define LLVM_HAVE_TF_AOT
37#endif
38
39// This weirdly named statistic tracks the number of times that, when attempting
40// to inline a function A into B, we analyze the callers of B in order to see
41// if those would be more profitable and blocked inline steps.
42STATISTIC(NumCallerCallersAnalyzed, "Number of caller-callers analyzed");
43
44/// Flag to add inline messages as callsite attributes 'inline-remark'.
45static cl::opt<bool>
46 InlineRemarkAttribute("inline-remark-attribute", cl::init(false),
48 cl::desc("Enable adding inline-remark attribute to"
49 " callsites processed by inliner but decided"
50 " to be not inlined"));
51
52static cl::opt<bool> EnableInlineDeferral("inline-deferral", cl::init(false),
54 cl::desc("Enable deferred inlining"));
55
56// An integer used to limit the cost of inline deferral. The default negative
57// number tells shouldBeDeferred to only take the secondary cost into account.
58static cl::opt<int>
59 InlineDeferralScale("inline-deferral-scale",
60 cl::desc("Scale to limit the cost of inline deferral"),
62
63static cl::opt<bool>
64 AnnotateInlinePhase("annotate-inline-phase", cl::Hidden, cl::init(false),
65 cl::desc("If true, annotate inline advisor remarks "
66 "with LTO and pass information."));
67
68// This flag is used to enable IR2Vec embeddings in the ML inliner; Only valid
69// with ML inliner. The vocab file is used to initialize the embeddings.
71 "ml-inliner-ir2vec-vocab-file", cl::Hidden,
72 cl::desc("Vocab file for IR2Vec; Setting this enables "
73 "configuring the model to use IR2Vec embeddings."));
74
75namespace llvm {
77} // namespace llvm
78
79namespace {
80using namespace llvm::ore;
81class MandatoryInlineAdvice : public InlineAdvice {
82public:
83 MandatoryInlineAdvice(InlineAdvisor *Advisor, CallBase &CB,
85 bool IsInliningMandatory)
86 : InlineAdvice(Advisor, CB, ORE, IsInliningMandatory) {}
87
88private:
90
91 void recordInliningImpl() override {
92 if (IsInliningRecommended)
93 emitInlinedInto(ORE, DLoc, Block, *Callee, *Caller, IsInliningRecommended,
95 Remark << ": always inline attribute";
96 });
97 }
98
99 void recordUnsuccessfulInliningImpl(const InlineResult &Result) override {
100 if (IsInliningRecommended)
101 ORE.emit([&]() {
103 "NotInlined", DLoc, Block)
104 << "'" << NV("Callee", Callee) << "' is not AlwaysInline into '"
105 << NV("Caller", Caller)
106 << "': " << NV("Reason", Result.getFailureReason());
107 });
108 }
109
110 void recordUnattemptedInliningImpl() override {
111 assert(!IsInliningRecommended && "Expected to attempt inlining");
112 }
113};
114} // namespace
115
116void DefaultInlineAdvice::recordUnsuccessfulInliningImpl(
117 const InlineResult &Result) {
118 using namespace ore;
119 llvm::setInlineRemark(*OriginalCB, std::string(Result.getFailureReason()) +
120 "; " + inlineCostStr(*OIC));
121 ORE.emit([&]() {
123 "NotInlined", DLoc, Block)
124 << "'" << NV("Callee", Callee) << "' is not inlined into '"
125 << NV("Caller", Caller)
126 << "': " << NV("Reason", Result.getFailureReason());
127 });
128}
129
130void DefaultInlineAdvice::recordInliningWithCalleeDeletedImpl() {
131 if (EmitRemarks)
133 /* ForProfileContext= */ false,
135}
136
137void DefaultInlineAdvice::recordInliningImpl() {
138 if (EmitRemarks)
140 /* ForProfileContext= */ false,
142}
143
144std::optional<llvm::InlineCost> static getDefaultInlineAdvice(
145 CallBase &CB, FunctionAnalysisManager &FAM, const InlineParams &Params) {
146 Function &Caller = *CB.getCaller();
147 ProfileSummaryInfo *PSI =
149 .getCachedResult<ProfileSummaryAnalysis>(
150 *CB.getParent()->getParent()->getParent());
151
153 auto GetAssumptionCache = [&](Function &F) -> AssumptionCache & {
155 };
156 auto GetBFI = [&](Function &F) -> BlockFrequencyInfo & {
158 };
159 auto GetTLI = [&](Function &F) -> const TargetLibraryInfo & {
161 };
162 auto GetEphValuesCache =
165 };
166
167 Function &Callee = *CB.getCalledFunction();
168 auto &CalleeTTI = FAM.getResult<TargetIRAnalysis>(Callee);
169 auto GetInlineCost = [&](CallBase &CB) {
170 bool RemarksEnabled =
171 Callee.getContext().getDiagHandlerPtr()->isMissedOptRemarkEnabled(
172 DEBUG_TYPE);
173 return getInlineCost(CB, Params, CalleeTTI, GetAssumptionCache, GetTLI,
174 GetBFI, PSI, RemarksEnabled ? &ORE : nullptr,
175 GetEphValuesCache);
176 };
177 return llvm::shouldInline(
178 CB, CalleeTTI, GetInlineCost, ORE,
179 Params.EnableDeferral.value_or(EnableInlineDeferral));
180}
181
182std::unique_ptr<InlineAdvice>
183DefaultInlineAdvisor::getAdviceImpl(CallBase &CB) {
184 auto OIC = getDefaultInlineAdvice(CB, FAM, Params);
185 return std::make_unique<DefaultInlineAdvice>(
186 this, CB, OIC,
188}
189
192 bool IsInliningRecommended)
193 : Advisor(Advisor), Caller(CB.getCaller()), Callee(CB.getCalledFunction()),
194 DLoc(CB.getDebugLoc()), Block(CB.getParent()), ORE(ORE),
195 IsInliningRecommended(IsInliningRecommended) {}
196
197void InlineAdvice::recordInlineStatsIfNeeded() {
199 Advisor->ImportedFunctionsStats->recordInline(*Caller, *Callee);
200}
201
203 markRecorded();
204 recordInlineStatsIfNeeded();
206}
207
209 markRecorded();
210 recordInlineStatsIfNeeded();
212}
213
216
217bool InlineAdvisorAnalysis::initializeIR2VecVocabIfRequested(
219 if (!IR2VecVocabFile.empty()) {
220 auto IR2VecVocabResult = MAM.getResult<IR2VecVocabAnalysis>(M);
221 if (!IR2VecVocabResult.isValid()) {
222 M.getContext().emitError("Failed to load IR2Vec vocabulary");
223 return false;
224 }
225 }
226 // No vocab file specified is OK; We just don't use IR2Vec
227 // embeddings.
228 return true;
229}
230
233 const ReplayInlinerSettings &ReplaySettings, InlineContext IC) {
234 auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
237 Advisor.reset(DA.Factory(M, FAM, Params, IC));
238 return !!Advisor;
239 }
240 auto GetDefaultAdvice = [&FAM, Params](CallBase &CB) {
241 auto OIC = getDefaultInlineAdvice(CB, FAM, Params);
242 return OIC.has_value();
243 };
244 switch (Mode) {
246 LLVM_DEBUG(dbgs() << "Using default inliner heuristic.\n");
247 Advisor.reset(new DefaultInlineAdvisor(M, FAM, Params, IC));
248 // Restrict replay to default advisor, ML advisors are stateful so
249 // replay will need augmentations to interleave with them correctly.
250 if (!ReplaySettings.ReplayFile.empty()) {
251 Advisor = llvm::getReplayInlineAdvisor(M, FAM, M.getContext(),
252 std::move(Advisor), ReplaySettings,
253 /* EmitRemarks =*/true, IC);
254 }
255 break;
256 // Run IR2VecVocabAnalysis once per module to get the vocabulary.
257 // We run it here because it is immutable and we want to avoid running it
258 // multiple times.
260#ifdef LLVM_HAVE_TFLITE
261 LLVM_DEBUG(dbgs() << "Using development-mode inliner policy.\n");
262 if (!InlineAdvisorAnalysis::initializeIR2VecVocabIfRequested(M, MAM))
263 return false;
264 Advisor = llvm::getDevelopmentModeAdvisor(M, MAM, GetDefaultAdvice);
265#endif
266 break;
268 LLVM_DEBUG(dbgs() << "Using release-mode inliner policy.\n");
269 if (!InlineAdvisorAnalysis::initializeIR2VecVocabIfRequested(M, MAM))
270 return false;
271 Advisor = llvm::getReleaseModeAdvisor(M, MAM, GetDefaultAdvice);
272 break;
273 }
274
275 return !!Advisor;
276}
277
278/// Return true if inlining of CB can block the caller from being
279/// inlined which is proved to be more beneficial. \p IC is the
280/// estimated inline cost associated with callsite \p CB.
281/// \p TotalSecondaryCost will be set to the estimated cost of inlining the
282/// caller if \p CB is suppressed for inlining.
283static bool
285 InlineCost IC, int &TotalSecondaryCost,
286 function_ref<InlineCost(CallBase &CB)> GetInlineCost) {
287 // For now we only handle local or inline functions.
288 if (!Caller->hasLocalLinkage() && !Caller->hasLinkOnceODRLinkage())
289 return false;
290 // If the cost of inlining CB is non-positive, it is not going to prevent the
291 // caller from being inlined into its callers and hence we don't need to
292 // defer.
293 if (IC.getCost() <= 0)
294 return false;
295 // Try to detect the case where the current inlining candidate caller (call
296 // it B) is a static or linkonce-ODR function and is an inlining candidate
297 // elsewhere, and the current candidate callee (call it C) is large enough
298 // that inlining it into B would make B too big to inline later. In these
299 // circumstances it may be best not to inline C into B, but to inline B into
300 // its callers.
301 //
302 // This only applies to static and linkonce-ODR functions because those are
303 // expected to be available for inlining in the translation units where they
304 // are used. Thus we will always have the opportunity to make local inlining
305 // decisions. Importantly the linkonce-ODR linkage covers inline functions
306 // and templates in C++.
307 //
308 // FIXME: All of this logic should be sunk into getInlineCost. It relies on
309 // the internal implementation of the inline cost metrics rather than
310 // treating them as truly abstract units etc.
311 TotalSecondaryCost = 0;
312 // The candidate cost to be imposed upon the current function.
313 int CandidateCost = IC.getCost() - 1;
314 // If the caller has local linkage and can be inlined to all its callers, we
315 // can apply a huge negative bonus to TotalSecondaryCost.
316 bool ApplyLastCallBonus = Caller->hasLocalLinkage() && !Caller->hasOneUse();
317 // This bool tracks what happens if we DO inline C into B.
318 bool InliningPreventsSomeOuterInline = false;
319 unsigned NumCallerUsers = 0;
320 for (User *U : Caller->users()) {
321 CallBase *CS2 = dyn_cast<CallBase>(U);
322
323 // If this isn't a call to Caller (it could be some other sort
324 // of reference) skip it. Such references will prevent the caller
325 // from being removed.
326 if (!CS2 || CS2->getCalledFunction() != Caller) {
327 ApplyLastCallBonus = false;
328 continue;
329 }
330
331 InlineCost IC2 = GetInlineCost(*CS2);
332 ++NumCallerCallersAnalyzed;
333 if (!IC2) {
334 ApplyLastCallBonus = false;
335 continue;
336 }
337 if (IC2.isAlways())
338 continue;
339
340 // See if inlining of the original callsite would erase the cost delta of
341 // this callsite. We subtract off the penalty for the call instruction,
342 // which we would be deleting.
343 if (IC2.getCostDelta() <= CandidateCost) {
344 InliningPreventsSomeOuterInline = true;
345 TotalSecondaryCost += IC2.getCost();
346 NumCallerUsers++;
347 }
348 }
349
350 if (!InliningPreventsSomeOuterInline)
351 return false;
352
353 // If all outer calls to Caller would get inlined, the cost for the last
354 // one is set very low by getInlineCost, in anticipation that Caller will
355 // be removed entirely. We did not account for this above unless there
356 // is only one caller of Caller.
357 if (ApplyLastCallBonus)
358 TotalSecondaryCost -= CalleeTTI.getInliningLastCallToStaticBonus();
359
360 // If InlineDeferralScale is negative, then ignore the cost of primary
361 // inlining -- IC.getCost() multiplied by the number of callers to Caller.
362 if (InlineDeferralScale < 0)
363 return TotalSecondaryCost < IC.getCost();
364
365 int TotalCost = TotalSecondaryCost + IC.getCost() * NumCallerUsers;
366 int Allowance = IC.getCost() * InlineDeferralScale;
367 return TotalCost < Allowance;
368}
369
370namespace llvm {
371static raw_ostream &operator<<(raw_ostream &R, const ore::NV &Arg) {
372 return R << Arg.Val;
373}
374
375template <class RemarkT>
376decltype(auto) operator<<(RemarkT &&R, const InlineCost &IC) {
377 using namespace ore;
378 if (IC.isAlways()) {
379 R << "(cost=always)";
380 } else if (IC.isNever()) {
381 R << "(cost=never)";
382 } else {
383 R << "(cost=" << ore::NV("Cost", IC.getCost())
384 << ", threshold=" << ore::NV("Threshold", IC.getThreshold()) << ")";
385 }
386 if (const char *Reason = IC.getReason())
387 R << ": " << ore::NV("Reason", Reason);
388 return std::forward<RemarkT>(R);
389}
390} // namespace llvm
391
392std::string llvm::inlineCostStr(const InlineCost &IC) {
393 std::string Buffer;
395 Remark << IC;
396 return Remark.str();
397}
398
401 return;
402
403 Attribute Attr = Attribute::get(CB.getContext(), "inline-remark", Message);
404 CB.addFnAttr(Attr);
405}
406
407/// Return the cost only if the inliner should attempt to inline at the given
408/// CallSite. If we return the cost, we will emit an optimisation remark later
409/// using that cost, so we won't do so from this function. Return std::nullopt
410/// if inlining should not be attempted.
411std::optional<InlineCost>
413 function_ref<InlineCost(CallBase &CB)> GetInlineCost,
414 OptimizationRemarkEmitter &ORE, bool EnableDeferral) {
415 using namespace ore;
416
417 InlineCost IC = GetInlineCost(CB);
418 Instruction *Call = &CB;
419 Function *Callee = CB.getCalledFunction();
420 Function *Caller = CB.getCaller();
421
422 if (IC.isAlways()) {
423 LLVM_DEBUG(dbgs() << " Inlining " << inlineCostStr(IC)
424 << ", Call: " << CB << "\n");
425 return IC;
426 }
427
428 if (!IC) {
429 LLVM_DEBUG(dbgs() << " NOT Inlining " << inlineCostStr(IC)
430 << ", Call: " << CB << "\n");
431 if (IC.isNever()) {
432 ORE.emit([&]() {
433 return OptimizationRemarkMissed(DEBUG_TYPE, "NeverInline", Call)
434 << "'" << NV("Callee", Callee) << "' not inlined into '"
435 << NV("Caller", Caller)
436 << "' because it should never be inlined " << IC;
437 });
438 } else {
439 ORE.emit([&]() {
440 return OptimizationRemarkMissed(DEBUG_TYPE, "TooCostly", Call)
441 << "'" << NV("Callee", Callee) << "' not inlined into '"
442 << NV("Caller", Caller) << "' because too costly to inline "
443 << IC;
444 });
445 }
447 return std::nullopt;
448 }
449
450 int TotalSecondaryCost = 0;
451 if (EnableDeferral && shouldBeDeferred(Caller, CalleeTTI, IC,
452 TotalSecondaryCost, GetInlineCost)) {
453 LLVM_DEBUG(dbgs() << " NOT Inlining: " << CB
454 << " Cost = " << IC.getCost()
455 << ", outer Cost = " << TotalSecondaryCost << '\n');
456 ORE.emit([&]() {
457 return OptimizationRemarkMissed(DEBUG_TYPE, "IncreaseCostInOtherContexts",
458 Call)
459 << "Not inlining. Cost of inlining '" << NV("Callee", Callee)
460 << "' increases the cost of inlining '" << NV("Caller", Caller)
461 << "' in other contexts";
462 });
463 setInlineRemark(CB, "deferred");
464 return std::nullopt;
465 }
466
467 LLVM_DEBUG(dbgs() << " Inlining " << inlineCostStr(IC) << ", Call: " << CB
468 << '\n');
469 return IC;
470}
471
473 const CallSiteFormat &Format) {
474 std::string Buffer;
475 raw_string_ostream CallSiteLoc(Buffer);
476 bool First = true;
477 for (DILocation *DIL = DLoc.get(); DIL; DIL = DIL->getInlinedAt()) {
478 if (!First)
479 CallSiteLoc << " @ ";
480 // Note that negative line offset is actually possible, but we use
481 // unsigned int to match line offset representation in remarks so
482 // it's directly consumable by relay advisor.
484 DIL->getLine() - DIL->getScope()->getSubprogram()->getLine();
485 uint32_t Discriminator = DIL->getBaseDiscriminator();
486 StringRef Name = DIL->getScope()->getSubprogram()->getLinkageName();
487 if (Name.empty())
488 Name = DIL->getScope()->getSubprogram()->getName();
489 CallSiteLoc << Name.str() << ":" << llvm::utostr(Offset);
490 if (Format.outputColumn())
491 CallSiteLoc << ":" << llvm::utostr(DIL->getColumn());
492 if (Format.outputDiscriminator() && Discriminator)
493 CallSiteLoc << "." << llvm::utostr(Discriminator);
494 First = false;
495 }
496
497 return CallSiteLoc.str();
498}
499
501 if (!DLoc) {
502 return;
503 }
504
505 bool First = true;
506 Remark << " at callsite ";
507 for (DILocation *DIL = DLoc.get(); DIL; DIL = DIL->getInlinedAt()) {
508 if (!First)
509 Remark << " @ ";
510 unsigned int Offset = DIL->getLine();
511 Offset -= DIL->getScope()->getSubprogram()->getLine();
512 unsigned int Discriminator = DIL->getBaseDiscriminator();
513 StringRef Name = DIL->getScope()->getSubprogram()->getLinkageName();
514 if (Name.empty())
515 Name = DIL->getScope()->getSubprogram()->getName();
516 Remark << Name << ":" << ore::NV("Line", Offset) << ":"
517 << ore::NV("Column", DIL->getColumn());
518 if (Discriminator)
519 Remark << "." << ore::NV("Disc", Discriminator);
520 First = false;
521 }
522
523 Remark << ";";
524}
525
528 const Function &Callee, const Function &Caller, bool AlwaysInline,
529 function_ref<void(OptimizationRemark &)> ExtraContext,
530 const char *PassName) {
531 ORE.emit([&]() {
532 StringRef RemarkName = AlwaysInline ? "AlwaysInline" : "Inlined";
534 DLoc, Block);
535 Remark << "'" << ore::NV("Callee", &Callee) << "' inlined into '"
536 << ore::NV("Caller", &Caller) << "'";
537 if (ExtraContext)
538 ExtraContext(Remark);
540 return Remark;
541 });
542}
543
546 const Function &Callee, const Function &Caller, const InlineCost &IC,
547 bool ForProfileContext, const char *PassName) {
549 ORE, DLoc, Block, Callee, Caller, IC.isAlways(),
551 if (ForProfileContext)
552 Remark << " to match profiling context";
553 Remark << " with " << IC;
554 },
555 PassName);
556}
557
559 std::optional<InlineContext> IC)
560 : M(M), FAM(FAM), IC(IC),
561 AnnotatedInlinePassName((IC && AnnotateInlinePhase)
563 : DEBUG_TYPE) {
566 std::make_unique<ImportedFunctionsInliningStatistics>();
567 ImportedFunctionsStats->setModuleInfo(M);
568 }
569}
570
576 }
577}
578
579std::unique_ptr<InlineAdvice> InlineAdvisor::getMandatoryAdvice(CallBase &CB,
580 bool Advice) {
581 return std::make_unique<MandatoryInlineAdvice>(this, CB, getCallerORE(CB),
582 Advice);
583}
584
585static inline const char *getLTOPhase(ThinOrFullLTOPhase LTOPhase) {
586 switch (LTOPhase) {
588 return "main";
591 return "prelink";
594 return "postlink";
595 }
596 llvm_unreachable("unreachable");
597}
598
599static inline const char *getInlineAdvisorContext(InlinePass IP) {
600 switch (IP) {
602 return "always-inline";
604 return "cgscc-inline";
606 return "early-inline";
608 return "ml-inline";
610 return "module-inline";
612 return "replay-cgscc-inline";
614 return "replay-sample-profile-inline";
616 return "sample-profile-inline";
617 }
618
619 llvm_unreachable("unreachable");
620}
621
623 return std::string(getLTOPhase(IC.LTOPhase)) + "-" +
624 std::string(getInlineAdvisorContext(IC.Pass));
625}
626
630 auto &Callee = *CB.getCalledFunction();
631
632 auto GetTLI = [&](Function &F) -> const TargetLibraryInfo & {
634 };
635
636 auto &TIR = FAM.getResult<TargetIRAnalysis>(Callee);
637
638 auto TrivialDecision =
639 llvm::getAttributeBasedInliningDecision(CB, &Callee, TIR, GetTLI);
640
641 if (TrivialDecision) {
642 if (TrivialDecision->isSuccess())
644 else
646 }
648}
649
650std::unique_ptr<InlineAdvice> InlineAdvisor::getAdvice(CallBase &CB,
651 bool MandatoryOnly) {
652 if (!MandatoryOnly)
653 return getAdviceImpl(CB);
654 bool Advice = CB.getCaller() != CB.getCalledFunction() &&
657 return getMandatoryAdvice(CB, Advice);
658}
659
662}
663
666 const auto *IA = MAM.getCachedResult<InlineAdvisorAnalysis>(M);
667 if (!IA)
668 OS << "No Inline Advisor\n";
669 else
670 IA->getAdvisor()->print(OS);
671 return PreservedAnalyses::all();
672}
673
676 CGSCCUpdateResult &UR) {
677 const auto &MAMProxy =
679
680 if (InitialC.size() == 0) {
681 OS << "SCC is empty!\n";
682 return PreservedAnalyses::all();
683 }
684 Module &M = *InitialC.begin()->getFunction().getParent();
685 const auto *IA = MAMProxy.getCachedResult<InlineAdvisorAnalysis>(M);
686 if (!IA)
687 OS << "No Inline Advisor\n";
688 else
689 IA->getAdvisor()->print(OS);
690 return PreservedAnalyses::all();
691}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static const Function * getParent(const Value *V)
std::string Name
#define DEBUG_TYPE
This file defines the IR2Vec vocabulary analysis(IR2VecVocabAnalysis), the core ir2vec::Embedder inte...
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
static bool shouldBeDeferred(Function *Caller, TargetTransformInfo &CalleeTTI, InlineCost IC, int &TotalSecondaryCost, function_ref< InlineCost(CallBase &CB)> GetInlineCost)
Return true if inlining of CB can block the caller from being inlined which is proved to be more bene...
static cl::opt< int > InlineDeferralScale("inline-deferral-scale", cl::desc("Scale to limit the cost of inline deferral"), cl::init(2), cl::Hidden)
static cl::opt< bool > InlineRemarkAttribute("inline-remark-attribute", cl::init(false), cl::Hidden, cl::desc("Enable adding inline-remark attribute to" " callsites processed by inliner but decided" " to be not inlined"))
Flag to add inline messages as callsite attributes 'inline-remark'.
static cl::opt< bool > EnableInlineDeferral("inline-deferral", cl::init(false), cl::Hidden, cl::desc("Enable deferred inlining"))
static cl::opt< bool > AnnotateInlinePhase("annotate-inline-phase", cl::Hidden, cl::init(false), cl::desc("If true, annotate inline advisor remarks " "with LTO and pass information."))
static const char * getLTOPhase(ThinOrFullLTOPhase LTOPhase)
static std::optional< llvm::InlineCost > getDefaultInlineAdvice(CallBase &CB, FunctionAnalysisManager &FAM, const InlineParams &Params)
static const char * getInlineAdvisorContext(InlinePass IP)
static cl::opt< std::string > IR2VecVocabFile("ml-inliner-ir2vec-vocab-file", cl::Hidden, cl::desc("Vocab file for IR2Vec; Setting this enables " "configuring the model to use IR2Vec embeddings."))
#define F(x, y, z)
Definition: MD5.cpp:55
static DebugLoc getDebugLoc(MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
Return the first found DebugLoc that has a DILocation, given a range of instructions.
static const Function * getCalledFunction(const Value *V)
FunctionAnalysisManager FAM
ModuleAnalysisManager MAM
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition: Statistic.h:167
This file contains some functions that are useful when dealing with strings.
#define LLVM_DEBUG(...)
Definition: Debug.h:119
This pass exposes codegen information to IR-level passes.
static const char PassName[]
A container for analyses that lazily runs them and caches their results.
Definition: PassManager.h:255
bool isPassRegistered() const
Returns true if the specified analysis pass is registered.
Definition: PassManager.h:404
PassT::Result * getCachedResult(IRUnitT &IR) const
Get the cached result of an analysis pass for a given IR unit.
Definition: PassManager.h:431
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Definition: PassManager.h:412
A function analysis which provides an AssumptionCache.
A cache of @llvm.assume calls within a function.
static LLVM_ABI Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)
Return a uniquified Attribute object.
Definition: Attributes.cpp:95
LLVM Basic Block Representation.
Definition: BasicBlock.h:62
Analysis pass which computes BlockFrequencyInfo.
BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Definition: InstrTypes.h:1116
void addFnAttr(Attribute::AttrKind Kind)
Adds the attribute to the function.
Definition: InstrTypes.h:1481
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
Definition: InstrTypes.h:1348
LLVM_ABI Function * getCaller()
Helper to get the caller (the parent function).
Debug location.
A debug info location.
Definition: DebugLoc.h:124
LLVM_ABI DILocation * get() const
Get the underlying DILocation.
Definition: DebugLoc.cpp:50
The default (manual heuristics) implementation of the InlineAdvisor.
A cache of ephemeral values within a function.
This analysis provides the vocabulary for IR2Vec.
Definition: IR2Vec.h:415
Capture state between an inlining decision having had been made, and its impact being observable.
Definition: InlineAdvisor.h:75
Function *const Callee
Function *const Caller
Caller and Callee are pre-inlining.
virtual void recordInliningWithCalleeDeletedImpl()
virtual void recordInliningImpl()
const BasicBlock *const Block
LLVM_ABI void recordInlining()
Exactly one of the record* APIs must be called.
OptimizationRemarkEmitter & ORE
virtual void recordUnsuccessfulInliningImpl(const InlineResult &Result)
InlineAdvisor *const Advisor
LLVM_ABI InlineAdvice(InlineAdvisor *Advisor, CallBase &CB, OptimizationRemarkEmitter &ORE, bool IsInliningRecommended)
virtual void recordUnattemptedInliningImpl()
const DebugLoc DLoc
LLVM_ABI void recordInliningWithCalleeDeleted()
Call after inlining succeeded, and results in the callee being delete-able, meaning,...
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
The InlineAdvisorAnalysis is a module pass because the InlineAdvisor needs to capture state right bef...
static LLVM_ABI AnalysisKey Key
Interface for deciding whether to inline a call site or not.
OptimizationRemarkEmitter & getCallerORE(CallBase &CB)
FunctionAnalysisManager & FAM
static MandatoryInliningKind getMandatoryKind(CallBase &CB, FunctionAnalysisManager &FAM, OptimizationRemarkEmitter &ORE)
virtual std::unique_ptr< InlineAdvice > getMandatoryAdvice(CallBase &CB, bool Advice)
std::unique_ptr< ImportedFunctionsInliningStatistics > ImportedFunctionsStats
const char * getAnnotatedInlinePassName() const
NOTE pass name is annotated only when inline advisor constructor provides InlineContext.
InlineAdvisor(InlineAdvisor &&)=delete
virtual std::unique_ptr< InlineAdvice > getAdviceImpl(CallBase &CB)=0
std::unique_ptr< InlineAdvice > getAdvice(CallBase &CB, bool MandatoryOnly=false)
Get an InlineAdvice containing a recommendation on whether to inline or not.
Represents the cost of inlining a function.
Definition: InlineCost.h:91
int getThreshold() const
Get the threshold against which the cost was computed.
Definition: InlineCost.h:152
const char * getReason() const
Get the reason of Always or Never.
Definition: InlineCost.h:167
int getCost() const
Get the inline cost estimate.
Definition: InlineCost.h:146
bool isAlways() const
Definition: InlineCost.h:140
int getCostDelta() const
Get the cost delta from the threshold for inlining.
Definition: InlineCost.h:176
bool isNever() const
Definition: InlineCost.h:141
InlineResult is basically true or false.
Definition: InlineCost.h:181
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
Definition: PassManager.h:585
An SCC of the call graph.
iterator begin() const
A lazily constructed view of the call graph of a module.
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:67
The optimization diagnostic interface.
LLVM_ABI void emit(DiagnosticInfoOptimizationBase &OptDiag)
Output the remark via the diagnostic handler and to the optimization record file.
Diagnostic information for missed-optimization remarks.
Diagnostic information for applied optimization remarks.
An analysis over an "inner" IR unit that provides access to an analysis manager over a "outer" IR uni...
Definition: PassManager.h:716
Used for dynamically registering InlineAdvisors as plugins.
static LLVM_ABI AnalysisKey Key
A set of analyses that are preserved following a run of a transformation pass.
Definition: Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: Analysis.h:118
Analysis providing profile information.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:55
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:151
Analysis pass providing the TargetTransformInfo.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
LLVM_ABI int getInliningLastCallToStaticBonus() const
LLVM_ABI LLVMContext & getContext() const
All values hold a context through their type.
Definition: Value.cpp:1098
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
Definition: ilist_node.h:34
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:662
std::string & str()
Returns the string's reference.
Definition: raw_ostream.h:680
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:444
Add a small namespace to avoid name clashes with the classes used in the streaming interface.
DiagnosticInfoOptimizationBase::Argument NV
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:477
LLVM_ABI void emitInlinedInto(OptimizationRemarkEmitter &ORE, DebugLoc DLoc, const BasicBlock *Block, const Function &Callee, const Function &Caller, bool IsMandatory, function_ref< void(OptimizationRemark &)> ExtraContext={}, const char *PassName=nullptr)
Emit ORE message.
LLVM_ABI std::string inlineCostStr(const InlineCost &IC)
Utility for extracting the inline cost message to a string.
InliningAdvisorMode
There are 4 scenarios we can use the InlineAdvisor:
Definition: InlineAdvisor.h:43
LLVM_ABI std::optional< InlineCost > shouldInline(CallBase &CB, TargetTransformInfo &CalleeTTI, function_ref< InlineCost(CallBase &CB)> GetInlineCost, OptimizationRemarkEmitter &ORE, bool EnableDeferral=true)
Return the cost only if the inliner should attempt to inline at the given CallSite.
LLVM_ABI std::unique_ptr< InlineAdvisor > getDevelopmentModeAdvisor(Module &M, ModuleAnalysisManager &MAM, std::function< bool(CallBase &)> GetDefaultAdvice)
LLVM_ABI std::unique_ptr< InlineAdvisor > getReleaseModeAdvisor(Module &M, ModuleAnalysisManager &MAM, std::function< bool(CallBase &)> GetDefaultAdvice)
LLVM_ABI void setInlineRemark(CallBase &CB, StringRef Message)
Set the inline-remark attribute.
LLVM_ABI std::string AnnotateInlinePassName(InlineContext IC)
ThinOrFullLTOPhase
This enumerates the LLVM full LTO or ThinLTO optimization phases.
Definition: Pass.h:77
@ FullLTOPreLink
Full LTO prelink phase.
@ ThinLTOPostLink
ThinLTO postlink (backend compile) phase.
@ None
No LTO/ThinLTO behavior needed.
@ FullLTOPostLink
Full LTO postlink (backend compile) phase.
@ ThinLTOPreLink
ThinLTO prelink (summary) phase.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:207
LLVM_ABI void emitInlinedIntoBasedOnCost(OptimizationRemarkEmitter &ORE, DebugLoc DLoc, const BasicBlock *Block, const Function &Callee, const Function &Caller, const InlineCost &IC, bool ForProfileContext=false, const char *PassName=nullptr)
Emit ORE message based in cost (default heuristic).
std::unique_ptr< InlineAdvisor > getReplayInlineAdvisor(Module &M, FunctionAnalysisManager &FAM, LLVMContext &Context, std::unique_ptr< InlineAdvisor > OriginalAdvisor, const ReplayInlinerSettings &ReplaySettings, bool EmitRemarks, InlineContext IC)
LLVM_ABI InlineCost getInlineCost(CallBase &Call, const InlineParams &Params, TargetTransformInfo &CalleeTTI, function_ref< AssumptionCache &(Function &)> GetAssumptionCache, function_ref< const TargetLibraryInfo &(Function &)> GetTLI, function_ref< BlockFrequencyInfo &(Function &)> GetBFI=nullptr, ProfileSummaryInfo *PSI=nullptr, OptimizationRemarkEmitter *ORE=nullptr, function_ref< EphemeralValuesCache &(Function &)> GetEphValuesCache=nullptr)
Get an InlineCost object representing the cost of inlining this callsite.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
LLVM_ABI std::optional< InlineResult > getAttributeBasedInliningDecision(CallBase &Call, Function *Callee, TargetTransformInfo &CalleeTTI, function_ref< const TargetLibraryInfo &(Function &)> GetTLI)
Returns InlineResult::success() if the call site should be always inlined because of user directives,...
cl::opt< InlinerFunctionImportStatsOpts > InlinerFunctionImportStats("inliner-function-import-stats", cl::init(InlinerFunctionImportStatsOpts::No), cl::values(clEnumValN(InlinerFunctionImportStatsOpts::Basic, "basic", "basic statistics"), clEnumValN(InlinerFunctionImportStatsOpts::Verbose, "verbose", "printing of statistics for each inlined function")), cl::Hidden, cl::desc("Enable inliner stats for imported functions"))
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
Definition: APFixedPoint.h:312
LLVM_ABI void addLocationToRemarks(OptimizationRemark &Remark, DebugLoc DLoc)
Add location info to ORE message.
std::string formatCallSiteLocation(DebugLoc DLoc, const CallSiteFormat &Format)
Get call site location as a string with the given format.
A special type used by analysis passes to provide an address that identifies that particular analysis...
Definition: Analysis.h:29
Support structure for SCC passes to communicate updates the call graph back to the CGSCC pass manager...
Used in the streaming interface as the general argument type.
LLVM_ABI bool tryCreate(InlineParams Params, InliningAdvisorMode Mode, const ReplayInlinerSettings &ReplaySettings, InlineContext IC)
Provides context on when an inline advisor is constructed in the pipeline (e.g., link phase,...
Definition: InlineAdvisor.h:59
ThinOrFullLTOPhase LTOPhase
Definition: InlineAdvisor.h:60
Thresholds to tune inline cost analysis.
Definition: InlineCost.h:207
std::optional< bool > EnableDeferral
Indicate whether we should allow inline deferral.
Definition: InlineCost.h:237