xref: /aosp_15_r20/external/llvm/lib/Transforms/Instrumentation/MaximumSpanningTree.h (revision 9880d6810fe72a1726cb53787c6711e909410d58)
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