14#ifndef LLVM_TRANSFORMS_INSTRUMENTATION_CFGMST_H
15#define LLVM_TRANSFORMS_INSTRUMENTATION_CFGMST_H
33#define DEBUG_TYPE "cfgmst"
41template <
class Edge,
class BBInfo>
class CFGMST {
46 std::vector<std::unique_ptr<Edge>> AllEdges;
53 bool ExitBlockFound =
false;
60 const bool InstrumentFuncEntry;
63 const bool InstrumentLoopEntries;
66 BBInfo *findAndCompressGroup(BBInfo *
G) {
68 G->Group = findAndCompressGroup(
static_cast<BBInfo *
>(
G->Group));
69 return static_cast<BBInfo *
>(
G->Group);
75 BBInfo *BB1G = findAndCompressGroup(&
getBBInfo(BB1));
76 BBInfo *BB2G = findAndCompressGroup(&
getBBInfo(BB2));
82 if (BB1G->Rank < BB2G->Rank)
87 if (BB1G->Rank == BB2G->Rank)
93 void handleCoroSuspendEdge(Edge *
E) {
124 (BFI !=
nullptr ? BFI->getEntryFreq().getFrequency() : 2);
126 if (InstrumentFuncEntry)
128 Edge *EntryIncoming =
nullptr, *EntryOutgoing =
nullptr,
129 *ExitOutgoing =
nullptr, *ExitIncoming =
nullptr;
130 uint64_t MaxEntryOutWeight = 0, MaxExitOutWeight = 0, MaxExitInWeight = 0;
133 EntryIncoming = &
addEdge(
nullptr, Entry, EntryWeight);
134 LLVM_DEBUG(
dbgs() <<
" Edge: from fake node to " << Entry->getName()
135 <<
" w = " << EntryWeight <<
"\n");
139 addEdge(Entry,
nullptr, EntryWeight);
143 static const uint32_t CriticalEdgeMultiplier = 1000;
148 (BFI !=
nullptr ? BFI->getBlockFreq(&BB).getFrequency() : 2);
156 if (scaleFactor <
UINT64_MAX / CriticalEdgeMultiplier)
157 scaleFactor *= CriticalEdgeMultiplier;
162 Weight = BPI->getEdgeProbability(&BB, TargetBB).scale(scaleFactor);
167 if (InstrumentLoopEntries && LI->isLoopHeader(TargetBB)) {
168 Loop *TargetLoop = LI->getLoopFor(TargetBB);
175 auto *
E = &
addEdge(&BB, TargetBB, Weight);
176 E->IsCritical = Critical;
177 handleCoroSuspendEdge(
E);
179 << TargetBB->
getName() <<
" w=" << Weight <<
"\n");
183 if (Weight > MaxEntryOutWeight) {
184 MaxEntryOutWeight = Weight;
190 if (TargetTI && !TargetTI->getNumSuccessors()) {
191 if (Weight > MaxExitInWeight) {
192 MaxExitInWeight = Weight;
198 ExitBlockFound =
true;
199 Edge *ExitO = &
addEdge(&BB,
nullptr, BBWeight);
200 if (BBWeight > MaxExitOutWeight) {
201 MaxExitOutWeight = BBWeight;
202 ExitOutgoing = ExitO;
204 LLVM_DEBUG(
dbgs() <<
" Edge: from " << BB.getName() <<
" to fake exit"
205 <<
" w = " << BBWeight <<
"\n");
219 uint64_t EntryInWeight = EntryWeight;
221 if (EntryInWeight >= MaxExitOutWeight &&
222 EntryInWeight * 2 < MaxExitOutWeight * 3) {
223 EntryIncoming->Weight = MaxExitOutWeight;
224 ExitOutgoing->Weight = EntryInWeight + 1;
227 if (MaxEntryOutWeight >= MaxExitInWeight &&
228 MaxEntryOutWeight * 2 < MaxExitInWeight * 3) {
229 EntryOutgoing->Weight = MaxExitInWeight;
230 ExitIncoming->Weight = MaxEntryOutWeight + 1;
235 void sortEdgesByWeight() {
237 const std::unique_ptr<Edge> &Edge2) {
238 return Edge1->Weight > Edge2->Weight;
244 void computeMinimumSpanningTree() {
248 for (
auto &Ei : AllEdges) {
251 if (Ei->IsCritical) {
252 if (Ei->DestBB && Ei->DestBB->isLandingPad()) {
253 if (unionGroups(Ei->SrcBB, Ei->DestBB))
259 for (
auto &Ei : AllEdges) {
264 if (!ExitBlockFound && Ei->SrcBB ==
nullptr)
266 if (unionGroups(Ei->SrcBB, Ei->DestBB))
271 [[maybe_unused]]
bool validateLoopEntryInstrumentation() {
272 if (!InstrumentLoopEntries)
274 for (
auto &Ei : AllEdges) {
277 if (Ei->DestBB && LI->isLoopHeader(Ei->DestBB) &&
278 !LI->getLoopFor(Ei->DestBB)->contains(Ei->SrcBB) && Ei->InMST)
287 if (!Message.
str().empty())
288 OS << Message <<
"\n";
289 OS <<
" Number of Basic Blocks: " << BBInfos.size() <<
"\n";
291 std::vector<std::pair<const BasicBlock *, const BBInfo *>> SortedBBInfos;
292 SortedBBInfos.reserve(BBInfos.size());
293 for (
const auto &BI : BBInfos)
294 SortedBBInfos.emplace_back(BI.first, BI.second.get());
298 for (
const auto &
P : SortedBBInfos)
300 "BBInfo indices should be unique");
303 llvm::sort(SortedBBInfos, [](
const auto &
A,
const auto &
B) {
305 if (
A.second->Index !=
B.second->Index)
306 return A.second->Index <
B.second->Index;
312 return NameA < NameB;
315 for (
const auto &
P : SortedBBInfos) {
317 const BBInfo *Info =
P.second;
318 OS <<
" BB: " << (BB ==
nullptr ?
"FakeNode" : BB->
getName()) <<
" "
319 << Info->infoString() <<
"\n";
321 OS <<
" Number of Edges: " << AllEdges.size()
322 <<
" (*: Instrument, C: CriticalEdge, -: Removed)\n";
324 for (
auto &EI : AllEdges)
325 OS <<
" Edge " <<
Count++ <<
": " <<
getBBInfo(EI->SrcBB).Index <<
"-->"
326 <<
getBBInfo(EI->DestBB).Index << EI->infoString() <<
"\n";
332 auto Iter = BBInfos.end();
334 std::tie(Iter, Inserted) = BBInfos.try_emplace(Src);
337 Iter->second = std::make_unique<BBInfo>(Index);
340 std::tie(Iter, Inserted) = BBInfos.try_emplace(Dest);
343 Iter->second = std::make_unique<BBInfo>(Index);
344 AllEdges.emplace_back(
new Edge(Src, Dest, W));
345 return *AllEdges.back();
351 : F(Func), BPI(BPI), BFI(BFI), LI(LI),
352 InstrumentFuncEntry(InstrumentFuncEntry),
353 InstrumentLoopEntries(InstrumentLoopEntries) {
354 assert(!(InstrumentLoopEntries && !LI) &&
355 "expected a LoopInfo to instrumenting loop entries");
358 computeMinimumSpanningTree();
359 assert(validateLoopEntryInstrumentation() &&
360 "Loop entries should not be in MST when "
361 "InstrumentLoopEntries is on");
362 if (AllEdges.size() > 1 && InstrumentFuncEntry)
363 std::iter_swap(std::move(AllEdges.begin()),
364 std::move(AllEdges.begin() + AllEdges.size() - 1));
367 const std::vector<std::unique_ptr<Edge>> &
allEdges()
const {
371 std::vector<std::unique_ptr<Edge>> &
allEdges() {
return AllEdges; }
373 size_t numEdges()
const {
return AllEdges.size(); }
379 auto It = BBInfos.find(BB);
380 assert(It->second.get() !=
nullptr);
381 return *It->second.get();
386 auto It = BBInfos.find(BB);
387 if (It == BBInfos.end())
389 return It->second.get();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
std::pair< BasicBlock *, BasicBlock * > Edge
LLVM Basic Block Representation.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...
Analysis providing branch probability information.
std::vector< std::unique_ptr< Edge > > & allEdges()
Edge & addEdge(BasicBlock *Src, BasicBlock *Dest, uint64_t W)
const std::vector< std::unique_ptr< Edge > > & allEdges() const
size_t bbInfoSize() const
CFGMST(Function &Func, bool InstrumentFuncEntry, bool InstrumentLoopEntries, BranchProbabilityInfo *BPI=nullptr, BlockFrequencyInfo *BFI=nullptr, LoopInfo *LI=nullptr)
BBInfo * findBBInfo(const BasicBlock *BB) const
BBInfo & getBBInfo(const BasicBlock *BB) const
void dumpEdges(raw_ostream &OS, const Twine &Message) const
LLVM_ABI unsigned getNumSuccessors() const LLVM_READONLY
Return the number of successors that this instruction has.
LLVM_ABI BasicBlock * getSuccessor(unsigned Idx) const LLVM_READONLY
Return the specified successor. This instruction must be a terminator.
bool contains(const LoopT *L) const
Return true if the specified loop is contained within in this loop.
Represents a single loop in the control flow graph.
Implements a dense probed hash-table based set with some number of buckets stored inline.
Represent a constant reference to a string, i.e.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM_ABI std::string str() const
Return the twine contents as a std::string.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
std::pair< iterator, bool > insert(const ValueT &V)
This class implements an extremely fast bulk output stream that can only output to a stream.
This is an optimization pass for GlobalISel generic memory operations.
void stable_sort(R &&Range)
bool succ_empty(const Instruction *I)
auto successors(const MachineBasicBlock *BB)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
LLVM_ABI bool isCriticalEdge(const Instruction *TI, unsigned SuccNum, bool AllowIdenticalEdges=false)
Return true if the specified edge is a critical edge.
LLVM_ABI bool isPresplitCoroSuspendExitEdge(const BasicBlock &Src, const BasicBlock &Dest)