Go to the documentation of this file.
31 #if defined(LLVM_HAVE_TF_AOT_INLINERSIZEMODEL)
34 #include "InlinerSizeModel.h"
36 std::unique_ptr<InlineAdvisor>
39 std::make_unique<ReleaseModeModelRunner<llvm::InlinerSizeModel>>(
41 return std::make_unique<MLInlineAdvisor>(M,
MAM,
std::move(AOTRunner));
45 #define DEBUG_TYPE "inline-ml"
48 "ml-advisor-size-increase-threshold",
cl::Hidden,
49 cl::desc(
"Maximum factor by which expected native size may increase before "
50 "blocking any further inlining."),
55 #define POPULATE_NAMES(_, NAME) TensorSpec::createSpec<int64_t>(NAME, {1} ),
61 #define POPULATE_NAMES(_, NAME, __) TensorSpec::createSpec<int64_t>(NAME, {1} ),
72 if (
auto *CS = dyn_cast<CallBase>(&
I))
74 if (!
Callee->isDeclaration()) {
82 std::unique_ptr<MLModelRunner> Runner)
87 InitialIRSize(getModuleIRSize()), CurrentIRSize(InitialIRSize) {
98 const std::vector<CallGraphNode *> &CGNodes = *
I;
100 for (
auto *CGNode : CGNodes) {
102 if (!
F ||
F->isDeclaration())
106 auto *Called = CS->getCalledFunction();
107 auto Pos = FunctionLevels.find(&CG.
get(*Called));
111 if (Pos == FunctionLevels.end())
117 for (
auto *CGNode : CGNodes) {
119 if (
F && !
F->isDeclaration())
123 for (
auto KVP : FunctionLevels) {
124 AllNodes.insert(KVP.first);
127 NodeCount = AllNodes.size();
148 NodeCount -=
static_cast<int64_t
>(NodesInLastSCC.size());
149 while (!NodesInLastSCC.empty()) {
150 const auto *
N = NodesInLastSCC.front();
151 NodesInLastSCC.pop_front();
154 assert(!
N->getFunction().isDeclaration());
159 for (
const auto &
E : *(*
N)) {
160 const auto *AdjNode = &
E.getNode();
161 assert(!AdjNode->isDead() && !AdjNode->getFunction().isDeclaration());
162 auto I = AllNodes.insert(AdjNode);
164 NodesInLastSCC.push_back(AdjNode);
168 EdgeCount -= EdgesOfLastSeenNodes;
169 EdgesOfLastSeenNodes = 0;
178 assert(NodesInLastSCC.empty());
180 EdgesOfLastSeenNodes = 0;
181 for (
const auto &
N : *LastSCC) {
184 NodesInLastSCC.push_back(&
N);
186 assert(EdgeCount >= EdgesOfLastSeenNodes);
191 .DirectCallsToDefinedFunctions;
200 bool CalleeWasDeleted) {
211 int64_t IRSizeAfter =
222 int64_t NewCallerAndCalleeEdges =
224 .DirectCallsToDefinedFunctions;
226 if (CalleeWasDeleted)
229 NewCallerAndCalleeEdges +=
231 .DirectCallsToDefinedFunctions;
233 assert(CurrentIRSize >= 0 && EdgeCount >= 0 && NodeCount >= 0);
236 int64_t MLInlineAdvisor::getModuleIRSize()
const {
239 if (!
F.isDeclaration())
271 <<
"Won't attempt inlining because module size grew too much.";
273 return std::make_unique<InlineAdvice>(
this, CB, ORE, Mandatory);
276 int CostEstimate = 0;
278 auto IsCallSiteInlinable =
280 if (!IsCallSiteInlinable) {
284 return std::make_unique<InlineAdvice>(
this, CB, ORE,
false);
286 CostEstimate = *IsCallSiteInlinable;
289 const auto CostFeatures =
292 return std::make_unique<InlineAdvice>(
this, CB, ORE,
false);
298 auto NrCtantParams = 0;
300 NrCtantParams += (isa<Constant>(*
I));
306 *
ModelRunner->getTensor<int64_t>(FeatureIndex::CalleeBasicBlockCount) =
307 CalleeBefore.BasicBlockCount;
308 *
ModelRunner->getTensor<int64_t>(FeatureIndex::CallSiteHeight) =
310 *
ModelRunner->getTensor<int64_t>(FeatureIndex::NodeCount) = NodeCount;
311 *
ModelRunner->getTensor<int64_t>(FeatureIndex::NrCtantParams) = NrCtantParams;
312 *
ModelRunner->getTensor<int64_t>(FeatureIndex::EdgeCount) = EdgeCount;
313 *
ModelRunner->getTensor<int64_t>(FeatureIndex::CallerUsers) =
316 FeatureIndex::CallerConditionallyExecutedBlocks) =
317 CallerBefore.BlocksReachedFromConditionalInstruction;
318 *
ModelRunner->getTensor<int64_t>(FeatureIndex::CallerBasicBlockCount) =
319 CallerBefore.BasicBlockCount;
321 FeatureIndex::CalleeConditionallyExecutedBlocks) =
322 CalleeBefore.BlocksReachedFromConditionalInstruction;
323 *
ModelRunner->getTensor<int64_t>(FeatureIndex::CalleeUsers) =
325 *
ModelRunner->getTensor<int64_t>(FeatureIndex::CostEstimate) = CostEstimate;
337 std::unique_ptr<MLInlineAdvice>
340 return std::make_unique<MLInlineAdvice>(
341 this, CB, ORE,
static_cast<bool>(
ModelRunner->evaluate<int64_t>()));
347 if (Advice && !ForceStop)
354 return std::make_unique<InlineAdvice>(
this, CB,
getCallerORE(CB), Advice);
357 std::unique_ptr<MLInlineAdvice>
359 return std::make_unique<MLInlineAdvice>(
this, CB,
getCallerORE(CB),
true);
362 void MLInlineAdvice::reportContextForRemark(
368 *getAdvisor()->getModelRunner().getTensor<int64_t>(
I));
375 reportContextForRemark(R);
385 reportContextForRemark(R);
396 reportContextForRemark(R);
403 reportContextForRemark(R);
A set of analyses that are preserved following a run of a transformation pass.
static cl::opt< float > SizeIncreaseThreshold("ml-advisor-size-increase-threshold", cl::Hidden, cl::desc("Maximum factor by which expected native size may increase before " "blocking any further inlining."), cl::init(2.0))
Analysis pass providing the TargetTransformInfo.
#define INLINE_COST_FEATURE_ITERATOR(M)
This is an optimization pass for GlobalISel generic memory operations.
std::unique_ptr< InlineAdvisor > getReleaseModeAdvisor(Module &M, ModuleAnalysisManager &MAM)
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
constexpr FeatureIndex inlineCostFeatureToMlFeature(InlineCostFeatureIndex Feature)
int64_t getLocalCalls(Function &F)
const std::array< TensorSpec, NumberOfFeatures > FeatureMap
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
void invalidate(IRUnitT &IR, const PreservedAnalyses &PA)
Invalidate cached analyses for an IR unit.
CallBase * getInlinableCS(Instruction &I)
The basic data container for the call graph of a Module of IR.
void abandon()
Mark an analysis as abandoned.
Node * lookup(const Function &F) const
Lookup a function in the graph which has already been scanned and added.
#define POPULATE_NAMES(_, NAME)
DiagnosticInfoOptimizationBase::Argument NV
std::unique_ptr< MLModelRunner > ModelRunner
User::op_iterator arg_begin()
Return the iterator pointing to the beginning of the argument list.
const int64_t CalleeIRSize
Common features for diagnostics dealing with optimization remarks that are used by both IR and MIR pa...
void recordInliningImpl() override
Function * getCallee() const
OptimizationRemarkEmitter & getCallerORE(CallBase &CB)
An SCC of the call graph.
const char *const DecisionName
void recordInliningWithCalleeDeletedImpl() override
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
OptimizationRemarkEmitter & ORE
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
ModuleAnalysisManager MAM
void recordUnsuccessfulInliningImpl(const InlineResult &Result) override
const char *const DefaultDecisionName
int64_t getIRSize(const Function &F) const
Function * getCaller() const
Function * getCaller()
Helper to get the caller (the parent function).
virtual std::unique_ptr< MLInlineAdvice > getMandatoryAdviceImpl(CallBase &CB)
Node & get(Function &F)
Get a graph node for a given function, scanning it to populate the graph data as necessary.
scc_iterator< T > scc_begin(const T &G)
Construct the begin iterator for a deduced graph type T.
inst_range instructions(Function *F)
MLInlineAdvisor(Module &M, ModuleAnalysisManager &MAM, std::unique_ptr< MLModelRunner > ModelRunner)
A function analysis which provides an AssumptionCache.
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
const BasicBlock *const Block
initializer< Ty > init(const Ty &Val)
std::unique_ptr< InlineAdvice > getMandatoryAdvice(CallBase &CB, bool Advice) override
const int64_t CallerAndCalleeEdges
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
A Module instance is used to store all the information related to an LLVM module.
User::op_iterator arg_end()
Return the iterator pointing to the end of the argument list.
bool isInliningRecommended() const
Get the inlining recommendation.
unsigned getInitialFunctionLevel(const Function &F) const
A cache of @llvm.assume calls within a function.
Interface for deciding whether to inline a call site or not.
StringRef getName() const
Return a constant reference to the value's name.
amdgpu Simplify well known AMD library false FunctionCallee Callee
void onPassEntry() override
This must be called when the Inliner pass is entered, to allow the InlineAdvisor update internal stat...
FunctionAnalysisManager & FAM
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Optional< InlineCostFeatures > getInliningCostFeatures(CallBase &Call, TargetTransformInfo &CalleeTTI, function_ref< AssumptionCache &(Function &)> GetAssumptionCache, function_ref< BlockFrequencyInfo &(Function &)> GetBFI=nullptr, ProfileSummaryInfo *PSI=nullptr, OptimizationRemarkEmitter *ORE=nullptr)
Get the expanded cost features.
void onPassExit(LazyCallGraph::SCC *SCC) override
This must be called when the Inliner pass is exited, as function passes may be run subsequently.
An analysis pass which computes the call graph for a module.
const int64_t CallerIRSize
void onSuccessfulInlining(const MLInlineAdvice &Advice, bool CalleeWasDeleted)
static MandatoryInliningKind getMandatoryKind(CallBase &CB, FunctionAnalysisManager &FAM, OptimizationRemarkEmitter &ORE)
Optional< int > getInliningCostEstimate(CallBase &Call, TargetTransformInfo &CalleeTTI, function_ref< AssumptionCache &(Function &)> GetAssumptionCache, function_ref< BlockFrequencyInfo &(Function &)> GetBFI=nullptr, ProfileSummaryInfo *PSI=nullptr, OptimizationRemarkEmitter *ORE=nullptr)
Get the cost estimate ignoring thresholds.
std::unique_ptr< InlineAdvice > getAdviceImpl(CallBase &CB) override
Align max(MaybeAlign Lhs, Align Rhs)
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
A container for analyses that lazily runs them and caches their results.
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
virtual std::unique_ptr< MLInlineAdvice > getAdviceFromModel(CallBase &CB, OptimizationRemarkEmitter &ORE)
constexpr size_t NumberOfFeatures
#define INLINE_FEATURE_ITERATOR(M)
InlineAdvice that tracks changes post inlining.
InlineResult is basically true or false.
const char *const RewardName
void recordUnattemptedInliningImpl() override