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)
132 &
I, TargetTransformInfo::TargetCostKind::TCK_CodeSize).
getValue());
141unsigned getMaxDominatorTreeDepth(
const Function &
F,
144 for (
const auto &BB :
F)
145 if (
const auto *TN = Tree.
getNode(&BB))
146 Ret = std::max(Ret, TN->getLevel());
151IRToNativeSizeLearning::FunctionFeatures
152IRToNativeSizeLearning::getFunctionFeatures(
Function &
F,
155 "expected function features are sorted");
159 size_t InstrCount = getMaxInstructionID() + 1;
162 FF.InstructionPairHistogram.resize(ImportantInstructionSuccessions.size());
165 int LastID = StartID;
166 auto getPairIndex = [](
size_t a,
size_t b) {
167 auto I =
llvm::find(ImportantInstructionSuccessions, std::make_pair(a, b));
168 if (
I == ImportantInstructionSuccessions.end())
170 return static_cast<int>(
171 std::distance(ImportantInstructionSuccessions.begin(),
I));
175 for (
const auto &BB :
F) {
176 for (
const auto &
I : BB.instructionsWithoutDebug()) {
177 auto ID =
I.getOpcode();
179 ++FF.InstructionHistogram[
ID];
180 int PairIndex = getPairIndex(LastID,
ID);
182 ++FF.InstructionPairHistogram[PairIndex];
184 if (isa<CallBase>(
I))
185 ++FF[NamedFeatureIndex::Calls];
189 FF[NamedFeatureIndex::InitialSize] =
getSize(
F,
FAM);
190 FF[NamedFeatureIndex::IsLocal] =
F.hasLocalLinkage();
191 FF[NamedFeatureIndex::IsLinkOnceODR] =
F.hasLinkOnceODRLinkage();
192 FF[NamedFeatureIndex::IsLinkOnce] =
F.hasLinkOnceLinkage();
193 FF[NamedFeatureIndex::Blocks] =
F.size();
195 FF[NamedFeatureIndex::Loops] = std::distance(LI.begin(), LI.end());
197 FF[NamedFeatureIndex::MaxLoopDepth] =
198 std::max(FF[NamedFeatureIndex::MaxLoopDepth],
199 static_cast<int32_t
>(
L->getLoopDepth()));
200 FF[NamedFeatureIndex::MaxDomTreeLevel] = getMaxDominatorTreeDepth(
F, DomTree);
204void IRToNativeSizeLearning::FunctionFeatures::fillTensor(int32_t *
Ptr)
const {
205 std::copy(NamedFeatures.begin(), NamedFeatures.end(),
Ptr);
206 Ptr += NamedFeatures.size();
207 std::copy(InstructionHistogram.begin(), InstructionHistogram.end(),
Ptr);
208 Ptr += InstructionHistogram.size();
209 std::copy(InstructionPairHistogram.begin(), InstructionPairHistogram.end(),
214 return !TFIR2NativeModelPath.empty();
221 std::vector<TensorSpec> InputSpecs{TensorSpec::createSpec<int32_t>(
222 "serving_default_input_1",
223 {1,
static_cast<int64_t
>(
224 IRToNativeSizeLearning::FunctionFeatures::FeatureCount)})};
225 std::vector<TensorSpec> OutputSpecs{
226 TensorSpec::createSpec<float>(
"StatefulPartitionedCall", {1})};
227 Evaluator = std::make_unique<TFModelEvaluator>(
228 TFIR2NativeModelPath.getValue().c_str(), InputSpecs, OutputSpecs);
240 auto Features = IRToNativeSizeLearning::getFunctionFeatures(
243 Features.fillTensor(V);
247 float Ret = *ER->getTensorValue<
float>(0);
250 return static_cast<size_t>(
Ret);
263InlineSizeEstimatorAnalysis ::InlineSizeEstimatorAnalysis(
277 OS <<
"[InlineSizeEstimatorAnalysis] size estimate for " <<
F.getName()
static unsigned InstrCount
DenseMap< Block *, BlockRelaxAux > Blocks
This header defines various interfaces for pass management in LLVM.
FunctionAnalysisManager FAM
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static unsigned getSize(unsigned Kind)
A container for analyses that lazily runs them and caches their results.
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
std::optional< CostType > getValue() const
This function is intended to be used as sparingly as possible, since the class provides the full rang...
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.
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...
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Implement std::hash so that hash_code can be used in STL containers.
A special type used by analysis passes to provide an address that identifies that particular analysis...