2626#include " llvm/IR/Analysis.h"
2727#include " llvm/IR/CFG.h"
2828#include " llvm/IR/Dominators.h"
29+ #include " llvm/IR/Instructions.h"
2930#include " llvm/IR/IntrinsicInst.h"
3031#include " llvm/IR/Module.h"
3132#include " llvm/IR/PassManager.h"
3435#include " llvm/Transforms/Instrumentation/PGOInstrumentation.h"
3536#include " llvm/Transforms/Scalar/DCE.h"
3637#include " llvm/Transforms/Utils/BasicBlockUtils.h"
38+ #include < deque>
3739
3840using namespace llvm ;
3941
@@ -51,29 +53,42 @@ class ProfileAnnotator final {
5153
5254 class BBInfo {
5355 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.
5461 SmallVector<EdgeInfo *> OutEdges;
5562 SmallVector<EdgeInfo *> InEdges;
5663 size_t UnknownCountOutEdges = 0 ;
5764 size_t UnknownCountInEdges = 0 ;
5865
5966 // Pass AssumeAllKnown when we try to propagate counts from edges to BBs -
6067 // 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+ }
6781 return Sum;
6882 }
6983
70- void computeCountFrom (const SmallVector<EdgeInfo *> &Edges) {
84+ bool computeCountFrom (const SmallVector<EdgeInfo *> &Edges) {
7185 assert (!Count.has_value ());
7286 Count = getEdgeSum (Edges, true );
87+ return Count.has_value ();
7388 }
7489
7590 void setSingleUnknownEdgeCount (SmallVector<EdgeInfo *> &Edges) {
76- uint64_t KnownSum = getEdgeSum (Edges, false );
91+ uint64_t KnownSum = getEdgeSum (Edges, false ). value_or ( 0U ) ;
7792 uint64_t EdgeVal = *Count > KnownSum ? *Count - KnownSum : 0U ;
7893 EdgeInfo *E = nullptr ;
7994 for (auto *I : Edges)
@@ -110,17 +125,15 @@ class ProfileAnnotator final {
110125 }
111126
112127 bool tryTakeCountFromKnownOutEdges (const BasicBlock &BB) {
113- if (!succ_empty (&BB) && !UnknownCountOutEdges) {
114- computeCountFrom (OutEdges);
115- return true ;
128+ if (!UnknownCountOutEdges) {
129+ return computeCountFrom (OutEdges);
116130 }
117131 return false ;
118132 }
119133
120134 bool tryTakeCountFromKnownInEdges (const BasicBlock &BB) {
121- if (!BB.isEntryBlock () && !UnknownCountInEdges) {
122- computeCountFrom (InEdges);
123- return true ;
135+ if (!UnknownCountInEdges) {
136+ return computeCountFrom (InEdges);
124137 }
125138 return false ;
126139 }
@@ -178,7 +191,7 @@ class ProfileAnnotator final {
178191 bool KeepGoing = true ;
179192 while (KeepGoing) {
180193 KeepGoing = false ;
181- for (const auto &BB : reverse (F) ) {
194+ for (const auto &BB : F ) {
182195 auto &Info = getBBInfo (BB);
183196 if (!Info.hasCount ())
184197 KeepGoing |= Info.tryTakeCountFromKnownOutEdges (BB) ||
@@ -198,6 +211,52 @@ class ProfileAnnotator final {
198211
199212 BBInfo &getBBInfo (const BasicBlock &BB) { return BBInfos.find (&BB)->second ; }
200213
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+
201260public:
202261 ProfileAnnotator (Function &F, const SmallVectorImpl<uint64_t > &Counters,
203262 InstrProfSummaryBuilder &PB)
@@ -216,6 +275,9 @@ class ProfileAnnotator final {
216275 " profile is managed by IPO transforms" );
217276 (void )Index;
218277 Count = Counters[Ins->getIndex ()->getZExtValue ()];
278+ } else if (isa<UnreachableInst>(BB.getTerminator ())) {
279+ // The program presumably didn't crash.
280+ Count = 0 ;
219281 }
220282 auto [It, Ins] =
221283 BBInfos.insert ({&BB, {pred_size (&BB), succ_size (&BB), Count}});
@@ -268,14 +330,16 @@ class ProfileAnnotator final {
268330 PB.addInternalCount (EdgeCount);
269331 }
270332
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);
278335 }
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" );
279343 }
280344};
281345
0 commit comments