[cfe-commits] r70059 - in /cfe/trunk: include/clang/Frontend/PCHReader.h lib/Frontend/PCHReader.cpp lib/Frontend/PCHWriter.cpp

Douglas Gregor dgregor at apple.com
Sat Apr 25 11:35:21 PDT 2009


Author: dgregor
Date: Sat Apr 25 13:35:21 2009
New Revision: 70059

URL: http://llvm.org/viewvc/llvm-project?rev=70059&view=rev
Log:
Write the declaration and type offset arrays into the bitstream as
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!".


Modified:
    cfe/trunk/include/clang/Frontend/PCHReader.h
    cfe/trunk/lib/Frontend/PCHReader.cpp
    cfe/trunk/lib/Frontend/PCHWriter.cpp

Modified: cfe/trunk/include/clang/Frontend/PCHReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHReader.h?rev=70059&r1=70058&r2=70059&view=diff

==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHReader.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHReader.h Sat Apr 25 13:35:21 2009
@@ -94,32 +94,23 @@
 
   /// \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.
+  /// \brief Declarations that have already been loaded from the PCH file.
   ///
-  /// 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.
-  ///
-  /// 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;

Modified: cfe/trunk/lib/Frontend/PCHReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReader.cpp?rev=70059&r1=70058&r2=70059&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReader.cpp Sat Apr 25 13:35:21 2009
@@ -1802,21 +1802,21 @@
       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 @@
 /// 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 @@
   }
 
   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::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 @@
       ++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(),

Modified: cfe/trunk/lib/Frontend/PCHWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriter.cpp?rev=70059&r1=70058&r2=70059&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriter.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriter.cpp Sat Apr 25 13:35:21 2009
@@ -2270,6 +2270,8 @@
     NumVisibleDeclContexts(0) { }
 
 void PCHWriter::WritePCH(Sema &SemaRef) {
+  using namespace llvm;
+
   ASTContext &Context = SemaRef.Context;
   Preprocessor &PP = SemaRef.PP;
 
@@ -2315,7 +2317,7 @@
 
   // 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 @@
   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();





More information about the cfe-commits mailing list