14#ifndef LLVM_TRANSFORMS_INSTRUMENTATION_CFGMST_H
15#define LLVM_TRANSFORMS_INSTRUMENTATION_CFGMST_H
32#define DEBUG_TYPE "cfgmst"
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;
166 if (InstrumentLoopEntries && LI->
isLoopHeader(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) {
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.
insert(std::make_pair(Src,
nullptr));
311 Iter->second = std::make_unique<BBInfo>(
Index);
314 std::tie(Iter, Inserted) = BBInfos.
insert(std::make_pair(Dest,
nullptr));
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();
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines the DenseMap class.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Basic Block Representation.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...
Analysis providing branch probability information.
BranchProbability getEdgeProbability(const BasicBlock *Src, unsigned IndexInSuccessors) const
Get an edge's probability, relative to other out-edges of the Src.
uint64_t scale(uint64_t Num) const
Scale a large integer.
An union-find based Minimum Spanning Tree for CFG.
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
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
unsigned getNumSuccessors() const LLVM_READONLY
Return the number of successors that this instruction has.
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.
bool isLoopHeader(const BlockT *BB) const
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
Represents a single loop in the control flow graph.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
std::string str() const
Return the twine contents as a std::string.
StringRef getName() const
Return a constant reference to the value's name.
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)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool isCriticalEdge(const Instruction *TI, unsigned SuccNum, bool AllowIdenticalEdges=false)
Return true if the specified edge is a critical edge.
bool isPresplitCoroSuspendExitEdge(const BasicBlock &Src, const BasicBlock &Dest)