]> granicus.if.org Git - clang/commitdiff
Lazy loading of builtins for precompiled headers.
authorDouglas Gregor <dgregor@apple.com>
Wed, 22 Apr 2009 18:49:13 +0000 (18:49 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 22 Apr 2009 18:49:13 +0000 (18:49 +0000)
PCH files now contain complete information about builtins, including
any declarations that have been synthesized as part of building the
PCH file. When using a PCH file, we do not initialize builtins at all;
when needed, they'll be found in the PCH file.

This optimization translations into a 9% speedup for "Hello, World!"
with Carbon.h as a prefix header and roughly a 5% speedup for 403.gcc
with its prefix header. We're also reading less of the PCH file for
"Hello, World!":

*** PCH Statistics:
  286/20693 types read (1.382110%)
  1630/59230 declarations read (2.751984%)
  764/44914 identifiers read (1.701029%)
  1/32954 statements read (0.003035%)
  5/6187 macros read (0.080815%)

down from

*** 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@69815 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/ASTContext.h
include/clang/AST/Builtins.h
include/clang/Frontend/PCHWriter.h
lib/AST/ASTContext.cpp
lib/AST/Builtins.cpp
lib/Frontend/PCHReader.cpp
lib/Frontend/PCHWriter.cpp
tools/clang-cc/clang-cc.cpp

index 2be3689bc0182f33e8a9f2179d280c69f8b07425..bba9cfb4006bb039af89486fea2a65a6dfc57ea9 100644 (file)
@@ -170,6 +170,8 @@ public:
   /// This is intentionally not serialized.  It is populated by the
   /// ASTContext ctor, and there are no external pointers/references to
   /// internal variables of BuiltinInfo.
+  // FIXME: PCH does serialize this information, so that we don't have to
+  // construct it again when the PCH is loaded.
   Builtin::Context BuiltinInfo;
 
   // Builtin Types.
@@ -188,10 +190,20 @@ public:
 
   ASTContext(const LangOptions& LOpts, SourceManager &SM, TargetInfo &t,
              IdentifierTable &idents, SelectorTable &sels, 
-             bool FreeMemory = true, unsigned size_reserve=0);
+             bool FreeMemory = true, unsigned size_reserve=0,
+             bool InitializeBuiltins = true);
 
   ~ASTContext();
 
+  /// \brief Initialize builtins.
+  ///
+  /// Typically, this routine will be called automatically by the
+  /// constructor. However, in certain cases (e.g., when there is a
+  /// PCH file to be loaded), the constructor does not perform
+  /// initialization for builtins. This routine can be called to
+  /// perform the initialization.
+  void InitializeBuiltins(IdentifierTable &idents);
+
   /// \brief Attach an external AST source to the AST context.
   ///
   /// The external AST source provides the ability to load parts of
index 9216029860d652ca987730b1fef7591c1cdbc2e8..b16d3bf34139d10afc5142d4189af53b1a8e33cc 100644 (file)
@@ -17,6 +17,7 @@
 
 #include <cstring>
 #include <string>
+#include "llvm/ADT/SmallVector.h"
 
 namespace clang {
   class TargetInfo;
@@ -60,6 +61,10 @@ public:
   /// appropriate builtin ID # and mark any non-portable builtin identifiers as
   /// such.
   void InitializeBuiltins(IdentifierTable &Table, bool NoBuiltins = false);
+
+  /// \brief Popular the vector with the names of all of the builtins.
+  void GetBuiltinNames(llvm::SmallVectorImpl<const char *> &Names,
+                       bool NoBuiltins);
   
   /// Builtin::GetName - Return the identifier name for the specified builtin,
   /// e.g. "__builtin_abs".
index 2db253e7ddbb76990a2398eee464953478a4514e..d721f1077f326ac24f8c84193c25ad11ff63f024 100644 (file)
@@ -171,6 +171,10 @@ public:
   /// \brief Emit a reference to an identifier
   void AddIdentifierRef(const IdentifierInfo *II, RecordData &Record);
 
+  /// \brief Get the unique number used to refer to the given
+  /// identifier.
+  pch::IdentID getIdentifierRef(const IdentifierInfo *II);
+
   /// \brief Retrieve the offset of the macro definition for the given
   /// identifier.
   ///
index 7d3c119d57a50770eea589e3dc0a882276081a8f..159110a0800d6c19c28dfb4a15957eab39b132df 100644 (file)
@@ -34,16 +34,17 @@ enum FloatingRank {
 ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM,
                        TargetInfo &t,
                        IdentifierTable &idents, SelectorTable &sels,
-                       bool FreeMem, unsigned size_reserve) : 
+                       bool FreeMem, unsigned size_reserve,
+                       bool InitializeBuiltins) : 
   GlobalNestedNameSpecifier(0), CFConstantStringTypeDecl(0), 
   ObjCFastEnumerationStateTypeDecl(0), SourceMgr(SM), LangOpts(LOpts), 
   FreeMemory(FreeMem), Target(t), Idents(idents), Selectors(sels),
   ExternalSource(0) {  
   if (size_reserve > 0) Types.reserve(size_reserve);    
   InitBuiltinTypes();
-  BuiltinInfo.InitializeTargetBuiltins(Target);
-  BuiltinInfo.InitializeBuiltins(idents, LangOpts.NoBuiltin);
   TUDecl = TranslationUnitDecl::Create(*this);
+  if (InitializeBuiltins)
+    this->InitializeBuiltins(idents);
 }
 
 ASTContext::~ASTContext() {
@@ -94,6 +95,11 @@ ASTContext::~ASTContext() {
   TUDecl->Destroy(*this);
 }
 
+void ASTContext::InitializeBuiltins(IdentifierTable &idents) {
+  BuiltinInfo.InitializeTargetBuiltins(Target);
+  BuiltinInfo.InitializeBuiltins(idents, LangOpts.NoBuiltin);
+}
+
 void 
 ASTContext::setExternalSource(llvm::OwningPtr<ExternalASTSource> &Source) {
   ExternalSource.reset(Source.take());
index ece9eeed76777a67eb53159f208fb2985e17aef7..3e1b3dc2a1f657e3a51285b9546d1be1418ac4d2 100644 (file)
@@ -58,6 +58,24 @@ void Builtin::Context::InitializeBuiltins(IdentifierTable &Table,
       Table.get(TSRecords[i].Name).setBuiltinID(i+Builtin::FirstTSBuiltin);
 }
 
+void 
+Builtin::Context::GetBuiltinNames(llvm::SmallVectorImpl<const char *> &Names,
+                                  bool NoBuiltins) {
+  // Final all target-independent names
+  for (unsigned i = Builtin::NotBuiltin+1; i != Builtin::FirstTSBuiltin; ++i)
+    if (!BuiltinInfo[i].Suppressed &&
+        (!NoBuiltins || !strchr(BuiltinInfo[i].Attributes, 'f')))
+      Names.push_back(BuiltinInfo[i].Name);
+  
+  // Find target-specific names.
+  for (unsigned i = 0, e = NumTSRecords; i != e; ++i)
+    if (!TSRecords[i].Suppressed &&
+        (!NoBuiltins || 
+         (TSRecords[i].Attributes && 
+          !strchr(TSRecords[i].Attributes, 'f'))))
+      Names.push_back(TSRecords[i].Name);
+}
+
 bool 
 Builtin::Context::isPrintfLike(unsigned ID, unsigned &FormatIdx, 
                                bool &HasVAListArg) {
index 031b71fbac67b5d80f26041e6006d6ac74e5f209..976b98dd11cf01521440f53d70b4fc062d3b6933 100644 (file)
@@ -1110,10 +1110,21 @@ public:
                            unsigned DataLen) {
     using namespace clang::io;
     uint32_t Bits = ReadUnalignedLE32(d); // FIXME: use these?
-    (void)Bits;
-    bool hasMacroDefinition = (Bits >> 3) & 0x01;
-    
+    bool CPlusPlusOperatorKeyword = Bits & 0x01;
+    Bits >>= 1;
+    bool Poisoned = Bits & 0x01;
+    Bits >>= 1;
+    bool ExtensionToken = Bits & 0x01;
+    Bits >>= 1;
+    bool hasMacroDefinition = Bits & 0x01;
+    Bits >>= 1;
+    unsigned ObjCOrBuiltinID = Bits & 0x3FF;
+    Bits >>= 10;
+    unsigned TokenID = Bits & 0xFF;
+    Bits >>= 8;
+
     pch::IdentID ID = ReadUnalignedLE32(d);
+    assert(Bits == 0 && "Extra bits in the identifier?");
     DataLen -= 8;
 
     // Build the IdentifierInfo itself and link the identifier ID with
@@ -1124,6 +1135,20 @@ public:
                                                  k.first, k.first + k.second);
     Reader.SetIdentifierInfo(ID, II);
 
+    // Set or check the various bits in the IdentifierInfo structure.
+    // FIXME: Load token IDs lazily, too?
+    assert((unsigned)II->getTokenID() == TokenID && 
+           "Incorrect token ID loaded"); 
+    (void)TokenID;
+    II->setObjCOrBuiltinID(ObjCOrBuiltinID);
+    assert(II->isExtensionToken() == ExtensionToken && 
+           "Incorrect extension token flag");
+    (void)ExtensionToken;
+    II->setIsPoisoned(Poisoned);
+    assert(II->isCPlusPlusOperatorKeyword() == CPlusPlusOperatorKeyword &&
+           "Incorrect C++ operator keyword flag");
+    (void)CPlusPlusOperatorKeyword;
+
     // If this identifier is a macro, deserialize the macro
     // definition.
     if (hasMacroDefinition) {
index f34323c1604c71d1d589ab712d99ceb7ecfc121f..15ee2369dd3bd43f357da9328f22702cf631b8be 100644 (file)
@@ -1800,8 +1800,8 @@ public:
       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) | hasMacroDefinition;
+    Bits = (Bits << 10) | (uint32_t)II->getObjCOrBuiltinID();
+    Bits = (Bits << 1) | hasMacroDefinition;
     Bits = (Bits << 1) | II->isExtensionToken();
     Bits = (Bits << 1) | II->isPoisoned();
     Bits = (Bits << 1) | II->isCPlusPlusOperatorKeyword();
@@ -2028,6 +2028,17 @@ void PCHWriter::WritePCH(Sema &SemaRef) {
   DeclIDs[Context.getTranslationUnitDecl()] = 1;
   DeclsToEmit.push(Context.getTranslationUnitDecl());
 
+  // Make sure that we emit IdentifierInfos (and any attached
+  // declarations) for builtins.
+  {
+    IdentifierTable &Table = PP.getIdentifierTable();
+    llvm::SmallVector<const char *, 32> BuiltinNames;
+    Context.BuiltinInfo.GetBuiltinNames(BuiltinNames,
+                                        Context.getLangOptions().NoBuiltin);
+    for (unsigned I = 0, N = BuiltinNames.size(); I != N; ++I)
+      getIdentifierRef(&Table.get(BuiltinNames[I]));
+  }
+
   // Write the remaining PCH contents.
   RecordData Record;
   Stream.EnterSubblock(pch::PCH_BLOCK_ID, 3);
@@ -2079,16 +2090,17 @@ void PCHWriter::AddAPFloat(const llvm::APFloat &Value, RecordData &Record) {
 }
 
 void PCHWriter::AddIdentifierRef(const IdentifierInfo *II, RecordData &Record) {
-  if (II == 0) {
-    Record.push_back(0);
-    return;
-  }
+  Record.push_back(getIdentifierRef(II));
+}
+
+pch::IdentID PCHWriter::getIdentifierRef(const IdentifierInfo *II) {
+  if (II == 0)
+    return 0;
 
   pch::IdentID &ID = IdentifierIDs[II];
   if (ID == 0)
     ID = IdentifierIDs.size();
-  
-  Record.push_back(ID);
+  return ID;
 }
 
 void PCHWriter::AddTypeRef(QualType T, RecordData &Record) {
index 4f2ab2b7463db1e03b2d57810777cbec6005b17e..37233134dadb3c66c89a07295adba6e84e57c754 100644 (file)
@@ -1760,7 +1760,9 @@ static void ProcessInputFile(Preprocessor &PP, PreprocessorFactory &PPF,
                                       PP.getTargetInfo(),
                                       PP.getIdentifierTable(),
                                       PP.getSelectorTable(),
-                                      /* FreeMemory = */ !DisableFree));
+                                      /* FreeMemory = */ !DisableFree,
+                                      /* size_reserve = */0,
+                       /* InitializeBuiltins = */ImplicitIncludePCH.empty()));
     
     if (!ImplicitIncludePCH.empty()) {
       // The user has asked us to include a precompiled header. Load
@@ -1788,6 +1790,11 @@ static void ProcessInputFile(Preprocessor &PP, PreprocessorFactory &PPF,
       case PCHReader::IgnorePCH:
         // No suitable PCH file could be found. Just ignore the
         // -include-pch option entirely.
+        
+        // We delayed the initialization of builtins in the hope of
+        // loading the PCH file. Since the PCH file could not be
+        // loaded, initialize builtins now.
+        ContextOwner->InitializeBuiltins(PP.getIdentifierTable());
         break;
       }