From 9f562c8d9ebfcd500e7ce256968099d5bab2940c Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Mon, 19 Dec 2011 15:27:36 +0000 Subject: [PATCH] Optimize serialized representation of redeclarable declarations for which there are no redeclarations. This reduced by size of the PCH file for Cocoa.h by ~650k: ~536k of that was in the new LOCAL_REDECLARATIONS table, which went from a ridiculous 540k down to an acceptable 3.5k, while the rest was due to the more compact abbreviated representation of redeclarable declaration kinds (which no longer need to store the 'first' declaration ID). llvm-svn: 146869 --- clang/lib/Serialization/ASTReaderDecl.cpp | 14 ++++- clang/lib/Serialization/ASTWriterDecl.cpp | 55 ++++++------------- .../test/Modules/Inputs/redecl-merge-bottom.h | 3 + clang/test/Modules/Inputs/redecl-merge-left.h | 4 ++ .../test/Modules/Inputs/redecl-merge-right.h | 2 + clang/test/Modules/Inputs/redecl-merge-top.h | 2 + clang/test/Modules/redecl-merge.m | 5 ++ 7 files changed, 45 insertions(+), 40 deletions(-) diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index d538d6ebb6e7..3e08d99ae606 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -1410,9 +1410,18 @@ ASTDeclReader::VisitDeclContext(DeclContext *DC) { template void ASTDeclReader::VisitRedeclarable(Redeclarable *D) { - enum RedeclKind { FirstInFile, PointsToPrevious }; + enum RedeclKind { OnlyDeclaration = 0, FirstInFile, PointsToPrevious }; RedeclKind Kind = (RedeclKind)Record[Idx++]; + // If this is the only known declaration of this entity, this module file + // has no additional redeclaration information. However, other module + // files might have redeclarations. + if (Kind == OnlyDeclaration) { + if (Reader.PendingDeclChainsKnown.insert(ThisDeclID)) + Reader.PendingDeclChains.push_back(ThisDeclID); + return; + } + // Read the first declaration ID, and note that we need to reconstruct // the redeclaration chain once we hit the top level. DeclID FirstDeclID = ReadDeclID(Record, Idx); @@ -1422,6 +1431,9 @@ void ASTDeclReader::VisitRedeclarable(Redeclarable *D) { T *FirstDecl = cast_or_null(Reader.GetDecl(FirstDeclID)); switch (Kind) { + case OnlyDeclaration: + llvm_unreachable("only declaration handled above"); + case FirstInFile: if (FirstDecl != D) D->RedeclLink = typename Redeclarable::PreviousDeclLink(FirstDecl); diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 4e9a315d22d4..bb4359a54b16 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -126,30 +126,6 @@ namespace clang { }; } -static bool isFirstDeclInFile(Decl *D) { - // FIXME: There must be a better way to abstract Redeclarable into a - // more-general "redeclarable type". - if (TagDecl *Tag = dyn_cast(D)) - return !Tag->getPreviousDeclaration() || - Tag->getPreviousDeclaration()->isFromASTFile(); - if (FunctionDecl *FD = dyn_cast(D)) - return !FD->getPreviousDeclaration() || - FD->getPreviousDeclaration()->isFromASTFile(); - if (VarDecl *VD = dyn_cast(D)) - return !VD->getPreviousDeclaration() || - VD->getPreviousDeclaration()->isFromASTFile(); - if (TypedefNameDecl *TD = dyn_cast(D)) - return !TD->getPreviousDeclaration() || - TD->getPreviousDeclaration()->isFromASTFile(); - if (ObjCInterfaceDecl *ID = dyn_cast(D)) - return !ID->getPreviousDeclaration() || - ID->getPreviousDeclaration()->isFromASTFile(); - - RedeclarableTemplateDecl *RTD = cast(D); - return !RTD->getPreviousDeclaration() || - RTD->getPreviousDeclaration()->isFromASTFile(); -} - void ASTDeclWriter::Visit(Decl *D) { DeclVisitor::Visit(D); @@ -212,7 +188,7 @@ void ASTDeclWriter::VisitTypedefDecl(TypedefDecl *D) { if (!D->hasAttrs() && !D->isImplicit() && !D->isUsed(false) && - isFirstDeclInFile(D) && + D->RedeclLink.getPointer() == D && !D->isInvalidDecl() && !D->isReferenced() && !D->isTopLevelDeclInObjCContainer() && @@ -262,7 +238,7 @@ void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) { !D->isImplicit() && !D->isUsed(false) && !D->hasExtInfo() && - isFirstDeclInFile(D) && + D->RedeclLink.getPointer() == D && !D->isInvalidDecl() && !D->isReferenced() && !D->isTopLevelDeclInObjCContainer() && @@ -286,7 +262,7 @@ void ASTDeclWriter::VisitRecordDecl(RecordDecl *D) { !D->isImplicit() && !D->isUsed(false) && !D->hasExtInfo() && - isFirstDeclInFile(D) && + D->RedeclLink.getPointer() == D && !D->isInvalidDecl() && !D->isReferenced() && !D->isTopLevelDeclInObjCContainer() && @@ -732,7 +708,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) { !D->isModulePrivate() && D->getDeclName().getNameKind() == DeclarationName::Identifier && !D->hasExtInfo() && - isFirstDeclInFile(D) && + D->RedeclLink.getPointer() == D && !D->hasCXXDirectInitializer() && D->getInit() == 0 && !isa(D) && @@ -1298,7 +1274,13 @@ void ASTDeclWriter::VisitDeclContext(DeclContext *DC, uint64_t LexicalOffset, template void ASTDeclWriter::VisitRedeclarable(Redeclarable *D) { - enum { FirstInFile, PointsToPrevious }; + enum { OnlyDeclaration = 0, FirstInFile, PointsToPrevious }; + if (D->RedeclLink.getPointer() == D) { + // This is the only declaration. + Record.push_back(OnlyDeclaration); + return; + } + T *First = D->getFirstDeclaration(); if (!D->getPreviousDeclaration() || D->getPreviousDeclaration()->isFromASTFile()) { @@ -1399,8 +1381,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv = new BitCodeAbbrev(); Abv->Add(BitCodeAbbrevOp(serialization::DECL_ENUM)); // Redeclarable - Abv->Add(BitCodeAbbrevOp(0)); // First in file - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // First ID + Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration // Decl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext @@ -1447,8 +1428,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv = new BitCodeAbbrev(); Abv->Add(BitCodeAbbrevOp(serialization::DECL_RECORD)); // Redeclarable - Abv->Add(BitCodeAbbrevOp(0)); // First in file - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // First ID + Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration // Decl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext @@ -1489,8 +1469,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv = new BitCodeAbbrev(); Abv->Add(BitCodeAbbrevOp(serialization::DECL_PARM_VAR)); // Redeclarable - Abv->Add(BitCodeAbbrevOp(0)); // First in file - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // First ID + Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration // Decl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext @@ -1540,8 +1519,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv = new BitCodeAbbrev(); Abv->Add(BitCodeAbbrevOp(serialization::DECL_TYPEDEF)); // Redeclarable - Abv->Add(BitCodeAbbrevOp(0)); // First in file - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // First ID + Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration // Decl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext @@ -1569,8 +1547,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs() { Abv = new BitCodeAbbrev(); Abv->Add(BitCodeAbbrevOp(serialization::DECL_VAR)); // Redeclarable - Abv->Add(BitCodeAbbrevOp(0)); // First in file - Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // First ID + Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration // Decl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalDeclContext diff --git a/clang/test/Modules/Inputs/redecl-merge-bottom.h b/clang/test/Modules/Inputs/redecl-merge-bottom.h index e45e0dea0477..198bde3e5faa 100644 --- a/clang/test/Modules/Inputs/redecl-merge-bottom.h +++ b/clang/test/Modules/Inputs/redecl-merge-bottom.h @@ -1,4 +1,7 @@ __import_module__ redecl_merge_left; __import_module__ redecl_merge_right; +@class B; + @class A; + diff --git a/clang/test/Modules/Inputs/redecl-merge-left.h b/clang/test/Modules/Inputs/redecl-merge-left.h index 085892234818..048b3e6c2def 100644 --- a/clang/test/Modules/Inputs/redecl-merge-left.h +++ b/clang/test/Modules/Inputs/redecl-merge-left.h @@ -4,4 +4,8 @@ __import_module__ redecl_merge_top; @class A; +@interface B +@end + @class A; + diff --git a/clang/test/Modules/Inputs/redecl-merge-right.h b/clang/test/Modules/Inputs/redecl-merge-right.h index 266146c9953e..d8fd45f2b94c 100644 --- a/clang/test/Modules/Inputs/redecl-merge-right.h +++ b/clang/test/Modules/Inputs/redecl-merge-right.h @@ -7,3 +7,5 @@ __import_module__ redecl_merge_top; - (Super*)init; @end +@class B; + diff --git a/clang/test/Modules/Inputs/redecl-merge-top.h b/clang/test/Modules/Inputs/redecl-merge-top.h index 886436cdda86..68dae5058e24 100644 --- a/clang/test/Modules/Inputs/redecl-merge-top.h +++ b/clang/test/Modules/Inputs/redecl-merge-top.h @@ -3,3 +3,5 @@ @class A; @class A; + +@class B; diff --git a/clang/test/Modules/redecl-merge.m b/clang/test/Modules/redecl-merge.m index d62d504868c5..fe2504416633 100644 --- a/clang/test/Modules/redecl-merge.m +++ b/clang/test/Modules/redecl-merge.m @@ -14,8 +14,13 @@ void f(A *a) { @class A; +@class B; + __import_module__ redecl_merge_bottom; +@implementation B +@end + void g(A *a) { [a init]; }