Using FoldingSet in SelectionDAG::getVTList.

VTList has a long life cycle through the module and getVTList is frequently called. In current getVTList, sequential search over a std::vector is used, this is inefficient in big module.
This patch use FoldingSet to implement hashing mechanism when searching.

Reviewer: Nadav Rotem
Test    : Pass unit tests & LNT test suite

llvm-svn: 193150
This commit is contained in:
Wan Xiaofei 2013-10-22 08:02:02 +00:00
parent 47b3bd3fbb
commit 2f8dc08b8c
2 changed files with 100 additions and 56 deletions

View File

@ -38,6 +38,45 @@ class TargetLowering;
class TargetSelectionDAGInfo; class TargetSelectionDAGInfo;
class TargetTransformInfo; class TargetTransformInfo;
class SDVTListNode : public FoldingSetNode {
friend struct FoldingSetTrait<SDVTListNode>;
/// FastID - A reference to an Interned FoldingSetNodeID for this node.
/// The Allocator in SelectionDAG holds the data.
/// SDVTList contains all types which are frequently accessed in SelectionDAG.
/// The size of this list is not expected big so it won't introduce memory penalty.
FoldingSetNodeIDRef FastID;
const EVT *VTs;
unsigned int NumVTs;
/// The hash value for SDVTList is fixed so cache it to avoid hash calculation
unsigned HashValue;
public:
SDVTListNode(const FoldingSetNodeIDRef ID, const EVT *VT, unsigned int Num) :
FastID(ID), VTs(VT), NumVTs(Num) {
HashValue = ID.ComputeHash();
}
SDVTList getSDVTList() {
SDVTList result = {VTs, NumVTs};
return result;
}
};
// Specialize FoldingSetTrait for SDVTListNode
// To avoid computing temp FoldingSetNodeID and hash value.
template<> struct FoldingSetTrait<SDVTListNode> : DefaultFoldingSetTrait<SDVTListNode> {
static void Profile(const SDVTListNode &X, FoldingSetNodeID& ID) {
ID = X.FastID;
}
static bool Equals(const SDVTListNode &X, const FoldingSetNodeID &ID,
unsigned IDHash, FoldingSetNodeID &TempID) {
if (X.HashValue != IDHash)
return false;
return ID == X.FastID;
}
static unsigned ComputeHash(const SDVTListNode &X, FoldingSetNodeID &TempID) {
return X.HashValue;
}
};
template<> struct ilist_traits<SDNode> : public ilist_default_traits<SDNode> { template<> struct ilist_traits<SDNode> : public ilist_default_traits<SDNode> {
private: private:
mutable ilist_half_node<SDNode> Sentinel; mutable ilist_half_node<SDNode> Sentinel;
@ -1093,7 +1132,7 @@ private:
void allnodes_clear(); void allnodes_clear();
/// VTList - List of non-single value types. /// VTList - List of non-single value types.
std::vector<SDVTList> VTList; FoldingSet<SDVTListNode> VTListMap;
/// CondCodeNodes - Maps to auto-CSE operations. /// CondCodeNodes - Maps to auto-CSE operations.
std::vector<CondCodeSDNode*> CondCodeNodes; std::vector<CondCodeSDNode*> CondCodeNodes;

View File

@ -4891,76 +4891,81 @@ SDVTList SelectionDAG::getVTList(EVT VT) {
} }
SDVTList SelectionDAG::getVTList(EVT VT1, EVT VT2) { SDVTList SelectionDAG::getVTList(EVT VT1, EVT VT2) {
for (std::vector<SDVTList>::reverse_iterator I = VTList.rbegin(), FoldingSetNodeID ID;
E = VTList.rend(); I != E; ++I) ID.AddInteger(2U);
if (I->NumVTs == 2 && I->VTs[0] == VT1 && I->VTs[1] == VT2) ID.AddInteger(VT1.getRawBits());
return *I; ID.AddInteger(VT2.getRawBits());
EVT *Array = Allocator.Allocate<EVT>(2); void *IP = 0;
Array[0] = VT1; SDVTListNode *Result = VTListMap.FindNodeOrInsertPos(ID, IP);
Array[1] = VT2; if (Result == NULL) {
SDVTList Result = makeVTList(Array, 2); EVT *Array = Allocator.Allocate<EVT>(2);
VTList.push_back(Result); Array[0] = VT1;
return Result; Array[1] = VT2;
Result = new (Allocator) SDVTListNode(ID.Intern(Allocator), Array, 2);
VTListMap.InsertNode(Result, IP);
}
return Result->getSDVTList();
} }
SDVTList SelectionDAG::getVTList(EVT VT1, EVT VT2, EVT VT3) { SDVTList SelectionDAG::getVTList(EVT VT1, EVT VT2, EVT VT3) {
for (std::vector<SDVTList>::reverse_iterator I = VTList.rbegin(), FoldingSetNodeID ID;
E = VTList.rend(); I != E; ++I) ID.AddInteger(3U);
if (I->NumVTs == 3 && I->VTs[0] == VT1 && I->VTs[1] == VT2 && ID.AddInteger(VT1.getRawBits());
I->VTs[2] == VT3) ID.AddInteger(VT2.getRawBits());
return *I; ID.AddInteger(VT3.getRawBits());
EVT *Array = Allocator.Allocate<EVT>(3); void *IP = 0;
Array[0] = VT1; SDVTListNode *Result = VTListMap.FindNodeOrInsertPos(ID, IP);
Array[1] = VT2; if (Result == NULL) {
Array[2] = VT3; EVT *Array = Allocator.Allocate<EVT>(3);
SDVTList Result = makeVTList(Array, 3); Array[0] = VT1;
VTList.push_back(Result); Array[1] = VT2;
return Result; Array[2] = VT3;
Result = new (Allocator) SDVTListNode(ID.Intern(Allocator), Array, 3);
VTListMap.InsertNode(Result, IP);
}
return Result->getSDVTList();
} }
SDVTList SelectionDAG::getVTList(EVT VT1, EVT VT2, EVT VT3, EVT VT4) { SDVTList SelectionDAG::getVTList(EVT VT1, EVT VT2, EVT VT3, EVT VT4) {
for (std::vector<SDVTList>::reverse_iterator I = VTList.rbegin(), FoldingSetNodeID ID;
E = VTList.rend(); I != E; ++I) ID.AddInteger(4U);
if (I->NumVTs == 4 && I->VTs[0] == VT1 && I->VTs[1] == VT2 && ID.AddInteger(VT1.getRawBits());
I->VTs[2] == VT3 && I->VTs[3] == VT4) ID.AddInteger(VT2.getRawBits());
return *I; ID.AddInteger(VT3.getRawBits());
ID.AddInteger(VT4.getRawBits());
EVT *Array = Allocator.Allocate<EVT>(4); void *IP = 0;
Array[0] = VT1; SDVTListNode *Result = VTListMap.FindNodeOrInsertPos(ID, IP);
Array[1] = VT2; if (Result == NULL) {
Array[2] = VT3; EVT *Array = Allocator.Allocate<EVT>(4);
Array[3] = VT4; Array[0] = VT1;
SDVTList Result = makeVTList(Array, 4); Array[1] = VT2;
VTList.push_back(Result); Array[2] = VT3;
return Result; Array[3] = VT4;
Result = new (Allocator) SDVTListNode(ID.Intern(Allocator), Array, 4);
VTListMap.InsertNode(Result, IP);
}
return Result->getSDVTList();
} }
SDVTList SelectionDAG::getVTList(const EVT *VTs, unsigned NumVTs) { SDVTList SelectionDAG::getVTList(const EVT *VTs, unsigned NumVTs) {
switch (NumVTs) { FoldingSetNodeID ID;
case 0: llvm_unreachable("Cannot have nodes without results!"); ID.AddInteger(NumVTs);
case 1: return getVTList(VTs[0]); for (unsigned index = 0; index < NumVTs; index++) {
case 2: return getVTList(VTs[0], VTs[1]); ID.AddInteger(VTs[index].getRawBits());
case 3: return getVTList(VTs[0], VTs[1], VTs[2]);
case 4: return getVTList(VTs[0], VTs[1], VTs[2], VTs[3]);
default: break;
} }
for (std::vector<SDVTList>::reverse_iterator I = VTList.rbegin(), void *IP = 0;
E = VTList.rend(); I != E; ++I) { SDVTListNode *Result = VTListMap.FindNodeOrInsertPos(ID, IP);
if (I->NumVTs != NumVTs || VTs[0] != I->VTs[0] || VTs[1] != I->VTs[1]) if (Result == NULL) {
continue; EVT *Array = Allocator.Allocate<EVT>(NumVTs);
std::copy(VTs, VTs + NumVTs, Array);
if (std::equal(&VTs[2], &VTs[NumVTs], &I->VTs[2])) Result = new (Allocator) SDVTListNode(ID.Intern(Allocator), Array, NumVTs);
return *I; VTListMap.InsertNode(Result, IP);
} }
return Result->getSDVTList();
EVT *Array = Allocator.Allocate<EVT>(NumVTs);
std::copy(VTs, VTs+NumVTs, Array);
SDVTList Result = makeVTList(Array, NumVTs);
VTList.push_back(Result);
return Result;
} }