Add code to resize the CSEMap hash table. This doesn't speedup codegen of
authorChris Lattner <sabre@nondot.org>
Mon, 14 Aug 2006 22:19:25 +0000 (22:19 +0000)
committerChris Lattner <sabre@nondot.org>
Mon, 14 Aug 2006 22:19:25 +0000 (22:19 +0000)
kimwitu, but seems like a good idea from a "avoid performance cliffs" standpoint :)

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@29675 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/CodeGen/SelectionDAG.h
include/llvm/CodeGen/SelectionDAGCSEMap.h
include/llvm/CodeGen/SelectionDAGNodes.h
lib/CodeGen/SelectionDAG/SelectionDAG.cpp
lib/CodeGen/SelectionDAG/SelectionDAGCSEMap.cpp

index 2cc6ba71011f36a9b8f30e79252dd1eb65c2fc50..a8af4a3b05e4ab6c2440377c9cf4bddd827a3829 100644 (file)
@@ -46,12 +46,16 @@ class SelectionDAG {
   MachineFunction &MF;
   MachineDebugInfo *DI;
 
-  // Root - The root of the entire DAG.  EntryNode - The starting token.
+  /// Root - The root of the entire DAG.  EntryNode - The starting token.
   SDOperand Root, EntryNode;
 
-  // AllNodes - A linked list of nodes in the current DAG.
+  /// AllNodes - A linked list of nodes in the current DAG.
   ilist<SDNode> AllNodes;
 
+  /// CSEMap - This structure is used to memoize nodes, automatically performing
+  /// CSE with existing nodes with a duplicate is requested.
+  SelectionDAGCSEMap CSEMap;
+
 public:
   SelectionDAG(TargetLowering &tli, MachineFunction &mf, MachineDebugInfo *di)
   : TLI(tli), MF(mf), DI(di) {
@@ -464,7 +468,6 @@ private:
   std::map<std::string, SDNode*> ExternalSymbols;
   std::map<std::string, SDNode*> TargetExternalSymbols;
   std::map<std::string, StringSDNode*> StringNodes;
-  SelectionDAGCSEMap CSEMap;
 };
 
 template <> struct GraphTraits<SelectionDAG*> : public GraphTraits<SDNode*> {
index dd1071a3173d687fb8cc8cc87d566470f06e7d33..e3771c9b5404b09a41125aee0dfddcdaa4b0f8bd 100644 (file)
@@ -117,8 +117,10 @@ namespace llvm {
     
   private:
     SDNode *GetNextPtr(void *NextInBucketPtr);
+    SDNode *GetNextPtr(void *NextInBucketPtr, void **Buckets, unsigned NumBuck);
     void **GetBucketPtr(void *NextInBucketPtr);
     void **GetBucketFor(const NodeID &ID) const;
+    void GrowHashTable();
   };
 }  // end namespace llvm
 
index fe6975b19f23bc521f960425a0597a57f9bbf1be..dc58bd97a0122a030d8ac2189c3c34ea6317ed04 100644 (file)
@@ -719,6 +719,7 @@ class SDNode {
 public:
   virtual ~SDNode() {
     assert(NumOperands == 0 && "Operand list not cleared before deletion");
+    assert(NextInBucket == 0 && "Still in CSEMap?");
     NodeType = ISD::DELETED_NODE;
   }
   
index 6fd8ba2a9ec4e56ef32da2e84aa062d1791bbd8c..1c17dfbee83118571d180a6467a8a182eda81582 100644 (file)
@@ -469,6 +469,7 @@ SDNode *SelectionDAG::FindModifiedNodeSlot(SDNode *N,
 SelectionDAG::~SelectionDAG() {
   while (!AllNodes.empty()) {
     SDNode *N = AllNodes.begin();
+    N->SetNextInBucket(0);
     delete [] N->OperandList;
     N->OperandList = 0;
     N->NumOperands = 0;
index b42c70bb56d0de5d7b4201fc4f6de239ec850616..cd255ba3272e00304d6bf30e47b30b4bfbd7c7d2 100644 (file)
@@ -157,7 +157,7 @@ bool SelectionDAGCSEMap::NodeID::operator==(const NodeID &RHS) const {
 // SelectionDAGCSEMap Implementation
 
 SelectionDAGCSEMap::SelectionDAGCSEMap() : NumNodes(0) {
-  NumBuckets = 256;
+  NumBuckets = 64;
   Buckets = new void*[NumBuckets];
   memset(Buckets, 0, NumBuckets*sizeof(void*));
 }
@@ -176,6 +176,15 @@ SDNode *SelectionDAGCSEMap::GetNextPtr(void *NextInBucketPtr) {
   return static_cast<SDNode*>(NextInBucketPtr);
 }
 
+/// GetNextPtr - This is just like the previous GetNextPtr implementation, but
+/// allows a bucket array to be specified.
+SDNode *SelectionDAGCSEMap::GetNextPtr(void *NextInBucketPtr, void **Bucks, 
+                                       unsigned NumBuck) {
+  if (NextInBucketPtr >= Bucks && NextInBucketPtr < Bucks+NumBuck)
+    return 0;
+  return static_cast<SDNode*>(NextInBucketPtr);
+}
+
 void **SelectionDAGCSEMap::GetBucketPtr(void *NextInBucketPtr) {
   //assert(NextInBucketPtr >= Buckets && NextInBucketPtr < Buckets+NumBuckets &&
   //       "NextInBucketPtr is not a bucket ptr");
@@ -185,13 +194,42 @@ void **SelectionDAGCSEMap::GetBucketPtr(void *NextInBucketPtr) {
 /// GetBucketFor - Hash the specified node ID and return the hash bucket for the
 /// specified ID.
 void **SelectionDAGCSEMap::GetBucketFor(const NodeID &ID) const {
-  // TODO: if load is high, resize hash table.
-  
   // NumBuckets is always a power of 2.
   unsigned BucketNum = ID.ComputeHash() & (NumBuckets-1);
   return Buckets+BucketNum;
 }
 
+/// GrowHashTable - Double the size of the hash table and rehash everything.
+///
+void SelectionDAGCSEMap::GrowHashTable() {
+  void **OldBuckets = Buckets;
+  unsigned OldNumBuckets = NumBuckets;
+  NumBuckets <<= 1;
+  
+  // Reset the node count to zero: we're going to reinsert everything.
+  NumNodes = 0;
+  
+  // Clear out new buckets.
+  Buckets = new void*[NumBuckets];
+  memset(Buckets, 0, NumBuckets*sizeof(void*));
+
+  // Walk the old buckets, rehashing nodes into their new place.
+  for (unsigned i = 0; i != OldNumBuckets; ++i) {
+    void *Probe = OldBuckets[i];
+    if (!Probe) continue;
+    while (SDNode *NodeInBucket = GetNextPtr(Probe, OldBuckets, OldNumBuckets)){
+      // Figure out the next link, remove NodeInBucket from the old link.
+      Probe = NodeInBucket->getNextInBucket();
+      NodeInBucket->SetNextInBucket(0);
+
+      // Insert the node into the new bucket, after recomputing the hash.
+      InsertNode(NodeInBucket, GetBucketFor(NodeID(NodeInBucket)));
+    }
+  }
+  
+  delete[] OldBuckets;
+}
+
 /// FindNodeOrInsertPos - Look up the node specified by ID.  If it exists,
 /// return it.  If not, return the insertion token that will make insertion
 /// faster.
@@ -226,6 +264,11 @@ SDNode *SelectionDAGCSEMap::FindNodeOrInsertPos(const NodeID &ID,
 /// FindNodeOrInsertPos.
 void SelectionDAGCSEMap::InsertNode(SDNode *N, void *InsertPos) {
   ++NumNodes;
+  // Do we need to grow the hashtable?
+  if (NumNodes > NumBuckets*2) {
+    GrowHashTable();
+    InsertPos = GetBucketFor(NodeID(N));
+  }
   
   /// The insert position is actually a bucket pointer.
   void **Bucket = static_cast<void**>(InsertPos);