LLVM 20.0.0git
InlineAdvisor.h
Go to the documentation of this file.
1//===- InlineAdvisor.h - Inlining decision making abstraction -*- C++ ---*-===//
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#ifndef LLVM_ANALYSIS_INLINEADVISOR_H
10#define LLVM_ANALYSIS_INLINEADVISOR_H
11
15#include "llvm/IR/PassManager.h"
16#include <memory>
17
18namespace llvm {
19class BasicBlock;
20class CallBase;
21class Function;
22class Module;
23class OptimizationRemark;
24class ImportedFunctionsInliningStatistics;
25class OptimizationRemarkEmitter;
26struct ReplayInlinerSettings;
27
28/// There are 4 scenarios we can use the InlineAdvisor:
29/// - Default - use manual heuristics.
30///
31/// - Release mode, the expected mode for production, day to day deployments.
32/// In this mode, when building the compiler, we also compile a pre-trained ML
33/// model to native code, and link it as a static library. This mode has low
34/// overhead and no additional dependencies for the compiler runtime.
35///
36/// - Development mode, for training new models.
37/// In this mode, we trade off runtime performance for flexibility. This mode
38/// requires the TFLite library, and evaluates models dynamically. This mode
39/// also permits generating training logs, for offline training.
40///
41/// - Dynamically load an advisor via a plugin (PluginInlineAdvisorAnalysis)
43
44// Each entry represents an inline driver.
45enum class InlinePass : int {
54};
55
56/// Provides context on when an inline advisor is constructed in the pipeline
57/// (e.g., link phase, inline driver).
60
62};
63
65
66class InlineAdvisor;
67/// Capture state between an inlining decision having had been made, and
68/// its impact being observable. When collecting model training data, this
69/// allows recording features/decisions/partial reward data sets.
70///
71/// Derivations of this type are expected to be tightly coupled with their
72/// InliningAdvisors. The base type implements the minimal contractual
73/// obligations.
75public:
78
80 InlineAdvice(const InlineAdvice &) = delete;
81 virtual ~InlineAdvice() {
82 assert(Recorded && "InlineAdvice should have been informed of the "
83 "inliner's decision in all cases");
84 }
85
86 /// Exactly one of the record* APIs must be called. Implementers may extend
87 /// behavior by implementing the corresponding record*Impl.
88 ///
89 /// Call after inlining succeeded, and did not result in deleting the callee.
90 void recordInlining();
91
92 /// Call after inlining succeeded, and results in the callee being
93 /// delete-able, meaning, it has no more users, and will be cleaned up
94 /// subsequently.
96
97 /// Call after the decision for a call site was to not inline.
99 markRecorded();
101 }
102
103 /// Call to indicate inlining was not attempted.
105 markRecorded();
107 }
108
109 /// Get the inlining recommendation.
111 const DebugLoc &getOriginalCallSiteDebugLoc() const { return DLoc; }
113
114protected:
115 virtual void recordInliningImpl() {}
117 virtual void recordUnsuccessfulInliningImpl(const InlineResult &Result) {}
119
121 /// Caller and Callee are pre-inlining.
124
125 // Capture the context of CB before inlining, as a successful inlining may
126 // change that context, and we want to report success or failure in the
127 // original context.
129 const BasicBlock *const Block;
132
133private:
134 void markRecorded() {
135 assert(!Recorded && "Recording should happen exactly once");
136 Recorded = true;
137 }
138 void recordInlineStatsIfNeeded();
139
140 bool Recorded = false;
141};
142
144public:
146 std::optional<InlineCost> OIC,
147 OptimizationRemarkEmitter &ORE, bool EmitRemarks = true)
148 : InlineAdvice(Advisor, CB, ORE, OIC.has_value()), OriginalCB(&CB),
149 OIC(OIC), EmitRemarks(EmitRemarks) {}
150
151private:
152 void recordUnsuccessfulInliningImpl(const InlineResult &Result) override;
153 void recordInliningWithCalleeDeletedImpl() override;
154 void recordInliningImpl() override;
155
156private:
157 CallBase *const OriginalCB;
158 std::optional<InlineCost> OIC;
159 bool EmitRemarks;
160};
161
162/// Interface for deciding whether to inline a call site or not.
164public:
166 virtual ~InlineAdvisor();
167
168 /// Get an InlineAdvice containing a recommendation on whether to
169 /// inline or not. \p CB is assumed to be a direct call. \p FAM is assumed to
170 /// be up-to-date wrt previous inlining decisions. \p MandatoryOnly indicates
171 /// only mandatory (always-inline) call sites should be recommended - this
172 /// allows the InlineAdvisor track such inlininings.
173 /// Returns:
174 /// - An InlineAdvice with the inlining recommendation.
175 /// - Null when no recommendation is made (https://reviews.llvm.org/D110658).
176 /// TODO: Consider removing the Null return scenario by incorporating the
177 /// SampleProfile inliner into an InlineAdvisor
178 std::unique_ptr<InlineAdvice> getAdvice(CallBase &CB,
179 bool MandatoryOnly = false);
180
181 /// This must be called when the Inliner pass is entered, to allow the
182 /// InlineAdvisor update internal state, as result of function passes run
183 /// between Inliner pass runs (for the same module).
184 virtual void onPassEntry(LazyCallGraph::SCC *SCC = nullptr) {}
185
186 /// This must be called when the Inliner pass is exited, as function passes
187 /// may be run subsequently. This allows an implementation of InlineAdvisor
188 /// to prepare for a partial update, based on the optional SCC.
189 virtual void onPassExit(LazyCallGraph::SCC *SCC = nullptr) {}
190
191 /// Support for printer pass
192 virtual void print(raw_ostream &OS) const {
193 OS << "Unimplemented InlineAdvisor print\n";
194 }
195
196 /// NOTE pass name is annotated only when inline advisor constructor provides InlineContext.
197 const char *getAnnotatedInlinePassName() const {
198 return AnnotatedInlinePassName.c_str();
199 }
200
201protected:
203 std::optional<InlineContext> IC = std::nullopt);
204 virtual std::unique_ptr<InlineAdvice> getAdviceImpl(CallBase &CB) = 0;
205 virtual std::unique_ptr<InlineAdvice> getMandatoryAdvice(CallBase &CB,
206 bool Advice);
207
210 const std::optional<InlineContext> IC;
211 const std::string AnnotatedInlinePassName;
212 std::unique_ptr<ImportedFunctionsInliningStatistics> ImportedFunctionsStats;
213
215
219
221
222private:
223 friend class InlineAdvice;
224};
225
226/// The default (manual heuristics) implementation of the InlineAdvisor. This
227/// implementation does not need to keep state between inliner pass runs, and is
228/// reusable as-is for inliner pass test scenarios, as well as for regular use.
230public:
233 : InlineAdvisor(M, FAM, IC), Params(Params) {}
234
235private:
236 std::unique_ptr<InlineAdvice> getAdviceImpl(CallBase &CB) override;
237
238 InlineParams Params;
239};
240
241/// Used for dynamically registering InlineAdvisors as plugins
242///
243/// An advisor plugin adds a new advisor at runtime by registering an instance
244/// of PluginInlineAdvisorAnalysis in the current ModuleAnalysisManager.
245/// For example, the following code dynamically registers a
246/// DefaultInlineAdvisor:
247///
248/// namespace {
249///
250/// InlineAdvisor *defaultAdvisorFactory(Module &M,
251/// FunctionAnalysisManager &FAM,
252/// InlineParams Params,
253/// InlineContext IC) {
254/// return new DefaultInlineAdvisor(M, FAM, Params, IC);
255/// }
256///
257/// } // namespace
258///
259/// extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo
260/// llvmGetPassPluginInfo() {
261/// return {LLVM_PLUGIN_API_VERSION, "DynamicDefaultAdvisor",
262/// LLVM_VERSION_STRING,
263/// [](PassBuilder &PB) {
264/// PB.registerAnalysisRegistrationCallback(
265/// [](ModuleAnalysisManager &MAM) {
266/// PluginInlineAdvisorAnalysis PA(defaultAdvisorFactory);
267/// MAM.registerPass([&] { return PA; });
268/// });
269/// }};
270/// }
271///
272/// A plugin must implement an AdvisorFactory and register it with a
273/// PluginInlineAdvisorAnlysis to the provided ModuleAnalysisManager.
274///
275/// If such a plugin has been registered
276/// InlineAdvisorAnalysis::Result::tryCreate will return the dynamically loaded
277/// advisor.
278///
280 : public AnalysisInfoMixin<PluginInlineAdvisorAnalysis> {
281public:
283
284 typedef InlineAdvisor *(*AdvisorFactory)(Module &M,
286 InlineParams Params,
287 InlineContext IC);
288
289 PluginInlineAdvisorAnalysis(AdvisorFactory Factory) : Factory(Factory) {
290 assert(Factory != nullptr &&
291 "The plugin advisor factory should not be a null pointer.");
292 }
293
294 struct Result {
296 };
297
298 Result run(Module &M, ModuleAnalysisManager &MAM) { return {Factory}; }
299 Result getResult() { return {Factory}; }
300
301private:
302 AdvisorFactory Factory;
303};
304
305/// The InlineAdvisorAnalysis is a module pass because the InlineAdvisor
306/// needs to capture state right before inlining commences over a module.
307class InlineAdvisorAnalysis : public AnalysisInfoMixin<InlineAdvisorAnalysis> {
308public:
311 struct Result {
315 // Check whether the analysis has been explicitly invalidated. Otherwise,
316 // it's stateless and remains preserved.
317 auto PAC = PA.getChecker<InlineAdvisorAnalysis>();
318 return !PAC.preservedWhenStateless();
319 }
321 const ReplayInlinerSettings &ReplaySettings,
322 InlineContext IC);
323 InlineAdvisor *getAdvisor() const { return Advisor.get(); }
324
325 private:
326 Module &M;
328 std::unique_ptr<InlineAdvisor> Advisor;
329 };
330
332};
333
334/// Printer pass for the InlineAdvisorAnalysis results.
336 : public PassInfoMixin<InlineAdvisorAnalysisPrinterPass> {
337 raw_ostream &OS;
338
339public:
341
343
346 static bool isRequired() { return true; }
347};
348
349std::unique_ptr<InlineAdvisor>
351 std::function<bool(CallBase &)> GetDefaultAdvice);
352
353std::unique_ptr<InlineAdvisor>
355 std::function<bool(CallBase &)> GetDefaultAdvice);
356
357// Default (manual policy) decision making helper APIs. Shared with the legacy
358// pass manager inliner.
359
360/// Return the cost only if the inliner should attempt to inline at the given
361/// CallSite. If we return the cost, we will emit an optimisation remark later
362/// using that cost, so we won't do so from this function. Return std::nullopt
363/// if inlining should not be attempted.
364std::optional<InlineCost>
366 function_ref<InlineCost(CallBase &CB)> GetInlineCost,
367 OptimizationRemarkEmitter &ORE, bool EnableDeferral = true);
368
369/// Emit ORE message.
371 const BasicBlock *Block, const Function &Callee,
372 const Function &Caller, bool IsMandatory,
373 function_ref<void(OptimizationRemark &)> ExtraContext = {},
374 const char *PassName = nullptr);
375
376/// Emit ORE message based in cost (default heuristic).
377void emitInlinedIntoBasedOnCost(OptimizationRemarkEmitter &ORE, DebugLoc DLoc,
378 const BasicBlock *Block, const Function &Callee,
379 const Function &Caller, const InlineCost &IC,
380 bool ForProfileContext = false,
381 const char *PassName = nullptr);
382
383/// Add location info to ORE message.
384void addLocationToRemarks(OptimizationRemark &Remark, DebugLoc DLoc);
385
386/// Set the inline-remark attribute.
387void setInlineRemark(CallBase &CB, StringRef Message);
388
389/// Utility for extracting the inline cost message to a string.
390std::string inlineCostStr(const InlineCost &IC);
391} // namespace llvm
392#endif // LLVM_ANALYSIS_INLINEADVISOR_H
This header provides classes for managing passes over SCCs of the call graph.
This header defines various interfaces for pass management in LLVM.
Implements a lazy call graph analysis and related passes for the new pass manager.
Machine Check Debug Module
FunctionAnalysisManager FAM
ModuleAnalysisManager MAM
static cl::opt< RegAllocEvictionAdvisorAnalysis::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Development, "development", "for training")))
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
static const char PassName[]
API to communicate dependencies between analyses during invalidation.
Definition: PassManager.h:292
A container for analyses that lazily runs them and caches their results.
Definition: PassManager.h:253
LLVM Basic Block Representation.
Definition: BasicBlock.h:61
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Definition: InstrTypes.h:1120
A debug info location.
Definition: DebugLoc.h:33
DefaultInlineAdvice(InlineAdvisor *Advisor, CallBase &CB, std::optional< InlineCost > OIC, OptimizationRemarkEmitter &ORE, bool EmitRemarks=true)
The default (manual heuristics) implementation of the InlineAdvisor.
DefaultInlineAdvisor(Module &M, FunctionAnalysisManager &FAM, InlineParams Params, InlineContext IC)
Capture state between an inlining decision having had been made, and its impact being observable.
Definition: InlineAdvisor.h:74
Function *const Callee
Function *const Caller
Caller and Callee are pre-inlining.
InlineAdvice(InlineAdvice &&)=delete
void recordUnsuccessfulInlining(const InlineResult &Result)
Call after the decision for a call site was to not inline.
Definition: InlineAdvisor.h:98
InlineAdvice(const InlineAdvice &)=delete
virtual void recordInliningWithCalleeDeletedImpl()
void recordUnattemptedInlining()
Call to indicate inlining was not attempted.
const DebugLoc & getOriginalCallSiteDebugLoc() const
virtual void recordInliningImpl()
const BasicBlock *const Block
const BasicBlock * getOriginalCallSiteBasicBlock() const
void recordInlining()
Exactly one of the record* APIs must be called.
OptimizationRemarkEmitter & ORE
virtual void recordUnsuccessfulInliningImpl(const InlineResult &Result)
virtual ~InlineAdvice()
Definition: InlineAdvisor.h:81
InlineAdvisor *const Advisor
virtual void recordUnattemptedInliningImpl()
const DebugLoc DLoc
void recordInliningWithCalleeDeleted()
Call after inlining succeeded, and results in the callee being delete-able, meaning,...
bool isInliningRecommended() const
Get the inlining recommendation.
const bool IsInliningRecommended
Printer pass for the InlineAdvisorAnalysis results.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
InlineAdvisorAnalysisPrinterPass(raw_ostream &OS)
The InlineAdvisorAnalysis is a module pass because the InlineAdvisor needs to capture state right bef...
Result run(Module &M, ModuleAnalysisManager &MAM)
static AnalysisKey Key
Interface for deciding whether to inline a call site or not.
const std::optional< InlineContext > IC
OptimizationRemarkEmitter & getCallerORE(CallBase &CB)
FunctionAnalysisManager & FAM
static MandatoryInliningKind getMandatoryKind(CallBase &CB, FunctionAnalysisManager &FAM, OptimizationRemarkEmitter &ORE)
virtual void print(raw_ostream &OS) const
Support for printer pass.
const std::string AnnotatedInlinePassName
virtual std::unique_ptr< InlineAdvice > getMandatoryAdvice(CallBase &CB, bool Advice)
std::unique_ptr< ImportedFunctionsInliningStatistics > ImportedFunctionsStats
virtual void onPassEntry(LazyCallGraph::SCC *SCC=nullptr)
This must be called when the Inliner pass is entered, to allow the InlineAdvisor update internal stat...
const char * getAnnotatedInlinePassName() const
NOTE pass name is annotated only when inline advisor constructor provides InlineContext.
virtual void onPassExit(LazyCallGraph::SCC *SCC=nullptr)
This must be called when the Inliner pass is exited, as function passes may be run subsequently.
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:89
InlineResult is basically true or false.
Definition: InlineCost.h:179
An SCC of the call graph.
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:65
The optimization diagnostic interface.
Diagnostic information for applied optimization remarks.
Used for dynamically registering InlineAdvisors as plugins.
PluginInlineAdvisorAnalysis(AdvisorFactory Factory)
InlineAdvisor *(* AdvisorFactory)(Module &M, FunctionAnalysisManager &FAM, InlineParams Params, InlineContext IC)
Result run(Module &M, ModuleAnalysisManager &MAM)
A set of analyses that are preserved following a run of a transformation pass.
Definition: Analysis.h:111
PreservedAnalysisChecker getChecker() const
Build a checker for this PreservedAnalyses and the specified analysis type.
Definition: Analysis.h:264
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
An efficient, type-erasing, non-owning reference to a callable.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
@ BasicBlock
Various leaf nodes.
Definition: ISDOpcodes.h:71
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
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.
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:42
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.
std::unique_ptr< InlineAdvisor > getReleaseModeAdvisor(Module &M, ModuleAnalysisManager &MAM, std::function< bool(CallBase &)> GetDefaultAdvice)
void setInlineRemark(CallBase &CB, StringRef Message)
Set the inline-remark attribute.
std::string AnnotateInlinePassName(InlineContext IC)
ThinOrFullLTOPhase
This enumerates the LLVM full LTO or ThinLTO optimization phases.
Definition: Pass.h:76
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 > getDevelopmentModeAdvisor(Module &M, ModuleAnalysisManager &MAM, std::function< bool(CallBase &)> GetDefaultAdvice)
void addLocationToRemarks(OptimizationRemark &Remark, DebugLoc DLoc)
Add location info to ORE message.
@ Default
The result values are uniform if and only if all operands are uniform.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition: MIRParser.h:38
A CRTP mix-in that provides informational APIs needed for analysis passes.
Definition: PassManager.h:92
A special type used by analysis passes to provide an address that identifies that particular analysis...
Definition: Analysis.h:28
Support structure for SCC passes to communicate updates the call graph back to the CGSCC pass manager...
bool tryCreate(InlineParams Params, InliningAdvisorMode Mode, const ReplayInlinerSettings &ReplaySettings, InlineContext IC)
InlineAdvisor * getAdvisor() const
Result(Module &M, ModuleAnalysisManager &MAM)
bool invalidate(Module &, const PreservedAnalyses &PA, ModuleAnalysisManager::Invalidator &)
Provides context on when an inline advisor is constructed in the pipeline (e.g., link phase,...
Definition: InlineAdvisor.h:58
ThinOrFullLTOPhase LTOPhase
Definition: InlineAdvisor.h:59
Thresholds to tune inline cost analysis.
Definition: InlineCost.h:205
A CRTP mix-in to automatically provide informational APIs needed for passes.
Definition: PassManager.h:69