Lazy deserialization of macro definitions for precompiled headers.

This optimization improves performance on the Carbon-prefixed "Hello,
World!" example by 57%. For reference, we're now about 2.25x faster
than GCC PCH. We're also pulling in far less of the PCH file:

*** PCH Statistics:
  411/20693 types read (1.986179%)
  2553/59230 declarations read (4.310316%)
  1093/44646 identifiers read (2.448148%)
  1/32954 statements read (0.003035%)
  21/6187 macros read (0.339421%)




git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69755 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index 1167250..bdcd359 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -1439,8 +1439,6 @@
   
   // Loop over all the macro definitions that are live at the end of the file,
   // emitting each to the PP section.
-  // FIXME: Eventually we want to emit an index so that we can lazily load
-  // macros.
   for (Preprocessor::macro_iterator I = PP.macro_begin(), E = PP.macro_end();
        I != E; ++I) {
     // FIXME: This emits macros in hash table order, we should do it in a stable
@@ -1452,7 +1450,9 @@
     if (MI->isBuiltinMacro())
       continue;
 
+    // FIXME: Remove this identifier reference?
     AddIdentifierRef(I->first, Record);
+    MacroOffsets[I->first] = Stream.GetCurrentBitNo();
     Record.push_back(MI->getDefinitionLoc().getRawEncoding());
     Record.push_back(MI->isUsed());
     
@@ -1494,7 +1494,7 @@
       Stream.EmitRecord(pch::PP_TOKEN, Record);
       Record.clear();
     }
-    
+    ++NumMacros;
   }
   
   Stream.ExitBlock();
@@ -1715,6 +1715,7 @@
 namespace {
 class VISIBILITY_HIDDEN PCHIdentifierTableTrait {
   PCHWriter &Writer;
+  Preprocessor &PP;
 
 public:
   typedef const IdentifierInfo* key_type;
@@ -1723,19 +1724,23 @@
   typedef pch::IdentID data_type;
   typedef data_type data_type_ref;
   
-  PCHIdentifierTableTrait(PCHWriter &Writer) : Writer(Writer) { }
+  PCHIdentifierTableTrait(PCHWriter &Writer, Preprocessor &PP) 
+    : Writer(Writer), PP(PP) { }
 
   static unsigned ComputeHash(const IdentifierInfo* II) {
     return clang::BernsteinHash(II->getName());
   }
   
-  static std::pair<unsigned,unsigned> 
+  std::pair<unsigned,unsigned> 
     EmitKeyDataLength(llvm::raw_ostream& Out, const IdentifierInfo* II, 
                       pch::IdentID ID) {
     unsigned KeyLen = strlen(II->getName()) + 1;
     clang::io::Emit16(Out, KeyLen);
     unsigned DataLen = 4 + 4; // 4 bytes for token ID, builtin, flags
                               // 4 bytes for the persistent ID
+    if (II->hasMacroDefinition() && 
+        !PP.getMacroInfo(const_cast<IdentifierInfo *>(II))->isBuiltinMacro())
+      DataLen += 8;
     for (IdentifierResolver::iterator D = IdentifierResolver::begin(II),
                                    DEnd = IdentifierResolver::end();
          D != DEnd; ++D)
@@ -1755,15 +1760,21 @@
   void EmitData(llvm::raw_ostream& Out, const IdentifierInfo* II, 
                 pch::IdentID ID, unsigned) {
     uint32_t Bits = 0;
+    bool hasMacroDefinition = 
+      II->hasMacroDefinition() && 
+      !PP.getMacroInfo(const_cast<IdentifierInfo *>(II))->isBuiltinMacro();
     Bits = Bits | (uint32_t)II->getTokenID();
     Bits = (Bits << 8) | (uint32_t)II->getObjCOrBuiltinID();
-    Bits = (Bits << 10) | II->hasMacroDefinition();
+    Bits = (Bits << 10) | hasMacroDefinition;
     Bits = (Bits << 1) | II->isExtensionToken();
     Bits = (Bits << 1) | II->isPoisoned();
     Bits = (Bits << 1) | II->isCPlusPlusOperatorKeyword();
     clang::io::Emit32(Out, Bits);
     clang::io::Emit32(Out, ID);
 
+    if (hasMacroDefinition)
+      clang::io::Emit64(Out, Writer.getMacroOffset(II));
+
     // Emit the declaration IDs in reverse order, because the
     // IdentifierResolver provides the declarations as they would be
     // visible (e.g., the function "stat" would come before the struct
@@ -1785,7 +1796,7 @@
 /// The identifier table consists of a blob containing string data
 /// (the actual identifiers themselves) and a separate "offsets" index
 /// that maps identifier IDs to locations within the blob.
-void PCHWriter::WriteIdentifierTable() {
+void PCHWriter::WriteIdentifierTable(Preprocessor &PP) {
   using namespace llvm;
 
   // Create and write out the blob that contains the identifier
@@ -1806,7 +1817,7 @@
     llvm::SmallVector<char, 4096> IdentifierTable; 
     uint32_t BucketOffset;
     {
-      PCHIdentifierTableTrait Trait(*this);
+      PCHIdentifierTableTrait Trait(*this, PP);
       llvm::raw_svector_ostream Out(IdentifierTable);
       BucketOffset = Generator.Emit(Out, Trait);
     }
@@ -1964,7 +1975,8 @@
 }
 
 PCHWriter::PCHWriter(llvm::BitstreamWriter &Stream) 
-  : Stream(Stream), NextTypeID(pch::NUM_PREDEF_TYPE_IDS), NumStatements(0) { }
+  : Stream(Stream), NextTypeID(pch::NUM_PREDEF_TYPE_IDS), 
+    NumStatements(0), NumMacros(0) { }
 
 void PCHWriter::WritePCH(Sema &SemaRef) {
   ASTContext &Context = SemaRef.Context;
@@ -1989,7 +2001,7 @@
   WritePreprocessor(PP);
   WriteTypesBlock(Context);
   WriteDeclsBlock(Context);
-  WriteIdentifierTable();
+  WriteIdentifierTable(PP);
   Stream.EmitRecord(pch::TYPE_OFFSET, TypeOffsets);
   Stream.EmitRecord(pch::DECL_OFFSET, DeclOffsets);
 
@@ -2004,6 +2016,7 @@
   // Some simple statistics
   Record.clear();
   Record.push_back(NumStatements);
+  Record.push_back(NumMacros);
   Stream.EmitRecord(pch::STATISTICS, Record);
   Stream.ExitBlock();
 }