> Sounds good, go ahead.

OK. I have committed the fix. The attached patch is a rebased version
with just the refactoring.

On the testcase with 16384 redeclarations clang -cc1 goes from
0m3.412s to 0m4.759s.
On the file from Postgres in pr10651 it goes from 0m0.604s to 0m0.716s.

So it looks like at least for now we cannot afford it :-(

Cheers,
Rafael
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index f8c69f9..946a703 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -49,6 +49,7 @@ struct PrintingPolicy;
 class Stmt;
 class StoredDeclsMap;
 class TranslationUnitDecl;
+class UsedAttr;
 class UsingDirectiveDecl;
 }
 
@@ -263,7 +264,7 @@ private:
 
   /// \brief Whether this declaration was "used", meaning that a definition is
   /// required.
-  unsigned Used : 1;
+  mutable unsigned Used : 1;
 
   /// \brief Whether this declaration was "referenced".
   /// The difference with 'Used' is whether the reference appears in a
@@ -505,10 +506,12 @@ public:
   /// whether the function is used.
   bool isUsed(bool CheckUsedAttr = true) const;
 
+  UsedAttr *getUsedAttr() const;
+
   /// \brief Set whether the declaration is used, in the sense of odr-use.
   ///
   /// This should only be used immediately after creating a declaration.
-  void setIsUsed() { Used = true; }
+  void setIsUsed();
 
   /// \brief Mark the declaration used, in the sense of odr-use.
   ///
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 88e1d04..3d6c240 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -7916,7 +7916,7 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
     return false;
 
   // Aliases and used decls are required.
-  if (D->hasAttr<AliasAttr>() || D->hasAttr<UsedAttr>())
+  if (D->hasAttr<AliasAttr>() || D->getUsedAttr())
     return true;
 
   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index be1992a..de3e939 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -280,25 +280,49 @@ unsigned Decl::getMaxAlignment() const {
   return Align;
 }
 
-bool Decl::isUsed(bool CheckUsedAttr) const { 
+bool Decl::isUsed(bool CheckUsedAttr) const {
   if (Used)
     return true;
-  
+
   // Check for used attribute.
   if (CheckUsedAttr && hasAttr<UsedAttr>())
     return true;
 
-  return false; 
+  const Decl *D = getMostRecentDecl();
+
+  if (D->Used) {
+    Used = true;
+    return true;
+  }
+
+  // Check for used attribute.
+  if (CheckUsedAttr && D->hasAttr<UsedAttr>())
+    return true;
+
+  return false;
+}
+
+UsedAttr *Decl::getUsedAttr() const {
+  if (UsedAttr *Attr = getAttr<UsedAttr>())
+    return Attr;
+  const Decl *D = getMostRecentDecl();
+  return D->getAttr<UsedAttr>();
+}
+
+void Decl::setIsUsed() {
+  Decl *D = getMostRecentDecl();
+  D->Used = true;
+  Used = true;
 }
 
 void Decl::markUsed(ASTContext &C) {
-  if (Used)
+  if (isUsed(false))
     return;
 
   if (C.getASTMutationListener())
     C.getASTMutationListener()->DeclarationMarkedUsed(this);
 
-  Used = true;
+  setIsUsed();
 }
 
 bool Decl::isReferenced() const { 
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 0f8ab1b..6a8b472 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -330,7 +330,7 @@ void CodeGenFunction::EmitStaticVarDecl(const VarDecl &D,
   if (const SectionAttr *SA = D.getAttr<SectionAttr>())
     var->setSection(SA->getName());
 
-  if (D.hasAttr<UsedAttr>())
+  if (D.getUsedAttr())
     CGM.AddUsedGlobal(var);
 
   // We may have to cast the constant because of the initializer
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index d0f34dd..b61fd0a 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -713,7 +713,7 @@ void CodeGenModule::SetCommonAttributes(const Decl *D,
   else
     GV->setVisibility(llvm::GlobalValue::DefaultVisibility);
 
-  if (D->hasAttr<UsedAttr>())
+  if (D->getUsedAttr())
     AddUsedGlobal(GV);
 
   if (const SectionAttr *SA = D->getAttr<SectionAttr>())
@@ -1689,7 +1689,7 @@ void CodeGenModule::MaybeHandleStaticInExternC(const SomeDecl *D,
 
   // Must have 'used' attribute, or else inline assembly can't rely on
   // the name existing.
-  if (!D->template hasAttr<UsedAttr>())
+  if (!D->getUsedAttr())
     return;
 
   // Must have internal linkage and an ordinary name.
diff --git a/lib/CodeGen/ModuleBuilder.cpp b/lib/CodeGen/ModuleBuilder.cpp
index bc7acbc..7f66968 100644
--- a/lib/CodeGen/ModuleBuilder.cpp
+++ b/lib/CodeGen/ModuleBuilder.cpp
@@ -100,7 +100,7 @@ namespace {
              M != MEnd; ++M)
           if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*M))
             if (Method->doesThisDeclarationHaveABody() &&
-                (Method->hasAttr<UsedAttr>() || 
+                (Method->getUsedAttr() ||
                  Method->hasAttr<ConstructorAttr>()))
               Builder->EmitTopLevelDecl(Method);
       }
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 41f72a6..2cea051 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -338,7 +338,7 @@ CastKind Sema::ScalarTypeToBooleanCastKind(QualType ScalarTy) {
 
 /// \brief Used to prune the decls of Sema's UnusedFileScopedDecls vector.
 static bool ShouldRemoveFromUnused(Sema *SemaRef, const DeclaratorDecl *D) {
-  if (D->getMostRecentDecl()->isUsed())
+  if (D->isUsed())
     return true;
 
   if (D->isExternallyVisible())
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 2edebab..09d2441 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -2099,7 +2099,7 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) {
 /// mergeDeclAttributes - Copy attributes from the Old decl to the New one.
 void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old,
                                AvailabilityMergeKind AMK) {
-  if (UsedAttr *OldAttr = Old->getMostRecentDecl()->getAttr<UsedAttr>()) {
+  if (UsedAttr *OldAttr = Old->getUsedAttr()) {
     UsedAttr *NewAttr = OldAttr->clone(Context);
     NewAttr->setInherited(true);
     New->addAttr(NewAttr);
@@ -2811,7 +2811,7 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old,
     New->setPure();
 
   // Merge "used" flag.
-  if (Old->getMostRecentDecl()->isUsed(false))
+  if (Old->isUsed(false))
     New->setIsUsed();
 
   // Merge attributes from the parameters.  These can mismatch with K&R
@@ -3125,7 +3125,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
   }
 
   // Merge "used" flag.
-  if (Old->getMostRecentDecl()->isUsed(false))
+  if (Old->isUsed(false))
     New->setIsUsed();
 
   // Keep a chain of previous declarations.
@@ -9712,7 +9712,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
     // The only way to be included in UndefinedButUsed is if there is an
     // ODR use before the definition. Avoid the expensive map lookup if this
     // is the first declaration.
-    if (!FD->isFirstDecl() && FD->getPreviousDecl()->isUsed()) {
+    if (!FD->isFirstDecl() && FD->isUsed()) {
       if (!FD->isExternallyVisible())
         UndefinedButUsed.erase(FD);
       else if (FD->isInlined() &&
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index c842ed0..cc52293 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -11216,17 +11216,7 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func) {
       UndefinedButUsed.insert(std::make_pair(Func->getCanonicalDecl(), Loc));
   }
 
-  // Normally the most current decl is marked used while processing the use and
-  // any subsequent decls are marked used by decl merging. This fails with
-  // template instantiation since marking can happen at the end of the file
-  // and, because of the two phase lookup, this function is called with at
-  // decl in the middle of a decl chain. We loop to maintain the invariant
-  // that once a decl is used, all decls after it are also used.
-  for (FunctionDecl *F = Func->getMostRecentDecl();; F = F->getPreviousDecl()) {
-    F->markUsed(Context);
-    if (F == Func)
-      break;
-  }
+  Func->markUsed(Context);
 }
 
 static void
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to