From 213a16c637926bfc38ba373d3aba6778e181e3ec Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Mon, 14 Aug 2006 22:19:25 +0000 Subject: [PATCH] Add code to resize the CSEMap hash table. This doesn't speedup codegen of 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 | 9 ++-- include/llvm/CodeGen/SelectionDAGCSEMap.h | 2 + include/llvm/CodeGen/SelectionDAGNodes.h | 1 + lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 1 + .../SelectionDAG/SelectionDAGCSEMap.cpp | 49 +++++++++++++++++-- 5 files changed, 56 insertions(+), 6 deletions(-) diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index 2cc6ba71011..a8af4a3b05e 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -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 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 ExternalSymbols; std::map TargetExternalSymbols; std::map StringNodes; - SelectionDAGCSEMap CSEMap; }; template <> struct GraphTraits : public GraphTraits { diff --git a/include/llvm/CodeGen/SelectionDAGCSEMap.h b/include/llvm/CodeGen/SelectionDAGCSEMap.h index dd1071a3173..e3771c9b540 100644 --- a/include/llvm/CodeGen/SelectionDAGCSEMap.h +++ b/include/llvm/CodeGen/SelectionDAGCSEMap.h @@ -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 diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index fe6975b19f2..dc58bd97a01 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -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; } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 6fd8ba2a9ec..1c17dfbee83 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -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; diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGCSEMap.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGCSEMap.cpp index b42c70bb56d..cd255ba3272 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGCSEMap.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGCSEMap.cpp @@ -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(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(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(InsertPos);