]> granicus.if.org Git - clang/commitdiff
Check the linkage cache at every recursive step.
authorRafael Espindola <rafael.espindola@gmail.com>
Tue, 28 May 2013 19:43:11 +0000 (19:43 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Tue, 28 May 2013 19:43:11 +0000 (19:43 +0000)
Before this patch the linkage cache was only used by the entry level function
(getLinkage). The function that does the actual computation (getLVForDecl),
never looked at it.

This means that we would not reuse an entry in the cache when getLVForDecl did
a recursive call. This patch fixes that by adding another computation enum
value for when we don't care about the linkage at all and having getLVForDecl
check the cache in that case.

When running "clang -cc1" over SemaExpr.ii this brings the number of linkage
computations from 93749 to 58426. When running "clang -cc1 -emit-llvm -O3" it
goes from 198708 to 161444.

For SemaExpr.ii at least linkage computation is a small enough percentage of
the work that the time difference was in the noise.

When asserts are enabled this patch also causes clang to check the linkage
cache even on recursive calls.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@182799 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Decl.h
include/clang/AST/DeclBase.h
lib/AST/Decl.cpp

index 8120d7bdabe56e95bc96a1e0dc8383f55d5677c7..673575af6c7470f3b8e19aba80d9379685eb42e6 100644 (file)
@@ -110,7 +110,6 @@ class NamedDecl : public Decl {
 
 private:
   NamedDecl *getUnderlyingDeclImpl();
-  void verifyLinkage() const;
 
 protected:
   NamedDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName N)
index 347c15dd936d49ead7712bda822bf65519d5839a..b6614b5601ab275a4b46f11c5004a8b2c8fa2403 100644 (file)
@@ -32,6 +32,7 @@ class DeclarationName;
 class DependentDiagnostic;
 class EnumDecl;
 class FunctionDecl;
+class LinkageComputer;
 class LinkageSpecDecl;
 class Module;
 class NamedDecl;
@@ -292,6 +293,7 @@ protected:
   friend class ASTDeclWriter;
   friend class ASTDeclReader;
   friend class ASTReader;
+  friend class LinkageComputer;
 
 private:
   void CheckAccessDeclContext() const;
index 089622fb186670886e319e836408562c0556309b..8c33a97dfbcf22bb76f9fdf5336220c906d5a169 100644 (file)
@@ -85,6 +85,7 @@ using namespace clang;
 // and settings from the immediate context.
 
 const unsigned IgnoreExplicitVisibilityBit = 2;
+const unsigned IgnoreAllVisibilityBit = 4;
 
 /// Kinds of LV computation.  The linkage side of the computation is
 /// always the same, but different things can change how visibility is
@@ -108,7 +109,11 @@ enum LVComputationKind {
   /// Do an LV computation for, ultimately, a non-type declaration
   /// that already has some sort of explicit visibility.  Visibility
   /// may only be restricted by the visibility of template arguments.
-  LVForExplicitValue = (LVForValue | IgnoreExplicitVisibilityBit)
+  LVForExplicitValue = (LVForValue | IgnoreExplicitVisibilityBit),
+
+  /// Do an LV computation when we only care about the linkage.
+  LVForLinkageOnly =
+      LVForValue | IgnoreExplicitVisibilityBit | IgnoreAllVisibilityBit
 };
 
 /// Does this computation kind permit us to consider additional
@@ -391,6 +396,8 @@ static bool hasDirectVisibilityAttribute(const NamedDecl *D,
     if (D->hasAttr<VisibilityAttr>())
       return true;
     return false;
+  case LVForLinkageOnly:
+    return false;
   }
   llvm_unreachable("bad visibility computation kind");
 }
@@ -899,59 +906,15 @@ bool NamedDecl::isLinkageValid() const {
 }
 
 Linkage NamedDecl::getLinkageInternal() const {
-  if (hasCachedLinkage())
-    return getCachedLinkage();
-
   // We don't care about visibility here, so ask for the cheapest
   // possible visibility analysis.
-  setCachedLinkage(getLVForDecl(this, LVForExplicitValue).getLinkage());
-
-#ifndef NDEBUG
-  verifyLinkage();
-#endif
-
-  return getCachedLinkage();
+  return getLVForDecl(this, LVForLinkageOnly).getLinkage();
 }
 
 LinkageInfo NamedDecl::getLinkageAndVisibility() const {
   LVComputationKind computation =
     (usesTypeVisibility(this) ? LVForType : LVForValue);
-  LinkageInfo LI = getLVForDecl(this, computation);
-  if (hasCachedLinkage()) {
-    assert(getCachedLinkage() == LI.getLinkage());
-    return LI;
-  }
-  setCachedLinkage(LI.getLinkage());
-
-#ifndef NDEBUG
-  verifyLinkage();
-#endif
-
-  return LI;
-}
-
-void NamedDecl::verifyLinkage() const {
-  // In C (because of gnu inline) and in c++ with microsoft extensions an
-  // static can follow an extern, so we can have two decls with different
-  // linkages.
-  const LangOptions &Opts = getASTContext().getLangOpts();
-  if (!Opts.CPlusPlus || Opts.MicrosoftExt)
-    return;
-
-  // We have just computed the linkage for this decl. By induction we know
-  // that all other computed linkages match, check that the one we just computed
-  // also does.
-  NamedDecl *D = NULL;
-  for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) {
-    NamedDecl *T = cast<NamedDecl>(*I);
-    if (T == this)
-      continue;
-    if (T->hasCachedLinkage()) {
-      D = T;
-      break;
-    }
-  }
-  assert(!D || D->getCachedLinkage() == getCachedLinkage());
+  return getLVForDecl(this, computation);
 }
 
 Optional<Visibility>
@@ -1077,8 +1040,8 @@ static LinkageInfo getLVForLocalDecl(const NamedDecl *D,
                      LV.isVisibilityExplicit());
 }
 
-static LinkageInfo getLVForDecl(const NamedDecl *D,
-                                LVComputationKind computation) {
+static LinkageInfo computeLVForDecl(const NamedDecl *D,
+                                    LVComputationKind computation) {
   // Objective-C: treat all Objective-C declarations as having external
   // linkage.
   switch (D->getKind()) {
@@ -1159,6 +1122,57 @@ static LinkageInfo getLVForDecl(const NamedDecl *D,
   return LinkageInfo::none();
 }
 
+namespace clang {
+class LinkageComputer {
+public:
+  static LinkageInfo getLVForDecl(const NamedDecl *D,
+                                  LVComputationKind computation) {
+    if (computation == LVForLinkageOnly && D->hasCachedLinkage())
+      return LinkageInfo(D->getCachedLinkage(), DefaultVisibility, false);
+
+    LinkageInfo LV = computeLVForDecl(D, computation);
+    if (D->hasCachedLinkage())
+      assert(D->getCachedLinkage() == LV.getLinkage());
+
+    D->setCachedLinkage(LV.getLinkage());
+
+#ifndef NDEBUG
+    // In C (because of gnu inline) and in c++ with microsoft extensions an
+    // static can follow an extern, so we can have two decls with different
+    // linkages.
+    const LangOptions &Opts = D->getASTContext().getLangOpts();
+    if (!Opts.CPlusPlus || Opts.MicrosoftExt)
+      return LV;
+
+    // We have just computed the linkage for this decl. By induction we know
+    // that all other computed linkages match, check that the one we just
+    // computed
+    // also does.
+    NamedDecl *Old = NULL;
+    for (NamedDecl::redecl_iterator I = D->redecls_begin(),
+                                    E = D->redecls_end();
+         I != E; ++I) {
+      NamedDecl *T = cast<NamedDecl>(*I);
+      if (T == D)
+        continue;
+      if (T->hasCachedLinkage()) {
+        Old = T;
+        break;
+      }
+    }
+    assert(!Old || Old->getCachedLinkage() == D->getCachedLinkage());
+#endif
+
+    return LV;
+  }
+};
+}
+
+static LinkageInfo getLVForDecl(const NamedDecl *D,
+                                LVComputationKind computation) {
+  return clang::LinkageComputer::getLVForDecl(D, computation);
+}
+
 std::string NamedDecl::getQualifiedNameAsString() const {
   return getQualifiedNameAsString(getASTContext().getPrintingPolicy());
 }