From: Daniel Dunbar Date: Fri, 9 Mar 2012 04:12:54 +0000 (+0000) Subject: [AST] Memoize ASTContext::getTypeInfo(). X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=bc5419a2edc4030d1a623576fe339fbd3eed17a6;p=clang [AST] Memoize ASTContext::getTypeInfo(). - On -emit-llvm-only of 403.gcc/combine.c, for example, we make 160k calls to getTypeInfo but only ever deal with 680 some distinct types. I saw these speedups (user time): 403.gcc/combine.c -- 3.1% OmniGroupFrameworks/NSBezierPath-OAExtensions.m -- 3.6% JavaScriptCore/Interpreter.cpp -- 1.4% which seems pretty sweet. I ran some histograms on those compiles and we end up doing a ton of getTypeInfo() on 'char' and 'int'. I tried splitting out a fast path for builtin types, but this wasn't a win. Still kinda seems like we could be doing better here. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152377 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 3bdac2de9a..425ee3cdb2 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -147,6 +147,11 @@ class ASTContext : public RefCountedBase { mutable llvm::DenseMap ObjCLayouts; + /// TypeInfoMap - A cache from types to size and alignment information. + typedef llvm::DenseMap > TypeInfoMap; + mutable TypeInfoMap MemoizedTypeInfo; + /// KeyFunctions - A cache mapping from CXXRecordDecls to key functions. llvm::DenseMap KeyFunctions; @@ -1220,6 +1225,7 @@ public: private: CanQualType getFromTargetType(unsigned Type) const; + std::pair getTypeInfoImpl(const Type *T) const; //===--------------------------------------------------------------------===// // Type Predicates. diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 0d6f6e612c..ba3f503e3b 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -815,14 +815,24 @@ ASTContext::getTypeInfoInChars(QualType T) const { return getTypeInfoInChars(T.getTypePtr()); } -/// getTypeSize - Return the size of the specified type, in bits. This method -/// does not work on incomplete types. +std::pair ASTContext::getTypeInfo(const Type *T) const { + TypeInfoMap::iterator it = MemoizedTypeInfo.find(T); + if (it != MemoizedTypeInfo.end()) + return it->second; + + std::pair Info = getTypeInfoImpl(T); + MemoizedTypeInfo.insert(std::make_pair(T, Info)); + return Info; +} + +/// getTypeInfoImpl - Return the size of the specified type, in bits. This +/// method does not work on incomplete types. /// /// FIXME: Pointers into different addr spaces could have different sizes and /// alignment requirements: getPointerInfo should take an AddrSpace, this /// should take a QualType, &c. std::pair -ASTContext::getTypeInfo(const Type *T) const { +ASTContext::getTypeInfoImpl(const Type *T) const { uint64_t Width=0; unsigned Align=8; switch (T->getTypeClass()) { @@ -851,7 +861,8 @@ ASTContext::getTypeInfo(const Type *T) const { std::pair EltInfo = getTypeInfo(CAT->getElementType()); uint64_t Size = CAT->getSize().getZExtValue(); - assert((Size == 0 || EltInfo.first <= (uint64_t)(-1)/Size) && "Overflow in array type bit size evaluation"); + assert((Size == 0 || EltInfo.first <= (uint64_t)(-1)/Size) && + "Overflow in array type bit size evaluation"); Width = EltInfo.first*Size; Align = EltInfo.second; Width = llvm::RoundUpToAlignment(Width, Align);