From 36f8e65eef77eabf0b29cabffd3fd12ffdd66808 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sat, 27 Jan 2007 08:31:04 +0000 Subject: [PATCH] Switch arraytypes over to using a FoldingSet instead of a stupid linear search. This reduces 'dumb' lookups from 1225 to 359, speeding up parse of carbon.h from 0.173 to 0.156s (10%). llvm-svn: 39319 --- clang/AST/ASTContext.cpp | 29 ++++++++++++++++------------ clang/AST/Type.cpp | 8 +++++++- clang/include/clang/AST/ASTContext.h | 3 ++- clang/include/clang/AST/Type.h | 9 ++++++++- 4 files changed, 34 insertions(+), 15 deletions(-) diff --git a/clang/AST/ASTContext.cpp b/clang/AST/ASTContext.cpp index fdadda73c765..7a9bc8534dad 100644 --- a/clang/AST/ASTContext.cpp +++ b/clang/AST/ASTContext.cpp @@ -164,26 +164,31 @@ TypeRef ASTContext::getArrayType(TypeRef EltTy,ArrayType::ArraySizeModifier ASM, unsigned EltTypeQuals, void *NumElts) { #warning "IGNORING SIZE" - // FIXME: This is obviously braindead! - // Unique array, to guarantee there is only one array of a particular + // Unique array types, to guarantee there is only one array of a particular // structure. - ++NumSlowLookups; - for (unsigned i = 0, e = Types.size(); i != e; ++i) - if (ArrayType *ATy = dyn_cast(Types[i])) - if (ATy->getElementType() == EltTy && - ATy->getSizeModifier() == ASM && - ATy->getIndexTypeQualifier() == EltTypeQuals) - return Types[i]; + FoldingSetNodeID ID; + ArrayType::Profile(ID, ASM, EltTypeQuals, EltTy); + + void *InsertPos = 0; + if (ArrayType *ATP = ArrayTypes.FindNodeOrInsertPos(ID, InsertPos)) + return ATP; // If the element type isn't canonical, this won't be a canonical type either, // so fill in the canonical type field. Type *Canonical = 0; - if (!EltTy->isCanonical()) + if (!EltTy->isCanonical()) { Canonical = getArrayType(EltTy.getCanonicalType(), ASM, EltTypeQuals, NumElts).getTypePtr(); + + // Get the new insert position for the node we care about. + ArrayType *NewIP = ArrayTypes.FindNodeOrInsertPos(ID, InsertPos); + assert(NewIP == 0 && "Shouldn't be in the map!"); + } - Types.push_back(new ArrayType(EltTy, ASM, EltTypeQuals, Canonical)); - return Types.back(); + ArrayType *New = new ArrayType(EltTy, ASM, EltTypeQuals, Canonical); + ArrayTypes.InsertNode(New, InsertPos); + Types.push_back(New); + return New; } /// getFunctionTypeNoProto - Return a K&R style C function type like 'int()'. diff --git a/clang/AST/Type.cpp b/clang/AST/Type.cpp index fddc5a05b3c9..929f9f367017 100644 --- a/clang/AST/Type.cpp +++ b/clang/AST/Type.cpp @@ -79,6 +79,13 @@ void PointerType::Profile(FoldingSetNodeID &ID, TypeRef Pointee) { ID.AddPointer(Pointee.getAsOpaquePtr()); } +void ArrayType::Profile(FoldingSetNodeID &ID, ArraySizeModifier SizeModifier, + unsigned IndexTypeQuals, TypeRef ElementType) { + ID.AddInteger(SizeModifier); + ID.AddInteger(IndexTypeQuals); + ID.AddPointer(ElementType.getAsOpaquePtr()); +} + void FunctionTypeProto::Profile(FoldingSetNodeID &ID, TypeRef Result, TypeRef* ArgTys, unsigned NumArgs, bool isVariadic) { @@ -171,7 +178,6 @@ void ArrayType::getAsString(std::string &S) const { ElementType.getAsString(S); } - void FunctionTypeNoProto::getAsString(std::string &S) const { // If needed for precedence reasons, wrap the inner part in grouping parens. if (!S.empty()) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 04aae16ec206..85e0cd463d15 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -27,8 +27,9 @@ namespace clang { class ASTContext { std::vector Types; unsigned NumSlowLookups; - FoldingSet FunctionTypeProtos; FoldingSet PointerTypes; + FoldingSet ArrayTypes; + FoldingSet FunctionTypeProtos; public: Preprocessor &PP; TargetInfo &Target; diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 0a7e458b6ccd..bcdc7ad54963 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -246,7 +246,7 @@ public: /// PointerType - C99 6.7.5.2 - Array Declarators. /// -class ArrayType : public Type { +class ArrayType : public Type, public FoldingSetNode { public: /// ArraySizeModifier - Capture whether this is a normal array (e.g. int X[4]) /// an array with a static size (e.g. int X[static 4]), or with a star size @@ -266,6 +266,7 @@ private: TypeRef ElementType; /// FIXME: Capture size for VLA or constant size. + /// FIXME: Update Profile()! /// Use this to implement Type::isIncompleteType. ArrayType(TypeRef et, ArraySizeModifier sm, unsigned tq, Type *can) @@ -279,6 +280,12 @@ public: virtual void getAsString(std::string &InnerString) const; + void Profile(FoldingSetNodeID &ID) { + Profile(ID, getSizeModifier(), getIndexTypeQualifier(), getElementType()); + } + static void Profile(FoldingSetNodeID &ID, ArraySizeModifier SizeModifier, + unsigned IndexTypeQuals, TypeRef ElementType); + static bool classof(const Type *T) { return T->getTypeClass() == Array; } static bool classof(const ArrayType *) { return true; } };