Change to use iterators instead of direct access
[oota-llvm.git] / include / llvm / Analysis / DSGraph.h
index 2b4a4803f3079af4bf7d564b1b076d17c511aa34..2cfcfb950564d355279bf3e4ee3786aea30e314f 100644 (file)
@@ -7,7 +7,8 @@
 // 
 //===----------------------------------------------------------------------===//
 //
-// This header defines the data structure graph.
+// This header defines the data structure graph (DSGraph) and the
+// ReachabilityCloner class.
 //
 //===----------------------------------------------------------------------===//
 
@@ -20,14 +21,78 @@ namespace llvm {
 
 class GlobalValue;
 
+//===----------------------------------------------------------------------===//
+/// DSScalarMap - An instance of this class is used to keep track of all of 
+/// which DSNode each scalar in a function points to.  This is specialized to
+/// keep track of globals with nodes in the function, and to keep track of the 
+/// unique DSNodeHandle being used by the scalar map.
+///
+/// This class is crucial to the efficiency of DSA with some large SCC's.  In 
+/// these cases, the cost of iterating over the scalar map dominates the cost
+/// of DSA.  In all of these cases, the DSA phase is really trying to identify 
+/// globals or unique node handles active in the function.
+///
+class DSScalarMap {
+  typedef hash_map<Value*, DSNodeHandle> ValueMapTy;
+  ValueMapTy ValueMap;
+
+  typedef hash_set<GlobalValue*> GlobalSetTy;
+  GlobalSetTy GlobalSet;
+public:
+
+  // Compatibility methods: provide an interface compatible with a map of 
+  // Value* to DSNodeHandle's.
+  typedef ValueMapTy::const_iterator const_iterator;
+  typedef ValueMapTy::iterator iterator;
+  iterator begin() { return ValueMap.begin(); }
+  iterator end()   { return ValueMap.end(); }
+  const_iterator begin() const { return ValueMap.begin(); }
+  const_iterator end() const { return ValueMap.end(); }
+  iterator find(Value *V) { return ValueMap.find(V); }
+  const_iterator find(Value *V) const { return ValueMap.find(V); }
+  unsigned count(Value *V) const { return ValueMap.count(V); }
+
+  void erase(Value *V) { erase(find(V)); }
+
+  DSNodeHandle &operator[](Value *V) {
+    std::pair<iterator,bool> IP = 
+      ValueMap.insert(std::make_pair(V, DSNodeHandle()));
+    if (IP.second) {  // Inserted the new entry into the map.
+      if (GlobalValue *GV = dyn_cast<GlobalValue>(V))
+        GlobalSet.insert(GV);
+    }
+    return IP.first->second;
+  }
+
+  void erase(iterator I) { 
+    assert(I != ValueMap.end() && "Cannot erase end!");
+    if (GlobalValue *GV = dyn_cast<GlobalValue>(I->first))
+      GlobalSet.erase(GV);
+    ValueMap.erase(I); 
+  }
+
+  void clear() {
+    ValueMap.clear();
+    GlobalSet.clear();
+  }
+
+  // Access to the global set: the set of all globals currently in the
+  // scalar map.
+  typedef GlobalSetTy::const_iterator global_iterator;
+  global_iterator global_begin() const { return GlobalSet.begin(); }
+  global_iterator global_end() const { return GlobalSet.end(); }
+};
+
+
 //===----------------------------------------------------------------------===//
 /// DSGraph - The graph that represents a function.
 ///
 struct DSGraph {
   // Public data-type declarations...
-  typedef hash_map<Value*, DSNodeHandle> ScalarMapTy;
+  typedef DSScalarMap ScalarMapTy;
   typedef hash_map<Function*, DSNodeHandle> ReturnNodesTy;
   typedef hash_set<GlobalValue*> GlobalSetTy;
+  typedef std::vector<DSNode*> NodeListTy;
 
   /// NodeMapTy - This data type is used when cloning one graph into another to
   /// keep track of the correspondence between the nodes in the old and new
@@ -37,7 +102,7 @@ private:
   DSGraph *GlobalsGraph;   // Pointer to the common graph of global objects
   bool PrintAuxCalls;      // Should this graph print the Aux calls vector?
 
-  std::vector<DSNode*> Nodes;
+  NodeListTy Nodes;
   ScalarMapTy ScalarMap;
 
   // ReturnNodes - A return value for every function merged into this graph.
@@ -106,8 +171,9 @@ public:
 
   /// getNodes - Get a vector of all the nodes in the graph
   /// 
-  const std::vector<DSNode*> &getNodes() const { return Nodes; }
-        std::vector<DSNode*> &getNodes()       { return Nodes; }
+  typedef NodeListTy::const_iterator node_iterator;
+  node_iterator node_begin() const { return Nodes.begin(); }
+  node_iterator node_end()   const { return Nodes.end(); }
 
   /// getFunctionNames - Return a space separated list of the name of the
   /// functions in this graph (if any)
@@ -202,8 +268,8 @@ public:
   /// is useful for clearing out markers like Incomplete.
   ///
   void maskNodeTypes(unsigned Mask) {
-    for (unsigned i = 0, e = Nodes.size(); i != e; ++i)
-      Nodes[i]->maskNodeTypes(Mask);
+    for (node_iterator I = node_begin(), E = node_end(); I != E; ++I)
+      (*I)->maskNodeTypes(Mask);
   }
   void maskIncompleteMarkers() { maskNodeTypes(~DSNode::Incomplete); }
 
@@ -243,19 +309,8 @@ public:
     UpdateInlinedGlobals  = 1 << 5, DontUpdateInlinedGlobals = 0,
   };
 
-private:
-  void cloneReachableNodes(const DSNode*  Node, unsigned BitsToClear,
-                           NodeMapTy& OldNodeMap, GlobalSetTy &Globals);
-
-public:
   void updateFromGlobalGraph();
 
-  void cloneReachableSubgraph(const DSGraph &G,
-                              hash_set<const DSNode*> &RootNodes,
-                              NodeMapTy &OldNodeMap,
-                              unsigned CloneFlags = 0);
-
-
   /// computeNodeMapping - Given roots in two different DSGraphs, traverse the
   /// nodes reachable from the two graphs, computing the mapping of nodes from
   /// the first to the second graph.
@@ -277,24 +332,6 @@ public:
                  ReturnNodesTy &OldReturnNodes, NodeMapTy &OldNodeMap,
                  unsigned CloneFlags = 0);
 
-  /// clonePartiallyInto - Clone the reachable subset of the specified DSGraph
-  /// into the current graph, for the specified function.
-  ///
-  /// This differs from cloneInto in that it only clones nodes reachable from
-  /// globals, call nodes, the scalars specified in ValBindings, and the return
-  /// value of the specified function.  This method merges the the cloned
-  /// version of the scalars and return value with the specified DSNodeHandles.
-  ///
-  /// On return, OldNodeMap contains a mapping from the original nodes to the
-  /// newly cloned nodes, for the subset of nodes that were actually cloned.
-  ///
-  /// The CloneFlags member controls various aspects of the cloning process.
-  ///
-  void clonePartiallyInto(const DSGraph &G, Function &F,
-                          const DSNodeHandle &RetVal,
-                          const ScalarMapTy &ValBindings, NodeMapTy &OldNodeMap,
-                          unsigned CloneFlags = 0);
-
   /// mergeInGraph - The method is used for merging graphs together.  If the
   /// argument graph is not *this, it makes a clone of the specified graph, then
   /// merges the nodes specified in the call site with the formal arguments in
@@ -312,7 +349,7 @@ public:
 
   // Methods for checking to make sure graphs are well formed...
   void AssertNodeInGraph(const DSNode *N) const {
-    assert((!N || find(Nodes.begin(), Nodes.end(), N) != Nodes.end()) &&
+    assert((!N || N->getParentGraph() == this) &&
            "AssertNodeInGraph: Node is not in graph!");
   }
   void AssertNodeContainsGlobal(const DSNode *N, GlobalValue *GV) const {
@@ -339,13 +376,6 @@ public:
 
   void AssertGraphOK() const;
 
-  /// mergeInGlobalsGraph - This method is useful for clients to incorporate the
-  /// globals graph into the DS, BU or TD graph for a function.  This code
-  /// retains all globals, i.e., does not delete unreachable globals after they
-  /// are inlined.
-  ///
-  void mergeInGlobalsGraph();
-
   /// removeTriviallyDeadNodes - After the graph has been constructed, this
   /// method removes all unreachable nodes that are created because they got
   /// merged with other nodes in the graph.  This is used as the first step of
@@ -354,6 +384,49 @@ public:
   void removeTriviallyDeadNodes();
 };
 
+
+  /// ReachabilityCloner - This class is used to incrementally clone and merge
+  /// nodes from a non-changing source graph into a potentially mutating
+  /// destination graph.  Nodes are only cloned over on demand, either in
+  /// responds to a merge() or getClonedNH() call.  When a node is cloned over,
+  /// all of the nodes reachable from it are automatically brought over as well.
+  class ReachabilityCloner {
+    DSGraph &Dest;
+    const DSGraph &Src;
+
+    /// BitsToKeep - These bits are retained from the source node when the
+    /// source nodes are merged into the destination graph.
+    unsigned BitsToKeep;
+    unsigned CloneFlags;
+
+    // NodeMap - A mapping from nodes in the source graph to the nodes that
+    // represent them in the destination graph.
+    DSGraph::NodeMapTy NodeMap;
+  public:
+    ReachabilityCloner(DSGraph &dest, const DSGraph &src, unsigned cloneFlags)
+      : Dest(dest), Src(src), CloneFlags(cloneFlags) {
+      assert(&Dest != &Src && "Cannot clone from graph to same graph!");
+      BitsToKeep = ~DSNode::DEAD;
+      if (CloneFlags & DSGraph::StripAllocaBit)
+        BitsToKeep &= ~DSNode::AllocaNode;
+      if (CloneFlags & DSGraph::StripModRefBits)
+        BitsToKeep &= ~(DSNode::Modified | DSNode::Read);
+      if (CloneFlags & DSGraph::StripIncompleteBit)
+        BitsToKeep &= ~DSNode::Incomplete;
+    }
+    
+    DSNodeHandle getClonedNH(const DSNodeHandle &SrcNH);
+
+    void merge(const DSNodeHandle &NH, const DSNodeHandle &SrcNH);
+
+    /// mergeCallSite - Merge the nodes reachable from the specified src call
+    /// site into the nodes reachable from DestCS.
+    void mergeCallSite(const DSCallSite &DestCS, const DSCallSite &SrcCS);
+
+    bool clonedNode() const { return !NodeMap.empty(); }
+
+    void destroy() { NodeMap.clear(); }
+  };
 } // End llvm namespace
 
 #endif