diff options
| author | Jay Foad <jay.foad@gmail.com> | 2012-02-21 09:25:52 +0000 | 
|---|---|---|
| committer | Jay Foad <jay.foad@gmail.com> | 2012-02-21 09:25:52 +0000 | 
| commit | 3f99d381b4bb00cedeef049cfdcf03aa3e1f689c (patch) | |
| tree | 568b2c31a1d5e186ebd9f048bc77613579e828db /llvm/lib/VMCore | |
| parent | 6ea6de7cadfbf59f0bf2956dedceea0760aedae6 (diff) | |
| download | bcm5719-llvm-3f99d381b4bb00cedeef049cfdcf03aa3e1f689c.tar.gz bcm5719-llvm-3f99d381b4bb00cedeef049cfdcf03aa3e1f689c.zip | |
PR1210: make uniquing of struct and function types more efficient by
using a DenseMap and Talin's new GeneralHash, avoiding the need for a
temporary std::vector on every lookup.
Patch by Meador Inge!
llvm-svn: 151049
Diffstat (limited to 'llvm/lib/VMCore')
| -rw-r--r-- | llvm/lib/VMCore/LLVMContextImpl.h | 109 | ||||
| -rw-r--r-- | llvm/lib/VMCore/Type.cpp | 56 | 
2 files changed, 131 insertions, 34 deletions
| diff --git a/llvm/lib/VMCore/LLVMContextImpl.h b/llvm/lib/VMCore/LLVMContextImpl.h index a27afc08b9f..9aba73781c4 100644 --- a/llvm/lib/VMCore/LLVMContextImpl.h +++ b/llvm/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 <vector>  namespace llvm { @@ -89,6 +90,107 @@ struct DenseMapAPFloatKeyInfo {    }  }; +struct AnonStructTypeKeyInfo { +  struct KeyTy { +    ArrayRef<Type*> ETypes; +    bool isPacked; +    KeyTy(const ArrayRef<Type*>& E, bool P) : +      ETypes(E), isPacked(P) {} +    KeyTy(const KeyTy& that) : +      ETypes(that.ETypes), isPacked(that.isPacked) {} +    KeyTy(const StructType* ST) : +      ETypes(ArrayRef<Type*>(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<StructType*>::getEmptyKey(); +  } +  static inline StructType* getTombstoneKey() { +    return DenseMapInfo<StructType*>::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<Type*> Params; +    bool isVarArg; +    KeyTy(const Type* R, const ArrayRef<Type*>& 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<Type*>(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<FunctionType*>::getEmptyKey(); +  } +  static inline FunctionType* getTombstoneKey() { +    return DenseMapInfo<FunctionType*>::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<unsigned, IntegerType*> IntegerTypes; -  // TODO: Optimize FunctionTypes/AnonStructTypes! -  std::map<std::vector<Type*>, FunctionType*> FunctionTypes; -  std::map<std::vector<Type*>, StructType*> AnonStructTypes; +  typedef DenseMap<FunctionType*, bool, FunctionTypeKeyInfo> FunctionTypeMap; +  FunctionTypeMap FunctionTypes; +  typedef DenseMap<StructType*, bool, AnonStructTypeKeyInfo> StructTypeMap; +  StructTypeMap AnonStructTypes;    StringMap<StructType*> NamedStructTypes;    unsigned NamedStructTypesUniqueID; diff --git a/llvm/lib/VMCore/Type.cpp b/llvm/lib/VMCore/Type.cpp index 5cdddb36ee3..0bc4f74af21 100644 --- a/llvm/lib/VMCore/Type.cpp +++ b/llvm/lib/VMCore/Type.cpp @@ -390,24 +390,20 @@ FunctionType::FunctionType(Type *Result, ArrayRef<Type*> Params,  // FunctionType::get - The factory function for the FunctionType class.  FunctionType *FunctionType::get(Type *ReturnType,                                  ArrayRef<Type*> Params, bool isVarArg) { -  // TODO: This is brutally slow. -  unsigned ParamsSize = Params.size(); -  std::vector<Type*> Key; -  Key.reserve(ParamsSize + 2); -  Key.push_back(const_cast<Type*>(ReturnType)); -  for (unsigned i = 0, e = ParamsSize; i != e; ++i) -    Key.push_back(const_cast<Type*>(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<FunctionType>::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<Type*> ETypes,                               bool isPacked) { -  // FIXME: std::vector is horribly inefficient for this probe. -  unsigned ETypesSize = ETypes.size(); -  std::vector<Type*> 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;  } | 

