[llvm-commits] [llvm] r151049 - in /llvm/trunk/lib/VMCore: LLVMContextImpl.h Type.cpp

Duncan Sands baldrick at free.fr
Tue Feb 21 01:56:15 PST 2012


Hi Jay, this nightly test builder
   http://lab.llvm.org:8011/builders/clang-x86_64-debian-fnt
is showing many failures since your commit.

Ciao, Duncan.

On 21/02/12 10:25, Jay Foad wrote:
> Author: foad
> Date: Tue Feb 21 03:25:52 2012
> New Revision: 151049
>
> URL: http://llvm.org/viewvc/llvm-project?rev=151049&view=rev
> Log:
> 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!
>
> Modified:
>      llvm/trunk/lib/VMCore/LLVMContextImpl.h
>      llvm/trunk/lib/VMCore/Type.cpp
>
> Modified: llvm/trunk/lib/VMCore/LLVMContextImpl.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/LLVMContextImpl.h?rev=151049&r1=151048&r2=151049&view=diff
> ==============================================================================
> --- llvm/trunk/lib/VMCore/LLVMContextImpl.h (original)
> +++ llvm/trunk/lib/VMCore/LLVMContextImpl.h Tue Feb 21 03:25:52 2012
> @@ -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 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 @@
>
>     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;
>
>
> Modified: llvm/trunk/lib/VMCore/Type.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Type.cpp?rev=151049&r1=151048&r2=151049&view=diff
> ==============================================================================
> --- llvm/trunk/lib/VMCore/Type.cpp (original)
> +++ llvm/trunk/lib/VMCore/Type.cpp Tue Feb 21 03:25:52 2012
> @@ -390,24 +390,20 @@
>   // 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 @@
>
>   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;
>   }
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits




More information about the llvm-commits mailing list