1*9880d681SAndroid Build Coastguard Worker //===- llvm/Analysis/MaximumSpanningTree.h - Interface ----------*- 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 module provides means for calculating a maximum spanning tree for a 11*9880d681SAndroid Build Coastguard Worker // given set of weighted edges. The type parameter T is the type of a node. 12*9880d681SAndroid Build Coastguard Worker // 13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 14*9880d681SAndroid Build Coastguard Worker 15*9880d681SAndroid Build Coastguard Worker #ifndef LLVM_ANALYSIS_MAXIMUMSPANNINGTREE_H 16*9880d681SAndroid Build Coastguard Worker #define LLVM_ANALYSIS_MAXIMUMSPANNINGTREE_H 17*9880d681SAndroid Build Coastguard Worker 18*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/EquivalenceClasses.h" 19*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/BasicBlock.h" 20*9880d681SAndroid Build Coastguard Worker #include <algorithm> 21*9880d681SAndroid Build Coastguard Worker #include <vector> 22*9880d681SAndroid Build Coastguard Worker 23*9880d681SAndroid Build Coastguard Worker namespace llvm { 24*9880d681SAndroid Build Coastguard Worker 25*9880d681SAndroid Build Coastguard Worker /// MaximumSpanningTree - A MST implementation. 26*9880d681SAndroid Build Coastguard Worker /// The type parameter T determines the type of the nodes of the graph. 27*9880d681SAndroid Build Coastguard Worker template <typename T> 28*9880d681SAndroid Build Coastguard Worker class MaximumSpanningTree { 29*9880d681SAndroid Build Coastguard Worker public: 30*9880d681SAndroid Build Coastguard Worker typedef std::pair<const T*, const T*> Edge; 31*9880d681SAndroid Build Coastguard Worker typedef std::pair<Edge, double> EdgeWeight; 32*9880d681SAndroid Build Coastguard Worker typedef std::vector<EdgeWeight> EdgeWeights; 33*9880d681SAndroid Build Coastguard Worker protected: 34*9880d681SAndroid Build Coastguard Worker typedef std::vector<Edge> MaxSpanTree; 35*9880d681SAndroid Build Coastguard Worker 36*9880d681SAndroid Build Coastguard Worker MaxSpanTree MST; 37*9880d681SAndroid Build Coastguard Worker 38*9880d681SAndroid Build Coastguard Worker private: 39*9880d681SAndroid Build Coastguard Worker // A comparing class for comparing weighted edges. 40*9880d681SAndroid Build Coastguard Worker struct EdgeWeightCompare { getBlockSizeEdgeWeightCompare41*9880d681SAndroid Build Coastguard Worker static bool getBlockSize(const T *X) { 42*9880d681SAndroid Build Coastguard Worker const BasicBlock *BB = dyn_cast_or_null<BasicBlock>(X); 43*9880d681SAndroid Build Coastguard Worker return BB ? BB->size() : 0; 44*9880d681SAndroid Build Coastguard Worker } 45*9880d681SAndroid Build Coastguard Worker operatorEdgeWeightCompare46*9880d681SAndroid Build Coastguard Worker bool operator()(EdgeWeight X, EdgeWeight Y) const { 47*9880d681SAndroid Build Coastguard Worker if (X.second > Y.second) return true; 48*9880d681SAndroid Build Coastguard Worker if (X.second < Y.second) return false; 49*9880d681SAndroid Build Coastguard Worker 50*9880d681SAndroid Build Coastguard Worker // Equal edge weights: break ties by comparing block sizes. 51*9880d681SAndroid Build Coastguard Worker size_t XSizeA = getBlockSize(X.first.first); 52*9880d681SAndroid Build Coastguard Worker size_t YSizeA = getBlockSize(Y.first.first); 53*9880d681SAndroid Build Coastguard Worker if (XSizeA > YSizeA) return true; 54*9880d681SAndroid Build Coastguard Worker if (XSizeA < YSizeA) return false; 55*9880d681SAndroid Build Coastguard Worker 56*9880d681SAndroid Build Coastguard Worker size_t XSizeB = getBlockSize(X.first.second); 57*9880d681SAndroid Build Coastguard Worker size_t YSizeB = getBlockSize(Y.first.second); 58*9880d681SAndroid Build Coastguard Worker if (XSizeB > YSizeB) return true; 59*9880d681SAndroid Build Coastguard Worker if (XSizeB < YSizeB) return false; 60*9880d681SAndroid Build Coastguard Worker 61*9880d681SAndroid Build Coastguard Worker return false; 62*9880d681SAndroid Build Coastguard Worker } 63*9880d681SAndroid Build Coastguard Worker }; 64*9880d681SAndroid Build Coastguard Worker 65*9880d681SAndroid Build Coastguard Worker public: 66*9880d681SAndroid Build Coastguard Worker static char ID; // Class identification, replacement for typeinfo 67*9880d681SAndroid Build Coastguard Worker 68*9880d681SAndroid Build Coastguard Worker /// MaximumSpanningTree() - Takes a vector of weighted edges and returns a 69*9880d681SAndroid Build Coastguard Worker /// spanning tree. MaximumSpanningTree(EdgeWeights & EdgeVector)70*9880d681SAndroid Build Coastguard Worker MaximumSpanningTree(EdgeWeights &EdgeVector) { 71*9880d681SAndroid Build Coastguard Worker 72*9880d681SAndroid Build Coastguard Worker std::stable_sort(EdgeVector.begin(), EdgeVector.end(), EdgeWeightCompare()); 73*9880d681SAndroid Build Coastguard Worker 74*9880d681SAndroid Build Coastguard Worker // Create spanning tree, Forest contains a special data structure 75*9880d681SAndroid Build Coastguard Worker // that makes checking if two nodes are already in a common (sub-)tree 76*9880d681SAndroid Build Coastguard Worker // fast and cheap. 77*9880d681SAndroid Build Coastguard Worker EquivalenceClasses<const T*> Forest; 78*9880d681SAndroid Build Coastguard Worker for (typename EdgeWeights::iterator EWi = EdgeVector.begin(), 79*9880d681SAndroid Build Coastguard Worker EWe = EdgeVector.end(); EWi != EWe; ++EWi) { 80*9880d681SAndroid Build Coastguard Worker Edge e = (*EWi).first; 81*9880d681SAndroid Build Coastguard Worker 82*9880d681SAndroid Build Coastguard Worker Forest.insert(e.first); 83*9880d681SAndroid Build Coastguard Worker Forest.insert(e.second); 84*9880d681SAndroid Build Coastguard Worker } 85*9880d681SAndroid Build Coastguard Worker 86*9880d681SAndroid Build Coastguard Worker // Iterate over the sorted edges, biggest first. 87*9880d681SAndroid Build Coastguard Worker for (typename EdgeWeights::iterator EWi = EdgeVector.begin(), 88*9880d681SAndroid Build Coastguard Worker EWe = EdgeVector.end(); EWi != EWe; ++EWi) { 89*9880d681SAndroid Build Coastguard Worker Edge e = (*EWi).first; 90*9880d681SAndroid Build Coastguard Worker 91*9880d681SAndroid Build Coastguard Worker if (Forest.findLeader(e.first) != Forest.findLeader(e.second)) { 92*9880d681SAndroid Build Coastguard Worker Forest.unionSets(e.first, e.second); 93*9880d681SAndroid Build Coastguard Worker // So we know now that the edge is not already in a subtree, so we push 94*9880d681SAndroid Build Coastguard Worker // the edge to the MST. 95*9880d681SAndroid Build Coastguard Worker MST.push_back(e); 96*9880d681SAndroid Build Coastguard Worker } 97*9880d681SAndroid Build Coastguard Worker } 98*9880d681SAndroid Build Coastguard Worker } 99*9880d681SAndroid Build Coastguard Worker begin()100*9880d681SAndroid Build Coastguard Worker typename MaxSpanTree::iterator begin() { 101*9880d681SAndroid Build Coastguard Worker return MST.begin(); 102*9880d681SAndroid Build Coastguard Worker } 103*9880d681SAndroid Build Coastguard Worker end()104*9880d681SAndroid Build Coastguard Worker typename MaxSpanTree::iterator end() { 105*9880d681SAndroid Build Coastguard Worker return MST.end(); 106*9880d681SAndroid Build Coastguard Worker } 107*9880d681SAndroid Build Coastguard Worker }; 108*9880d681SAndroid Build Coastguard Worker 109*9880d681SAndroid Build Coastguard Worker } // End llvm namespace 110*9880d681SAndroid Build Coastguard Worker 111*9880d681SAndroid Build Coastguard Worker #endif 112