r310437 - [AST] Cache intermediate visibility/linkage results
George Burgess IV via cfe-commits
cfe-commits at lists.llvm.org
Tue Aug 8 21:12:17 PDT 2017
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; }
More information about the cfe-commits
mailing list