26
26
#include " llvm/IR/Analysis.h"
27
27
#include " llvm/IR/CFG.h"
28
28
#include " llvm/IR/Dominators.h"
29
+ #include " llvm/IR/Instructions.h"
29
30
#include " llvm/IR/IntrinsicInst.h"
30
31
#include " llvm/IR/Module.h"
31
32
#include " llvm/IR/PassManager.h"
34
35
#include " llvm/Transforms/Instrumentation/PGOInstrumentation.h"
35
36
#include " llvm/Transforms/Scalar/DCE.h"
36
37
#include " llvm/Transforms/Utils/BasicBlockUtils.h"
38
+ #include < deque>
37
39
38
40
using namespace llvm ;
39
41
@@ -51,29 +53,42 @@ class ProfileAnnotator final {
51
53
52
54
class BBInfo {
53
55
std::optional<uint64_t > Count;
56
+ // OutEdges is dimensioned to match the number of terminator operands.
57
+ // Entries in the vector match the index in the terminator operand list. In
58
+ // some cases - see `shouldExcludeEdge` and its implementation - an entry
59
+ // will be nullptr.
60
+ // InEdges doesn't have the above constraint.
54
61
SmallVector<EdgeInfo *> OutEdges;
55
62
SmallVector<EdgeInfo *> InEdges;
56
63
size_t UnknownCountOutEdges = 0 ;
57
64
size_t UnknownCountInEdges = 0 ;
58
65
59
66
// Pass AssumeAllKnown when we try to propagate counts from edges to BBs -
60
67
// because all the edge counters must be known.
61
- uint64_t getEdgeSum (const SmallVector<EdgeInfo *> &Edges,
62
- bool AssumeAllKnown) const {
63
- uint64_t Sum = 0 ;
64
- for (const auto *E : Edges)
65
- if (E)
66
- Sum += AssumeAllKnown ? *E->Count : E->Count .value_or (0U );
68
+ // Return std::nullopt if there were no edges to sum. The user can decide
69
+ // how to interpret that.
70
+ std::optional<uint64_t > getEdgeSum (const SmallVector<EdgeInfo *> &Edges,
71
+ bool AssumeAllKnown) const {
72
+ std::optional<uint64_t > Sum;
73
+ for (const auto *E : Edges) {
74
+ // `Edges` may be `OutEdges`, case in which `E` could be nullptr.
75
+ if (E) {
76
+ if (!Sum.has_value ())
77
+ Sum = 0 ;
78
+ *Sum += (AssumeAllKnown ? *E->Count : E->Count .value_or (0U ));
79
+ }
80
+ }
67
81
return Sum;
68
82
}
69
83
70
- void computeCountFrom (const SmallVector<EdgeInfo *> &Edges) {
84
+ bool computeCountFrom (const SmallVector<EdgeInfo *> &Edges) {
71
85
assert (!Count.has_value ());
72
86
Count = getEdgeSum (Edges, true );
87
+ return Count.has_value ();
73
88
}
74
89
75
90
void setSingleUnknownEdgeCount (SmallVector<EdgeInfo *> &Edges) {
76
- uint64_t KnownSum = getEdgeSum (Edges, false );
91
+ uint64_t KnownSum = getEdgeSum (Edges, false ). value_or ( 0U ) ;
77
92
uint64_t EdgeVal = *Count > KnownSum ? *Count - KnownSum : 0U ;
78
93
EdgeInfo *E = nullptr ;
79
94
for (auto *I : Edges)
@@ -110,17 +125,15 @@ class ProfileAnnotator final {
110
125
}
111
126
112
127
bool tryTakeCountFromKnownOutEdges (const BasicBlock &BB) {
113
- if (!succ_empty (&BB) && !UnknownCountOutEdges) {
114
- computeCountFrom (OutEdges);
115
- return true ;
128
+ if (!UnknownCountOutEdges) {
129
+ return computeCountFrom (OutEdges);
116
130
}
117
131
return false ;
118
132
}
119
133
120
134
bool tryTakeCountFromKnownInEdges (const BasicBlock &BB) {
121
- if (!BB.isEntryBlock () && !UnknownCountInEdges) {
122
- computeCountFrom (InEdges);
123
- return true ;
135
+ if (!UnknownCountInEdges) {
136
+ return computeCountFrom (InEdges);
124
137
}
125
138
return false ;
126
139
}
@@ -178,7 +191,7 @@ class ProfileAnnotator final {
178
191
bool KeepGoing = true ;
179
192
while (KeepGoing) {
180
193
KeepGoing = false ;
181
- for (const auto &BB : reverse (F) ) {
194
+ for (const auto &BB : F ) {
182
195
auto &Info = getBBInfo (BB);
183
196
if (!Info.hasCount ())
184
197
KeepGoing |= Info.tryTakeCountFromKnownOutEdges (BB) ||
@@ -198,6 +211,52 @@ class ProfileAnnotator final {
198
211
199
212
BBInfo &getBBInfo (const BasicBlock &BB) { return BBInfos.find (&BB)->second ; }
200
213
214
+ const BBInfo &getBBInfo (const BasicBlock &BB) const {
215
+ return BBInfos.find (&BB)->second ;
216
+ }
217
+
218
+ // validation function after we propagate the counters: all BBs and edges'
219
+ // counters must have a value.
220
+ bool allCountersAreAssigned () const {
221
+ for (const auto &BBInfo : BBInfos)
222
+ if (!BBInfo.second .hasCount ())
223
+ return false ;
224
+ for (const auto &EdgeInfo : EdgeInfos)
225
+ if (!EdgeInfo.Count .has_value ())
226
+ return false ;
227
+ return true ;
228
+ }
229
+
230
+ // / Check that all paths from the entry basic block that use edges with
231
+ // / non-zero counts arrive at a basic block with no successors (i.e. "exit")
232
+ bool allTakenPathsExit () const {
233
+ std::deque<const BasicBlock *> Worklist;
234
+ DenseSet<const BasicBlock *> Visited;
235
+ Worklist.push_back (&F.getEntryBlock ());
236
+ Visited.insert (&F.getEntryBlock ());
237
+ while (!Worklist.empty ()) {
238
+ const auto *BB = Worklist.front ();
239
+ Worklist.pop_front ();
240
+ if (succ_size (BB) <= 1 )
241
+ continue ;
242
+ const auto &BBInfo = getBBInfo (*BB);
243
+ bool Inserted = false ;
244
+ for (auto I = 0U ; I < BB->getTerminator ()->getNumSuccessors (); ++I) {
245
+ const auto *Succ = BB->getTerminator ()->getSuccessor (I);
246
+ if (!shouldExcludeEdge (*BB, *Succ)) {
247
+ if (BBInfo.getEdgeCount (I) > 0 )
248
+ if (Visited.insert (Succ).second ) {
249
+ Worklist.push_back (Succ);
250
+ Inserted = true ;
251
+ }
252
+ }
253
+ }
254
+ if (!Inserted)
255
+ return false ;
256
+ }
257
+ return true ;
258
+ }
259
+
201
260
public:
202
261
ProfileAnnotator (Function &F, const SmallVectorImpl<uint64_t > &Counters,
203
262
InstrProfSummaryBuilder &PB)
@@ -216,6 +275,9 @@ class ProfileAnnotator final {
216
275
" profile is managed by IPO transforms" );
217
276
(void )Index;
218
277
Count = Counters[Ins->getIndex ()->getZExtValue ()];
278
+ } else if (isa<UnreachableInst>(BB.getTerminator ())) {
279
+ // The program presumably didn't crash.
280
+ Count = 0 ;
219
281
}
220
282
auto [It, Ins] =
221
283
BBInfos.insert ({&BB, {pred_size (&BB), succ_size (&BB), Count}});
@@ -268,14 +330,16 @@ class ProfileAnnotator final {
268
330
PB.addInternalCount (EdgeCount);
269
331
}
270
332
271
- if (MaxCount == 0 )
272
- F.getContext ().emitError (
273
- " [ctx-prof] Encountered a BB with more than one successor, where "
274
- " all outgoing edges have a 0 count. This occurs in non-exiting "
275
- " functions (message pumps, usually) which are not supported in the "
276
- " contextual profiling case" );
277
- setProfMetadata (F.getParent (), Term, EdgeCounts, MaxCount);
333
+ if (MaxCount != 0 )
334
+ setProfMetadata (F.getParent (), Term, EdgeCounts, MaxCount);
278
335
}
336
+ assert (allCountersAreAssigned () &&
337
+ " Expected all counters have been assigned." );
338
+ assert (allTakenPathsExit () &&
339
+ " [ctx-prof] Encountered a BB with more than one successor, where "
340
+ " all outgoing edges have a 0 count. This occurs in non-exiting "
341
+ " functions (message pumps, usually) which are not supported in the "
342
+ " contextual profiling case" );
279
343
}
280
344
};
281
345
0 commit comments