diff --git a/lib/VMCore/LLVMContextImpl.h b/lib/VMCore/LLVMContextImpl.h index a27afc08b9f..9aba73781c4 100644 --- a/lib/VMCore/LLVMContextImpl.h +++ b/lib/VMCore/LLVMContextImpl.h @@ -29,6 +29,7 @@ #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/Hashing.h" #include namespace llvm { @@ -89,6 +90,107 @@ struct DenseMapAPFloatKeyInfo { } }; +struct AnonStructTypeKeyInfo { + struct KeyTy { + ArrayRef ETypes; + bool isPacked; + KeyTy(const ArrayRef& E, bool P) : + ETypes(E), isPacked(P) {} + KeyTy(const KeyTy& that) : + ETypes(that.ETypes), isPacked(that.isPacked) {} + KeyTy(const StructType* ST) : + ETypes(ArrayRef(ST->element_begin(), ST->element_end())), + isPacked(ST->isPacked()) {} + bool operator==(const KeyTy& that) const { + if (isPacked != that.isPacked) + return false; + if (ETypes != that.ETypes) + return false; + return true; + } + bool operator!=(const KeyTy& that) const { + return !this->operator==(that); + } + }; + static inline StructType* getEmptyKey() { + return DenseMapInfo::getEmptyKey(); + } + static inline StructType* getTombstoneKey() { + return DenseMapInfo::getTombstoneKey(); + } + static unsigned getHashValue(const KeyTy& Key) { + GeneralHash Hash; + Hash.add(Key.ETypes); + Hash.add(Key.isPacked); + return Hash.finish(); + } + static unsigned getHashValue(const StructType *ST) { + return getHashValue(KeyTy(ST)); + } + static bool isEqual(const KeyTy& LHS, const StructType *RHS) { + if (RHS == getEmptyKey() || RHS == getTombstoneKey()) + return false; + return LHS == KeyTy(RHS); + } + static bool isEqual(const StructType *LHS, const StructType *RHS) { + return LHS == RHS; + } +}; + +struct FunctionTypeKeyInfo { + struct KeyTy { + const Type *ReturnType; + ArrayRef Params; + bool isVarArg; + KeyTy(const Type* R, const ArrayRef& P, bool V) : + ReturnType(R), Params(P), isVarArg(V) {} + KeyTy(const KeyTy& that) : + ReturnType(that.ReturnType), + Params(that.Params), + isVarArg(that.isVarArg) {} + KeyTy(const FunctionType* FT) : + ReturnType(FT->getReturnType()), + Params(ArrayRef(FT->param_begin(), FT->param_end())), + isVarArg(FT->isVarArg()) {} + bool operator==(const KeyTy& that) const { + if (ReturnType != that.ReturnType) + return false; + if (isVarArg != that.isVarArg) + return false; + if (Params != that.Params) + return false; + return true; + } + bool operator!=(const KeyTy& that) const { + return !this->operator==(that); + } + }; + static inline FunctionType* getEmptyKey() { + return DenseMapInfo::getEmptyKey(); + } + static inline FunctionType* getTombstoneKey() { + return DenseMapInfo::getTombstoneKey(); + } + static unsigned getHashValue(const KeyTy& Key) { + GeneralHash Hash; + Hash.add(Key.ReturnType); + Hash.add(Key.Params); + Hash.add(Key.isVarArg); + return Hash.finish(); + } + static unsigned getHashValue(const FunctionType *FT) { + return getHashValue(KeyTy(FT)); + } + static bool isEqual(const KeyTy& LHS, const FunctionType *RHS) { + if (RHS == getEmptyKey() || RHS == getTombstoneKey()) + return false; + return LHS == KeyTy(RHS); + } + static bool isEqual(const FunctionType *LHS, const FunctionType *RHS) { + return LHS == RHS; + } +}; + /// DebugRecVH - This is a CallbackVH used to keep the Scope -> index maps /// up to date as MDNodes mutate. This class is implemented in DebugLoc.cpp. class DebugRecVH : public CallbackVH { @@ -180,9 +282,10 @@ public: DenseMap IntegerTypes; - // TODO: Optimize FunctionTypes/AnonStructTypes! - std::map, FunctionType*> FunctionTypes; - std::map, StructType*> AnonStructTypes; + typedef DenseMap FunctionTypeMap; + FunctionTypeMap FunctionTypes; + typedef DenseMap StructTypeMap; + StructTypeMap AnonStructTypes; StringMap NamedStructTypes; unsigned NamedStructTypesUniqueID; diff --git a/lib/VMCore/Type.cpp b/lib/VMCore/Type.cpp index 5cdddb36ee3..0bc4f74af21 100644 --- a/lib/VMCore/Type.cpp +++ b/lib/VMCore/Type.cpp @@ -390,24 +390,20 @@ FunctionType::FunctionType(Type *Result, ArrayRef Params, // FunctionType::get - The factory function for the FunctionType class. FunctionType *FunctionType::get(Type *ReturnType, ArrayRef Params, bool isVarArg) { - // TODO: This is brutally slow. - unsigned ParamsSize = Params.size(); - std::vector Key; - Key.reserve(ParamsSize + 2); - Key.push_back(const_cast(ReturnType)); - for (unsigned i = 0, e = ParamsSize; i != e; ++i) - Key.push_back(const_cast(Params[i])); - if (isVarArg) - Key.push_back(0); - LLVMContextImpl *pImpl = ReturnType->getContext().pImpl; - FunctionType *&FT = pImpl->FunctionTypes[Key]; - - if (FT == 0) { + FunctionTypeKeyInfo::KeyTy Key(ReturnType, Params, isVarArg); + LLVMContextImpl::FunctionTypeMap::iterator I = + pImpl->FunctionTypes.find_as(Key); + FunctionType *FT; + + if (I == pImpl->FunctionTypes.end()) { FT = (FunctionType*) pImpl->TypeAllocator. - Allocate(sizeof(FunctionType) + sizeof(Type*) * (ParamsSize + 1), + Allocate(sizeof(FunctionType) + sizeof(Type*) * (Params.size() + 1), AlignOf::Alignment); new (FT) FunctionType(ReturnType, Params, isVarArg); + pImpl->FunctionTypes[FT] = true; + } else { + FT = I->first; } return FT; @@ -440,24 +436,22 @@ bool FunctionType::isValidArgumentType(Type *ArgTy) { StructType *StructType::get(LLVMContext &Context, ArrayRef ETypes, bool isPacked) { - // FIXME: std::vector is horribly inefficient for this probe. - unsigned ETypesSize = ETypes.size(); - std::vector Key(ETypesSize); - for (unsigned i = 0, e = ETypesSize; i != e; ++i) { - assert(isValidElementType(ETypes[i]) && - "Invalid type for structure element!"); - Key[i] = ETypes[i]; + LLVMContextImpl *pImpl = Context.pImpl; + AnonStructTypeKeyInfo::KeyTy Key(ETypes, isPacked); + LLVMContextImpl::StructTypeMap::iterator I = + pImpl->AnonStructTypes.find_as(Key); + StructType *ST; + + if (I == pImpl->AnonStructTypes.end()) { + // Value not found. Create a new type! + ST = new (Context.pImpl->TypeAllocator) StructType(Context); + ST->setSubclassData(SCDB_IsLiteral); // Literal struct. + ST->setBody(ETypes, isPacked); + Context.pImpl->AnonStructTypes[ST] = true; + } else { + ST = I->first; } - if (isPacked) - Key.push_back(0); - - StructType *&ST = Context.pImpl->AnonStructTypes[Key]; - if (ST) return ST; - - // Value not found. Create a new type! - ST = new (Context.pImpl->TypeAllocator) StructType(Context); - ST->setSubclassData(SCDB_IsLiteral); // Literal struct. - ST->setBody(ETypes, isPacked); + return ST; }