1*9880d681SAndroid Build Coastguard Worker //===-- CFGMST.h - Minimum Spanning Tree for CFG ----------------*- C++ -*-===// 2*9880d681SAndroid Build Coastguard Worker // 3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure 4*9880d681SAndroid Build Coastguard Worker // 5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source 6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details. 7*9880d681SAndroid Build Coastguard Worker // 8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 9*9880d681SAndroid Build Coastguard Worker // 10*9880d681SAndroid Build Coastguard Worker // This file implements a Union-find algorithm to compute Minimum Spanning Tree 11*9880d681SAndroid Build Coastguard Worker // for a given CFG. 12*9880d681SAndroid Build Coastguard Worker // 13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 14*9880d681SAndroid Build Coastguard Worker 15*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/DenseMap.h" 16*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/STLExtras.h" 17*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/BlockFrequencyInfo.h" 18*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/BranchProbabilityInfo.h" 19*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/CFG.h" 20*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/BranchProbability.h" 21*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h" 22*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h" 23*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/Utils/BasicBlockUtils.h" 24*9880d681SAndroid Build Coastguard Worker #include <utility> 25*9880d681SAndroid Build Coastguard Worker #include <vector> 26*9880d681SAndroid Build Coastguard Worker 27*9880d681SAndroid Build Coastguard Worker namespace llvm { 28*9880d681SAndroid Build Coastguard Worker 29*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "cfgmst" 30*9880d681SAndroid Build Coastguard Worker 31*9880d681SAndroid Build Coastguard Worker /// \brief An union-find based Minimum Spanning Tree for CFG 32*9880d681SAndroid Build Coastguard Worker /// 33*9880d681SAndroid Build Coastguard Worker /// Implements a Union-find algorithm to compute Minimum Spanning Tree 34*9880d681SAndroid Build Coastguard Worker /// for a given CFG. 35*9880d681SAndroid Build Coastguard Worker template <class Edge, class BBInfo> class CFGMST { 36*9880d681SAndroid Build Coastguard Worker public: 37*9880d681SAndroid Build Coastguard Worker Function &F; 38*9880d681SAndroid Build Coastguard Worker 39*9880d681SAndroid Build Coastguard Worker // Store all the edges in CFG. It may contain some stale edges 40*9880d681SAndroid Build Coastguard Worker // when Removed is set. 41*9880d681SAndroid Build Coastguard Worker std::vector<std::unique_ptr<Edge>> AllEdges; 42*9880d681SAndroid Build Coastguard Worker 43*9880d681SAndroid Build Coastguard Worker // This map records the auxiliary information for each BB. 44*9880d681SAndroid Build Coastguard Worker DenseMap<const BasicBlock *, std::unique_ptr<BBInfo>> BBInfos; 45*9880d681SAndroid Build Coastguard Worker 46*9880d681SAndroid Build Coastguard Worker // Find the root group of the G and compress the path from G to the root. findAndCompressGroup(BBInfo * G)47*9880d681SAndroid Build Coastguard Worker BBInfo *findAndCompressGroup(BBInfo *G) { 48*9880d681SAndroid Build Coastguard Worker if (G->Group != G) 49*9880d681SAndroid Build Coastguard Worker G->Group = findAndCompressGroup(static_cast<BBInfo *>(G->Group)); 50*9880d681SAndroid Build Coastguard Worker return static_cast<BBInfo *>(G->Group); 51*9880d681SAndroid Build Coastguard Worker } 52*9880d681SAndroid Build Coastguard Worker 53*9880d681SAndroid Build Coastguard Worker // Union BB1 and BB2 into the same group and return true. 54*9880d681SAndroid Build Coastguard Worker // Returns false if BB1 and BB2 are already in the same group. unionGroups(const BasicBlock * BB1,const BasicBlock * BB2)55*9880d681SAndroid Build Coastguard Worker bool unionGroups(const BasicBlock *BB1, const BasicBlock *BB2) { 56*9880d681SAndroid Build Coastguard Worker BBInfo *BB1G = findAndCompressGroup(&getBBInfo(BB1)); 57*9880d681SAndroid Build Coastguard Worker BBInfo *BB2G = findAndCompressGroup(&getBBInfo(BB2)); 58*9880d681SAndroid Build Coastguard Worker 59*9880d681SAndroid Build Coastguard Worker if (BB1G == BB2G) 60*9880d681SAndroid Build Coastguard Worker return false; 61*9880d681SAndroid Build Coastguard Worker 62*9880d681SAndroid Build Coastguard Worker // Make the smaller rank tree a direct child or the root of high rank tree. 63*9880d681SAndroid Build Coastguard Worker if (BB1G->Rank < BB2G->Rank) 64*9880d681SAndroid Build Coastguard Worker BB1G->Group = BB2G; 65*9880d681SAndroid Build Coastguard Worker else { 66*9880d681SAndroid Build Coastguard Worker BB2G->Group = BB1G; 67*9880d681SAndroid Build Coastguard Worker // If the ranks are the same, increment root of one tree by one. 68*9880d681SAndroid Build Coastguard Worker if (BB1G->Rank == BB2G->Rank) 69*9880d681SAndroid Build Coastguard Worker BB1G->Rank++; 70*9880d681SAndroid Build Coastguard Worker } 71*9880d681SAndroid Build Coastguard Worker return true; 72*9880d681SAndroid Build Coastguard Worker } 73*9880d681SAndroid Build Coastguard Worker 74*9880d681SAndroid Build Coastguard Worker // Give BB, return the auxiliary information. getBBInfo(const BasicBlock * BB)75*9880d681SAndroid Build Coastguard Worker BBInfo &getBBInfo(const BasicBlock *BB) const { 76*9880d681SAndroid Build Coastguard Worker auto It = BBInfos.find(BB); 77*9880d681SAndroid Build Coastguard Worker assert(It->second.get() != nullptr); 78*9880d681SAndroid Build Coastguard Worker return *It->second.get(); 79*9880d681SAndroid Build Coastguard Worker } 80*9880d681SAndroid Build Coastguard Worker 81*9880d681SAndroid Build Coastguard Worker // Traverse the CFG using a stack. Find all the edges and assign the weight. 82*9880d681SAndroid Build Coastguard Worker // Edges with large weight will be put into MST first so they are less likely 83*9880d681SAndroid Build Coastguard Worker // to be instrumented. buildEdges()84*9880d681SAndroid Build Coastguard Worker void buildEdges() { 85*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Build Edge on " << F.getName() << "\n"); 86*9880d681SAndroid Build Coastguard Worker 87*9880d681SAndroid Build Coastguard Worker const BasicBlock *BB = &(F.getEntryBlock()); 88*9880d681SAndroid Build Coastguard Worker uint64_t EntryWeight = (BFI != nullptr ? BFI->getEntryFreq() : 2); 89*9880d681SAndroid Build Coastguard Worker // Add a fake edge to the entry. 90*9880d681SAndroid Build Coastguard Worker addEdge(nullptr, BB, EntryWeight); 91*9880d681SAndroid Build Coastguard Worker 92*9880d681SAndroid Build Coastguard Worker // Special handling for single BB functions. 93*9880d681SAndroid Build Coastguard Worker if (succ_empty(BB)) { 94*9880d681SAndroid Build Coastguard Worker addEdge(BB, nullptr, EntryWeight); 95*9880d681SAndroid Build Coastguard Worker return; 96*9880d681SAndroid Build Coastguard Worker } 97*9880d681SAndroid Build Coastguard Worker 98*9880d681SAndroid Build Coastguard Worker static const uint32_t CriticalEdgeMultiplier = 1000; 99*9880d681SAndroid Build Coastguard Worker 100*9880d681SAndroid Build Coastguard Worker for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { 101*9880d681SAndroid Build Coastguard Worker TerminatorInst *TI = BB->getTerminator(); 102*9880d681SAndroid Build Coastguard Worker uint64_t BBWeight = 103*9880d681SAndroid Build Coastguard Worker (BFI != nullptr ? BFI->getBlockFreq(&*BB).getFrequency() : 2); 104*9880d681SAndroid Build Coastguard Worker uint64_t Weight = 2; 105*9880d681SAndroid Build Coastguard Worker if (int successors = TI->getNumSuccessors()) { 106*9880d681SAndroid Build Coastguard Worker for (int i = 0; i != successors; ++i) { 107*9880d681SAndroid Build Coastguard Worker BasicBlock *TargetBB = TI->getSuccessor(i); 108*9880d681SAndroid Build Coastguard Worker bool Critical = isCriticalEdge(TI, i); 109*9880d681SAndroid Build Coastguard Worker uint64_t scaleFactor = BBWeight; 110*9880d681SAndroid Build Coastguard Worker if (Critical) { 111*9880d681SAndroid Build Coastguard Worker if (scaleFactor < UINT64_MAX / CriticalEdgeMultiplier) 112*9880d681SAndroid Build Coastguard Worker scaleFactor *= CriticalEdgeMultiplier; 113*9880d681SAndroid Build Coastguard Worker else 114*9880d681SAndroid Build Coastguard Worker scaleFactor = UINT64_MAX; 115*9880d681SAndroid Build Coastguard Worker } 116*9880d681SAndroid Build Coastguard Worker if (BPI != nullptr) 117*9880d681SAndroid Build Coastguard Worker Weight = BPI->getEdgeProbability(&*BB, TargetBB).scale(scaleFactor); 118*9880d681SAndroid Build Coastguard Worker addEdge(&*BB, TargetBB, Weight).IsCritical = Critical; 119*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << " Edge: from " << BB->getName() << " to " 120*9880d681SAndroid Build Coastguard Worker << TargetBB->getName() << " w=" << Weight << "\n"); 121*9880d681SAndroid Build Coastguard Worker } 122*9880d681SAndroid Build Coastguard Worker } else { 123*9880d681SAndroid Build Coastguard Worker addEdge(&*BB, nullptr, BBWeight); 124*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << " Edge: from " << BB->getName() << " to exit" 125*9880d681SAndroid Build Coastguard Worker << " w = " << BBWeight << "\n"); 126*9880d681SAndroid Build Coastguard Worker } 127*9880d681SAndroid Build Coastguard Worker } 128*9880d681SAndroid Build Coastguard Worker } 129*9880d681SAndroid Build Coastguard Worker 130*9880d681SAndroid Build Coastguard Worker // Sort CFG edges based on its weight. sortEdgesByWeight()131*9880d681SAndroid Build Coastguard Worker void sortEdgesByWeight() { 132*9880d681SAndroid Build Coastguard Worker std::stable_sort(AllEdges.begin(), AllEdges.end(), 133*9880d681SAndroid Build Coastguard Worker [](const std::unique_ptr<Edge> &Edge1, 134*9880d681SAndroid Build Coastguard Worker const std::unique_ptr<Edge> &Edge2) { 135*9880d681SAndroid Build Coastguard Worker return Edge1->Weight > Edge2->Weight; 136*9880d681SAndroid Build Coastguard Worker }); 137*9880d681SAndroid Build Coastguard Worker } 138*9880d681SAndroid Build Coastguard Worker 139*9880d681SAndroid Build Coastguard Worker // Traverse all the edges and compute the Minimum Weight Spanning Tree 140*9880d681SAndroid Build Coastguard Worker // using union-find algorithm. computeMinimumSpanningTree()141*9880d681SAndroid Build Coastguard Worker void computeMinimumSpanningTree() { 142*9880d681SAndroid Build Coastguard Worker // First, put all the critical edge with landing-pad as the Dest to MST. 143*9880d681SAndroid Build Coastguard Worker // This works around the insufficient support of critical edges split 144*9880d681SAndroid Build Coastguard Worker // when destination BB is a landing pad. 145*9880d681SAndroid Build Coastguard Worker for (auto &Ei : AllEdges) { 146*9880d681SAndroid Build Coastguard Worker if (Ei->Removed) 147*9880d681SAndroid Build Coastguard Worker continue; 148*9880d681SAndroid Build Coastguard Worker if (Ei->IsCritical) { 149*9880d681SAndroid Build Coastguard Worker if (Ei->DestBB && Ei->DestBB->isLandingPad()) { 150*9880d681SAndroid Build Coastguard Worker if (unionGroups(Ei->SrcBB, Ei->DestBB)) 151*9880d681SAndroid Build Coastguard Worker Ei->InMST = true; 152*9880d681SAndroid Build Coastguard Worker } 153*9880d681SAndroid Build Coastguard Worker } 154*9880d681SAndroid Build Coastguard Worker } 155*9880d681SAndroid Build Coastguard Worker 156*9880d681SAndroid Build Coastguard Worker for (auto &Ei : AllEdges) { 157*9880d681SAndroid Build Coastguard Worker if (Ei->Removed) 158*9880d681SAndroid Build Coastguard Worker continue; 159*9880d681SAndroid Build Coastguard Worker if (unionGroups(Ei->SrcBB, Ei->DestBB)) 160*9880d681SAndroid Build Coastguard Worker Ei->InMST = true; 161*9880d681SAndroid Build Coastguard Worker } 162*9880d681SAndroid Build Coastguard Worker } 163*9880d681SAndroid Build Coastguard Worker 164*9880d681SAndroid Build Coastguard Worker // Dump the Debug information about the instrumentation. dumpEdges(raw_ostream & OS,const Twine & Message)165*9880d681SAndroid Build Coastguard Worker void dumpEdges(raw_ostream &OS, const Twine &Message) const { 166*9880d681SAndroid Build Coastguard Worker if (!Message.str().empty()) 167*9880d681SAndroid Build Coastguard Worker OS << Message << "\n"; 168*9880d681SAndroid Build Coastguard Worker OS << " Number of Basic Blocks: " << BBInfos.size() << "\n"; 169*9880d681SAndroid Build Coastguard Worker for (auto &BI : BBInfos) { 170*9880d681SAndroid Build Coastguard Worker const BasicBlock *BB = BI.first; 171*9880d681SAndroid Build Coastguard Worker OS << " BB: " << (BB == nullptr ? "FakeNode" : BB->getName()) << " " 172*9880d681SAndroid Build Coastguard Worker << BI.second->infoString() << "\n"; 173*9880d681SAndroid Build Coastguard Worker } 174*9880d681SAndroid Build Coastguard Worker 175*9880d681SAndroid Build Coastguard Worker OS << " Number of Edges: " << AllEdges.size() 176*9880d681SAndroid Build Coastguard Worker << " (*: Instrument, C: CriticalEdge, -: Removed)\n"; 177*9880d681SAndroid Build Coastguard Worker uint32_t Count = 0; 178*9880d681SAndroid Build Coastguard Worker for (auto &EI : AllEdges) 179*9880d681SAndroid Build Coastguard Worker OS << " Edge " << Count++ << ": " << getBBInfo(EI->SrcBB).Index << "-->" 180*9880d681SAndroid Build Coastguard Worker << getBBInfo(EI->DestBB).Index << EI->infoString() << "\n"; 181*9880d681SAndroid Build Coastguard Worker } 182*9880d681SAndroid Build Coastguard Worker 183*9880d681SAndroid Build Coastguard Worker // Add an edge to AllEdges with weight W. addEdge(const BasicBlock * Src,const BasicBlock * Dest,uint64_t W)184*9880d681SAndroid Build Coastguard Worker Edge &addEdge(const BasicBlock *Src, const BasicBlock *Dest, uint64_t W) { 185*9880d681SAndroid Build Coastguard Worker uint32_t Index = BBInfos.size(); 186*9880d681SAndroid Build Coastguard Worker auto Iter = BBInfos.end(); 187*9880d681SAndroid Build Coastguard Worker bool Inserted; 188*9880d681SAndroid Build Coastguard Worker std::tie(Iter, Inserted) = BBInfos.insert(std::make_pair(Src, nullptr)); 189*9880d681SAndroid Build Coastguard Worker if (Inserted) { 190*9880d681SAndroid Build Coastguard Worker // Newly inserted, update the real info. 191*9880d681SAndroid Build Coastguard Worker Iter->second = std::move(llvm::make_unique<BBInfo>(Index)); 192*9880d681SAndroid Build Coastguard Worker Index++; 193*9880d681SAndroid Build Coastguard Worker } 194*9880d681SAndroid Build Coastguard Worker std::tie(Iter, Inserted) = BBInfos.insert(std::make_pair(Dest, nullptr)); 195*9880d681SAndroid Build Coastguard Worker if (Inserted) 196*9880d681SAndroid Build Coastguard Worker // Newly inserted, update the real info. 197*9880d681SAndroid Build Coastguard Worker Iter->second = std::move(llvm::make_unique<BBInfo>(Index)); 198*9880d681SAndroid Build Coastguard Worker AllEdges.emplace_back(new Edge(Src, Dest, W)); 199*9880d681SAndroid Build Coastguard Worker return *AllEdges.back(); 200*9880d681SAndroid Build Coastguard Worker } 201*9880d681SAndroid Build Coastguard Worker 202*9880d681SAndroid Build Coastguard Worker BranchProbabilityInfo *BPI; 203*9880d681SAndroid Build Coastguard Worker BlockFrequencyInfo *BFI; 204*9880d681SAndroid Build Coastguard Worker 205*9880d681SAndroid Build Coastguard Worker public: 206*9880d681SAndroid Build Coastguard Worker CFGMST(Function &Func, BranchProbabilityInfo *BPI_ = nullptr, 207*9880d681SAndroid Build Coastguard Worker BlockFrequencyInfo *BFI_ = nullptr) F(Func)208*9880d681SAndroid Build Coastguard Worker : F(Func), BPI(BPI_), BFI(BFI_) { 209*9880d681SAndroid Build Coastguard Worker buildEdges(); 210*9880d681SAndroid Build Coastguard Worker sortEdgesByWeight(); 211*9880d681SAndroid Build Coastguard Worker computeMinimumSpanningTree(); 212*9880d681SAndroid Build Coastguard Worker } 213*9880d681SAndroid Build Coastguard Worker }; 214*9880d681SAndroid Build Coastguard Worker 215*9880d681SAndroid Build Coastguard Worker #undef DEBUG_TYPE // "cfgmst" 216*9880d681SAndroid Build Coastguard Worker } // end namespace llvm 217