LLVM  12.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_INLINEADVISOR_H_
10 #define LLVM_INLINEADVISOR_H_
11 
12 #include <memory>
13 #include <unordered_set>
14 #include <vector>
15 
17 #include "llvm/IR/PassManager.h"
18 
19 namespace llvm {
20 class BasicBlock;
21 class CallBase;
22 class Function;
23 class Module;
24 class OptimizationRemarkEmitter;
25 
26 /// There are 3 scenarios we can use the InlineAdvisor:
27 /// - Default - use manual heuristics.
28 ///
29 /// - Release mode, the expected mode for production, day to day deployments.
30 /// In this mode, when building the compiler, we also compile a pre-trained ML
31 /// model to native code, and link it as a static library. This mode has low
32 /// overhead and no additional dependencies for the compiler runtime.
33 ///
34 /// - Development mode, for training new models.
35 /// In this mode, we trade off runtime performance for flexibility. This mode
36 /// requires the full C Tensorflow API library, and evaluates models
37 /// dynamically. This mode also permits generating training logs, for offline
38 /// training.
40 
41 class InlineAdvisor;
42 /// Capture state between an inlining decision having had been made, and
43 /// its impact being observable. When collecting model training data, this
44 /// allows recording features/decisions/partial reward data sets.
45 ///
46 /// Derivations of this type are expected to be tightly coupled with their
47 /// InliningAdvisors. The base type implements the minimal contractual
48 /// obligations.
49 class InlineAdvice {
50 public:
51  InlineAdvice(InlineAdvisor *Advisor, CallBase &CB,
52  OptimizationRemarkEmitter &ORE, bool IsInliningRecommended);
53 
54  InlineAdvice(InlineAdvice &&) = delete;
55  InlineAdvice(const InlineAdvice &) = delete;
56  virtual ~InlineAdvice() {
57  assert(Recorded && "InlineAdvice should have been informed of the "
58  "inliner's decision in all cases");
59  }
60 
61  /// Exactly one of the record* APIs must be called. Implementers may extend
62  /// behavior by implementing the corresponding record*Impl.
63  ///
64  /// Call after inlining succeeded, and did not result in deleting the callee.
65  void recordInlining() {
66  markRecorded();
67  recordInliningImpl();
68  }
69 
70  /// Call after inlining succeeded, and resulted in deleting the callee.
71  void recordInliningWithCalleeDeleted();
72 
73  /// Call after the decision for a call site was to not inline.
75  markRecorded();
76  recordUnsuccessfulInliningImpl(Result);
77  }
78 
79  /// Call to indicate inlining was not attempted.
81  markRecorded();
82  recordUnattemptedInliningImpl();
83  }
84 
85  /// Get the inlining recommendation.
86  bool isInliningRecommended() const { return IsInliningRecommended; }
87  const DebugLoc &getOriginalCallSiteDebugLoc() const { return DLoc; }
88  const BasicBlock *getOriginalCallSiteBasicBlock() const { return Block; }
89 
90 protected:
91  virtual void recordInliningImpl() {}
93  virtual void recordUnsuccessfulInliningImpl(const InlineResult &Result) {}
95 
97  /// Caller and Callee are pre-inlining.
98  Function *const Caller;
99  Function *const Callee;
100 
101  // Capture the context of CB before inlining, as a successful inlining may
102  // change that context, and we want to report success or failure in the
103  // original context.
104  const DebugLoc DLoc;
105  const BasicBlock *const Block;
108 
109 private:
110  void markRecorded() {
111  assert(!Recorded && "Recording should happen exactly once");
112  Recorded = true;
113  }
114 
115  bool Recorded = false;
116 };
117 
118 /// Interface for deciding whether to inline a call site or not.
120 public:
121  InlineAdvisor(InlineAdvisor &&) = delete;
122  virtual ~InlineAdvisor() { freeDeletedFunctions(); }
123 
124  /// Get an InlineAdvice containing a recommendation on whether to
125  /// inline or not. \p CB is assumed to be a direct call. \p FAM is assumed to
126  /// be up-to-date wrt previous inlining decisions.
127  /// Returns an InlineAdvice with the inlining recommendation.
128  virtual std::unique_ptr<InlineAdvice> getAdvice(CallBase &CB) = 0;
129 
130  /// This must be called when the Inliner pass is entered, to allow the
131  /// InlineAdvisor update internal state, as result of function passes run
132  /// between Inliner pass runs (for the same module).
133  virtual void onPassEntry() {}
134 
135  /// This must be called when the Inliner pass is exited, as function passes
136  /// may be run subsequently. This allows an implementation of InlineAdvisor
137  /// to prepare for a partial update.
138  virtual void onPassExit() {}
139 
140 protected:
142 
144 
145  /// We may want to defer deleting functions to after the inlining for a whole
146  /// module has finished. This allows us to reliably use function pointers as
147  /// unique identifiers, as an efficient implementation detail of the
148  /// InlineAdvisor. Otherwise, it is possible the memory allocator
149  /// re-allocate Function objects at the same address of a deleted Function;
150  /// and Functions are potentially created during the function passes called
151  /// after each SCC inlining (e.g. argument promotion does that).
152  void freeDeletedFunctions();
153 
154  bool isFunctionDeleted(const Function *F) const {
155  return DeletedFunctions.count(F);
156  }
157 
158 private:
159  friend class InlineAdvice;
160  void markFunctionAsDeleted(Function *F);
161  std::unordered_set<const Function *> DeletedFunctions;
162 };
163 
164 /// The default (manual heuristics) implementation of the InlineAdvisor. This
165 /// implementation does not need to keep state between inliner pass runs, and is
166 /// reusable as-is for inliner pass test scenarios, as well as for regular use.
168 public:
170  : InlineAdvisor(FAM), Params(Params) {}
171 
172 private:
173  std::unique_ptr<InlineAdvice> getAdvice(CallBase &CB) override;
174 
175  void onPassExit() override { freeDeletedFunctions(); }
176 
177  InlineParams Params;
178 };
179 
180 /// The InlineAdvisorAnalysis is a module pass because the InlineAdvisor
181 /// needs to capture state right before inlining commences over a module.
182 class InlineAdvisorAnalysis : public AnalysisInfoMixin<InlineAdvisorAnalysis> {
183 public:
184  static AnalysisKey Key;
185  InlineAdvisorAnalysis() = default;
186  struct Result {
187  Result(Module &M, ModuleAnalysisManager &MAM) : M(M), MAM(MAM) {}
190  // InlineAdvisor must be preserved across analysis invalidations.
191  return false;
192  }
193  bool tryCreate(InlineParams Params, InliningAdvisorMode Mode);
194  InlineAdvisor *getAdvisor() const { return Advisor.get(); }
195  void clear() { Advisor.reset(); }
196 
197  private:
198  Module &M;
200  std::unique_ptr<InlineAdvisor> Advisor;
201  };
202 
203  Result run(Module &M, ModuleAnalysisManager &MAM) { return Result(M, MAM); }
204 };
205 
206 #ifdef LLVM_HAVE_TF_AOT
207 std::unique_ptr<InlineAdvisor>
208 getReleaseModeAdvisor(Module &M, ModuleAnalysisManager &MAM);
209 #endif
210 
211 // Default (manual policy) decision making helper APIs. Shared with the legacy
212 // pass manager inliner.
213 
214 /// Return the cost only if the inliner should attempt to inline at the given
215 /// CallSite. If we return the cost, we will emit an optimisation remark later
216 /// using that cost, so we won't do so from this function. Return None if
217 /// inlining should not be attempted.
219 shouldInline(CallBase &CB, function_ref<InlineCost(CallBase &CB)> GetInlineCost,
220  OptimizationRemarkEmitter &ORE, bool EnableDeferral = true);
221 
222 /// Emit ORE message.
224  const BasicBlock *Block, const Function &Callee,
225  const Function &Caller, const InlineCost &IC,
226  bool ForProfileContext = false,
227  const char *PassName = nullptr);
228 
229 /// Add location info to ORE message.
231 
232 /// Set the inline-remark attribute.
233 void setInlineRemark(CallBase &CB, StringRef Message);
234 
235 /// Utility for extracting the inline cost message to a string.
236 std::string inlineCostStr(const InlineCost &IC);
237 } // namespace llvm
238 #endif // LLVM_INLINEADVISOR_H_
virtual ~InlineAdvice()
Definition: InlineAdvisor.h:56
Capture state between an inlining decision having had been made, and its impact being observable...
Definition: InlineAdvisor.h:49
Thresholds to tune inline cost analysis.
Definition: InlineCost.h:160
The default (manual heuristics) implementation of the InlineAdvisor.
SI Whole Quad Mode
InlineAdvisor * getAdvisor() const
This class represents lattice values for constants.
Definition: AllocatorList.h:23
Various leaf nodes.
Definition: ISDOpcodes.h:64
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:67
Machine Debugify Module
void addLocationToRemarks(OptimizationRemark &Remark, DebugLoc DLoc)
Add location info to ORE message.
An efficient, type-erasing, non-owning reference to a callable.
Definition: STLExtras.h:176
static AnalysisKey Key
InliningAdvisorMode
There are 3 scenarios we can use the InlineAdvisor:
Definition: InlineAdvisor.h:39
A debug info location.
Definition: DebugLoc.h:33
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Definition: InstrTypes.h:1100
F(f)
Represents the cost of inlining a function.
Definition: InlineCost.h:67
void recordInlining()
Exactly one of the record* APIs must be called.
Definition: InlineAdvisor.h:65
Interface for deciding whether to inline a call site or not.
std::string inlineCostStr(const InlineCost &IC)
Utility for extracting the inline cost message to a string.
The InlineAdvisorAnalysis is a module pass because the InlineAdvisor needs to capture state right bef...
void setInlineRemark(CallBase &CB, StringRef Message)
Set the inline-remark attribute.
InlineAdvisor(FunctionAnalysisManager &FAM)
OptimizationRemarkEmitter & ORE
virtual void onPassExit()
This must be called when the Inliner pass is exited, as function passes may be run subsequently...
InlineResult is basically true or false.
Definition: InlineCost.h:134
Function *const Callee
Definition: InlineAdvisor.h:99
bool isInliningRecommended() const
Get the inlining recommendation.
Definition: InlineAdvisor.h:86
A set of analyses that are preserved following a run of a transformation pass.
Definition: PassManager.h:154
LLVM Basic Block Representation.
Definition: BasicBlock.h:58
Function *const Caller
Caller and Callee are pre-inlining.
Definition: InlineAdvisor.h:98
void recordUnattemptedInlining()
Call to indicate inlining was not attempted.
Definition: InlineAdvisor.h:80
A CRTP mix-in that provides informational APIs needed for analysis passes.
Definition: PassManager.h:390
Diagnostic information for applied optimization remarks.
const DebugLoc & getOriginalCallSiteDebugLoc() const
Definition: InlineAdvisor.h:87
DefaultInlineAdvisor(FunctionAnalysisManager &FAM, InlineParams Params)
virtual void onPassEntry()
This must be called when the Inliner pass is entered, to allow the InlineAdvisor update internal stat...
const bool IsInliningRecommended
bool invalidate(Module &, const PreservedAnalyses &, ModuleAnalysisManager::Invalidator &)
Optional< InlineCost > shouldInline(CallBase &CB, 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.
void recordUnsuccessfulInlining(const InlineResult &Result)
Call after the decision for a call site was to not inline.
Definition: InlineAdvisor.h:74
bool isFunctionDeleted(const Function *F) const
virtual void recordUnsuccessfulInliningImpl(const InlineResult &Result)
Definition: InlineAdvisor.h:93
amdgpu Simplify well known AMD library false FunctionCallee Callee
virtual ~InlineAdvisor()
FunctionAnalysisManager & FAM
const BasicBlock *const Block
virtual void recordInliningImpl()
Definition: InlineAdvisor.h:91
void emitInlinedInto(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.
Result run(Module &M, ModuleAnalysisManager &MAM)
API to communicate dependencies between analyses during invalidation.
Definition: PassManager.h:654
const DebugLoc DLoc
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Result(Module &M, ModuleAnalysisManager &MAM)
InlineAdvisor *const Advisor
Definition: InlineAdvisor.h:96
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
A container for analyses that lazily runs them and caches their results.
This header defines various interfaces for pass management in LLVM.
const BasicBlock * getOriginalCallSiteBasicBlock() const
Definition: InlineAdvisor.h:88
virtual void recordInliningWithCalleeDeletedImpl()
Definition: InlineAdvisor.h:92
virtual void recordUnattemptedInliningImpl()
Definition: InlineAdvisor.h:94
The optimization diagnostic interface.
A special type used by analysis passes to provide an address that identifies that particular analysis...
Definition: PassManager.h:71