diff --git a/lib/VMCore/LLVMContextImpl.h b/lib/VMCore/LLVMContextImpl.h index 9aba73781c4..a27afc08b9f 100644 --- a/lib/VMCore/LLVMContextImpl.h +++ b/lib/VMCore/LLVMContextImpl.h @@ -29,7 +29,6 @@ #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringMap.h" -#include "llvm/ADT/Hashing.h" #include namespace llvm { @@ -90,107 +89,6 @@ 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 { @@ -282,10 +180,9 @@ public: DenseMap IntegerTypes; - typedef DenseMap FunctionTypeMap; - FunctionTypeMap FunctionTypes; - typedef DenseMap StructTypeMap; - StructTypeMap AnonStructTypes; + // TODO: Optimize FunctionTypes/AnonStructTypes! + std::map, FunctionType*> FunctionTypes; + std::map, StructType*> AnonStructTypes; StringMap NamedStructTypes; unsigned NamedStructTypesUniqueID; diff --git a/lib/VMCore/Type.cpp b/lib/VMCore/Type.cpp index 0bc4f74af21..5cdddb36ee3 100644 --- a/lib/VMCore/Type.cpp +++ b/lib/VMCore/Type.cpp @@ -390,20 +390,24 @@ 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; - FunctionTypeKeyInfo::KeyTy Key(ReturnType, Params, isVarArg); - LLVMContextImpl::FunctionTypeMap::iterator I = - pImpl->FunctionTypes.find_as(Key); - FunctionType *FT; - - if (I == pImpl->FunctionTypes.end()) { + FunctionType *&FT = pImpl->FunctionTypes[Key]; + + if (FT == 0) { FT = (FunctionType*) pImpl->TypeAllocator. - Allocate(sizeof(FunctionType) + sizeof(Type*) * (Params.size() + 1), + Allocate(sizeof(FunctionType) + sizeof(Type*) * (ParamsSize + 1), AlignOf::Alignment); new (FT) FunctionType(ReturnType, Params, isVarArg); - pImpl->FunctionTypes[FT] = true; - } else { - FT = I->first; } return FT; @@ -436,22 +440,24 @@ bool FunctionType::isValidArgumentType(Type *ArgTy) { StructType *StructType::get(LLVMContext &Context, ArrayRef ETypes, bool isPacked) { - 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; + // 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]; } - + 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; }