]> granicus.if.org Git - clang/commitdiff
Keep track of canonical decls in Redeclarable.
authorManuel Klimek <klimek@google.com>
Wed, 25 Mar 2015 23:18:30 +0000 (23:18 +0000)
committerManuel Klimek <klimek@google.com>
Wed, 25 Mar 2015 23:18:30 +0000 (23:18 +0000)
More than 2x speedup on modules builds with large redecl chains.
Roughly 15-20% speedup on non-modules builds for very large TUs.
Between 2-3% cost in memory on large TUs.

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

include/clang/AST/Decl.h
include/clang/AST/Redeclarable.h
lib/Serialization/ASTReaderDecl.cpp

index 009335dc58eacc0ab6f52687f2bc6f43b48ad75d..7f7e437b736f7de850340c1bc1535077ee94b7ef 100644 (file)
@@ -3738,8 +3738,6 @@ void Redeclarable<decl_type>::setPreviousDecl(decl_type *PrevDecl) {
   assert(RedeclLink.NextIsLatest() &&
          "setPreviousDecl on a decl already in a redeclaration chain");
 
-  decl_type *First;
-
   if (PrevDecl) {
     // Point to previous. Make sure that this is actually the most recent
     // redeclaration, or we can build invalid chains. If the most recent
index c798d708326a87a0fcbaaf5ef0623212e9d79891..92046d582bf38975e8d53dc23a806902b037f6da 100644 (file)
@@ -121,14 +121,15 @@ protected:
   ///
   /// If there is only one declaration, it is <pointer to self, true>
   DeclLink RedeclLink;
+  decl_type *First;
 
   decl_type *getNextRedeclaration() const {
     return RedeclLink.getNext(static_cast<const decl_type *>(this));
   }
 
 public:
 Redeclarable(const ASTContext &Ctx)
-      : RedeclLink(LatestDeclLink(Ctx)) {}
+ Redeclarable(const ASTContext &Ctx)
+     : RedeclLink(LatestDeclLink(Ctx)), First(static_cast<decl_type *>(this)) {}
 
   /// \brief Return the previous declaration of this declaration or NULL if this
   /// is the first declaration.
@@ -144,21 +145,11 @@ public:
 
   /// \brief Return the first declaration of this declaration or itself if this
   /// is the only declaration.
-  decl_type *getFirstDecl() {
-    decl_type *D = static_cast<decl_type*>(this);
-    while (D->getPreviousDecl())
-      D = D->getPreviousDecl();
-    return D;
-  }
+  decl_type *getFirstDecl() { return First; }
 
   /// \brief Return the first declaration of this declaration or itself if this
   /// is the only declaration.
-  const decl_type *getFirstDecl() const {
-    const decl_type *D = static_cast<const decl_type*>(this);
-    while (D->getPreviousDecl())
-      D = D->getPreviousDecl();
-    return D;
-  }
+  const decl_type *getFirstDecl() const { return First; }
 
   /// \brief True if this is the first declaration in its redeclaration chain.
   bool isFirstDecl() const { return RedeclLink.NextIsLatest(); }
index d384f3d46e8656bc11dd54a3c4ac0cdd44e5cecf..10de9f754de667c36da6e93971f678c43393b2f0 100644 (file)
@@ -2106,6 +2106,7 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) {
     // which is the one that matters and mark the real previous DeclID to be
     // loaded & attached later on.
     D->RedeclLink = Redeclarable<T>::PreviousDeclLink(FirstDecl);
+    D->First = FirstDecl->getCanonicalDecl();
   }    
   
   // Note that this declaration has been deserialized.
@@ -2209,6 +2210,7 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *Existing,
     // of the existing declaration, so that this declaration has the
     // appropriate canonical declaration.
     D->RedeclLink = Redeclarable<T>::PreviousDeclLink(ExistingCanon);
+    D->First = ExistingCanon;
 
     // When we merge a namespace, update its pointer to the first namespace.
     // We cannot have loaded any redeclarations of this declaration yet, so
@@ -2828,6 +2830,7 @@ void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader,
                                            Redeclarable<DeclT> *D,
                                            Decl *Previous, Decl *Canon) {
   D->RedeclLink.setPrevious(cast<DeclT>(Previous));
+  D->First = cast<DeclT>(Previous)->First;
 }
 namespace clang {
 template<>
@@ -2838,6 +2841,7 @@ void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader,
   FunctionDecl *PrevFD = cast<FunctionDecl>(Previous);
 
   FD->RedeclLink.setPrevious(PrevFD);
+  FD->First = PrevFD->First;
 
   // If the previous declaration is an inline function declaration, then this
   // declaration is too.