forked from OSchip/llvm-project
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 :) llvm-svn: 29675
This commit is contained in:
parent
fdb296850c
commit
63268f0672
|
@ -46,12 +46,16 @@ class SelectionDAG {
|
||||||
MachineFunction &MF;
|
MachineFunction &MF;
|
||||||
MachineDebugInfo *DI;
|
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;
|
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;
|
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:
|
public:
|
||||||
SelectionDAG(TargetLowering &tli, MachineFunction &mf, MachineDebugInfo *di)
|
SelectionDAG(TargetLowering &tli, MachineFunction &mf, MachineDebugInfo *di)
|
||||||
: TLI(tli), MF(mf), DI(di) {
|
: TLI(tli), MF(mf), DI(di) {
|
||||||
|
@ -464,7 +468,6 @@ private:
|
||||||
std::map<std::string, SDNode*> ExternalSymbols;
|
std::map<std::string, SDNode*> ExternalSymbols;
|
||||||
std::map<std::string, SDNode*> TargetExternalSymbols;
|
std::map<std::string, SDNode*> TargetExternalSymbols;
|
||||||
std::map<std::string, StringSDNode*> StringNodes;
|
std::map<std::string, StringSDNode*> StringNodes;
|
||||||
SelectionDAGCSEMap CSEMap;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct GraphTraits<SelectionDAG*> : public GraphTraits<SDNode*> {
|
template <> struct GraphTraits<SelectionDAG*> : public GraphTraits<SDNode*> {
|
||||||
|
|
|
@ -117,8 +117,10 @@ namespace llvm {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SDNode *GetNextPtr(void *NextInBucketPtr);
|
SDNode *GetNextPtr(void *NextInBucketPtr);
|
||||||
|
SDNode *GetNextPtr(void *NextInBucketPtr, void **Buckets, unsigned NumBuck);
|
||||||
void **GetBucketPtr(void *NextInBucketPtr);
|
void **GetBucketPtr(void *NextInBucketPtr);
|
||||||
void **GetBucketFor(const NodeID &ID) const;
|
void **GetBucketFor(const NodeID &ID) const;
|
||||||
|
void GrowHashTable();
|
||||||
};
|
};
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
||||||
|
|
|
@ -719,6 +719,7 @@ class SDNode {
|
||||||
public:
|
public:
|
||||||
virtual ~SDNode() {
|
virtual ~SDNode() {
|
||||||
assert(NumOperands == 0 && "Operand list not cleared before deletion");
|
assert(NumOperands == 0 && "Operand list not cleared before deletion");
|
||||||
|
assert(NextInBucket == 0 && "Still in CSEMap?");
|
||||||
NodeType = ISD::DELETED_NODE;
|
NodeType = ISD::DELETED_NODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -469,6 +469,7 @@ SDNode *SelectionDAG::FindModifiedNodeSlot(SDNode *N,
|
||||||
SelectionDAG::~SelectionDAG() {
|
SelectionDAG::~SelectionDAG() {
|
||||||
while (!AllNodes.empty()) {
|
while (!AllNodes.empty()) {
|
||||||
SDNode *N = AllNodes.begin();
|
SDNode *N = AllNodes.begin();
|
||||||
|
N->SetNextInBucket(0);
|
||||||
delete [] N->OperandList;
|
delete [] N->OperandList;
|
||||||
N->OperandList = 0;
|
N->OperandList = 0;
|
||||||
N->NumOperands = 0;
|
N->NumOperands = 0;
|
||||||
|
|
|
@ -157,7 +157,7 @@ bool SelectionDAGCSEMap::NodeID::operator==(const NodeID &RHS) const {
|
||||||
// SelectionDAGCSEMap Implementation
|
// SelectionDAGCSEMap Implementation
|
||||||
|
|
||||||
SelectionDAGCSEMap::SelectionDAGCSEMap() : NumNodes(0) {
|
SelectionDAGCSEMap::SelectionDAGCSEMap() : NumNodes(0) {
|
||||||
NumBuckets = 256;
|
NumBuckets = 64;
|
||||||
Buckets = new void*[NumBuckets];
|
Buckets = new void*[NumBuckets];
|
||||||
memset(Buckets, 0, NumBuckets*sizeof(void*));
|
memset(Buckets, 0, NumBuckets*sizeof(void*));
|
||||||
}
|
}
|
||||||
|
@ -176,6 +176,15 @@ SDNode *SelectionDAGCSEMap::GetNextPtr(void *NextInBucketPtr) {
|
||||||
return static_cast<SDNode*>(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) {
|
void **SelectionDAGCSEMap::GetBucketPtr(void *NextInBucketPtr) {
|
||||||
//assert(NextInBucketPtr >= Buckets && NextInBucketPtr < Buckets+NumBuckets &&
|
//assert(NextInBucketPtr >= Buckets && NextInBucketPtr < Buckets+NumBuckets &&
|
||||||
// "NextInBucketPtr is not a bucket ptr");
|
// "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
|
/// GetBucketFor - Hash the specified node ID and return the hash bucket for the
|
||||||
/// specified ID.
|
/// specified ID.
|
||||||
void **SelectionDAGCSEMap::GetBucketFor(const NodeID &ID) const {
|
void **SelectionDAGCSEMap::GetBucketFor(const NodeID &ID) const {
|
||||||
// TODO: if load is high, resize hash table.
|
|
||||||
|
|
||||||
// NumBuckets is always a power of 2.
|
// NumBuckets is always a power of 2.
|
||||||
unsigned BucketNum = ID.ComputeHash() & (NumBuckets-1);
|
unsigned BucketNum = ID.ComputeHash() & (NumBuckets-1);
|
||||||
return Buckets+BucketNum;
|
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,
|
/// FindNodeOrInsertPos - Look up the node specified by ID. If it exists,
|
||||||
/// return it. If not, return the insertion token that will make insertion
|
/// return it. If not, return the insertion token that will make insertion
|
||||||
/// faster.
|
/// faster.
|
||||||
|
@ -226,6 +264,11 @@ SDNode *SelectionDAGCSEMap::FindNodeOrInsertPos(const NodeID &ID,
|
||||||
/// FindNodeOrInsertPos.
|
/// FindNodeOrInsertPos.
|
||||||
void SelectionDAGCSEMap::InsertNode(SDNode *N, void *InsertPos) {
|
void SelectionDAGCSEMap::InsertNode(SDNode *N, void *InsertPos) {
|
||||||
++NumNodes;
|
++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.
|
/// The insert position is actually a bucket pointer.
|
||||||
void **Bucket = static_cast<void**>(InsertPos);
|
void **Bucket = static_cast<void**>(InsertPos);
|
||||||
|
|
Loading…
Reference in New Issue