diff options
author | Andreas Neustifter <astifter-llvm@gmx.at> | 2009-09-04 12:34:44 +0000 |
---|---|---|
committer | Andreas Neustifter <astifter-llvm@gmx.at> | 2009-09-04 12:34:44 +0000 |
commit | ed1ac4ae8eadb907ec6a41bb74cae1777a4e28d2 (patch) | |
tree | 9ceb7513e74ec9a45f565cac05396d485da9380b /lib/Transforms/Instrumentation/MaximumSpanningTree.h | |
parent | 859fff476dfe8d83abdf4621b1d20062c0daa85c (diff) |
Converted MaximumSpanningTree algorithm to a generic template, this could go
into llvm/ADT.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@81001 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/Instrumentation/MaximumSpanningTree.h')
-rw-r--r-- | lib/Transforms/Instrumentation/MaximumSpanningTree.h | 78 |
1 files changed, 61 insertions, 17 deletions
diff --git a/lib/Transforms/Instrumentation/MaximumSpanningTree.h b/lib/Transforms/Instrumentation/MaximumSpanningTree.h index 2343985f23..2951dbcea9 100644 --- a/lib/Transforms/Instrumentation/MaximumSpanningTree.h +++ b/lib/Transforms/Instrumentation/MaximumSpanningTree.h @@ -7,43 +7,87 @@ // //===----------------------------------------------------------------------===// // -// This module privides means for calculating a maximum spanning tree for the -// CFG of a function according to a given profile. +// This module privides means for calculating a maximum spanning tree for a +// given set of weighted edges. The type parameter T is the type of a node. // //===----------------------------------------------------------------------===// #ifndef LLVM_ANALYSIS_MAXIMUMSPANNINGTREE_H #define LLVM_ANALYSIS_MAXIMUMSPANNINGTREE_H -#include "llvm/Analysis/ProfileInfo.h" -#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/EquivalenceClasses.h" #include <vector> +#include <algorithm> namespace llvm { - class Function; + /// MaximumSpanningTree - A MST implementation. + /// The type parameter T determines the type of the nodes of the graph. + template <typename T> class MaximumSpanningTree { - public: - typedef std::vector<ProfileInfo::Edge> MaxSpanTree; + // A comparing class for comparing weighted edges. + template <typename CT> + struct EdgeWeightCompare { + bool operator()(typename MaximumSpanningTree<CT>::EdgeWeight X, + typename MaximumSpanningTree<CT>::EdgeWeight Y) const { + if (X.second > Y.second) return true; + if (X.second < Y.second) return false; + return false; + } + }; + + public: + typedef std::pair<const T*, const T*> Edge; + typedef std::pair<Edge, double> EdgeWeight; + typedef std::vector<EdgeWeight> EdgeWeights; protected: + typedef std::vector<Edge> MaxSpanTree; + MaxSpanTree MST; public: static char ID; // Class identification, replacement for typeinfo - // MaxSpanTree() - Calculates a MST for a function according to a profile. - // If inverted is true, all the edges *not* in the MST are returned. As a - // special also all leaf edges of the MST are not included, this makes it - // easier for the OptimalEdgeProfileInstrumentation to use this MST to do - // an optimal profiling. - MaximumSpanningTree(std::vector<ProfileInfo::EdgeWeight>&); - virtual ~MaximumSpanningTree() {} + /// MaximumSpanningTree() - Takes a vector of weighted edges and returns a + /// spanning tree. + MaximumSpanningTree(EdgeWeights &EdgeVector) { + + std::stable_sort(EdgeVector.begin(), EdgeVector.end(), EdgeWeightCompare<T>()); + + // Create spanning tree, Forest contains a special data structure + // that makes checking if two nodes are already in a common (sub-)tree + // fast and cheap. + EquivalenceClasses<const T*> Forest; + for (typename EdgeWeights::iterator EWi = EdgeVector.begin(), + EWe = EdgeVector.end(); EWi != EWe; ++EWi) { + Edge e = (*EWi).first; + + Forest.insert(e.first); + Forest.insert(e.second); + } + + // Iterate over the sorted edges, biggest first. + for (typename EdgeWeights::iterator EWi = EdgeVector.begin(), + EWe = EdgeVector.end(); EWi != EWe; ++EWi) { + Edge e = (*EWi).first; + + if (Forest.findLeader(e.first) != Forest.findLeader(e.second)) { + Forest.unionSets(e.first, e.second); + // So we know now that the edge is not already in a subtree, so we push + // the edge to the MST. + MST.push_back(e); + } + } + } - virtual MaxSpanTree::iterator begin(); - virtual MaxSpanTree::iterator end(); + typename MaxSpanTree::iterator begin() { + return MST.begin(); + } - virtual void dump(); + typename MaxSpanTree::iterator end() { + return MST.end(); + } }; } // End llvm namespace |