From 2eafc1b56347f772729e082e6bac824b0ef1b585 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Sun, 26 Apr 2009 00:07:37 +0000 Subject: [PATCH] Don't read all of the records in the PCH file's preprocessor block, most of which are ignored. Instead, move the __COUNTER__ value out to a PCH-level record (since it is handled eagerly) and move the header file information into the SourceManager block (which is also, currently, loaded eagerly). This results in another 17% performance improvement in the Cocoa-prefixed "Hello, World" with PCH. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@70097 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Frontend/PCHBitCodes.h | 21 +++--- include/clang/Frontend/PCHReader.h | 3 +- include/clang/Frontend/PCHWriter.h | 3 +- lib/Frontend/PCHReader.cpp | 102 +++++---------------------- lib/Frontend/PCHWriter.cpp | 55 ++++++++------- 5 files changed, 59 insertions(+), 125 deletions(-) diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index 26e2c1744c..f486920316 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -169,7 +169,11 @@ namespace clang { SELECTOR_OFFSETS = 12, /// \brief Record code for the Objective-C method pool, - METHOD_POOL = 13 + METHOD_POOL = 13, + + /// \brief The value of the next __COUNTER__ to dispense. + /// [PP_COUNTER_VALUE, Val] + PP_COUNTER_VALUE = 14 }; /// \brief Record types used within a source manager block. @@ -189,7 +193,10 @@ namespace clang { SM_SLOC_INSTANTIATION_ENTRY = 4, /// \brief Describes the SourceManager's line table, with /// information about #line directives. - SM_LINE_TABLE = 5 + SM_LINE_TABLE = 5, + /// \brief Describes one header file info [isImport, DirInfo, NumIncludes] + /// ControllingMacro is optional. + SM_HEADER_FILE_INFO = 6 }; /// \brief Record types used within a preprocessor block. @@ -208,15 +215,7 @@ namespace clang { /// \brief Describes one token. /// [PP_TOKEN, SLoc, Length, IdentInfoID, Kind, Flags] - PP_TOKEN = 3, - - /// \brief The value of the next __COUNTER__ to dispense. - /// [PP_COUNTER_VALUE, Val] - PP_COUNTER_VALUE = 4, - - /// \brief Describes one header file info [isImport, DirInfo, NumIncludes] - /// ControlloingMacro is optional. - PP_HEADER_FILE_INFO = 5 + PP_TOKEN = 3 }; /// \defgroup PCHAST Precompiled header AST constants diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h index 98e32fcf0e..8f53405c52 100644 --- a/include/clang/Frontend/PCHReader.h +++ b/include/clang/Frontend/PCHReader.h @@ -245,12 +245,11 @@ private: /// Objective-C protocols. llvm::SmallVector InterestingDecls; - PCHReadResult ReadPCHBlock(uint64_t &PreprocessorBlockOffset); + PCHReadResult ReadPCHBlock(); bool CheckPredefinesBuffer(const char *PCHPredef, unsigned PCHPredefLen, FileID PCHBufferID); PCHReadResult ReadSourceManagerBlock(); - bool ReadPreprocessorBlock(); bool ParseLanguageOptions(const llvm::SmallVectorImpl &Record); QualType ReadTypeRecord(uint64_t Offset); diff --git a/include/clang/Frontend/PCHWriter.h b/include/clang/Frontend/PCHWriter.h index a597d68ee3..034c1afb28 100644 --- a/include/clang/Frontend/PCHWriter.h +++ b/include/clang/Frontend/PCHWriter.h @@ -156,7 +156,8 @@ private: void WriteTargetTriple(const TargetInfo &Target); void WriteLanguageOptions(const LangOptions &LangOpts); - void WriteSourceManagerBlock(SourceManager &SourceMgr); + void WriteSourceManagerBlock(SourceManager &SourceMgr, + const Preprocessor &PP); void WritePreprocessor(const Preprocessor &PP); void WriteType(const Type *T); void WriteTypesBlock(ASTContext &Context); diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index c351a24118..d824c56848 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -1473,6 +1473,7 @@ PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() { SourceManager &SourceMgr = Context.getSourceManager(); RecordData Record; + unsigned NumHeaderInfos = 0; while (true) { unsigned Code = Stream.ReadCode(); if (Code == llvm::bitc::END_BLOCK) { @@ -1557,6 +1558,16 @@ PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() { if (ParseLineTable(SourceMgr, Record)) return Failure; break; + + case pch::SM_HEADER_FILE_INFO: { + HeaderFileInfo HFI; + HFI.isImport = Record[0]; + HFI.DirInfo = Record[1]; + HFI.NumIncludes = Record[2]; + HFI.ControllingMacroID = Record[3]; + PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, NumHeaderInfos++); + break; + } } } } @@ -1597,10 +1608,6 @@ void PCHReader::ReadMacroRecord(uint64_t Offset) { pch::PreprocessorRecordTypes RecType = (pch::PreprocessorRecordTypes)Stream.ReadRecord(Code, Record); switch (RecType) { - case pch::PP_COUNTER_VALUE: - // Skip this record. - break; - case pch::PP_MACRO_OBJECT_LIKE: case pch::PP_MACRO_FUNCTION_LIKE: { // If we already have a macro, that means that we've hit the end @@ -1663,70 +1670,12 @@ void PCHReader::ReadMacroRecord(uint64_t Offset) { Macro->AddTokenToBody(Tok); break; } - case pch::PP_HEADER_FILE_INFO: - break; // Already processed by ReadPreprocessorBlock(). } } } -bool PCHReader::ReadPreprocessorBlock() { - if (Stream.EnterSubBlock(pch::PREPROCESSOR_BLOCK_ID)) - return Error("Malformed preprocessor block record"); - - RecordData Record; - unsigned NumHeaderInfos = 0; - while (true) { - unsigned Code = Stream.ReadCode(); - switch (Code) { - case llvm::bitc::END_BLOCK: - if (Stream.ReadBlockEnd()) - return Error("Error at end of preprocessor block"); - return false; - - case llvm::bitc::ENTER_SUBBLOCK: - // No known subblocks, always skip them. - Stream.ReadSubBlockID(); - if (Stream.SkipBlock()) - return Error("Malformed block record"); - continue; - - case llvm::bitc::DEFINE_ABBREV: - Stream.ReadAbbrevRecord(); - continue; - default: break; - } - - // Read a record. - Record.clear(); - pch::PreprocessorRecordTypes RecType = - (pch::PreprocessorRecordTypes)Stream.ReadRecord(Code, Record); - switch (RecType) { - default: // Default behavior: ignore unknown records. - break; - case pch::PP_COUNTER_VALUE: - if (!Record.empty()) - PP.setCounterValue(Record[0]); - break; - - case pch::PP_MACRO_OBJECT_LIKE: - case pch::PP_MACRO_FUNCTION_LIKE: - case pch::PP_TOKEN: - break; - case pch::PP_HEADER_FILE_INFO: { - HeaderFileInfo HFI; - HFI.isImport = Record[0]; - HFI.DirInfo = Record[1]; - HFI.NumIncludes = Record[2]; - HFI.ControllingMacroID = Record[3]; - PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, NumHeaderInfos++); - break; - } - } - } -} - PCHReader::PCHReadResult -PCHReader::ReadPCHBlock(uint64_t &PreprocessorBlockOffset) { +PCHReader::ReadPCHBlock() { if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) { Error("Malformed block record"); return Failure; @@ -1757,13 +1706,6 @@ PCHReader::ReadPCHBlock(uint64_t &PreprocessorBlockOffset) { break; case pch::PREPROCESSOR_BLOCK_ID: - // Skip the preprocessor block for now, but remember where it is. We - // want to read it in after the identifier table. - if (PreprocessorBlockOffset) { - Error("Multiple preprocessor blocks found."); - return Failure; - } - PreprocessorBlockOffset = Stream.GetCurrentBitNo(); if (Stream.SkipBlock()) { Error("Malformed block record"); return Failure; @@ -1907,6 +1849,11 @@ PCHReader::ReadPCHBlock(uint64_t &PreprocessorBlockOffset) { PCHMethodPoolLookupTrait(*this)); TotalSelectorsInMethodPool = Record[1]; break; + + case pch::PP_COUNTER_VALUE: + if (!Record.empty()) + PP.setCounterValue(Record[0]); + break; } } Error("Premature end of bitstream"); @@ -1938,10 +1885,6 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) { return IgnorePCH; } - // We expect a number of well-defined blocks, though we don't necessarily - // need to understand them all. - uint64_t PreprocessorBlockOffset = 0; - while (!Stream.AtEndOfStream()) { unsigned Code = Stream.ReadCode(); @@ -1961,7 +1904,7 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) { } break; case pch::PCH_BLOCK_ID: - switch (ReadPCHBlock(PreprocessorBlockOffset)) { + switch (ReadPCHBlock()) { case Success: break; @@ -2036,15 +1979,6 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) { if (unsigned FastEnum = SpecialTypes[pch::SPECIAL_TYPE_OBJC_FAST_ENUMERATION_STATE]) Context.setObjCFastEnumerationStateType(GetType(FastEnum)); - // If we saw the preprocessor block, read it now. - if (PreprocessorBlockOffset) { - SavedStreamPosition SavedPos(Stream); - Stream.JumpToBit(PreprocessorBlockOffset); - if (ReadPreprocessorBlock()) { - Error("Malformed preprocessor block"); - return Failure; - } - } return Success; } diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index bce941a849..59aabfe0e4 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -1359,7 +1359,8 @@ static unsigned CreateSLocInstantiationAbbrev(llvm::BitstreamWriter &Stream) { /// entries for files that we actually need. In the common case (no /// errors), we probably won't have to create file entries for any of /// the files in the AST. -void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr) { +void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr, + const Preprocessor &PP) { // Enter the source manager block. Stream.EnterSubblock(pch::SOURCE_MANAGER_BLOCK_ID, 3); @@ -1481,6 +1482,22 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr) { } } + // Loop over all the header files. + HeaderSearch &HS = PP.getHeaderSearchInfo(); + for (HeaderSearch::header_file_iterator I = HS.header_file_begin(), + E = HS.header_file_end(); + I != E; ++I) { + Record.push_back(I->isImport); + Record.push_back(I->DirInfo); + Record.push_back(I->NumIncludes); + if (I->ControllingMacro) + AddIdentifierRef(I->ControllingMacro, Record); + else + Record.push_back(0); + Stream.EmitRecord(pch::SM_HEADER_FILE_INFO, Record); + Record.clear(); + } + Stream.ExitBlock(); } @@ -1488,14 +1505,6 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr) { /// preprocessor. /// void PCHWriter::WritePreprocessor(const Preprocessor &PP) { - // Enter the preprocessor block. - Stream.EnterSubblock(pch::PREPROCESSOR_BLOCK_ID, 2); - - // If the PCH file contains __DATE__ or __TIME__ emit a warning about this. - // FIXME: use diagnostics subsystem for localization etc. - if (PP.SawDateOrTime()) - fprintf(stderr, "warning: precompiled header used __DATE__ or __TIME__.\n"); - RecordData Record; // If the preprocessor __COUNTER__ value has been bumped, remember it. @@ -1503,8 +1512,16 @@ void PCHWriter::WritePreprocessor(const Preprocessor &PP) { Record.push_back(PP.getCounterValue()); Stream.EmitRecord(pch::PP_COUNTER_VALUE, Record); Record.clear(); - } + } + + // Enter the preprocessor block. + Stream.EnterSubblock(pch::PREPROCESSOR_BLOCK_ID, 2); + // If the PCH file contains __DATE__ or __TIME__ emit a warning about this. + // FIXME: use diagnostics subsystem for localization etc. + if (PP.SawDateOrTime()) + fprintf(stderr, "warning: precompiled header used __DATE__ or __TIME__.\n"); + // Loop over all the macro definitions that are live at the end of the file, // emitting each to the PP section. for (Preprocessor::macro_iterator I = PP.macro_begin(), E = PP.macro_end(); @@ -1564,22 +1581,6 @@ void PCHWriter::WritePreprocessor(const Preprocessor &PP) { } ++NumMacros; } - - // Loop over all the header files. - HeaderSearch &HS = PP.getHeaderSearchInfo(); - for (HeaderSearch::header_file_iterator I = HS.header_file_begin(), - E = HS.header_file_end(); - I != E; ++I) { - Record.push_back(I->isImport); - Record.push_back(I->DirInfo); - Record.push_back(I->NumIncludes); - if (I->ControllingMacro) - AddIdentifierRef(I->ControllingMacro, Record); - else - Record.push_back(0); - Stream.EmitRecord(pch::PP_HEADER_FILE_INFO, Record); - Record.clear(); - } Stream.ExitBlock(); } @@ -2365,7 +2366,7 @@ void PCHWriter::WritePCH(Sema &SemaRef) { Stream.EnterSubblock(pch::PCH_BLOCK_ID, 4); WriteTargetTriple(Context.Target); WriteLanguageOptions(Context.getLangOptions()); - WriteSourceManagerBlock(Context.getSourceManager()); + WriteSourceManagerBlock(Context.getSourceManager(), PP); WritePreprocessor(PP); WriteTypesBlock(Context); WriteDeclsBlock(Context); -- 2.40.0