]> granicus.if.org Git - clang/commitdiff
Write the declaration and type offset arrays into the bitstream as
authorDouglas Gregor <dgregor@apple.com>
Sat, 25 Apr 2009 18:35:21 +0000 (18:35 +0000)
committerDouglas Gregor <dgregor@apple.com>
Sat, 25 Apr 2009 18:35:21 +0000 (18:35 +0000)
blobs, so that we don't need to do any work to get these arrays into
memory at PCH load time.

This gives another 19% performance improvement to the Cocoa-prefixed
"Hello, World!".

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

include/clang/Frontend/PCHReader.h
lib/Frontend/PCHReader.cpp
lib/Frontend/PCHWriter.cpp

index c3de6093aa14bea94818d5d301c29a66fa036b9a..fe23185bed7168b97d6121747ae2d373c3f37de0 100644 (file)
@@ -94,32 +94,23 @@ private:
 
   /// \brief Offset of each type within the bitstream, indexed by the
   /// type ID, or the representation of a Type*.
-  llvm::SmallVector<uint64_t, 16> TypeOffsets;
+  const uint64_t *TypeOffsets;
 
-  /// \brief Whether the type with a given index has already been loaded.
+  /// \brief Types that have already been loaded from the PCH file.
   /// 
-  /// When the bit at a given index I is true, then TypeOffsets[I] is
-  /// the already-loaded Type*. Otherwise, TypeOffsets[I] is the
-  /// location of the type's record in the PCH file.
-  ///
-  /// FIXME: We can probably eliminate this, e.g., by bitmangling the
-  /// values in TypeOffsets.
-  std::vector<bool> TypeAlreadyLoaded;
+  /// When the pointer at index I is non-NULL, the type with 
+  /// ID = (I + 1) << 3 has already been loaded from the PCH file.
+  std::vector<Type *> TypesLoaded;
 
   /// \brief Offset of each declaration within the bitstream, indexed
-  /// by the declaration ID.
-  llvm::SmallVector<uint64_t, 16> DeclOffsets;
+  /// by the declaration ID (-1).
+  const uint64_t *DeclOffsets;
 
-  /// \brief Whether the declaration with a given index has already
-  /// been loaded.
-  ///
-  /// When the bit at the given index I is true, then DeclOffsets[I]
-  /// is the already-loaded Decl*. Otherwise, DeclOffsets[I] is the
-  /// location of the declaration's record in the PCH file.
+  /// \brief Declarations that have already been loaded from the PCH file.
   ///
-  /// FIXME: We can probably eliminate this, e.g., by bitmangling the
-  /// values in DeclOffsets.
-  std::vector<bool> DeclAlreadyLoaded;
+  /// When the pointer at index I is non-NULL, the declaration with ID
+  /// = I + 1 has already been loaded.
+  std::vector<Decl *> DeclsLoaded;
 
   typedef llvm::DenseMap<const DeclContext *, std::pair<uint64_t, uint64_t> >
     DeclContextOffsetsMap;
index 3e612be6296272088d70190f301bd68bf3c3f274..897a0e77135d3d1785f985536068ca6248523574 100644 (file)
@@ -1802,21 +1802,21 @@ PCHReader::ReadPCHBlock(uint64_t &PreprocessorBlockOffset) {
       break;
 
     case pch::TYPE_OFFSET:
-      if (!TypeOffsets.empty()) {
+      if (!TypesLoaded.empty()) {
         Error("Duplicate TYPE_OFFSET record in PCH file");
         return Failure;
       }
-      TypeOffsets.swap(Record);
-      TypeAlreadyLoaded.resize(TypeOffsets.size(), false);
+      TypeOffsets = (const uint64_t *)BlobStart;
+      TypesLoaded.resize(Record[0]);
       break;
 
     case pch::DECL_OFFSET:
-      if (!DeclOffsets.empty()) {
+      if (!DeclsLoaded.empty()) {
         Error("Duplicate DECL_OFFSET record in PCH file");
         return Failure;
       }
-      DeclOffsets.swap(Record);
-      DeclAlreadyLoaded.resize(DeclOffsets.size(), false);
+      DeclOffsets = (const uint64_t *)BlobStart;
+      DeclsLoaded.resize(Record[0]);
       break;
 
     case pch::LANGUAGE_OPTIONS:
@@ -2340,9 +2340,8 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
 /// so that future GetDecl calls will return this declaration rather
 /// than trying to load a new declaration.
 inline void PCHReader::LoadedDecl(unsigned Index, Decl *D) {
-  assert(!DeclAlreadyLoaded[Index] && "Decl loaded twice?");
-  DeclAlreadyLoaded[Index] = true;
-  DeclOffsets[Index] = reinterpret_cast<uint64_t>(D);
+  assert(!DeclsLoaded[Index] && "Decl loaded twice?");
+  DeclsLoaded[Index] = D;
 }
 
 /// \brief Determine whether the consumer will be interested in seeing
@@ -2591,27 +2590,26 @@ QualType PCHReader::GetType(pch::TypeID ID) {
   }
 
   Index -= pch::NUM_PREDEF_TYPE_IDS;
-  if (!TypeAlreadyLoaded[Index]) {
-    // Load the type from the PCH file.
-    TypeOffsets[Index] = reinterpret_cast<uint64_t>(
-                             ReadTypeRecord(TypeOffsets[Index]).getTypePtr());
-    TypeAlreadyLoaded[Index] = true;
-  }
+  if (!TypesLoaded[Index])
+    TypesLoaded[Index] = ReadTypeRecord(TypeOffsets[Index]).getTypePtr();
     
-  return QualType(reinterpret_cast<Type *>(TypeOffsets[Index]), Quals);
+  return QualType(TypesLoaded[Index], Quals);
 }
 
 Decl *PCHReader::GetDecl(pch::DeclID ID) {
   if (ID == 0)
     return 0;
 
+  if (ID > DeclsLoaded.size()) {
+    Error("Declaration ID out-of-range for PCH file");
+    return 0;
+  }
+
   unsigned Index = ID - 1;
-  assert(Index < DeclAlreadyLoaded.size() && "Declaration ID out of range");
-  if (DeclAlreadyLoaded[Index])
-    return reinterpret_cast<Decl *>(DeclOffsets[Index]);
+  if (!DeclsLoaded[Index])
+    ReadDeclRecord(DeclOffsets[Index], Index);
 
-  // Load the declaration from the PCH file.
-  return ReadDeclRecord(DeclOffsets[Index], Index);
+  return DeclsLoaded[Index];
 }
 
 Stmt *PCHReader::GetStmt(uint64_t Offset) {
@@ -2712,12 +2710,12 @@ void PCHReader::StartTranslationUnit(ASTConsumer *Consumer) {
 void PCHReader::PrintStats() {
   std::fprintf(stderr, "*** PCH Statistics:\n");
 
-  unsigned NumTypesLoaded = std::count(TypeAlreadyLoaded.begin(),
-                                       TypeAlreadyLoaded.end(),
-                                       true);
-  unsigned NumDeclsLoaded = std::count(DeclAlreadyLoaded.begin(),
-                                       DeclAlreadyLoaded.end(),
-                                       true);
+  unsigned NumTypesLoaded = 
+    TypesLoaded.size() - std::count(TypesLoaded.begin(), TypesLoaded.end(),
+                                    (Type *)0);
+  unsigned NumDeclsLoaded = 
+    DeclsLoaded.size() - std::count(DeclsLoaded.begin(), DeclsLoaded.end(),
+                                    (Decl *)0);
   unsigned NumIdentifiersLoaded = 0;
   for (unsigned I = 0; I < IdentifierData.size(); ++I) {
     if ((IdentifierData[I] & 0x01) == 0)
@@ -2729,14 +2727,14 @@ void PCHReader::PrintStats() {
       ++NumSelectorsLoaded;
   }
 
-  if (!TypeAlreadyLoaded.empty())
+  if (!TypesLoaded.empty())
     std::fprintf(stderr, "  %u/%u types read (%f%%)\n",
-                 NumTypesLoaded, (unsigned)TypeAlreadyLoaded.size(),
-                 ((float)NumTypesLoaded/TypeAlreadyLoaded.size() * 100));
-  if (!DeclAlreadyLoaded.empty())
+                 NumTypesLoaded, (unsigned)TypesLoaded.size(),
+                 ((float)NumTypesLoaded/TypesLoaded.size() * 100));
+  if (!DeclsLoaded.empty())
     std::fprintf(stderr, "  %u/%u declarations read (%f%%)\n",
-                 NumDeclsLoaded, (unsigned)DeclAlreadyLoaded.size(),
-                 ((float)NumDeclsLoaded/DeclAlreadyLoaded.size() * 100));
+                 NumDeclsLoaded, (unsigned)DeclsLoaded.size(),
+                 ((float)NumDeclsLoaded/DeclsLoaded.size() * 100));
   if (!IdentifierData.empty())
     std::fprintf(stderr, "  %u/%u identifiers read (%f%%)\n",
                  NumIdentifiersLoaded, (unsigned)IdentifierData.size(),
index 56c8296c949504fa2fd98f0122ca36554eb996be..91ddbf41826da55bd9bc97427e3b5603c8a9104b 100644 (file)
@@ -2270,6 +2270,8 @@ PCHWriter::PCHWriter(llvm::BitstreamWriter &Stream)
     NumVisibleDeclContexts(0) { }
 
 void PCHWriter::WritePCH(Sema &SemaRef) {
+  using namespace llvm;
+
   ASTContext &Context = SemaRef.Context;
   Preprocessor &PP = SemaRef.PP;
 
@@ -2315,7 +2317,7 @@ void PCHWriter::WritePCH(Sema &SemaRef) {
 
   // Write the remaining PCH contents.
   RecordData Record;
-  Stream.EnterSubblock(pch::PCH_BLOCK_ID, 3);
+  Stream.EnterSubblock(pch::PCH_BLOCK_ID, 4);
   WriteTargetTriple(Context.Target);
   WriteLanguageOptions(Context.getLangOptions());
   WriteSourceManagerBlock(Context.getSourceManager());
@@ -2324,8 +2326,32 @@ void PCHWriter::WritePCH(Sema &SemaRef) {
   WriteDeclsBlock(Context);
   WriteMethodPool(SemaRef);
   WriteIdentifierTable(PP);
-  Stream.EmitRecord(pch::TYPE_OFFSET, TypeOffsets);
-  Stream.EmitRecord(pch::DECL_OFFSET, DeclOffsets);
+
+  // Write the type offsets array
+  BitCodeAbbrev *Abbrev = new BitCodeAbbrev();
+  Abbrev->Add(BitCodeAbbrevOp(pch::TYPE_OFFSET));
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of types
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // types block
+  unsigned TypeOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
+  Record.clear();
+  Record.push_back(pch::TYPE_OFFSET);
+  Record.push_back(TypeOffsets.size());
+  Stream.EmitRecordWithBlob(TypeOffsetAbbrev, Record,
+                            (const char *)&TypeOffsets.front(), 
+                            TypeOffsets.size() * sizeof(uint64_t));
+  
+  // Write the declaration offsets array
+  Abbrev = new BitCodeAbbrev();
+  Abbrev->Add(BitCodeAbbrevOp(pch::DECL_OFFSET));
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // # of declarations
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // declarations block
+  unsigned DeclOffsetAbbrev = Stream.EmitAbbrev(Abbrev);
+  Record.clear();
+  Record.push_back(pch::DECL_OFFSET);
+  Record.push_back(DeclOffsets.size());
+  Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record,
+                            (const char *)&DeclOffsets.front(), 
+                            DeclOffsets.size() * sizeof(uint64_t));
 
   // Write the record of special types.
   Record.clear();