NestedSCR.hpp

Go to the documentation of this file.
00001 
00039 /* 
00040    NOTES: 
00041      - A clean re-write in C++ would greatly enhance the style and
00042        clarity of the code.
00043      - Nathan Tallent: Added the DGraph-node -> SCRId map to get
00044        around the unmet assumption that DGraph-node-ids go from 0-n.
00045 */
00046 
00047 #ifndef NestedStronglyConnectedRegions_H
00048 #define NestedStronglyConnectedRegions_H
00049 
00050 #include <iostream>
00051 
00052 #include <OpenAnalysis/Utils/RIFG.hpp>
00053 #include <OpenAnalysis/Utils/UnionFindUniverse.hpp>
00054 
00055 //***************************************************************************
00056 
00057 namespace OA {
00058 
00059 //***************************************************************************
00060 // Class: NestedSCR
00061 //
00062 // Description:
00063 //    A Tree of strongly connected regions
00064 //
00065 //***************************************************************************
00066 
00067 class TarjWork;
00068 class TarjTreeNode;
00069 
00070   
00071 class NestedSCR {
00072 public:
00073   
00074   enum Node_t { NODE_NOTHING, 
00075                 NODE_ACYCLIC, 
00076                 NODE_INTERVAL, 
00077                 NODE_IRREDUCIBLE };
00078 
00079   enum Edge_t { EDGE_NORMAL, 
00080                 EDGE_LOOP_ENTRY, 
00081                 EDGE_IRRED_ENTRY, 
00082                 EDGE_ITERATE };
00083 
00084   typedef unsigned int DFNUM_t;
00085 
00086 public:
00087   // Construct the Tarjan interval tree for the graph.
00088   NestedSCR(OA::OA_ptr<OA::RIFG> rifg);
00089   ~NestedSCR();
00090   
00091   OA::OA_ptr<OA::RIFG> getRIFG() { return rifg; }
00092 
00093 
00094   // Obtain a pointer to tree. [FIXME: Do we want to allow this?]
00095   TarjTreeNode* getTree();
00096 
00097 
00098   bool isFirst(RIFG::NodeId id);
00099   bool isLast(RIFG::NodeId id);
00100   bool isHeader(RIFG::NodeId id);
00101 
00102   
00103   // Given an interval header, return its first nested interval.
00104   RIFG::NodeId getInners(RIFG::NodeId id);
00105 
00106   // Given an interval header, return its last nested interval.
00107   RIFG::NodeId getInnersLast(RIFG::NodeId id);
00108 
00109   // Given an interval, return its parent (header) interval.
00110   RIFG::NodeId getOuter(RIFG::NodeId id);
00111 
00112   // Given an interval, return its next sibling interval. 
00113   RIFG::NodeId getNext(RIFG::NodeId id);
00114 
00115 
00116   // Given an interval, return its nesting level.
00117   int getLevel(RIFG::NodeId id);
00118 
00119   // Given an interval, return its unique index.
00120   int getLoopIndex(RIFG::NodeId id);
00121 
00122   // Given a node, return its type (acyclic, interval, irreducible).
00123   Node_t getNodeType(RIFG::NodeId id);
00124   Edge_t getEdgeType(RIFG::NodeId src, RIFG::NodeId sink);
00125 
00126   // Return true if the edge is a backedge, false otherwise.
00127   bool isBackEdge(RIFG::EdgeId e);
00128 
00129   // Return number of loops exited in traversing g edge from src to sink.
00130   int getExits(RIFG::NodeId src, RIFG::NodeId sink);
00131 
00132   // Return outermost loop exited in traversing g edge from src to sink
00133   // (RIFG::NIL if no loops exited).
00134   RIFG::NodeId getLoopExited(RIFG::NodeId src, RIFG::NodeId sink);
00135   
00136   
00137   bool Contains(RIFG::NodeId a, RIFG::NodeId b);
00138 
00139   // Return the least-common-ancestor of two nodes in the tree.
00140   RIFG::NodeId LCA(RIFG::NodeId a, RIFG::NodeId b);
00141 
00142   
00143   // Updates the prenumbering of the tree.  Useful if some change
00144   // has been made to the cfg where one knows how to update the
00145   // interval tree (as when adding pre-header nodes).
00146   void Renumber();
00147   void Prenumber(int n);
00148 
00149 
00150   // Pretty-print the interval tree. [N.B.: ignores 'os' at the moment]
00151   void dump(std::ostream& os);
00152   
00153 private: // methods
00154   void Create();
00155 
00156   void Init();
00157   void InitArrays();
00158   void DFS(RIFG::NodeId n);
00159   void FillPredLists();
00160   void GetTarjans();
00161   void Build();
00162   void Sort();
00163   void ComputeIntervalIndex();
00164   void ComputeIntervalIndexSubTree(int node, int value);
00165   void FreeWork();
00166 
00167   void DumpSubTree(std::ostream& os, int node, int indent);
00168 
00169   int FIND(int v);
00170   void UNION(int i, int j, int k);
00171 
00172 private: // data
00173   // The graph to analyze.
00174   OA::OA_ptr<OA::RIFG> rifg;
00175 
00176   // Work data
00177   UnionFindUniverse *uf;
00178   TarjWork *wk;       // maps RIFG::NodeId to TarjWork
00179   TarjTreeNode *tarj; // maps RIFG::NodeId to TarjTreeNode
00180   
00181   // List of nodes in reverse topological order.
00182   std::list<RIFG::NodeId> rev_top_list;
00183 
00184   // A map from RIFG::NodeId to DFS number.
00185   std::map<RIFG::NodeId, DFNUM_t> nodeid_to_dfnum_map;
00186 };
00187 
00188 
00189   
00190 } // end of namespace OA
00191 
00192 #endif