15#ifdef LLVM_HAVE_TFLITE
26#ifdef LLVM_HAVE_TFLITE
42 cl::desc(
"Path to saved model evaluating native size from IR."));
44#define DEBUG_TYPE "inline-size-estimator"
46unsigned getMaxInstructionID() {
47#define LAST_OTHER_INST(NR) return NR;
48#include "llvm/IR/Instruction.def"
51class IRToNativeSizeLearning {
53 enum class NamedFeatureIndex :
size_t {
66 static const size_t NumNamedFeatures =
67 static_cast<size_t>(NamedFeatureIndex::NumNamedFeatures);
68 struct FunctionFeatures {
71 std::array<int32_t, NumNamedFeatures> NamedFeatures = {0};
72 std::vector<int32_t> InstructionHistogram;
73 std::vector<int32_t> InstructionPairHistogram;
75 void fillTensor(int32_t *
Ptr)
const;
76 int32_t &operator[](NamedFeatureIndex Pos) {
77 return NamedFeatures[
static_cast<size_t>(Pos)];
80 IRToNativeSizeLearning() =
default;
82 static FunctionFeatures getFunctionFeatures(
Function &
F,
94static const std::array<std::pair<size_t, size_t>, 137>
95 ImportantInstructionSuccessions{
96 {{1, 1}, {1, 4}, {1, 5}, {1, 7}, {1, 8}, {1, 9}, {1, 11},
97 {1, 12}, {1, 13}, {1, 14}, {1, 18}, {1, 20}, {1, 22}, {1, 24},
98 {1, 25}, {1, 26}, {1, 27}, {1, 28}, {1, 29}, {1, 30}, {1, 31},
99 {1, 32}, {1, 33}, {1, 34}, {1, 39}, {1, 40}, {1, 42}, {1, 45},
100 {2, 1}, {2, 2}, {2, 13}, {2, 28}, {2, 29}, {2, 32}, {2, 33},
101 {2, 34}, {2, 38}, {2, 48}, {2, 49}, {2, 53}, {2, 55}, {2, 56},
102 {13, 2}, {13, 13}, {13, 26}, {13, 33}, {13, 34}, {13, 56}, {15, 27},
103 {28, 2}, {28, 48}, {28, 53}, {29, 2}, {29, 33}, {29, 56}, {31, 31},
104 {31, 33}, {31, 34}, {31, 49}, {32, 1}, {32, 2}, {32, 13}, {32, 15},
105 {32, 28}, {32, 29}, {32, 32}, {32, 33}, {32, 34}, {32, 39}, {32, 40},
106 {32, 48}, {32, 49}, {32, 53}, {32, 56}, {33, 1}, {33, 2}, {33, 32},
107 {33, 33}, {33, 34}, {33, 49}, {33, 53}, {33, 56}, {34, 1}, {34, 2},
108 {34, 32}, {34, 33}, {34, 34}, {34, 49}, {34, 53}, {34, 56}, {38, 34},
109 {39, 57}, {40, 34}, {47, 15}, {47, 49}, {48, 2}, {48, 34}, {48, 56},
110 {49, 1}, {49, 2}, {49, 28}, {49, 32}, {49, 33}, {49, 34}, {49, 39},
111 {49, 49}, {49, 56}, {53, 1}, {53, 2}, {53, 28}, {53, 34}, {53, 53},
112 {53, 57}, {55, 1}, {55, 28}, {55, 34}, {55, 53}, {55, 55}, {55, 56},
113 {56, 1}, {56, 2}, {56, 7}, {56, 13}, {56, 32}, {56, 33}, {56, 34},
114 {56, 49}, {56, 53}, {56, 56}, {56, 64}, {57, 34}, {57, 56}, {57, 57},
115 {64, 1}, {64, 64}, {65, 1}, {65, 65}}};
124const size_t IRToNativeSizeLearning::FunctionFeatures::FeatureCount =
125 ImportantInstructionSuccessions.size() + getMaxInstructionID() + 1 +
126 IRToNativeSizeLearning::NumNamedFeatures;
130 for (
const auto &BB :
F)
131 for (
const auto &
I : BB)
133 &
I, TargetTransformInfo::TargetCostKind::TCK_CodeSize).
getValue());
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];
185 if (isa<CallBase>(
I))
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();
222 std::vector<TensorSpec> InputSpecs{TensorSpec::createSpec<int32_t>(
223 "serving_default_input_1",
224 {1,
static_cast<int64_t
>(
225 IRToNativeSizeLearning::FunctionFeatures::FeatureCount)})};
226 std::vector<TensorSpec> OutputSpecs{
227 TensorSpec::createSpec<float>(
"StatefulPartitionedCall", {1})};
228 Evaluator = std::make_unique<TFModelEvaluator>(
229 TFIR2NativeModelPath.getValue().c_str(), InputSpecs, OutputSpecs);
241 auto Features = IRToNativeSizeLearning::getFunctionFeatures(
244 Features.fillTensor(V);
248 float Ret = *ER->getTensorValue<
float>(0);
251 return static_cast<size_t>(
Ret);
264InlineSizeEstimatorAnalysis ::InlineSizeEstimatorAnalysis(
278 OS <<
"[InlineSizeEstimatorAnalysis] size estimate for " <<
F.getName()
static unsigned InstrCount
DenseMap< Block *, BlockRelaxAux > Blocks
FunctionAnalysisManager FAM
This header defines various interfaces for pass management in LLVM.
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...