@@ -67,8 +67,6 @@ class IRToNativeSizeLearning {
67
67
static const size_t NumNamedFeatures =
68
68
static_cast <size_t >(NamedFeatureIndex::NumNamedFeatures);
69
69
struct FunctionFeatures {
70
- static std::vector<std::pair<size_t , size_t >>
71
- ImportantInstructionSuccessions;
72
70
static const size_t FeatureCount;
73
71
74
72
std::array<int32_t , NumNamedFeatures> NamedFeatures = {0 };
@@ -84,53 +82,38 @@ class IRToNativeSizeLearning {
84
82
85
83
static FunctionFeatures getFunctionFeatures (Function &F,
86
84
FunctionAnalysisManager &FAM);
87
-
88
- private:
89
- // / Sort once the feature tuples.
90
- struct SortFeatureTuples {
91
- bool IsSorted = false ;
92
- SortFeatureTuples () {
93
- std::sort (FunctionFeatures::ImportantInstructionSuccessions.begin (),
94
- FunctionFeatures::ImportantInstructionSuccessions.end ());
95
- IsSorted = true ;
96
- }
97
- };
98
-
99
- static llvm::ManagedStatic<SortFeatureTuples> TupleSorter;
100
-
101
- static bool ensureSortedTuples () { return TupleSorter->IsSorted ; }
102
85
};
103
- llvm::ManagedStatic<IRToNativeSizeLearning::SortFeatureTuples>
104
- IRToNativeSizeLearning::TupleSorter;
105
86
106
87
// This is a point in time - we determined including these pairs of
107
88
// consecutive instructions (in the IR layout available at inline time) as
108
89
// features improves the model performance. We want to move away from manual
109
90
// feature selection.
110
- // The vector is given in opcode pairs rather than labels because 1) labels
111
- // weren't readily available, and 2) the successions were hand - extracted
112
- std::vector<std::pair<size_t , size_t >>
113
- IRToNativeSizeLearning::FunctionFeatures::ImportantInstructionSuccessions =
114
- {{1 , 34 }, {15 , 27 }, {53 , 53 }, {53 , 34 }, {1 , 11 }, {32 , 2 }, {2 , 48 },
115
- {28 , 48 }, {1 , 45 }, {49 , 32 }, {57 , 56 }, {55 , 53 }, {1 , 28 }, {57 , 34 },
116
- {1 , 1 }, {32 , 28 }, {32 , 15 }, {49 , 28 }, {53 , 1 }, {2 , 53 }, {48 , 34 },
117
- {28 , 53 }, {2 , 32 }, {1 , 40 }, {32 , 48 }, {29 , 56 }, {56 , 32 }, {55 , 56 },
118
- {48 , 56 }, {1 , 31 }, {33 , 34 }, {2 , 28 }, {1 , 12 }, {55 , 1 }, {31 , 31 },
119
- {65 , 1 }, {33 , 56 }, {32 , 32 }, {13 , 13 }, {1 , 26 }, {13 , 26 }, {2 , 1 },
120
- {1 , 33 }, {47 , 49 }, {64 , 1 }, {2 , 38 }, {34 , 53 }, {48 , 2 }, {55 , 34 },
121
- {34 , 32 }, {1 , 5 }, {56 , 13 }, {2 , 2 }, {2 , 49 }, {33 , 2 }, {49 , 39 },
122
- {56 , 49 }, {33 , 49 }, {32 , 39 }, {39 , 57 }, {29 , 33 }, {31 , 34 }, {32 , 29 },
123
- {47 , 15 }, {13 , 34 }, {2 , 33 }, {32 , 49 }, {49 , 34 }, {56 , 33 }, {1 , 30 },
124
- {33 , 33 }, {31 , 33 }, {2 , 29 }, {56 , 7 }, {32 , 13 }, {2 , 55 }, {56 , 56 },
125
- {2 , 34 }, {1 , 42 }, {34 , 49 }, {1 , 20 }, {32 , 33 }, {1 , 25 }, {53 , 28 },
126
- {1 , 14 }, {31 , 49 }, {28 , 2 }, {2 , 13 }, {2 , 56 }, {1 , 32 }, {56 , 53 },
127
- {65 , 65 }, {33 , 53 }, {64 , 64 }, {13 , 2 }, {34 , 33 }, {1 , 4 }, {49 , 2 },
128
- {1 , 9 }, {56 , 1 }, {33 , 1 }, {53 , 57 }, {32 , 53 }, {13 , 56 }, {32 , 56 },
129
- {55 , 55 }, {1 , 18 }, {49 , 56 }, {34 , 34 }, {1 , 7 }, {56 , 64 }, {32 , 1 },
130
- {13 , 33 }, {55 , 28 }, {49 , 33 }, {57 , 57 }, {56 , 34 }, {34 , 56 }, {33 , 32 },
131
- {32 , 40 }, {1 , 29 }, {53 , 2 }, {34 , 1 }, {32 , 34 }, {49 , 49 }, {1 , 24 },
132
- {40 , 34 }, {1 , 13 }, {38 , 34 }, {29 , 2 }, {34 , 2 }, {1 , 39 }, {1 , 22 },
133
- {1 , 27 }, {49 , 1 }, {1 , 8 }, {56 , 2 }};
91
+ // The array is given in opcode pairs rather than labels because 1) labels
92
+ // weren't readily available, and 2) the successions were hand - extracted.
93
+ //
94
+ // This array must be sorted.
95
+ static const std::array<std::pair<size_t , size_t >, 137 >
96
+ ImportantInstructionSuccessions{
97
+ {{1 , 1 }, {1 , 4 }, {1 , 5 }, {1 , 7 }, {1 , 8 }, {1 , 9 }, {1 , 11 },
98
+ {1 , 12 }, {1 , 13 }, {1 , 14 }, {1 , 18 }, {1 , 20 }, {1 , 22 }, {1 , 24 },
99
+ {1 , 25 }, {1 , 26 }, {1 , 27 }, {1 , 28 }, {1 , 29 }, {1 , 30 }, {1 , 31 },
100
+ {1 , 32 }, {1 , 33 }, {1 , 34 }, {1 , 39 }, {1 , 40 }, {1 , 42 }, {1 , 45 },
101
+ {2 , 1 }, {2 , 2 }, {2 , 13 }, {2 , 28 }, {2 , 29 }, {2 , 32 }, {2 , 33 },
102
+ {2 , 34 }, {2 , 38 }, {2 , 48 }, {2 , 49 }, {2 , 53 }, {2 , 55 }, {2 , 56 },
103
+ {13 , 2 }, {13 , 13 }, {13 , 26 }, {13 , 33 }, {13 , 34 }, {13 , 56 }, {15 , 27 },
104
+ {28 , 2 }, {28 , 48 }, {28 , 53 }, {29 , 2 }, {29 , 33 }, {29 , 56 }, {31 , 31 },
105
+ {31 , 33 }, {31 , 34 }, {31 , 49 }, {32 , 1 }, {32 , 2 }, {32 , 13 }, {32 , 15 },
106
+ {32 , 28 }, {32 , 29 }, {32 , 32 }, {32 , 33 }, {32 , 34 }, {32 , 39 }, {32 , 40 },
107
+ {32 , 48 }, {32 , 49 }, {32 , 53 }, {32 , 56 }, {33 , 1 }, {33 , 2 }, {33 , 32 },
108
+ {33 , 33 }, {33 , 34 }, {33 , 49 }, {33 , 53 }, {33 , 56 }, {34 , 1 }, {34 , 2 },
109
+ {34 , 32 }, {34 , 33 }, {34 , 34 }, {34 , 49 }, {34 , 53 }, {34 , 56 }, {38 , 34 },
110
+ {39 , 57 }, {40 , 34 }, {47 , 15 }, {47 , 49 }, {48 , 2 }, {48 , 34 }, {48 , 56 },
111
+ {49 , 1 }, {49 , 2 }, {49 , 28 }, {49 , 32 }, {49 , 33 }, {49 , 34 }, {49 , 39 },
112
+ {49 , 49 }, {49 , 56 }, {53 , 1 }, {53 , 2 }, {53 , 28 }, {53 , 34 }, {53 , 53 },
113
+ {53 , 57 }, {55 , 1 }, {55 , 28 }, {55 , 34 }, {55 , 53 }, {55 , 55 }, {55 , 56 },
114
+ {56 , 1 }, {56 , 2 }, {56 , 7 }, {56 , 13 }, {56 , 32 }, {56 , 33 }, {56 , 34 },
115
+ {56 , 49 }, {56 , 53 }, {56 , 56 }, {56 , 64 }, {57 , 34 }, {57 , 56 }, {57 , 57 },
116
+ {64 , 1 }, {64 , 64 }, {65 , 1 }, {65 , 65 }}};
134
117
135
118
// We have: 9 calculated features (the features here); 1 feature for each
136
119
// instruction opcode; and 1 feature for each manually-identified sequence.
@@ -140,14 +123,13 @@ std::vector<std::pair<size_t, size_t>>
140
123
// Note that instruction opcodes start from 1. For convenience, we also have an
141
124
// always 0 feature for the '0' opcode, hence the extra 1.
142
125
const size_t IRToNativeSizeLearning::FunctionFeatures::FeatureCount =
143
- IRToNativeSizeLearning::FunctionFeatures::ImportantInstructionSuccessions
144
- .size() +
145
- getMaxInstructionID () + 1 + IRToNativeSizeLearning::NumNamedFeatures;
126
+ ImportantInstructionSuccessions.size() + getMaxInstructionID() + 1 +
127
+ IRToNativeSizeLearning::NumNamedFeatures;
146
128
147
129
size_t getSize (Function &F, TargetTransformInfo &TTI) {
148
130
size_t Ret = 0 ;
149
- for (auto &BB : F)
150
- for (auto &I : BB)
131
+ for (const auto &BB : F)
132
+ for (const auto &I : BB)
151
133
Ret += TTI.getInstructionCost (
152
134
&I, TargetTransformInfo::TargetCostKind::TCK_CodeSize);
153
135
return Ret;
@@ -161,8 +143,8 @@ size_t getSize(Function &F, FunctionAnalysisManager &FAM) {
161
143
unsigned getMaxDominatorTreeDepth (const Function &F,
162
144
const DominatorTree &Tree) {
163
145
unsigned Ret = 0 ;
164
- for (auto &BB : F)
165
- if (auto *TN = Tree.getNode (&BB))
146
+ for (const auto &BB : F)
147
+ if (const auto *TN = Tree.getNode (&BB))
166
148
Ret = std::max (Ret, TN->getLevel ());
167
149
return Ret;
168
150
}
@@ -171,42 +153,37 @@ unsigned getMaxDominatorTreeDepth(const Function &F,
171
153
IRToNativeSizeLearning::FunctionFeatures
172
154
IRToNativeSizeLearning::getFunctionFeatures (Function &F,
173
155
FunctionAnalysisManager &FAM) {
174
- ensureSortedTuples ();
156
+ assert (llvm::is_sorted (ImportantInstructionSuccessions) &&
157
+ " expected function features are sorted" );
175
158
176
159
auto &DomTree = FAM.getResult <DominatorTreeAnalysis>(F);
177
160
FunctionFeatures FF;
178
161
size_t InstrCount = getMaxInstructionID () + 1 ;
179
162
FF.InstructionHistogram .resize (InstrCount);
180
163
181
- FF.InstructionPairHistogram .resize (
182
- FunctionFeatures::ImportantInstructionSuccessions.size ());
164
+ FF.InstructionPairHistogram .resize (ImportantInstructionSuccessions.size ());
183
165
184
- auto StartID = 0 ;
185
- auto LastID = StartID;
166
+ int StartID = 0 ;
167
+ int LastID = StartID;
186
168
auto getPairIndex = [](size_t a, size_t b) {
187
- auto I =
188
- std::find (FunctionFeatures::ImportantInstructionSuccessions.begin (),
189
- FunctionFeatures::ImportantInstructionSuccessions.end (),
190
- std::make_pair (a, b));
191
- if (I == FunctionFeatures::ImportantInstructionSuccessions.end ())
169
+ auto I = llvm::find (ImportantInstructionSuccessions, std::make_pair (a, b));
170
+ if (I == ImportantInstructionSuccessions.end ())
192
171
return -1 ;
193
- return static_cast <int >(std::distance (
194
- FunctionFeatures:: ImportantInstructionSuccessions.begin (), I));
172
+ return static_cast <int >(
173
+ std::distance ( ImportantInstructionSuccessions.begin (), I));
195
174
};
196
175
197
176
// We don't want debug calls, because they'd just add noise.
198
- for (auto &BB : F) {
199
- for (auto I = BB.instructionsWithoutDebug ().begin (),
200
- E = BB.instructionsWithoutDebug ().end ();
201
- I != E; ++I) {
202
- auto ID = I->getOpcode ();
177
+ for (const auto &BB : F) {
178
+ for (const auto &I : BB.instructionsWithoutDebug ()) {
179
+ auto ID = I.getOpcode ();
203
180
204
181
++FF.InstructionHistogram [ID];
205
182
int PairIndex = getPairIndex (LastID, ID);
206
183
if (PairIndex >= 0 )
207
184
++FF.InstructionPairHistogram [PairIndex];
208
185
LastID = ID;
209
- if (isa<CallBase>(* I))
186
+ if (isa<CallBase>(I))
210
187
++FF[NamedFeatureIndex::Calls];
211
188
}
212
189
}
0 commit comments