40template <
class Edge,
class BBInfo>
class CFGMST {
45 std::vector<std::unique_ptr<Edge>> AllEdges;
52 bool ExitBlockFound =
false;
59 const bool InstrumentFuncEntry;
62 const bool InstrumentLoopEntries;
65 BBInfo *findAndCompressGroup(BBInfo *
G) {
67 G->Group = findAndCompressGroup(
static_cast<BBInfo *
>(
G->Group));
68 return static_cast<BBInfo *
>(
G->Group);
74 BBInfo *BB1G = findAndCompressGroup(&
getBBInfo(BB1));
75 BBInfo *BB2G = findAndCompressGroup(&
getBBInfo(BB2));
81 if (BB1G->Rank < BB2G->Rank)
86 if (BB1G->Rank == BB2G->Rank)
92 void handleCoroSuspendEdge(Edge *
E) {
123 (BFI !=
nullptr ? BFI->getEntryFreq().getFrequency() : 2);
125 if (InstrumentFuncEntry)
127 Edge *EntryIncoming =
nullptr, *EntryOutgoing =
nullptr,
128 *ExitOutgoing =
nullptr, *ExitIncoming =
nullptr;
129 uint64_t MaxEntryOutWeight = 0, MaxExitOutWeight = 0, MaxExitInWeight = 0;
132 EntryIncoming = &
addEdge(
nullptr, Entry, EntryWeight);
133 LLVM_DEBUG(
dbgs() <<
" Edge: from fake node to " << Entry->getName()
134 <<
" w = " << EntryWeight <<
"\n");
138 addEdge(Entry,
nullptr, EntryWeight);
142 static const uint32_t CriticalEdgeMultiplier = 1000;
147 (BFI !=
nullptr ? BFI->getBlockFreq(&BB).getFrequency() : 2);
155 if (scaleFactor <
UINT64_MAX / CriticalEdgeMultiplier)
156 scaleFactor *= CriticalEdgeMultiplier;
161 Weight = BPI->getEdgeProbability(&BB, TargetBB).scale(scaleFactor);
166 if (InstrumentLoopEntries && LI->isLoopHeader(TargetBB)) {
167 Loop *TargetLoop = LI->getLoopFor(TargetBB);
174 auto *
E = &
addEdge(&BB, TargetBB, Weight);
175 E->IsCritical = Critical;
176 handleCoroSuspendEdge(
E);
178 << TargetBB->
getName() <<
" w=" << Weight <<
"\n");
182 if (Weight > MaxEntryOutWeight) {
183 MaxEntryOutWeight = Weight;
189 if (TargetTI && !TargetTI->getNumSuccessors()) {
190 if (Weight > MaxExitInWeight) {
191 MaxExitInWeight = Weight;
197 ExitBlockFound =
true;
198 Edge *ExitO = &
addEdge(&BB,
nullptr, BBWeight);
199 if (BBWeight > MaxExitOutWeight) {
200 MaxExitOutWeight = BBWeight;
201 ExitOutgoing = ExitO;
203 LLVM_DEBUG(
dbgs() <<
" Edge: from " << BB.getName() <<
" to fake exit"
204 <<
" w = " << BBWeight <<
"\n");
218 uint64_t EntryInWeight = EntryWeight;
220 if (EntryInWeight >= MaxExitOutWeight &&
221 EntryInWeight * 2 < MaxExitOutWeight * 3) {
222 EntryIncoming->Weight = MaxExitOutWeight;
223 ExitOutgoing->Weight = EntryInWeight + 1;
226 if (MaxEntryOutWeight >= MaxExitInWeight &&
227 MaxEntryOutWeight * 2 < MaxExitInWeight * 3) {
228 EntryOutgoing->Weight = MaxExitInWeight;
229 ExitIncoming->Weight = MaxEntryOutWeight + 1;
234 void sortEdgesByWeight() {
236 const std::unique_ptr<Edge> &Edge2) {
237 return Edge1->Weight > Edge2->Weight;
243 void computeMinimumSpanningTree() {
247 for (
auto &Ei : AllEdges) {
250 if (Ei->IsCritical) {
251 if (Ei->DestBB && Ei->DestBB->isLandingPad()) {
252 if (unionGroups(Ei->SrcBB, Ei->DestBB))
258 for (
auto &Ei : AllEdges) {
263 if (!ExitBlockFound && Ei->SrcBB ==
nullptr)
265 if (unionGroups(Ei->SrcBB, Ei->DestBB))
270 [[maybe_unused]]
bool validateLoopEntryInstrumentation() {
271 if (!InstrumentLoopEntries)
273 for (
auto &Ei : AllEdges) {
276 if (Ei->DestBB && LI->isLoopHeader(Ei->DestBB) &&
277 !LI->getLoopFor(Ei->DestBB)->contains(Ei->SrcBB) && Ei->InMST)
286 if (!Message.
str().empty())
287 OS << Message <<
"\n";
288 OS <<
" Number of Basic Blocks: " << BBInfos.size() <<
"\n";
289 for (
auto &BI : BBInfos) {
291 OS <<
" BB: " << (BB ==
nullptr ?
"FakeNode" : BB->
getName()) <<
" "
292 << BI.second->infoString() <<
"\n";
295 OS <<
" Number of Edges: " << AllEdges.size()
296 <<
" (*: Instrument, C: CriticalEdge, -: Removed)\n";
298 for (
auto &EI : AllEdges)
299 OS <<
" Edge " <<
Count++ <<
": " <<
getBBInfo(EI->SrcBB).Index <<
"-->"
300 <<
getBBInfo(EI->DestBB).Index << EI->infoString() <<
"\n";
306 auto Iter = BBInfos.end();
308 std::tie(Iter, Inserted) = BBInfos.try_emplace(Src);
311 Iter->second = std::make_unique<BBInfo>(Index);
314 std::tie(Iter, Inserted) = BBInfos.try_emplace(Dest);
317 Iter->second = std::make_unique<BBInfo>(Index);
318 AllEdges.emplace_back(
new Edge(Src, Dest, W));
319 return *AllEdges.back();
325 : F(Func), BPI(BPI), BFI(BFI), LI(LI),
326 InstrumentFuncEntry(InstrumentFuncEntry),
327 InstrumentLoopEntries(InstrumentLoopEntries) {
328 assert(!(InstrumentLoopEntries && !LI) &&
329 "expected a LoopInfo to instrumenting loop entries");
332 computeMinimumSpanningTree();
333 assert(validateLoopEntryInstrumentation() &&
334 "Loop entries should not be in MST when "
335 "InstrumentLoopEntries is on");
336 if (AllEdges.size() > 1 && InstrumentFuncEntry)
337 std::iter_swap(std::move(AllEdges.begin()),
338 std::move(AllEdges.begin() + AllEdges.size() - 1));
341 const std::vector<std::unique_ptr<Edge>> &
allEdges()
const {
345 std::vector<std::unique_ptr<Edge>> &
allEdges() {
return AllEdges; }
347 size_t numEdges()
const {
return AllEdges.size(); }
353 auto It = BBInfos.find(BB);
354 assert(It->second.get() !=
nullptr);
355 return *It->second.get();
360 auto It = BBInfos.find(BB);
361 if (It == BBInfos.end())
363 return It->second.get();
CFGMST(Function &Func, bool InstrumentFuncEntry, bool InstrumentLoopEntries, BranchProbabilityInfo *BPI=nullptr, BlockFrequencyInfo *BFI=nullptr, LoopInfo *LI=nullptr)