15#ifdef LLVM_HAVE_TFLITE
26#ifdef LLVM_HAVE_TFLITE
41 cl::desc(
"Path to saved model evaluating native size from IR."));
43#define DEBUG_TYPE "inline-size-estimator"
45unsigned getMaxInstructionID() {
46#define LAST_OTHER_INST(NR) return NR;
47#include "llvm/IR/Instruction.def"
50class IRToNativeSizeLearning {
52 enum class NamedFeatureIndex :
size_t {
65 static const size_t NumNamedFeatures =
66 static_cast<size_t>(NamedFeatureIndex::NumNamedFeatures);
67 struct FunctionFeatures {
70 std::array<int32_t, NumNamedFeatures> NamedFeatures = {0};
71 std::vector<int32_t> InstructionHistogram;
72 std::vector<int32_t> InstructionPairHistogram;
74 void fillTensor(int32_t *
Ptr)
const;
75 int32_t &operator[](NamedFeatureIndex Pos) {
76 return NamedFeatures[
static_cast<size_t>(Pos)];
79 IRToNativeSizeLearning() =
default;
81 static FunctionFeatures getFunctionFeatures(Function &
F,
93static const std::array<std::pair<size_t, size_t>, 137>
94 ImportantInstructionSuccessions{
95 {{1, 1}, {1, 4}, {1, 5}, {1, 7}, {1, 8}, {1, 9}, {1, 11},
96 {1, 12}, {1, 13}, {1, 14}, {1, 18}, {1, 20}, {1, 22}, {1, 24},
97 {1, 25}, {1, 26}, {1, 27}, {1, 28}, {1, 29}, {1, 30}, {1, 31},
98 {1, 32}, {1, 33}, {1, 34}, {1, 39}, {1, 40}, {1, 42}, {1, 45},
99 {2, 1}, {2, 2}, {2, 13}, {2, 28}, {2, 29}, {2, 32}, {2, 33},
100 {2, 34}, {2, 38}, {2, 48}, {2, 49}, {2, 53}, {2, 55}, {2, 56},
101 {13, 2}, {13, 13}, {13, 26}, {13, 33}, {13, 34}, {13, 56}, {15, 27},
102 {28, 2}, {28, 48}, {28, 53}, {29, 2}, {29, 33}, {29, 56}, {31, 31},
103 {31, 33}, {31, 34}, {31, 49}, {32, 1}, {32, 2}, {32, 13}, {32, 15},
104 {32, 28}, {32, 29}, {32, 32}, {32, 33}, {32, 34}, {32, 39}, {32, 40},
105 {32, 48}, {32, 49}, {32, 53}, {32, 56}, {33, 1}, {33, 2}, {33, 32},
106 {33, 33}, {33, 34}, {33, 49}, {33, 53}, {33, 56}, {34, 1}, {34, 2},
107 {34, 32}, {34, 33}, {34, 34}, {34, 49}, {34, 53}, {34, 56}, {38, 34},
108 {39, 57}, {40, 34}, {47, 15}, {47, 49}, {48, 2}, {48, 34}, {48, 56},
109 {49, 1}, {49, 2}, {49, 28}, {49, 32}, {49, 33}, {49, 34}, {49, 39},
110 {49, 49}, {49, 56}, {53, 1}, {53, 2}, {53, 28}, {53, 34}, {53, 53},
111 {53, 57}, {55, 1}, {55, 28}, {55, 34}, {55, 53}, {55, 55}, {55, 56},
112 {56, 1}, {56, 2}, {56, 7}, {56, 13}, {56, 32}, {56, 33}, {56, 34},
113 {56, 49}, {56, 53}, {56, 56}, {56, 64}, {57, 34}, {57, 56}, {57, 57},
114 {64, 1}, {64, 64}, {65, 1}, {65, 65}}};
123const size_t IRToNativeSizeLearning::FunctionFeatures::FeatureCount =
124 ImportantInstructionSuccessions.size() + getMaxInstructionID() + 1 +
125 IRToNativeSizeLearning::NumNamedFeatures;
129 for (
const auto &BB :
F)
130 for (
const auto &
I : BB)
131 Ret +=
TTI.getInstructionCost(
142unsigned getMaxDominatorTreeDepth(
const Function &
F,
145 for (
const auto &BB :
F)
146 if (
const auto *TN = Tree.
getNode(&BB))
147 Ret = std::max(Ret, TN->getLevel());
152IRToNativeSizeLearning::FunctionFeatures
153IRToNativeSizeLearning::getFunctionFeatures(
Function &
F,
156 "expected function features are sorted");
160 size_t InstrCount = getMaxInstructionID() + 1;
163 FF.InstructionPairHistogram.resize(ImportantInstructionSuccessions.size());
166 int LastID = StartID;
167 auto getPairIndex = [](
size_t a,
size_t b) {
168 auto I =
llvm::find(ImportantInstructionSuccessions, std::make_pair(a, b));
169 if (
I == ImportantInstructionSuccessions.end())
171 return static_cast<int>(
172 std::distance(ImportantInstructionSuccessions.begin(),
I));
176 for (
const auto &BB :
F) {
177 for (
const auto &
I : BB.instructionsWithoutDebug()) {
178 auto ID =
I.getOpcode();
180 ++FF.InstructionHistogram[
ID];
181 int PairIndex = getPairIndex(LastID,
ID);
183 ++FF.InstructionPairHistogram[PairIndex];
186 ++FF[NamedFeatureIndex::Calls];
190 FF[NamedFeatureIndex::InitialSize] =
getSize(
F,
FAM);
191 FF[NamedFeatureIndex::IsLocal] =
F.hasLocalLinkage();
192 FF[NamedFeatureIndex::IsLinkOnceODR] =
F.hasLinkOnceODRLinkage();
193 FF[NamedFeatureIndex::IsLinkOnce] =
F.hasLinkOnceLinkage();
194 FF[NamedFeatureIndex::Blocks] =
F.size();
196 FF[NamedFeatureIndex::Loops] = std::distance(LI.begin(), LI.end());
198 FF[NamedFeatureIndex::MaxLoopDepth] =
199 std::max(FF[NamedFeatureIndex::MaxLoopDepth],
200 static_cast<int32_t
>(
L->getLoopDepth()));
201 FF[NamedFeatureIndex::MaxDomTreeLevel] = getMaxDominatorTreeDepth(
F, DomTree);
205void IRToNativeSizeLearning::FunctionFeatures::fillTensor(int32_t *
Ptr)
const {
206 std::copy(NamedFeatures.begin(), NamedFeatures.end(),
Ptr);
207 Ptr += NamedFeatures.size();
208 std::copy(InstructionHistogram.begin(), InstructionHistogram.end(),
Ptr);
209 Ptr += InstructionHistogram.size();
210 std::copy(InstructionPairHistogram.begin(), InstructionPairHistogram.end(),
215 return !TFIR2NativeModelPath.empty();
223 "serving_default_input_1",
224 {1,
static_cast<int64_t
>(
225 IRToNativeSizeLearning::FunctionFeatures::FeatureCount)})};
226 std::vector<TensorSpec> OutputSpecs{
228 Evaluator = std::make_unique<TFModelEvaluator>(
229 TFIR2NativeModelPath.getValue().c_str(), InputSpecs, OutputSpecs);
230 if (!Evaluator || !Evaluator->isValid()) {
241 auto Features = IRToNativeSizeLearning::getFunctionFeatures(
243 int32_t *
V = Evaluator->getInput<int32_t>(0);
244 Features.fillTensor(V);
245 auto ER = Evaluator->evaluate();
248 float Ret = *ER->getTensorValue<
float>(0);
251 return static_cast<size_t>(
Ret);
264InlineSizeEstimatorAnalysis ::InlineSizeEstimatorAnalysis(
278 OS <<
"[InlineSizeEstimatorAnalysis] size estimate for " <<
F.getName()
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static unsigned InstrCount
This header defines various interfaces for pass management in LLVM.
FunctionAnalysisManager FAM
static unsigned getSize(unsigned Kind)
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Analysis pass which computes a DominatorTree.
DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const
getNode - return the (Post)DominatorTree node for the specified basic block.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
This class evaluates LLVM IR, producing the Constant representing each SSA instruction.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
InlineSizeEstimatorAnalysis()
~InlineSizeEstimatorAnalysis()
Result run(const Function &F, FunctionAnalysisManager &FAM)
static bool isEvaluatorRequested()
std::optional< size_t > Result
Analysis pass that exposes the LoopInfo for a function.
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.
Analysis pass providing the TargetTransformInfo.
static TensorSpec createSpec(const std::string &Name, const std::vector< int64_t > &Shape, int Port=0)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
This is an optimization pass for GlobalISel generic memory operations.
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
bool is_sorted(R &&Range, Compare C)
Wrapper function around std::is_sorted to check if elements in a range R are sorted with respect to a...
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...
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
A special type used by analysis passes to provide an address that identifies that particular analysis...