modocache created this revision.

`gcc -ftime-report` provides a breakdown of how much time GCC spends
doing preprocessing, parsing, template instantiation, and more:

  g++ -ftime-report foo.cpp
  Execution times (seconds)
   phase setup             :   0.00 ( 0%) usr   0.00 ( 0%) sys   0.00 ( 0%) 
wall    1414 kB ( 8%) ggc
   phase parsing           :   0.10 (100%) usr   0.08 (100%) sys   0.18 (95%) 
wall   15955 kB (88%) ggc
   phase opt and generate  :   0.00 ( 0%) usr   0.00 ( 0%) sys   0.01 ( 5%) 
wall     489 kB ( 3%) ggc
   |name lookup            :   0.00 ( 0%) usr   0.00 ( 0%) sys   0.04 (21%) 
wall    1054 kB ( 6%) ggc
   preprocessing           :   0.02 (20%) usr   0.01 (13%) sys   0.03 (16%) 
wall     896 kB ( 5%) ggc
   parser (global)         :   0.00 ( 0%) usr   0.03 (38%) sys   0.04 (21%) 
wall    6603 kB (37%) ggc
   parser struct body      :   0.04 (40%) usr   0.00 ( 0%) sys   0.04 (21%) 
wall    2791 kB (15%) ggc
   parser enumerator list  :   0.01 (10%) usr   0.00 ( 0%) sys   0.00 ( 0%) 
wall      44 kB ( 0%) ggc
   parser function body    :   0.00 ( 0%) usr   0.02 (25%) sys   0.02 (11%) 
wall    1047 kB ( 6%) ggc
   parser inl. meth. body  :   0.01 (10%) usr   0.01 (13%) sys   0.03 (16%) 
wall    1093 kB ( 6%) ggc
   template instantiation  :   0.02 (20%) usr   0.01 (12%) sys   0.02 (11%) 
wall    3280 kB (18%) ggc
   LRA non-specific        :   0.00 ( 0%) usr   0.00 ( 0%) sys   0.01 ( 5%) 
wall       0 kB ( 0%) ggc
   TOTAL                 :   0.10             0.08             0.19             
 18028 kB

`clang -ftime-report` gives an incredibly detailed breakdown of how long
each LLVM pass takes, but when it comes to front-end times, only
provides the generic "Clang front-end timer", or "Code Generation Time".
Here's an example of its output:
https://gist.github.com/modocache/d74833818107ed50d11387a5a4e3fb72

As a result, when attempting to diagnose slow compile times with Clang,
users are forced to use external profiling tools in order to determine
whether the bottleneck is in parsing, template instantiation, or LLVM.

This diff adds the first of several timers that aim to match
`gcc -ftime-report`: a timer that outputs the amount of time spent in the Clang
preprocessor.

I'm curious whether Clang maintainers think this timer is useful, and whether
there's interest in adding more timers, especially around the Clang parser.


https://reviews.llvm.org/D36492

Files:
  include/clang/Lex/Preprocessor.h
  include/clang/Lex/PreprocessorOptions.h
  lib/Frontend/CompilerInstance.cpp
  lib/Lex/PPDirectives.cpp
  lib/Lex/Preprocessor.cpp


Index: lib/Lex/Preprocessor.cpp
===================================================================
--- lib/Lex/Preprocessor.cpp
+++ lib/Lex/Preprocessor.cpp
@@ -88,6 +88,7 @@
       CurDirLookup(nullptr), CurLexerKind(CLK_Lexer),
       CurLexerSubmodule(nullptr), Callbacks(nullptr),
       CurSubmoduleState(&NullSubmoduleState), MacroArgCache(nullptr),
+      PreprocessingTimer("preprocessor", "Preprocessing"),
       Record(nullptr), MIChainHead(nullptr) {
   OwnsHeaderSearch = OwnsHeaders;
   
@@ -656,6 +657,8 @@
 
   IdentifierInfo &II = *Identifier.getIdentifierInfo();
 
+  llvm::TimeRegion(PPOpts->ShowTimers ? &PreprocessingTimer : nullptr);
+
   // If the information about this identifier is out of date, update it from
   // the external source.
   // We have to treat __VA_ARGS__ in a special way, since it gets
Index: lib/Lex/PPDirectives.cpp
===================================================================
--- lib/Lex/PPDirectives.cpp
+++ lib/Lex/PPDirectives.cpp
@@ -871,6 +871,8 @@
 /// lexer/preprocessor state, and advances the lexer(s) so that the next token
 /// read is the correct one.
 void Preprocessor::HandleDirective(Token &Result) {
+  llvm::TimeRegion(PPOpts->ShowTimers ? &PreprocessingTimer : nullptr);
+
   // FIXME: Traditional: # with whitespace before it not recognized by K&R?
 
   // We just parsed a # character at the start of a line, so we're in directive
Index: lib/Frontend/CompilerInstance.cpp
===================================================================
--- lib/Frontend/CompilerInstance.cpp
+++ lib/Frontend/CompilerInstance.cpp
@@ -367,7 +367,9 @@
 // Preprocessor
 
 void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
-  const PreprocessorOptions &PPOpts = getPreprocessorOpts();
+  PreprocessorOptions &PPOpts = getPreprocessorOpts();
+  if (getFrontendOpts().ShowTimers)
+    PPOpts.ShowTimers = true;
 
   // Create a PTH manager if we are using some form of a token cache.
   PTHManager *PTHMgr = nullptr;
Index: include/clang/Lex/PreprocessorOptions.h
===================================================================
--- include/clang/Lex/PreprocessorOptions.h
+++ include/clang/Lex/PreprocessorOptions.h
@@ -127,7 +127,11 @@
   /// manipulation of the compiler invocation object, in cases where the 
   /// compiler invocation and its buffers will be reused.
   bool RetainRemappedFileBuffers;
-  
+
+  /// \brief Whether to measure the amount of time spent in code related to
+  /// preprocessing. This flag defaults to false.
+  bool ShowTimers;
+
   /// \brief The Objective-C++ ARC standard library that we should support,
   /// by providing appropriate definitions to retrofit the standard library
   /// with support for lifetime-qualified pointers.
@@ -164,6 +168,7 @@
                           GeneratePreamble(false),
                           RemappedFilesKeepOriginalName(true),
                           RetainRemappedFileBuffers(false),
+                          ShowTimers(false),
                           ObjCXXARCStandardLibrary(ARCXX_nolib) { }
 
   void addMacroDef(StringRef Name) { Macros.emplace_back(Name, false); }
Index: include/clang/Lex/Preprocessor.h
===================================================================
--- include/clang/Lex/Preprocessor.h
+++ include/clang/Lex/Preprocessor.h
@@ -33,6 +33,7 @@
 #include "llvm/ADT/TinyPtrVector.h"
 #include "llvm/Support/Allocator.h"
 #include "llvm/Support/Registry.h"
+#include "llvm/Support/Timer.h"
 #include <memory>
 #include <vector>
 
@@ -624,6 +625,9 @@
   unsigned NumFastMacroExpanded, NumTokenPaste, NumFastTokenPaste;
   unsigned NumSkipped;
 
+  // A timer to keep track of how much time was spent on preprocessing.
+  llvm::Timer PreprocessingTimer;
+
   /// \brief The predefined macros that preprocessor should use from the
   /// command line etc.
   std::string Predefines;


Index: lib/Lex/Preprocessor.cpp
===================================================================
--- lib/Lex/Preprocessor.cpp
+++ lib/Lex/Preprocessor.cpp
@@ -88,6 +88,7 @@
       CurDirLookup(nullptr), CurLexerKind(CLK_Lexer),
       CurLexerSubmodule(nullptr), Callbacks(nullptr),
       CurSubmoduleState(&NullSubmoduleState), MacroArgCache(nullptr),
+      PreprocessingTimer("preprocessor", "Preprocessing"),
       Record(nullptr), MIChainHead(nullptr) {
   OwnsHeaderSearch = OwnsHeaders;
   
@@ -656,6 +657,8 @@
 
   IdentifierInfo &II = *Identifier.getIdentifierInfo();
 
+  llvm::TimeRegion(PPOpts->ShowTimers ? &PreprocessingTimer : nullptr);
+
   // If the information about this identifier is out of date, update it from
   // the external source.
   // We have to treat __VA_ARGS__ in a special way, since it gets
Index: lib/Lex/PPDirectives.cpp
===================================================================
--- lib/Lex/PPDirectives.cpp
+++ lib/Lex/PPDirectives.cpp
@@ -871,6 +871,8 @@
 /// lexer/preprocessor state, and advances the lexer(s) so that the next token
 /// read is the correct one.
 void Preprocessor::HandleDirective(Token &Result) {
+  llvm::TimeRegion(PPOpts->ShowTimers ? &PreprocessingTimer : nullptr);
+
   // FIXME: Traditional: # with whitespace before it not recognized by K&R?
 
   // We just parsed a # character at the start of a line, so we're in directive
Index: lib/Frontend/CompilerInstance.cpp
===================================================================
--- lib/Frontend/CompilerInstance.cpp
+++ lib/Frontend/CompilerInstance.cpp
@@ -367,7 +367,9 @@
 // Preprocessor
 
 void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
-  const PreprocessorOptions &PPOpts = getPreprocessorOpts();
+  PreprocessorOptions &PPOpts = getPreprocessorOpts();
+  if (getFrontendOpts().ShowTimers)
+    PPOpts.ShowTimers = true;
 
   // Create a PTH manager if we are using some form of a token cache.
   PTHManager *PTHMgr = nullptr;
Index: include/clang/Lex/PreprocessorOptions.h
===================================================================
--- include/clang/Lex/PreprocessorOptions.h
+++ include/clang/Lex/PreprocessorOptions.h
@@ -127,7 +127,11 @@
   /// manipulation of the compiler invocation object, in cases where the 
   /// compiler invocation and its buffers will be reused.
   bool RetainRemappedFileBuffers;
-  
+
+  /// \brief Whether to measure the amount of time spent in code related to
+  /// preprocessing. This flag defaults to false.
+  bool ShowTimers;
+
   /// \brief The Objective-C++ ARC standard library that we should support,
   /// by providing appropriate definitions to retrofit the standard library
   /// with support for lifetime-qualified pointers.
@@ -164,6 +168,7 @@
                           GeneratePreamble(false),
                           RemappedFilesKeepOriginalName(true),
                           RetainRemappedFileBuffers(false),
+                          ShowTimers(false),
                           ObjCXXARCStandardLibrary(ARCXX_nolib) { }
 
   void addMacroDef(StringRef Name) { Macros.emplace_back(Name, false); }
Index: include/clang/Lex/Preprocessor.h
===================================================================
--- include/clang/Lex/Preprocessor.h
+++ include/clang/Lex/Preprocessor.h
@@ -33,6 +33,7 @@
 #include "llvm/ADT/TinyPtrVector.h"
 #include "llvm/Support/Allocator.h"
 #include "llvm/Support/Registry.h"
+#include "llvm/Support/Timer.h"
 #include <memory>
 #include <vector>
 
@@ -624,6 +625,9 @@
   unsigned NumFastMacroExpanded, NumTokenPaste, NumFastTokenPaste;
   unsigned NumSkipped;
 
+  // A timer to keep track of how much time was spent on preprocessing.
+  llvm::Timer PreprocessingTimer;
+
   /// \brief The predefined macros that preprocessor should use from the
   /// command line etc.
   std::string Predefines;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to