40 "inliner-interactive-channel-base",
cl::Hidden,
42 "Base file path for the interactive mode. The incoming filename should "
43 "have the name <inliner-interactive-channel-base>.in, while the "
44 "outgoing name should be <inliner-interactive-channel-base>.out"));
46 (
Twine(
"In interactive mode, also send the default policy decision: ") +
59 "if-caller-not-cold",
"if the caller is not cold")));
67#if defined(LLVM_HAVE_TF_AOT_INLINERSIZEMODEL)
69#include "InlinerSizeModel.h"
76#include "llvm/Analysis/InlinerModels.h"
80#define MLGO_MODEL(CLASS_NAME, CLI_FLAG) CLASS_NAME,
81#include "llvm/Analysis/InlinerModels.def"
88 "Use standard heuristic")
90 ,
clEnumValN(EmitCModelChoice::CLASS_NAME, CLI_FLAG, \
91 "Use the " CLI_FLAG
" MLGO model")
92#include
"llvm/Analysis/InlinerModels.def"
95static std::unique_ptr<MLModelRunner>
101#define MLGO_MODEL(CLASS_NAME, CLI_FLAG) \
102 case EmitCModelChoice::CLASS_NAME: \
103 return std::make_unique<EmitCModelRunner<CLASS_NAME>>(Ctx, InputFeatures);
104#include "llvm/Analysis/InlinerModels.def"
109std::unique_ptr<InlineAdvisor>
111 std::function<
bool(
CallBase &)> GetDefaultAdvice) {
115 auto RunnerFactory = [&](
const std::vector<TensorSpec> &
InputFeatures)
116 -> std::unique_ptr<MLModelRunner> {
122 return std::make_unique<MLInlineAdvisor>(M,
MAM, RunnerFactory,
126#define DEBUG_TYPE "inline-ml"
129 "ml-advisor-size-increase-threshold",
cl::Hidden,
130 cl::desc(
"Maximum factor by which expected native size may increase before "
131 "blocking any further inlining."),
137 "For test - keep the ML Inline advisor's FunctionPropertiesInfo cache"),
143#define POPULATE_NAMES(DTYPE, SHAPE, NAME, __) TensorSpec::createSpec<DTYPE>(#NAME, SHAPE),
165 if (
Function *Callee = CS->getCalledFunction()) {
166 if (!Callee->isDeclaration()) {
176 std::unique_ptr<MLModelRunner>(
const std::vector<TensorSpec> &)>
184 InitialIRSize(getModuleIRSize()), CurrentIRSize(InitialIRSize),
194 const std::vector<CallGraphNode *> &CGNodes = *
I;
196 for (
auto *CGNode : CGNodes) {
198 if (!
F ||
F->isDeclaration())
202 auto *Called = CS->getCalledFunction();
203 auto Pos = FunctionLevels.find(&CG.get(*Called));
207 if (Pos == FunctionLevels.end())
209 Level = std::max(Level, Pos->second + 1);
213 for (
auto *CGNode : CGNodes) {
215 if (
F && !
F->isDeclaration())
216 FunctionLevels[&CG.get(*
F)] = Level;
219 for (
auto KVP : FunctionLevels) {
220 AllNodes.insert(KVP.first);
223 NodeCount = AllNodes.size();
226 if (!IR2VecVocabResult->isValid()) {
227 M.getContext().emitError(
"IR2VecVocabAnalysis is not valid");
231 auto IR2VecDim = IR2VecVocabResult->getDimension();
242 M.getContext().emitError(
"Could not create model runner");
250 return CG.lookup(
F) ? FunctionLevels.at(CG.lookup(
F)) : 0;
254 if (!CurSCC || ForceStop)
274 while (!NodesInLastSCC.empty()) {
275 const auto *
N = *NodesInLastSCC.begin();
277 NodesInLastSCC.erase(
N);
279 const auto NLevel = FunctionLevels.at(
N);
280 for (
const auto &E : *(*
N)) {
281 const auto *AdjNode = &E.getNode();
282 assert(!AdjNode->isDead() && !AdjNode->getFunction().isDeclaration());
283 auto I = AllNodes.insert(AdjNode);
287 NodesInLastSCC.insert(AdjNode);
288 FunctionLevels[AdjNode] = NLevel;
293 EdgeCount -= EdgesOfLastSeenNodes;
294 EdgesOfLastSeenNodes = 0;
298 assert(NodesInLastSCC.empty());
299 for (
const auto &
N : *CurSCC)
300 NodesInLastSCC.insert(&
N);
307 if (!CurSCC || ForceStop)
312 EdgesOfLastSeenNodes = 0;
321 for (
const auto &
N : *CurSCC) {
323 auto I = NodesInLastSCC.insert(&
N);
327 assert(NodeCount >= NodesInLastSCC.size());
328 assert(EdgeCount >= EdgesOfLastSeenNodes);
341 bool CalleeWasDeleted) {
350 FAM.invalidate(*Caller, PA);
353 if (Caller == Callee) {
354 assert(!CalleeWasDeleted);
363 int64_t IRSizeAfter =
372 int64_t NewCallerAndCalleeEdges =
378 if (CalleeWasDeleted) {
380 NodesInLastSCC.erase(CG.lookup(*Callee));
381 DeadFunctions.insert(Callee);
383 NewCallerAndCalleeEdges +=
391 assert(CurrentIRSize >= 0 && EdgeCount >= 0 && NodeCount >= 0);
394int64_t MLInlineAdvisor::getModuleIRSize()
const {
397 if (!
F.isDeclaration())
403 auto InsertPair = FPICache.try_emplace(&
F);
404 if (!InsertPair.second)
405 return InsertPair.first->second;
407 return InsertPair.first->second;
411 if (
auto Skip = getSkipAdviceIfUnreachableCallsite(CB))
424 if (!PSI.isFunctionEntryCold(&Caller)) {
430 return ForceStop ? std::make_unique<InlineAdvice>(
this, CB, ORE,
432 : std::make_unique<MLInlineAdvice>(
this, CB, ORE,
453 <<
"Won't attempt inlining because module size grew too much.";
455 return std::make_unique<InlineAdvice>(
this, CB, ORE, Mandatory);
458 int CostEstimate = 0;
460 auto IsCallSiteInlinable =
462 if (!IsCallSiteInlinable) {
466 return std::make_unique<InlineAdvice>(
this, CB, ORE,
false);
468 CostEstimate = *IsCallSiteInlinable;
471 const auto CostFeatures =
474 return std::make_unique<InlineAdvice>(
this, CB, ORE,
false);
480 auto NumCtantParams = 0;
488 *
ModelRunner->getTensor<int64_t>(FeatureIndex::callee_basic_block_count) =
489 CalleeBefore.BasicBlockCount;
490 *
ModelRunner->getTensor<int64_t>(FeatureIndex::callsite_height) =
492 *
ModelRunner->getTensor<int64_t>(FeatureIndex::node_count) = NodeCount;
493 *
ModelRunner->getTensor<int64_t>(FeatureIndex::nr_ctant_params) =
495 *
ModelRunner->getTensor<int64_t>(FeatureIndex::edge_count) = EdgeCount;
496 *
ModelRunner->getTensor<int64_t>(FeatureIndex::caller_users) =
499 FeatureIndex::caller_conditionally_executed_blocks) =
500 CallerBefore.BlocksReachedFromConditionalInstruction;
501 *
ModelRunner->getTensor<int64_t>(FeatureIndex::caller_basic_block_count) =
502 CallerBefore.BasicBlockCount;
504 FeatureIndex::callee_conditionally_executed_blocks) =
505 CalleeBefore.BlocksReachedFromConditionalInstruction;
506 *
ModelRunner->getTensor<int64_t>(FeatureIndex::callee_users) =
508 *
ModelRunner->getTensor<int64_t>(FeatureIndex::cost_estimate) = CostEstimate;
509 *
ModelRunner->getTensor<int64_t>(FeatureIndex::is_callee_avail_external) =
510 Callee.hasAvailableExternallyLinkage();
511 *
ModelRunner->getTensor<int64_t>(FeatureIndex::is_caller_avail_external) =
512 Caller.hasAvailableExternallyLinkage();
521 [](
double Val) { return static_cast<float>(Val); });
524 setEmbedding(CalleeBefore.getFunctionEmbedding(),
526 setEmbedding(CallerBefore.getFunctionEmbedding(),
543std::unique_ptr<MLInlineAdvice>
546 return std::make_unique<MLInlineAdvice>(
547 this, CB, ORE,
static_cast<bool>(
ModelRunner->evaluate<int64_t>()));
550std::unique_ptr<InlineAdvice>
551MLInlineAdvisor::getSkipAdviceIfUnreachableCallsite(
CallBase &CB) {
554 return std::make_unique<InlineAdvice>(
this, CB,
getCallerORE(CB),
false);
561 if (
auto Skip = getSkipAdviceIfUnreachableCallsite(CB))
563 if (Advice && !ForceStop)
570 return std::make_unique<InlineAdvice>(
this, CB,
getCallerORE(CB), Advice);
573std::unique_ptr<MLInlineAdvice>
575 return std::make_unique<MLInlineAdvice>(
this, CB,
getCallerORE(CB),
true);
578void MLInlineAdvisor::print(
raw_ostream &OS)
const {
579 OS <<
"[MLInlineAdvisor] Nodes: " << NodeCount <<
" Edges: " << EdgeCount
580 <<
" EdgesOfLastSeenNodes: " << EdgesOfLastSeenNodes <<
"\n";
581 OS <<
"[MLInlineAdvisor] FPI:\n";
582 for (
auto I : FPICache) {
583 OS <<
I.first->getName() <<
":\n";
588 OS <<
"[MLInlineAdvisor] FuncLevels:\n";
589 for (
auto I : FunctionLevels)
590 OS << (DeadFunctions.
contains(&
I.first->getFunction())
592 :
I.first->getFunction().getName())
593 <<
" : " <<
I.second <<
"\n";
613void MLInlineAdvice::reportContextForRemark(
618 OR << NV(getAdvisor()->getFeatureMap()[
I].
name(),
619 *getAdvisor()->getModelRunner().getTensor<int64_t>(
I));
630 reportContextForRemark(R);
633 getAdvisor()->onSuccessfulInlining(*
this,
false);
640 reportContextForRemark(R);
643 getAdvisor()->onSuccessfulInlining(*
this,
true);
648 getAdvisor()->getCachedFPI(*
Caller) = PreInlineCallerFPI;
652 reportContextForRemark(R);
660 reportContextForRemark(R);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Expand Atomic instructions
This file provides interfaces used to build and manipulate a call graph, which is a very useful tool ...
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
This file implements a model runner wrapping an EmitC compiled ML model.
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
#define INLINE_COST_FEATURE_ITERATOR(M)
#define INLINE_FEATURE_ITERATOR(M)
Implements a lazy call graph analysis and related passes for the new pass manager.
This file provides helper functions for creating MLModelRunners and checking model validity in releas...
static std::unique_ptr< MLModelRunner > createEmitCModelRunner(LLVMContext &Ctx, const std::vector< TensorSpec > &InputFeatures)
static cl::opt< bool > KeepFPICache("ml-advisor-keep-fpi-cache", cl::Hidden, cl::desc("For test - keep the ML Inline advisor's FunctionPropertiesInfo cache"), cl::init(false))
#define MLGO_MODEL(CLASS_NAME, CLI_FLAG)
static cl::opt< std::string > ModelSelector("ml-inliner-model-selector", cl::Hidden, cl::init(""))
CallBase * getInlinableCS(Instruction &I)
NoopSavedModelImpl CompiledModelType
static cl::opt< std::string > InteractiveChannelBaseName("inliner-interactive-channel-base", cl::Hidden, cl::desc("Base file path for the interactive mode. The incoming filename should " "have the name <inliner-interactive-channel-base>.in, while the " "outgoing name should be <inliner-interactive-channel-base>.out"))
#define POPULATE_NAMES(DTYPE, SHAPE, NAME, __)
static cl::opt< bool > StopImmediatelyForTest("ml-inliner-stop-immediately", cl::Hidden)
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))
static const std::string InclDefaultMsg
static cl::opt< SkipMLPolicyCriteria > SkipPolicy("ml-inliner-skip-policy", cl::Hidden, cl::init(SkipMLPolicyCriteria::Never), cl::values(clEnumValN(SkipMLPolicyCriteria::Never, "never", "never"), clEnumValN(SkipMLPolicyCriteria::IfCallerIsNotCold, "if-caller-not-cold", "if the caller is not cold")))
static cl::opt< bool > InteractiveIncludeDefault("inliner-interactive-include-default", cl::Hidden, cl::desc(InclDefaultMsg))
static llvm::cl::opt< EmitCModelChoice > SelectedMLGOModel("mlgo-model", llvm::cl::desc("Select the MLGO model to execute:"), llvm::cl::init(EmitCModelChoice::Default), llvm::cl::values(clEnumValN(EmitCModelChoice::Default, "default", "Use standard heuristic") #define MLGO_MODEL(CLASS_NAME, CLI_FLAG) \ \))
FunctionAnalysisManager FAM
ModuleAnalysisManager MAM
This builds on the llvm/ADT/GraphTraits.h file to find the strongly connected components (SCCs) of a ...
A function analysis which provides an AssumptionCache.
A cache of @llvm.assume calls within a function.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
User::op_iterator arg_begin()
Return the iterator pointing to the beginning of the argument list.
User::op_iterator arg_end()
Return the iterator pointing to the end of the argument list.
LLVM_ABI Function * getCaller()
Helper to get the caller (the parent function).
The basic data container for the call graph of a Module of IR.
Common features for diagnostics dealing with optimization remarks that are used by both IR and MIR pa...
Analysis pass which computes a DominatorTree.
int64_t DirectCallsToDefinedFunctions
Number of direct calls made from this function to other functions defined in this module.
This analysis provides the vocabulary for IR2Vec.
Function *const Caller
Caller and Callee are pre-inlining.
const BasicBlock *const Block
OptimizationRemarkEmitter & ORE
InlineAdvisor *const Advisor
LLVM_ABI InlineAdvice(InlineAdvisor *Advisor, CallBase &CB, OptimizationRemarkEmitter &ORE, bool IsInliningRecommended)
bool isInliningRecommended() const
Get the inlining recommendation.
OptimizationRemarkEmitter & getCallerORE(CallBase &CB)
FunctionAnalysisManager & FAM
static MandatoryInliningKind getMandatoryKind(CallBase &CB, FunctionAnalysisManager &FAM, OptimizationRemarkEmitter &ORE)
InlineAdvisor(InlineAdvisor &&)=delete
InlineResult is basically true or false.
This is an important class for using LLVM in a threaded context.
An analysis pass which computes the call graph for a module.
A node in the call graph.
An SCC of the call graph.
Analysis pass that exposes the LoopInfo for a function.
InlineAdvice that tracks changes post inlining.
void updateCachedCallerFPI(FunctionAnalysisManager &FAM) const
const int64_t CallerIRSize
MLInlineAdvice(MLInlineAdvisor *Advisor, CallBase &CB, OptimizationRemarkEmitter &ORE, bool Recommendation)
const int64_t CalleeIRSize
void recordInliningImpl() override
Function * getCaller() const
const int64_t CallerAndCalleeEdges
void recordUnsuccessfulInliningImpl(const InlineResult &Result) override
Function * getCallee() const
void recordInliningWithCalleeDeletedImpl() override
void recordUnattemptedInliningImpl() override
const std::vector< TensorSpec > & getFeatureMap() const
std::unique_ptr< MLModelRunner > ModelRunner
FunctionPropertiesInfo & getCachedFPI(Function &) const
void onPassExit(LazyCallGraph::SCC *SCC) override
This must be called when the Inliner pass is exited, as function passes may be run subsequently.
void onSuccessfulInlining(const MLInlineAdvice &Advice, bool CalleeWasDeleted)
static const std::vector< TensorSpec > & getInitialFeatureMap()
virtual std::unique_ptr< MLInlineAdvice > getMandatoryAdviceImpl(CallBase &CB)
void onPassEntry(LazyCallGraph::SCC *SCC) override
This must be called when the Inliner pass is entered, to allow the InlineAdvisor update internal stat...
MLInlineAdvisor(Module &M, ModuleAnalysisManager &MAM, std::function< std::unique_ptr< MLModelRunner >(const std::vector< TensorSpec > &)> GetModelRunner, std::function< bool(CallBase &)> GetDefaultAdvice)
int64_t getLocalCalls(Function &F)
std::vector< TensorSpec > FeatureMap
virtual std::unique_ptr< MLInlineAdvice > getAdviceFromModel(CallBase &CB, OptimizationRemarkEmitter &ORE)
int64_t getIRSize(Function &F) const
std::function< bool(CallBase &)> GetDefaultAdvice
std::unique_ptr< InlineAdvice > getAdviceImpl(CallBase &CB) override
std::unique_ptr< InlineAdvice > getMandatoryAdvice(CallBase &CB, bool Advice) override
unsigned getInitialFunctionLevel(const Function &F) const
A Module instance is used to store all the information related to an LLVM module.
A mock class satisfying the interface expected by ReleaseModeModelRunner for its TGen parameter.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & abandon()
Mark an analysis as abandoned.
An analysis pass based on the new PM to deliver ProfileSummaryInfo.
Analysis pass providing the TargetTransformInfo.
static TensorSpec createSpec(const std::string &Name, const std::vector< int64_t > &Shape, int Port=0)
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
const ParentTy * getParent() const
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
Add a small namespace to avoid name clashes with the classes used in the streaming interface.
This is an optimization pass for GlobalISel generic memory operations.
constexpr FeatureIndex inlineCostFeatureToMlFeature(InlineCostFeatureIndex Feature)
LLVM_ABI const char *const DefaultDecisionName
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
scc_iterator< T > scc_begin(const T &G)
Construct the begin iterator for a deduced graph type T.
LLVM_ABI std::unique_ptr< InlineAdvisor > getReleaseModeAdvisor(Module &M, ModuleAnalysisManager &MAM, std::function< bool(CallBase &)> GetDefaultAdvice)
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
bool isReleaseModelValid(StringRef InteractiveChannelBaseName, const cl::opt< EnumType, ExternalStorage, ParserClass > &SelectedModel, EnumType DefaultModelVal=EnumType::Default)
Helper to check if a release-mode ML advisor has a valid model to execute.
OutputIt transform(R &&Range, OutputIt d_first, UnaryFunction F)
Wrapper function around std::transform to apply a function to a range and store the result elsewhere.
LLVM_ABI const TensorSpec DefaultDecisionSpec
std::unique_ptr< MLModelRunner > createReleaseModeModelRunner(LLVMContext &Ctx, const std::vector< TensorSpec > &InputFeatures, StringRef DecisionName, const std::string &InteractiveChannelBaseName, const TensorSpec &InteractiveDecisionSpec, CreateEmitCFunc &&CreateEmitCModelRunner, const EmbeddedModelRunnerOptions &Options={})
Helper to construct the appropriate MLModelRunner in release mode:
LLVM_ABI const char *const DecisionName
@ Never
Never set the bit.
static const std::vector< TensorSpec > InputFeatures
LLVM_ABI std::optional< InlineCostFeatures > getInliningCostFeatures(CallBase &Call, TargetTransformInfo &CalleeTTI, function_ref< AssumptionCache &(Function &)> GetAssumptionCache, function_ref< BlockFrequencyInfo &(Function &)> GetBFI=nullptr, function_ref< const TargetLibraryInfo &(Function &)> GetTLI=nullptr, ProfileSummaryInfo *PSI=nullptr, OptimizationRemarkEmitter *ORE=nullptr)
Get the expanded cost features.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI const TensorSpec InlineDecisionSpec
LLVM_ABI const char *const RewardName
LLVM_ABI std::optional< int > getInliningCostEstimate(CallBase &Call, TargetTransformInfo &CalleeTTI, function_ref< AssumptionCache &(Function &)> GetAssumptionCache, function_ref< BlockFrequencyInfo &(Function &)> GetBFI=nullptr, function_ref< const TargetLibraryInfo &(Function &)> GetTLI=nullptr, ProfileSummaryInfo *PSI=nullptr, OptimizationRemarkEmitter *ORE=nullptr)
Get the cost estimate ignoring thresholds.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
ReleaseModeModelRunner - production mode implementation of the MLModelRunner.
Embedding is a datatype that wraps std::vector<double>.