diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h index 886384adff5..6ff033715db 100644 --- a/include/llvm/IR/Attributes.h +++ b/include/llvm/IR/Attributes.h @@ -18,6 +18,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/FoldingSet.h" #include "llvm/Support/MathExtras.h" #include #include @@ -129,6 +130,10 @@ public: bool operator==(AttrKind K) const; bool operator!=(AttrKind K) const; + bool operator<(Attribute A) const; + + void Profile(FoldingSetNodeID &ID) const; + // FIXME: Remove these 'operator' methods. bool operator==(const Attribute &A) const { return pImpl == A.pImpl; diff --git a/lib/IR/AttributeImpl.h b/lib/IR/AttributeImpl.h index 0843fd8ac88..b02cc8bdefe 100644 --- a/lib/IR/AttributeImpl.h +++ b/lib/IR/AttributeImpl.h @@ -56,6 +56,8 @@ public: bool operator==(StringRef Kind) const; bool operator!=(StringRef Kind) const; + bool operator<(const AttributeImpl &AI) const; + uint64_t Raw() const; // FIXME: Remove. static uint64_t getAttrMask(Attribute::AttrKind Val); @@ -69,7 +71,38 @@ public: //===----------------------------------------------------------------------===// /// \class -/// \brief This class represents a set of attributes. +/// \brief This class represents a group of attributes that apply to one +/// element: function, return type, or parameter. +class AttributeSetNode : public FoldingSetNode { + SmallVector AttrList; + + AttributeSetNode(ArrayRef Attrs) + : AttrList(Attrs.begin(), Attrs.end()) {} +public: + static AttributeSetNode *get(LLVMContext &C, ArrayRef Attrs); + + typedef SmallVectorImpl::iterator iterator; + typedef SmallVectorImpl::const_iterator const_iterator; + + iterator begin() { return AttrList.begin(); } + iterator end() { return AttrList.end(); } + + const_iterator begin() const { return AttrList.begin(); } + const_iterator end() const { return AttrList.end(); } + + void Profile(FoldingSetNodeID &ID) const { + Profile(ID, AttrList); + } + static void Profile(FoldingSetNodeID &ID, ArrayRef AttrList) { + for (unsigned I = 0, E = AttrList.size(); I != E; ++I) + AttrList[I].Profile(ID); + } +}; + +//===----------------------------------------------------------------------===// +/// \class +/// \brief This class represents a set of attributes that apply to the function, +/// return type, and parameters. class AttributeSetImpl : public FoldingSetNode { LLVMContext &Context; SmallVector AttrList; diff --git a/lib/IR/Attributes.cpp b/lib/IR/Attributes.cpp index 94615da6d05..8623b98b9f6 100644 --- a/lib/IR/Attributes.cpp +++ b/lib/IR/Attributes.cpp @@ -23,6 +23,7 @@ #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Mutex.h" #include "llvm/Support/raw_ostream.h" +#include using namespace llvm; //===----------------------------------------------------------------------===// @@ -91,6 +92,18 @@ bool Attribute::operator!=(AttrKind K) const { return !(*this == K); } +bool Attribute::operator<(Attribute A) const { + if (!pImpl && !A.pImpl) return false; + if (!pImpl) return true; + if (!A.pImpl) return false; + return *pImpl < *A.pImpl; +} + + +void Attribute::Profile(FoldingSetNodeID &ID) const { + ID.AddPointer(pImpl); +} + uint64_t Attribute::Raw() const { return pImpl ? pImpl->Raw() : 0; } @@ -431,10 +444,34 @@ bool AttributeImpl::operator==(StringRef Kind) const { return CDA->getAsString() == Kind; return false; } + bool AttributeImpl::operator!=(StringRef Kind) const { return !(*this == Kind); } +bool AttributeImpl::operator<(const AttributeImpl &AI) const { + if (!Data && !AI.Data) return false; + if (!Data && AI.Data) return true; + if (Data && !AI.Data) return false; + + ConstantInt *ThisCI = dyn_cast(Data); + ConstantInt *ThatCI = dyn_cast(AI.Data); + + ConstantDataArray *ThisCDA = dyn_cast(Data); + ConstantDataArray *ThatCDA = dyn_cast(AI.Data); + + if (ThisCI && ThatCI) + return ThisCI->getZExtValue() < ThatCI->getZExtValue(); + + if (ThisCI && ThatCDA) + return true; + + if (ThisCDA && ThatCI) + return false; + + return ThisCDA->getAsString() < ThatCDA->getAsString(); +} + uint64_t AttributeImpl::Raw() const { // FIXME: Remove this. return cast(Data)->getZExtValue(); @@ -522,6 +559,41 @@ AttributeWithIndex AttributeWithIndex::get(LLVMContext &C, unsigned Idx, return get(Idx, Attribute::get(C, B)); } +//===----------------------------------------------------------------------===// +// AttributeSetNode Definition +//===----------------------------------------------------------------------===// + +AttributeSetNode *AttributeSetNode::get(LLVMContext &C, + ArrayRef Attrs) { + if (Attrs.empty()) + return 0; + + // Otherwise, build a key to look up the existing attributes. + LLVMContextImpl *pImpl = C.pImpl; + FoldingSetNodeID ID; + + SmallVector SortedAttrs(Attrs.begin(), Attrs.end()); + std::sort(SortedAttrs.begin(), SortedAttrs.end()); + + for (SmallVectorImpl::iterator I = SortedAttrs.begin(), + E = SortedAttrs.end(); I != E; ++I) + I->Profile(ID); + + void *InsertPoint; + AttributeSetNode *PA = + pImpl->AttrsSetNodes.FindNodeOrInsertPos(ID, InsertPoint); + + // If we didn't find any existing attributes of the same shape then create a + // new one and insert it. + if (!PA) { + PA = new AttributeSetNode(SortedAttrs); + pImpl->AttrsSetNodes.InsertNode(PA, InsertPoint); + } + + // Return the AttributesListNode that we found or created. + return PA; +} + //===----------------------------------------------------------------------===// // AttributeSetImpl Definition //===----------------------------------------------------------------------===// diff --git a/lib/IR/LLVMContextImpl.h b/lib/IR/LLVMContextImpl.h index 30fd6666fda..cc7ca5e1288 100644 --- a/lib/IR/LLVMContextImpl.h +++ b/lib/IR/LLVMContextImpl.h @@ -249,6 +249,7 @@ public: FoldingSet AttrsSet; FoldingSet AttrsLists; + FoldingSet AttrsSetNodes; StringMap MDStringCache;