Author: gbiv Date: Tue Aug 8 21:12:17 2017 New Revision: 310437 URL: http://llvm.org/viewvc/llvm-project?rev=310437&view=rev Log: [AST] Cache intermediate visibility/linkage results
This is a follow-up to r310436 with actual functional changes. Please see that commit message for a description of why a cache is appearing here. Suggestions for less-bad ways of testing this are appreciated. :) This fixes PR29160. Added: cfe/trunk/test/CodeGenCXX/pr29160.cpp Modified: cfe/trunk/lib/AST/Decl.cpp cfe/trunk/lib/AST/Linkage.h cfe/trunk/lib/AST/Type.cpp Modified: cfe/trunk/lib/AST/Decl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=310437&r1=310436&r2=310437&view=diff ============================================================================== --- cfe/trunk/lib/AST/Decl.cpp (original) +++ cfe/trunk/lib/AST/Decl.cpp Tue Aug 8 21:12:17 2017 @@ -192,7 +192,7 @@ LinkageInfo LinkageComputer::getLVForTyp LVComputationKind computation) { if (computation == LVForLinkageOnly) return LinkageInfo(T.getLinkage(), DefaultVisibility, true); - return T.getLinkageAndVisibility(); + return getTypeLinkageAndVisibility(&T); } /// \brief Get the most restrictive linkage for the types in the given @@ -224,7 +224,7 @@ LinkageInfo LinkageComputer::getLVForTem for (unsigned i = 0, n = NTTP->getNumExpansionTypes(); i != n; ++i) { QualType type = NTTP->getExpansionType(i); if (!type->isDependentType()) - LV.merge(type->getLinkageAndVisibility()); + LV.merge(getTypeLinkageAndVisibility(type)); } continue; } @@ -291,7 +291,7 @@ LinkageComputer::getLVForTemplateArgumen continue; case TemplateArgument::NullPtr: - LV.merge(Arg.getNullPtrType()->getLinkageAndVisibility()); + LV.merge(getTypeLinkageAndVisibility(Arg.getNullPtrType())); continue; case TemplateArgument::Template: @@ -610,7 +610,7 @@ LinkageComputer::getLVForNamespaceScopeD PrevVar = PrevVar->getPreviousDecl()) { if (PrevVar->getStorageClass() == SC_PrivateExtern && Var->getStorageClass() == SC_None) - return PrevVar->getLinkageAndVisibility(); + return getDeclLinkageAndVisibility(PrevVar); // Explicitly declared static. if (PrevVar->getStorageClass() == SC_Static) return getInternalLinkageFor(Var); @@ -1358,11 +1358,15 @@ LinkageInfo LinkageComputer::getLVForDec if (computation == LVForLinkageOnly && D->hasCachedLinkage()) return LinkageInfo(D->getCachedLinkage(), DefaultVisibility, false); + if (llvm::Optional<LinkageInfo> LI = lookup(D, computation)) + return *LI; + LinkageInfo LV = computeLVForDecl(D, computation); if (D->hasCachedLinkage()) assert(D->getCachedLinkage() == LV.getLinkage()); D->setCachedLinkage(LV.getLinkage()); + cache(D, computation, LV); #ifndef NDEBUG // In C (because of gnu inline) and in c++ with microsoft extensions an Modified: cfe/trunk/lib/AST/Linkage.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Linkage.h?rev=310437&r1=310436&r2=310437&view=diff ============================================================================== --- cfe/trunk/lib/AST/Linkage.h (original) +++ cfe/trunk/lib/AST/Linkage.h Tue Aug 8 21:12:17 2017 @@ -19,6 +19,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/Type.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Optional.h" namespace clang { enum : unsigned { @@ -54,8 +55,50 @@ enum LVComputationKind { LVForLinkageOnly = LVForValue | IgnoreExplicitVisibilityBit | IgnoreAllVisibilityBit }; +} // namespace clang +namespace llvm { +template <> struct DenseMapInfo<clang::LVComputationKind> { + static inline clang::LVComputationKind getEmptyKey() { + return static_cast<clang::LVComputationKind>(-1); + } + static inline clang::LVComputationKind getTombstoneKey() { + return static_cast<clang::LVComputationKind>(-2); + } + static unsigned getHashValue(const clang::LVComputationKind &Val) { + return Val; + } + static bool isEqual(const clang::LVComputationKind &LHS, + const clang::LVComputationKind &RHS) { + return LHS == RHS; + } +}; +} // namespace llvm + +namespace clang { class LinkageComputer { + // We have a cache for repeated linkage/visibility computations. This saves us + // from exponential behavior in heavily templated code, such as: + // + // template <typename T, typename V> struct {}; + // using A = int; + // using B = Foo<A, A>; + // using C = Foo<B, B>; + // using D = Foo<C, C>; + using QueryType = std::pair<const NamedDecl *, LVComputationKind>; + llvm::SmallDenseMap<QueryType, LinkageInfo, 8> CachedLinkageInfo; + llvm::Optional<LinkageInfo> lookup(const NamedDecl *ND, + LVComputationKind Kind) const { + auto Iter = CachedLinkageInfo.find(std::make_pair(ND, Kind)); + if (Iter == CachedLinkageInfo.end()) + return None; + return Iter->second; + } + + void cache(const NamedDecl *ND, LVComputationKind Kind, LinkageInfo Info) { + CachedLinkageInfo[std::make_pair(ND, Kind)] = Info; + } + LinkageInfo getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args, LVComputationKind computation); Modified: cfe/trunk/lib/AST/Type.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=310437&r1=310436&r2=310437&view=diff ============================================================================== --- cfe/trunk/lib/AST/Type.cpp (original) +++ cfe/trunk/lib/AST/Type.cpp Tue Aug 8 21:12:17 2017 @@ -3453,7 +3453,7 @@ LinkageInfo LinkageComputer::computeType case Type::Record: case Type::Enum: - return cast<TagType>(T)->getDecl()->getLinkageAndVisibility(); + return getDeclLinkageAndVisibility(cast<TagType>(T)->getDecl()); case Type::Complex: return computeTypeLinkageInfo(cast<ComplexType>(T)->getElementType()); @@ -3487,7 +3487,7 @@ LinkageInfo LinkageComputer::computeType return LV; } case Type::ObjCInterface: - return cast<ObjCInterfaceType>(T)->getDecl()->getLinkageAndVisibility(); + return getDeclLinkageAndVisibility(cast<ObjCInterfaceType>(T)->getDecl()); case Type::ObjCObject: return computeTypeLinkageInfo(cast<ObjCObjectType>(T)->getBaseType()); case Type::ObjCObjectPointer: Added: cfe/trunk/test/CodeGenCXX/pr29160.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/pr29160.cpp?rev=310437&view=auto ============================================================================== --- cfe/trunk/test/CodeGenCXX/pr29160.cpp (added) +++ cfe/trunk/test/CodeGenCXX/pr29160.cpp Tue Aug 8 21:12:17 2017 @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -std=c++11 %s -o /dev/null -S +// +// This test's failure mode is running ~forever. (For some value of "forever" +// that's greater than 25 minutes on my machine) + +template <typename... Ts> +struct Foo { + template <typename... T> + static void ignore() {} + Foo() { ignore<Ts...>(); } +}; + +struct Base { + Base(); + ~Base(); +}; + +#define STAMP(thiz, prev) using thiz = Foo< \ + prev, prev, prev, prev, prev, prev, prev, prev, prev, prev, prev, prev, \ + prev, prev, prev, prev, prev, prev, prev, prev, prev, prev, prev, prev, \ + prev, prev, prev, prev, prev, prev, prev, prev, prev, prev, prev, prev \ + >; +STAMP(A, Base); +STAMP(B, A); +STAMP(C, B); +STAMP(D, C); +STAMP(E, D); +STAMP(F, E); +STAMP(G, F); +STAMP(H, G); +STAMP(I, H); +STAMP(J, I); +STAMP(K, J); +STAMP(L, K); +STAMP(M, L); +STAMP(N, M); +STAMP(O, N); +STAMP(P, O); +STAMP(Q, P); + +int main() { Q q; } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits