avt77 updated this revision to Diff 142198.
avt77 added a reviewer: davezarzycki.
avt77 added a comment.
Herald added a subscriber: mgorny.

I removed the dependence on TimePassesIsEnabled (as @davezarzycki sugested) and 
fixed the issue with failed test (tnx to @russell.gallop). As result the patch 
was redesigned.


https://reviews.llvm.org/D43578

Files:
  include/clang/Frontend/FrontendAction.h
  include/clang/Frontend/Utils.h
  include/clang/Lex/HeaderSearch.h
  include/clang/Parse/Parser.h
  include/clang/Sema/Sema.h
  lib/Basic/CMakeLists.txt
  lib/CodeGen/BackendUtil.cpp
  lib/CodeGen/CodeGenAction.cpp
  lib/Frontend/ASTMerge.cpp
  lib/Frontend/CompilerInstance.cpp
  lib/Frontend/FrontendActions.cpp
  lib/Lex/HeaderSearch.cpp
  lib/Lex/PPMacroExpansion.cpp
  lib/Lex/Pragma.cpp
  lib/Parse/ParseTemplate.cpp
  lib/Parse/Parser.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaChecking.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaExpr.cpp
  lib/Sema/SemaTemplate.cpp
  test/Frontend/ftime-report-template-decl.cpp

Index: test/Frontend/ftime-report-template-decl.cpp
===================================================================
--- test/Frontend/ftime-report-template-decl.cpp
+++ test/Frontend/ftime-report-template-decl.cpp
@@ -0,0 +1,161 @@
+// RUN: %clang %s -S -o - -ftime-report  2>&1 | FileCheck %s
+// RUN: %clang %s -S -o - -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING -ftime-report  2>&1 | FileCheck %s
+
+// Template function declarations
+template <typename T>
+void foo();
+template <typename T, typename U>
+void foo();
+
+// Template function definitions.
+template <typename T>
+void foo() {}
+
+// Template class (forward) declarations
+template <typename T>
+struct A;
+template <typename T, typename U>
+struct b;
+template <typename>
+struct C;
+template <typename, typename>
+struct D;
+
+// Forward declarations with default parameters?
+template <typename T = int>
+class X1;
+template <typename = int>
+class X2;
+
+// Forward declarations w/template template parameters
+template <template <typename> class T>
+class TTP1;
+template <template <typename> class>
+class TTP2;
+template <template <typename X, typename Y> class T>
+class TTP5;
+
+// Forward declarations with non-type params
+template <int>
+class NTP0;
+template <int N>
+class NTP1;
+template <int N = 5>
+class NTP2;
+template <int = 10>
+class NTP3;
+template <unsigned int N = 12u>
+class NTP4;
+template <unsigned int = 12u>
+class NTP5;
+template <unsigned = 15u>
+class NTP6;
+template <typename T, T Obj>
+class NTP7;
+
+// Template class declarations
+template <typename T>
+struct A {};
+template <typename T, typename U>
+struct B {};
+
+namespace PR6184 {
+namespace N {
+template <typename T>
+void bar(typename T::x);
+}
+
+template <typename T>
+void N::bar(typename T::x) {}
+}
+
+// This PR occurred only in template parsing mode.
+namespace PR17637 {
+template <int>
+struct L {
+  template <typename T>
+  struct O {
+    template <typename U>
+    static void Fun(U);
+  };
+};
+
+template <int k>
+template <typename T>
+template <typename U>
+void L<k>::O<T>::Fun(U) {}
+
+void Instantiate() { L<0>::O<int>::Fun(0); }
+}
+
+namespace explicit_partial_specializations {
+typedef char (&oneT)[1];
+typedef char (&twoT)[2];
+typedef char (&threeT)[3];
+typedef char (&fourT)[4];
+typedef char (&fiveT)[5];
+typedef char (&sixT)[6];
+
+char one[1];
+char two[2];
+char three[3];
+char four[4];
+char five[5];
+char six[6];
+
+template <bool b>
+struct bool_ { typedef int type; };
+template <>
+struct bool_<false> {};
+
+#define XCAT(x, y) x##y
+#define CAT(x, y) XCAT(x, y)
+#define sassert(_b_) bool_<(_b_)>::type CAT(var, __LINE__);
+
+template <int>
+struct L {
+  template <typename T>
+  struct O {
+    template <typename U>
+    static oneT Fun(U);
+  };
+};
+template <int k>
+template <typename T>
+template <typename U>
+oneT L<k>::O<T>::Fun(U) { return one; }
+
+template <>
+template <>
+template <typename U>
+oneT L<0>::O<char>::Fun(U) { return one; }
+
+void Instantiate() {
+  sassert(sizeof(L<0>::O<int>::Fun(0)) == sizeof(one));
+  sassert(sizeof(L<0>::O<char>::Fun(0)) == sizeof(one));
+}
+}
+
+template <class>
+struct Foo {
+  template <class _Other>
+  using rebind_alloc = _Other;
+};
+template <class _Alloc>
+struct _Wrap_alloc {
+  template <class _Other>
+  using rebind_alloc = typename Foo<_Alloc>::template rebind_alloc<_Other>;
+  template <class>
+  using rebind = _Wrap_alloc;
+};
+_Wrap_alloc<int>::rebind<int> w;
+
+// CHECK:   ===== Clang Parser =====
+// CHECK:   ---User Time---
+// CHECK:   Parse Top Level Decl
+// CHECK:   Parse Template
+// CHECK:   Parse Function Definition
+// CHECK:   PP Append Macro
+// CHECK:   Scope manipulation
+// CHECK:   PP Find Handler
+// CHECK:   Total
Index: lib/Sema/SemaTemplate.cpp
===================================================================
--- lib/Sema/SemaTemplate.cpp
+++ lib/Sema/SemaTemplate.cpp
@@ -22,6 +22,7 @@
 #include "clang/Basic/LangOptions.h"
 #include "clang/Basic/PartialDiagnostic.h"
 #include "clang/Basic/TargetInfo.h"
+#include "clang/Frontend/Utils.h"
 #include "clang/Sema/DeclSpec.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/ParsedTemplate.h"
@@ -32,6 +33,7 @@
 #include "llvm/ADT/SmallBitVector.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/ManagedStatic.h"
 
 #include <iterator>
 using namespace clang;
@@ -187,7 +189,6 @@
   }
 
   QualType ObjectType = ObjectTypePtr.get();
-
   LookupResult R(*this, TName, Name.getLocStart(), LookupOrdinaryName);
   LookupTemplateName(R, S, SS, ObjectType, EnteringContext,
                      MemberOfUnknownSpecialization);
@@ -298,11 +299,16 @@
   return true;
 }
 
+static llvm::ManagedStatic<llvm::Timer> LTNTimer;
+static int LTNTimerLevel = 0;
+
 void Sema::LookupTemplateName(LookupResult &Found,
                               Scope *S, CXXScopeSpec &SS,
                               QualType ObjectType,
                               bool EnteringContext,
                               bool &MemberOfUnknownSpecialization) {
+  FrontendTimeRAII T(&*LTNTimer, &LTNTimerLevel, "ltntimer",
+                     "Lookup Template Name Time");
   // Determine where to perform name lookup
   MemberOfUnknownSpecialization = false;
   DeclContext *LookupCtx = nullptr;
@@ -543,6 +549,9 @@
                                  const DeclarationNameInfo &NameInfo,
                                  bool isAddressOfOperand,
                            const TemplateArgumentListInfo *TemplateArgs) {
+  llvm::NamedRegionTimer T("actondependent", "Act On Dependent Id Expression",
+                           GroupName, GroupDescription,
+                           clang::FrontendTimesIsEnabled);
   DeclContext *DC = getFunctionLevelDeclContext();
 
   // C++11 [expr.prim.general]p12:
@@ -4049,7 +4058,6 @@
   LookupResult R(*this, NameInfo, LookupOrdinaryName);
   LookupTemplateName(R, (Scope*)nullptr, SS, QualType(), /*Entering*/ false,
                      MemberOfUnknownSpecialization);
-
   if (R.isAmbiguous())
     return ExprError();
 
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -29,6 +29,7 @@
 #include "clang/Basic/PartialDiagnostic.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TargetInfo.h"
+#include "clang/Frontend/Utils.h"
 #include "clang/Lex/LiteralSupport.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Sema/AnalysisBasedWarnings.h"
@@ -1308,6 +1309,10 @@
                                 Expr *ControllingExpr,
                                 ArrayRef<ParsedType> ArgTypes,
                                 ArrayRef<Expr *> ArgExprs) {
+  llvm::NamedRegionTimer T("actongenericselection",
+                           "Act On Generic Selection Expr", GroupName,
+                           GroupDescription, clang::FrontendTimesIsEnabled);
+
   unsigned NumAssocs = ArgTypes.size();
   assert(NumAssocs == ArgExprs.size());
 
@@ -1520,6 +1525,9 @@
 ExprResult
 Sema::ActOnStringLiteral(ArrayRef<Token> StringToks, Scope *UDLScope) {
   assert(!StringToks.empty() && "Must have at least one string!");
+  llvm::NamedRegionTimer T("actonstringliteral", "Act On String Literal",
+                           GroupName, GroupDescription,
+                           clang::FrontendTimesIsEnabled);
 
   StringLiteralParser Literal(StringToks, PP);
   if (Literal.hadError)
@@ -2027,6 +2035,8 @@
                         bool IsInlineAsmIdentifier, Token *KeywordReplacement) {
   assert(!(IsAddressOfOperand && HasTrailingLParen) &&
          "cannot be direct & operand and have a trailing lparen");
+  llvm::NamedRegionTimer T("actonid", "Act On Id Expression", GroupName,
+                           GroupDescription, clang::FrontendTimesIsEnabled);
   if (SS.isInvalid())
     return ExprError();
 
@@ -3063,6 +3073,10 @@
 }
 
 ExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind) {
+  llvm::NamedRegionTimer T("actonpredefined", "Act On Predefined Expr",
+                           GroupName, GroupDescription,
+                           clang::FrontendTimesIsEnabled);
+
   PredefinedExpr::IdentType IT;
 
   switch (Kind) {
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -28,6 +28,7 @@
 #include "clang/Basic/PartialDiagnostic.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TargetInfo.h"
+#include "clang/Frontend/Utils.h"
 #include "clang/Lex/HeaderSearch.h" // TODO: Sema shouldn't depend on Lex
 #include "clang/Lex/Lexer.h" // TODO: Extract static functions to fix layering.
 #include "clang/Lex/ModuleLoader.h" // TODO: Sema shouldn't depend on Lex
@@ -849,6 +850,8 @@
                    SourceLocation NameLoc, const Token &NextToken,
                    bool IsAddressOfOperand,
                    std::unique_ptr<CorrectionCandidateCallback> CCC) {
+  llvm::NamedRegionTimer T("classifyname", "Classify Name", GroupName,
+                           GroupDescription, clang::FrontendTimesIsEnabled);
   DeclarationNameInfo NameInfo(Name, NameLoc);
   ObjCMethodDecl *CurMethod = getCurMethodDecl();
 
@@ -5321,6 +5324,8 @@
 
 NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
                                   MultiTemplateParamsArg TemplateParamLists) {
+  llvm::NamedRegionTimer T("handledeclarator", "Handle Declarator", GroupName,
+                           GroupDescription, clang::FrontendTimesIsEnabled);
   // TODO: consider using NameInfo for diagnostic.
   DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
   DeclarationName Name = NameInfo.getName();
Index: lib/Sema/SemaChecking.cpp
===================================================================
--- lib/Sema/SemaChecking.cpp
+++ lib/Sema/SemaChecking.cpp
@@ -52,6 +52,7 @@
 #include "clang/Basic/TargetCXXABI.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Basic/TypeTraits.h"
+#include "clang/Frontend/Utils.h"
 #include "clang/Lex/Lexer.h" // TODO: Extract static functions to fix layering.
 #include "clang/Sema/Initialization.h"
 #include "clang/Sema/Lookup.h"
@@ -491,6 +492,9 @@
 ///                    void (^block)(local void*, ...),
 ///                    uint size0, ...)
 static bool SemaOpenCLBuiltinEnqueueKernel(Sema &S, CallExpr *TheCall) {
+  llvm::NamedRegionTimer T(
+      "semaopenclbuiltin", "Sema OpenCL Builtin Enqueue Kernel",
+      Sema::GroupName, Sema::GroupDescription, clang::FrontendTimesIsEnabled);
   unsigned NumArgs = TheCall->getNumArgs();
 
   if (NumArgs < 4) {
@@ -853,6 +857,9 @@
 ExprResult
 Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
                                CallExpr *TheCall) {
+  llvm::NamedRegionTimer T("checkbuiltinfunction",
+                           "Check Builtin Function Call", GroupName,
+                           GroupDescription, clang::FrontendTimesIsEnabled);
   ExprResult TheCallResult(TheCall);
 
   // Find out if any arguments are required to be integer constant expressions.
@@ -2309,6 +2316,9 @@
 }
 
 bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
+  llvm::NamedRegionTimer T("checkx86builtin", "Check X86 Builtin Function Call",
+                           GroupName, GroupDescription,
+                           clang::FrontendTimesIsEnabled);
   if (BuiltinID == X86::BI__builtin_cpu_supports)
     return SemaBuiltinCpuSupports(*this, TheCall);
 
@@ -2750,6 +2760,8 @@
                      const Expr *ThisArg, ArrayRef<const Expr *> Args,
                      bool IsMemberFunction, SourceLocation Loc,
                      SourceRange Range, VariadicCallType CallType) {
+  llvm::NamedRegionTimer T("checkcall", "Check Call", GroupName,
+                           GroupDescription, clang::FrontendTimesIsEnabled);
   // FIXME: We should check as much as we can in the template definition.
   if (CurContext->isDependentContext())
     return;
@@ -3388,6 +3400,10 @@
 /// builtins,
 ExprResult
 Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
+  llvm::NamedRegionTimer T("semabuiltinatomic",
+                           "Sema Builtin Atomic Overloaded", GroupName,
+                           GroupDescription, clang::FrontendTimesIsEnabled);
+
   CallExpr *TheCall = (CallExpr *)TheCallResult.get();
   DeclRefExpr *DRE =cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts());
   FunctionDecl *FDecl = cast<FunctionDecl>(DRE->getDecl());
@@ -9575,6 +9591,9 @@
 static void
 CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC,
                         bool *ICContext = nullptr) {
+  llvm::NamedRegionTimer NRT("checkimplicit", "Check Implicit Conversion",
+                             Sema::GroupName, Sema::GroupDescription,
+                             clang::FrontendTimesIsEnabled);
   if (E->isTypeDependent() || E->isValueDependent()) return;
 
   const Type *Source = S.Context.getCanonicalType(E->getType()).getTypePtr();
Index: lib/Sema/Sema.cpp
===================================================================
--- lib/Sema/Sema.cpp
+++ lib/Sema/Sema.cpp
@@ -24,6 +24,7 @@
 #include "clang/Basic/DiagnosticOptions.h"
 #include "clang/Basic/PartialDiagnostic.h"
 #include "clang/Basic/TargetInfo.h"
+#include "clang/Frontend/Utils.h"
 #include "clang/Lex/HeaderSearch.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Sema/CXXFieldCollector.h"
@@ -842,6 +843,9 @@
 /// translation unit when EOF is reached and all but the top-level scope is
 /// popped.
 void Sema::ActOnEndOfTranslationUnit() {
+  llvm::NamedRegionTimer T(
+      "actoneou1", "Act On End Of Translation Unit: Common case", GroupName,
+      GroupDescription, clang::FrontendTimesIsEnabled);
   assert(DelayedDiagnostics.getCurrentPool() == nullptr
          && "reached end of translation unit with a pool attached?");
 
@@ -867,6 +871,9 @@
   // Complete translation units and modules define vtables and perform implicit
   // instantiations. PCH files do not.
   if (TUKind != TU_Prefix) {
+    llvm::NamedRegionTimer T(
+        "actoneou2", "Act On End Of Translation Unit: TUKind != TU_Prefix",
+        GroupName, GroupDescription, clang::FrontendTimesIsEnabled);
     DiagnoseUseOfUnimplementedSelectors();
 
     // If DefinedUsedVTables ends up marking any virtual member functions it
@@ -929,6 +936,9 @@
       UnusedFileScopedDecls.end());
 
   if (TUKind == TU_Prefix) {
+    llvm::NamedRegionTimer T(
+        "actoneou3", "Act On End Of Translation Unit: TUKind == TU_Prefix",
+        GroupName, GroupDescription, clang::FrontendTimesIsEnabled);
     // Translation unit prefixes don't need any of the checking below.
     if (!PP.isIncrementalProcessingEnabled())
       TUScope = nullptr;
@@ -963,6 +973,9 @@
   }
 
   if (TUKind == TU_Module) {
+    llvm::NamedRegionTimer T(
+        "actoneou4", "Act On End Of Translation Unit: TUKind == TU_Module",
+        GroupName, GroupDescription, clang::FrontendTimesIsEnabled);
     // If we are building a module interface unit, we need to have seen the
     // module declaration by now.
     if (getLangOpts().getCompilingModule() ==
@@ -1557,6 +1570,9 @@
 ///  name, this parameter is populated with the decls of the various overloads.
 bool Sema::tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy,
                          UnresolvedSetImpl &OverloadSet) {
+  llvm::NamedRegionTimer T("tryascall", "Try Expr As Call", GroupName,
+                           GroupDescription, clang::FrontendTimesIsEnabled);
+
   ZeroArgCallReturnTy = QualType();
   OverloadSet.clear();
 
@@ -1719,6 +1735,9 @@
 bool Sema::tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD,
                                 bool ForceComplain,
                                 bool (*IsPlausibleResult)(QualType)) {
+  llvm::NamedRegionTimer T("trytorecover", "Try To Recover With Call",
+                           GroupName, GroupDescription,
+                           clang::FrontendTimesIsEnabled);
   SourceLocation Loc = E.get()->getExprLoc();
   SourceRange Range = E.get()->getSourceRange();
 
Index: lib/Parse/Parser.cpp
===================================================================
--- lib/Parse/Parser.cpp
+++ lib/Parse/Parser.cpp
@@ -15,6 +15,7 @@
 #include "clang/AST/ASTConsumer.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclTemplate.h"
+#include "clang/Frontend/Utils.h"
 #include "clang/Parse/ParseDiagnostic.h"
 #include "clang/Parse/RAIIObjectsForParser.h"
 #include "clang/Sema/DeclSpec.h"
@@ -368,6 +369,8 @@
 /// ExitScope - Pop a scope off the scope stack.
 void Parser::ExitScope() {
   assert(getCurScope() && "Scope imbalance!");
+  llvm::NamedRegionTimer NRT("clangscope", "Scope manipulation", GroupName,
+                             GroupDescription, clang::FrontendTimesIsEnabled);
 
   // Inform the actions module that this scope is going away if there are any
   // decls in it.
@@ -543,6 +546,9 @@
 /// ParseTopLevelDecl - Parse one top-level declaration, return whatever the
 /// action tells us to.  This returns true if the EOF was encountered.
 bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) {
+  llvm::NamedRegionTimer NRT("parsetopleveldecl", "Parse Top Level Decl",
+                             GroupName, GroupDescription,
+                             clang::FrontendTimesIsEnabled);
   DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(TemplateIds);
 
   // Skip over the EOF token, flagging end of previous input for incremental
@@ -1046,6 +1052,9 @@
 Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
                                       const ParsedTemplateInfo &TemplateInfo,
                                       LateParsedAttrList *LateParsedAttrs) {
+  llvm::NamedRegionTimer NRT("parsefdef", "Parse Function Definition",
+                             GroupName, GroupDescription,
+                             clang::FrontendTimesIsEnabled);
   // Poison SEH identifiers so they are flagged as illegal in function bodies.
   PoisonSEHIdentifiersRAIIObject PoisonSEHIdentifiers(*this, true);
   const DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
@@ -1922,6 +1931,9 @@
 
 SourceLocation Parser::handleUnexpectedCodeCompletionToken() {
   assert(Tok.is(tok::code_completion));
+  llvm::NamedRegionTimer NRT("codecompletion", "Code completion operations",
+                             GroupName, GroupDescription,
+                             clang::FrontendTimesIsEnabled);
   PrevTokLocation = Tok.getLocation();
 
   for (Scope *S = getCurScope(); S; S = S->getParent()) {
@@ -1947,29 +1959,47 @@
 // Code-completion pass-through functions
 
 void Parser::CodeCompleteDirective(bool InConditional) {
+  llvm::NamedRegionTimer NRT("codecompletion", "Code completion operations",
+                             GroupName, GroupDescription,
+                             clang::FrontendTimesIsEnabled);
   Actions.CodeCompletePreprocessorDirective(InConditional);
 }
 
 void Parser::CodeCompleteInConditionalExclusion() {
+  llvm::NamedRegionTimer NRT("codecompletion", "Code completion operations",
+                             GroupName, GroupDescription,
+                             clang::FrontendTimesIsEnabled);
   Actions.CodeCompleteInPreprocessorConditionalExclusion(getCurScope());
 }
 
 void Parser::CodeCompleteMacroName(bool IsDefinition) {
+  llvm::NamedRegionTimer NRT("codecompletion", "Code completion operations",
+                             GroupName, GroupDescription,
+                             clang::FrontendTimesIsEnabled);
   Actions.CodeCompletePreprocessorMacroName(IsDefinition);
 }
 
-void Parser::CodeCompletePreprocessorExpression() { 
+void Parser::CodeCompletePreprocessorExpression() {
+  llvm::NamedRegionTimer NRT("codecompletion", "Code completion operations",
+                             GroupName, GroupDescription,
+                             clang::FrontendTimesIsEnabled);
   Actions.CodeCompletePreprocessorExpression();
 }
 
 void Parser::CodeCompleteMacroArgument(IdentifierInfo *Macro,
                                        MacroInfo *MacroInfo,
                                        unsigned ArgumentIndex) {
+  llvm::NamedRegionTimer NRT("codecompletion", "Code completion operations",
+                             GroupName, GroupDescription,
+                             clang::FrontendTimesIsEnabled);
   Actions.CodeCompletePreprocessorMacroArgument(getCurScope(), Macro, MacroInfo,
                                                 ArgumentIndex);
 }
 
 void Parser::CodeCompleteNaturalLanguage() {
+  llvm::NamedRegionTimer NRT("codecompletion", "Code completion operations",
+                             GroupName, GroupDescription,
+                             clang::FrontendTimesIsEnabled);
   Actions.CodeCompleteNaturalLanguage();
 }
 
@@ -2078,6 +2108,9 @@
 ///
 /// Note that 'partition' is a context-sensitive keyword.
 Parser::DeclGroupPtrTy Parser::ParseModuleDecl() {
+  llvm::NamedRegionTimer NRT("moduleoperations", "Module related operations",
+                             GroupName, GroupDescription,
+                             clang::FrontendTimesIsEnabled);
   SourceLocation StartLoc = Tok.getLocation();
 
   Sema::ModuleDeclKind MDK = TryConsumeToken(tok::kw_export)
@@ -2123,6 +2156,9 @@
   assert((AtLoc.isInvalid() ? Tok.is(tok::kw_import)
                             : Tok.isObjCAtKeyword(tok::objc_import)) &&
          "Improper start to module import");
+  llvm::NamedRegionTimer NRT("moduleoperations", "Module related operations",
+                             GroupName, GroupDescription,
+                             clang::FrontendTimesIsEnabled);
   SourceLocation ImportLoc = ConsumeToken();
   SourceLocation StartLoc = AtLoc.isInvalid() ? ImportLoc : AtLoc;
   
@@ -2160,6 +2196,9 @@
     SourceLocation UseLoc,
     SmallVectorImpl<std::pair<IdentifierInfo *, SourceLocation>> &Path,
     bool IsImport) {
+  llvm::NamedRegionTimer NRT("moduleoperations", "Module related operations",
+                             GroupName, GroupDescription,
+                             clang::FrontendTimesIsEnabled);
   // Parse the module path.
   while (true) {
     if (!Tok.is(tok::identifier)) {
@@ -2190,6 +2229,9 @@
 /// \returns false if the recover was successful and parsing may be continued, or
 /// true if parser must bail out to top level and handle the token there.
 bool Parser::parseMisplacedModuleImport() {
+  llvm::NamedRegionTimer NRT("moduleoperations", "Module related operations",
+                             GroupName, GroupDescription,
+                             clang::FrontendTimesIsEnabled);
   while (true) {
     switch (Tok.getKind()) {
     case tok::annot_module_end:
Index: lib/Parse/ParseTemplate.cpp
===================================================================
--- lib/Parse/ParseTemplate.cpp
+++ lib/Parse/ParseTemplate.cpp
@@ -13,6 +13,7 @@
 
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclTemplate.h"
+#include "clang/Frontend/Utils.h"
 #include "clang/Parse/ParseDiagnostic.h"
 #include "clang/Parse/Parser.h"
 #include "clang/Parse/RAIIObjectsForParser.h"
@@ -28,6 +29,8 @@
                                              SourceLocation &DeclEnd,
                                              AccessSpecifier AS,
                                              AttributeList *AccessAttrs) {
+  llvm::NamedRegionTimer NRT("parsetemplate", "Parse Template", GroupName,
+                             GroupDescription, clang::FrontendTimesIsEnabled);
   ObjCDeclContextSwitch ObjCDC(*this);
   
   if (Tok.is(tok::kw_template) && NextToken().isNot(tok::less)) {
Index: lib/Lex/Pragma.cpp
===================================================================
--- lib/Lex/Pragma.cpp
+++ lib/Lex/Pragma.cpp
@@ -22,27 +22,29 @@
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TokenKinds.h"
+#include "clang/Frontend/Utils.h"
 #include "clang/Lex/HeaderSearch.h"
 #include "clang/Lex/LexDiagnostic.h"
 #include "clang/Lex/Lexer.h"
 #include "clang/Lex/LiteralSupport.h"
 #include "clang/Lex/MacroInfo.h"
 #include "clang/Lex/ModuleLoader.h"
 #include "clang/Lex/PPCallbacks.h"
+#include "clang/Lex/PTHLexer.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Lex/PreprocessorLexer.h"
-#include "clang/Lex/PTHLexer.h"
 #include "clang/Lex/Token.h"
 #include "clang/Lex/TokenLexer.h"
+#include "clang/Parse/Parser.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringSwitch.h"
 #include "llvm/ADT/StringRef.h"
-#include "llvm/Support/CrashRecoveryContext.h"
+#include "llvm/ADT/StringSwitch.h"
 #include "llvm/Support/Compiler.h"
+#include "llvm/Support/CrashRecoveryContext.h"
 #include "llvm/Support/ErrorHandling.h"
 #include <algorithm>
 #include <cassert>
@@ -82,6 +84,8 @@
 /// the null handler isn't returned on failure to match.
 PragmaHandler *PragmaNamespace::FindHandler(StringRef Name,
                                             bool IgnoreNull) const {
+  llvm::NamedRegionTimer NRT("ppfindhandler", "PP Find Handler", GroupName,
+                             GroupDescription, clang::FrontendTimesIsEnabled);
   if (PragmaHandler *Handler = Handlers.lookup(Name))
     return Handler;
   return IgnoreNull ? nullptr : Handlers.lookup(StringRef());
@@ -128,6 +132,8 @@
 /// rest of the pragma, passing it to the registered pragma handlers.
 void Preprocessor::HandlePragmaDirective(SourceLocation IntroducerLoc,
                                          PragmaIntroducerKind Introducer) {
+  llvm::NamedRegionTimer NRT("pppragma", "Handle Pragma Directive", GroupName,
+                             GroupDescription, clang::FrontendTimesIsEnabled);
   if (Callbacks)
     Callbacks->PragmaDirective(IntroducerLoc, Introducer);
 
Index: lib/Lex/PPMacroExpansion.cpp
===================================================================
--- lib/Lex/PPMacroExpansion.cpp
+++ lib/Lex/PPMacroExpansion.cpp
@@ -20,25 +20,27 @@
 #include "clang/Basic/ObjCRuntime.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/TargetInfo.h"
+#include "clang/Frontend/Utils.h"
 #include "clang/Lex/CodeCompletionHandler.h"
 #include "clang/Lex/DirectoryLookup.h"
 #include "clang/Lex/ExternalPreprocessorSource.h"
 #include "clang/Lex/LexDiagnostic.h"
 #include "clang/Lex/MacroArgs.h"
 #include "clang/Lex/MacroInfo.h"
+#include "clang/Lex/PTHLexer.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Lex/PreprocessorLexer.h"
-#include "clang/Lex/PTHLexer.h"
 #include "clang/Lex/Token.h"
+#include "clang/Parse/Parser.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/FoldingSet.h"
 #include "llvm/ADT/None.h"
 #include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Config/llvm-config.h"
@@ -69,6 +71,8 @@
 void Preprocessor::appendMacroDirective(IdentifierInfo *II, MacroDirective *MD){
   assert(MD && "MacroDirective should be non-zero!");
   assert(!MD->getPrevious() && "Already attached to a MacroDirective history.");
+  llvm::NamedRegionTimer NRT("appendmacro", "PP Append Macro", GroupName,
+                             GroupDescription, clang::FrontendTimesIsEnabled);
 
   MacroState &StoredMD = CurSubmoduleState->Macros[II];
   auto *OldMD = StoredMD.getLatest();
@@ -131,6 +135,8 @@
                                           MacroInfo *Macro,
                                           ArrayRef<ModuleMacro *> Overrides,
                                           bool &New) {
+  llvm::NamedRegionTimer NRT("addmodulemacro", "PP Add Module Macro", GroupName,
+                             GroupDescription, clang::FrontendTimesIsEnabled);
   llvm::FoldingSetNodeID ID;
   ModuleMacro::Profile(ID, Mod, II);
 
@@ -182,6 +188,9 @@
   assert(Info.ActiveModuleMacrosGeneration !=
              CurSubmoduleState->VisibleModules.getGeneration() &&
          "don't need to update this macro name info");
+  llvm::NamedRegionTimer NRT("updatemodulemacro", "PP Update Module Macro",
+                             GroupName, GroupDescription,
+                             clang::FrontendTimesIsEnabled);
   Info.ActiveModuleMacrosGeneration =
       CurSubmoduleState->VisibleModules.getGeneration();
 
@@ -754,6 +763,8 @@
 MacroArgs *Preprocessor::ReadMacroCallArgumentList(Token &MacroName,
                                                    MacroInfo *MI,
                                                    SourceLocation &MacroEnd) {
+  llvm::NamedRegionTimer NRT("ppmacrocall", "PP Macro Call Args", GroupName,
+                             GroupDescription, clang::FrontendTimesIsEnabled);
   // The number of fixed arguments to parse.
   unsigned NumFixedArgsLeft = MI->getNumParams();
   bool isVariadic = MI->isVariadic();
Index: lib/Lex/HeaderSearch.cpp
===================================================================
--- lib/Lex/HeaderSearch.cpp
+++ lib/Lex/HeaderSearch.cpp
@@ -18,6 +18,7 @@
 #include "clang/Basic/Module.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/VirtualFileSystem.h"
+#include "clang/Frontend/Utils.h"
 #include "clang/Lex/DirectoryLookup.h"
 #include "clang/Lex/ExternalPreprocessorSource.h"
 #include "clang/Lex/HeaderMap.h"
@@ -199,6 +200,9 @@
 }
 
 Module *HeaderSearch::lookupModule(StringRef ModuleName, bool AllowSearch) {
+  llvm::NamedRegionTimer T("lookupmodule", "Lookup Module", IncGroupName,
+                           IncGroupDescription, clang::FrontendTimesIsEnabled);
+
   // Look in the module map to determine if there is a module by this name.
   Module *Module = ModMap.findModule(ModuleName);
   if (Module || !AllowSearch || !HSOpts->ImplicitModuleMaps)
@@ -223,6 +227,8 @@
 }
 
 Module *HeaderSearch::lookupModule(StringRef ModuleName, StringRef SearchName) {
+  llvm::NamedRegionTimer T("lookupmodule", "Lookup Module", IncGroupName,
+                           IncGroupDescription, clang::FrontendTimesIsEnabled);
   Module *Module = nullptr;
 
   // Look through the various header search paths to load any available module
@@ -340,6 +346,8 @@
     bool &InUserSpecifiedSystemFramework,
     bool &HasBeenMapped,
     SmallVectorImpl<char> &MappedName) const {
+  llvm::NamedRegionTimer T("lookupfile", "Lookup File", IncGroupName,
+                           IncGroupDescription, clang::FrontendTimesIsEnabled);
   InUserSpecifiedSystemFramework = false;
   HasBeenMapped = false;
 
@@ -467,6 +475,8 @@
     SmallVectorImpl<char> *RelativePath, Module *RequestingModule,
     ModuleMap::KnownHeader *SuggestedModule,
     bool &InUserSpecifiedSystemFramework) const {
+  llvm::NamedRegionTimer T("lookupfw", "Lookup Framework", IncGroupName,
+                           IncGroupDescription, clang::FrontendTimesIsEnabled);
   FileManager &FileMgr = HS.getFileMgr();
 
   // Framework names must have a '/' in the filename.
@@ -633,6 +643,8 @@
     SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath,
     Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule,
     bool *IsMapped, bool SkipCache, bool BuildSystemModule) {
+  llvm::NamedRegionTimer T("lookupfile2", "Lookup File2", IncGroupName,
+                           IncGroupDescription, clang::FrontendTimesIsEnabled);
   if (IsMapped)
     *IsMapped = false;
 
@@ -894,6 +906,8 @@
                          Module *RequestingModule,
                          ModuleMap::KnownHeader *SuggestedModule) {
   assert(ContextFileEnt && "No context file?");
+  llvm::NamedRegionTimer T("lookupsubfm", "Lookup SubFramework", IncGroupName,
+                           IncGroupDescription, clang::FrontendTimesIsEnabled);
 
   // Framework names must have a '/' in the filename.  Find it.
   // FIXME: Should we permit '\' on Windows?
@@ -1111,6 +1125,9 @@
 bool HeaderSearch::ShouldEnterIncludeFile(Preprocessor &PP,
                                           const FileEntry *File, bool isImport,
                                           bool ModulesEnabled, Module *M) {
+  llvm::NamedRegionTimer T("shouldenterinc", "Should Enter Include File",
+                           IncGroupName, IncGroupDescription,
+                           clang::FrontendTimesIsEnabled);
   ++NumIncluded; // Count # of attempted #includes.
 
   // Get information about this file.
@@ -1287,6 +1304,9 @@
 bool HeaderSearch::findUsableModuleForHeader(
     const FileEntry *File, const DirectoryEntry *Root, Module *RequestingModule,
     ModuleMap::KnownHeader *SuggestedModule, bool IsSystemHeaderDir) {
+  llvm::NamedRegionTimer T("findmodule4header", "Find Usable Module For Header",
+                           IncGroupName, IncGroupDescription,
+                           clang::FrontendTimesIsEnabled);
   if (File && needModuleLookup(RequestingModule, SuggestedModule)) {
     // If there is a module that corresponds to this header, suggest it.
     hasModuleMap(File->getName(), Root, IsSystemHeaderDir);
@@ -1299,6 +1319,9 @@
     const FileEntry *File, StringRef FrameworkName, Module *RequestingModule,
     ModuleMap::KnownHeader *SuggestedModule, bool IsSystemFramework) {
   // If we're supposed to suggest a module, look for one now.
+  llvm::NamedRegionTimer T(
+      "findmodule4fwheader", "Find Usable Module For Framework Header",
+      IncGroupName, IncGroupDescription, clang::FrontendTimesIsEnabled);
   if (needModuleLookup(RequestingModule, SuggestedModule)) {
     // Find the top-level framework based on this framework.
     SmallVector<std::string, 4> SubmodulePath;
@@ -1483,6 +1506,8 @@
 }
 
 void HeaderSearch::collectAllModules(SmallVectorImpl<Module *> &Modules) {
+  llvm::NamedRegionTimer T("allmodules", "Collect All Modules", IncGroupName,
+                           IncGroupDescription, clang::FrontendTimesIsEnabled);
   Modules.clear();
 
   if (HSOpts->ImplicitModuleMaps) {
Index: lib/Frontend/FrontendActions.cpp
===================================================================
--- lib/Frontend/FrontendActions.cpp
+++ lib/Frontend/FrontendActions.cpp
@@ -262,6 +262,8 @@
 }
 
 void VerifyPCHAction::ExecuteAction() {
+  llvm::NamedRegionTimer T("verifypch", "Verify PCH actions", GroupName,
+                           GroupDescription, clang::FrontendTimesIsEnabled);
   CompilerInstance &CI = getCompilerInstance();
   bool Preamble = CI.getPreprocessorOpts().PrecompiledPreambleBytes.first != 0;
   const std::string &Sysroot = CI.getHeaderSearchOpts().Sysroot;
@@ -659,6 +661,8 @@
 }
 
 void PrintPreprocessedAction::ExecuteAction() {
+  llvm::NamedRegionTimer T("printpp", "Print PP actions", GroupName,
+                           GroupDescription, clang::FrontendTimesIsEnabled);
   CompilerInstance &CI = getCompilerInstance();
   // Output file may need to be set to 'Binary', to avoid converting Unix style
   // line feeds (<LF>) to Microsoft style line feeds (<CR><LF>).
Index: lib/Frontend/CompilerInstance.cpp
===================================================================
--- lib/Frontend/CompilerInstance.cpp
+++ lib/Frontend/CompilerInstance.cpp
@@ -54,6 +54,8 @@
 #include <utility>
 
 using namespace clang;
+static const char *const GroupName = "frontend";
+static const char *const GroupDescription = "===== Frontend =====";
 
 CompilerInstance::CompilerInstance(
     std::shared_ptr<PCHContainerOperations> PCHContainerOps,
@@ -935,6 +937,10 @@
   assert(!getFrontendOpts().ShowHelp && "Client must handle '-help'!");
   assert(!getFrontendOpts().ShowVersion && "Client must handle '-version'!");
 
+  llvm::NamedRegionTimer T("compilerinstance", "Compiler Instance actions",
+                           GroupName, GroupDescription,
+                           clang::FrontendTimesIsEnabled);
+
   // FIXME: Take this as an argument, once all the APIs we used have moved to
   // taking it as an input instead of hard-coding llvm::errs.
   raw_ostream &OS = llvm::errs();
Index: lib/Frontend/ASTMerge.cpp
===================================================================
--- lib/Frontend/ASTMerge.cpp
+++ lib/Frontend/ASTMerge.cpp
@@ -31,6 +31,8 @@
 }
 
 void ASTMergeAction::ExecuteAction() {
+  llvm::NamedRegionTimer T("astmerge", "AST Merge actions", GroupName,
+                           GroupDescription, clang::FrontendTimesIsEnabled);
   CompilerInstance &CI = getCompilerInstance();
   CI.getDiagnostics().getClient()->BeginSourceFile(
                                              CI.getASTContext().getLangOpts());
Index: lib/CodeGen/CodeGenAction.cpp
===================================================================
--- lib/CodeGen/CodeGenAction.cpp
+++ lib/CodeGen/CodeGenAction.cpp
@@ -51,7 +51,7 @@
   public:
     ClangDiagnosticHandler(const CodeGenOptions &CGOpts, BackendConsumer *BCon)
         : CodeGenOpts(CGOpts), BackendCon(BCon) {}
-  
+
     bool handleDiagnostics(const DiagnosticInfo &DI) override;
 
     bool isAnalysisRemarkEnabled(StringRef PassName) const override {
@@ -90,9 +90,8 @@
     const LangOptions &LangOpts;
     std::unique_ptr<raw_pwrite_stream> AsmOutStream;
     ASTContext *Context;
-
-    Timer LLVMIRGeneration;
-    unsigned LLVMIRGenerationRefCount;
+    static constexpr const char *GroupName = "frontend";
+    static constexpr const char *GroupDescription = "===== Frontend =====";
 
     /// True if we've finished generating IR. This prevents us from generating
     /// additional LLVM IR after emitting output in HandleTranslationUnit. This
@@ -121,12 +120,10 @@
         : Diags(Diags), Action(Action), HeaderSearchOpts(HeaderSearchOpts),
           CodeGenOpts(CodeGenOpts), TargetOpts(TargetOpts), LangOpts(LangOpts),
           AsmOutStream(std::move(OS)), Context(nullptr),
-          LLVMIRGeneration("irgen", "LLVM IR Generation Time"),
-          LLVMIRGenerationRefCount(0),
           Gen(CreateLLVMCodeGen(Diags, InFile, HeaderSearchOpts, PPOpts,
                                 CodeGenOpts, C, CoverageInfo)),
           LinkModules(std::move(LinkModules)) {
-      llvm::TimePassesIsEnabled = TimePasses;
+      clang::FrontendTimesIsEnabled = TimePasses;
     }
     llvm::Module *getModule() const { return Gen->GetModule(); }
     std::unique_ptr<llvm::Module> takeModule() {
@@ -141,52 +138,34 @@
 
     void Initialize(ASTContext &Ctx) override {
       assert(!Context && "initialized multiple times");
-
       Context = &Ctx;
-
-      if (llvm::TimePassesIsEnabled)
-        LLVMIRGeneration.startTimer();
-
+      NamedRegionTimer T("initbackendconsumer", "Init Backend Consumer",
+                         GroupName, GroupDescription,
+                         clang::FrontendTimesIsEnabled);
       Gen->Initialize(Ctx);
-
-      if (llvm::TimePassesIsEnabled)
-        LLVMIRGeneration.stopTimer();
     }
 
     bool HandleTopLevelDecl(DeclGroupRef D) override {
       PrettyStackTraceDecl CrashInfo(*D.begin(), SourceLocation(),
                                      Context->getSourceManager(),
                                      "LLVM IR generation of declaration");
-
-      // Recurse.
-      if (llvm::TimePassesIsEnabled) {
-        LLVMIRGenerationRefCount += 1;
-        if (LLVMIRGenerationRefCount == 1)
-          LLVMIRGeneration.startTimer();
-      }
+      NamedRegionTimer T("handlehophevelhecl", "Handle Top Level Decl",
+                         GroupName, GroupDescription,
+                         clang::FrontendTimesIsEnabled);
 
       Gen->HandleTopLevelDecl(D);
-
-      if (llvm::TimePassesIsEnabled) {
-        LLVMIRGenerationRefCount -= 1;
-        if (LLVMIRGenerationRefCount == 0)
-          LLVMIRGeneration.stopTimer();
-      }
-
       return true;
     }
 
     void HandleInlineFunctionDefinition(FunctionDecl *D) override {
       PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
                                      Context->getSourceManager(),
                                      "LLVM IR generation of inline function");
-      if (llvm::TimePassesIsEnabled)
-        LLVMIRGeneration.startTimer();
+      NamedRegionTimer T("handleinlinefunction",
+                         "Handle Inline Function Definition", GroupName,
+                         GroupDescription, clang::FrontendTimesIsEnabled);
 
       Gen->HandleInlineFunctionDefinition(D);
-
-      if (llvm::TimePassesIsEnabled)
-        LLVMIRGeneration.stopTimer();
     }
 
     void HandleInterestingDecl(DeclGroupRef D) override {
@@ -197,6 +176,8 @@
 
     // Links each entry in LinkModules into our module.  Returns true on error.
     bool LinkInModules() {
+      NamedRegionTimer T("linkinmodules", "Link In Modules", GroupName,
+                         GroupDescription, clang::FrontendTimesIsEnabled);
       for (auto &LM : LinkModules) {
         if (LM.PropagateAttrs)
           for (Function &F : *LM.Module)
@@ -227,21 +208,12 @@
     void HandleTranslationUnit(ASTContext &C) override {
       {
         PrettyStackTraceString CrashInfo("Per-file LLVM IR generation");
-        if (llvm::TimePassesIsEnabled) {
-          LLVMIRGenerationRefCount += 1;
-          if (LLVMIRGenerationRefCount == 1)
-            LLVMIRGeneration.startTimer();
-        }
+        NamedRegionTimer T("handletranslationunit", "Handle Translation Unit",
+                           GroupName, GroupDescription,
+                           clang::FrontendTimesIsEnabled);
 
         Gen->HandleTranslationUnit(C);
-
-        if (llvm::TimePassesIsEnabled) {
-          LLVMIRGenerationRefCount -= 1;
-          if (LLVMIRGenerationRefCount == 0)
-            LLVMIRGeneration.stopTimer();
-        }
-
-	IRGenFinished = true;
+        IRGenFinished = true;
       }
 
       // Silently ignore if we weren't initialized for some reason.
@@ -309,23 +281,37 @@
     }
 
     void HandleTagDeclRequiredDefinition(const TagDecl *D) override {
+      NamedRegionTimer T("handletagdecl", "Handle Tag Decl Required Definition",
+                         GroupName, GroupDescription,
+                         clang::FrontendTimesIsEnabled);
       Gen->HandleTagDeclRequiredDefinition(D);
     }
 
     void CompleteTentativeDefinition(VarDecl *D) override {
+      NamedRegionTimer T("completetentative", "Complete Tentative Definition",
+                         GroupName, GroupDescription,
+                         clang::FrontendTimesIsEnabled);
       Gen->CompleteTentativeDefinition(D);
     }
 
     void AssignInheritanceModel(CXXRecordDecl *RD) override {
+      NamedRegionTimer T("assigninheritance", "Assign Inheritance Model",
+                         GroupName, GroupDescription,
+                         clang::FrontendTimesIsEnabled);
       Gen->AssignInheritanceModel(RD);
     }
 
     void HandleVTable(CXXRecordDecl *RD) override {
+      NamedRegionTimer T("handlevtable", "Handle VTable", GroupName,
+                         GroupDescription, clang::FrontendTimesIsEnabled);
       Gen->HandleVTable(RD);
     }
 
     static void InlineAsmDiagHandler(const llvm::SMDiagnostic &SM,void *Context,
                                      unsigned LocCookie) {
+      NamedRegionTimer T("inlineasmhandler", "Inline Asm Diag Handler",
+                         GroupName, GroupDescription,
+                         clang::FrontendTimesIsEnabled);
       SourceLocation Loc = SourceLocation::getFromRawEncoding(LocCookie);
       ((BackendConsumer*)Context)->InlineAsmDiagHandler2(SM, Loc);
     }
@@ -932,6 +918,8 @@
 }
 
 std::unique_ptr<llvm::Module> CodeGenAction::loadModule(MemoryBufferRef MBRef) {
+  NamedRegionTimer T("loadmodule", "Load Module", GroupName, GroupDescription,
+                     clang::FrontendTimesIsEnabled);
   CompilerInstance &CI = getCompilerInstance();
   SourceManager &SM = CI.getSourceManager();
 
@@ -999,6 +987,8 @@
 void CodeGenAction::ExecuteAction() {
   // If this is an IR file, we have to treat it specially.
   if (getCurrentFileKind().getLanguage() == InputKind::LLVM_IR) {
+    NamedRegionTimer T("executeaction", "LLVM_IR ExecuteAction", GroupName,
+                       GroupDescription, clang::FrontendTimesIsEnabled);
     BackendAction BA = static_cast<BackendAction>(Act);
     CompilerInstance &CI = getCompilerInstance();
     std::unique_ptr<raw_pwrite_stream> OS =
Index: lib/CodeGen/BackendUtil.cpp
===================================================================
--- lib/CodeGen/BackendUtil.cpp
+++ lib/CodeGen/BackendUtil.cpp
@@ -718,7 +718,7 @@
 
 void EmitAssemblyHelper::EmitAssembly(BackendAction Action,
                                       std::unique_ptr<raw_pwrite_stream> OS) {
-  TimeRegion Region(llvm::TimePassesIsEnabled ? &CodeGenerationTime : nullptr);
+  TimeRegion Region(FrontendTimesIsEnabled ? &CodeGenerationTime : nullptr);
 
   setCommandLineOpts(CodeGenOpts);
 
@@ -848,7 +848,7 @@
 /// `EmitAssembly` at some point in the future when the default switches.
 void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
     BackendAction Action, std::unique_ptr<raw_pwrite_stream> OS) {
-  TimeRegion Region(llvm::TimePassesIsEnabled ? &CodeGenerationTime : nullptr);
+  TimeRegion Region(FrontendTimesIsEnabled ? &CodeGenerationTime : nullptr);
   setCommandLineOpts(CodeGenOpts);
 
   // The new pass manager always makes a target machine available to passes
Index: lib/Basic/CMakeLists.txt
===================================================================
--- lib/Basic/CMakeLists.txt
+++ lib/Basic/CMakeLists.txt
@@ -54,6 +54,7 @@
   DiagnosticOptions.cpp
   FileManager.cpp
   FileSystemStatCache.cpp
+  FrontendTiming.cpp
   IdentifierTable.cpp
   LangOptions.cpp
   MemoryBufferCache.cpp
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -304,6 +304,9 @@
   bool shouldLinkPossiblyHiddenDecl(LookupResult &Old, const NamedDecl *New);
 
 public:
+  static constexpr const char *GroupName = "sema";
+  static constexpr const char *GroupDescription = "===== Sema =====";
+
   typedef OpaquePtr<DeclGroupRef> DeclGroupPtrTy;
   typedef OpaquePtr<TemplateName> TemplateTy;
   typedef OpaquePtr<QualType> TypeTy;
Index: include/clang/Parse/Parser.h
===================================================================
--- include/clang/Parse/Parser.h
+++ include/clang/Parse/Parser.h
@@ -2851,4 +2851,6 @@
 
 }  // end namespace clang
 
+static const char *const GroupName = "clangparser";
+static const char *const GroupDescription = "===== Clang Parser =====";
 #endif
Index: include/clang/Lex/HeaderSearch.h
===================================================================
--- include/clang/Lex/HeaderSearch.h
+++ include/clang/Lex/HeaderSearch.h
@@ -21,16 +21,20 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringSet.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
 #include "llvm/Support/Allocator.h"
+#include "llvm/Support/Timer.h"
 #include <cassert>
 #include <cstddef>
 #include <memory>
 #include <string>
 #include <utility>
 #include <vector>
 
+static const char *const IncGroupName = "includefiles";
+static const char *const IncGroupDescription = "===== Include Files =====";
+
 namespace clang {
 
 class DiagnosticsEngine;
Index: include/clang/Frontend/Utils.h
===================================================================
--- include/clang/Frontend/Utils.h
+++ include/clang/Frontend/Utils.h
@@ -17,12 +17,13 @@
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/VirtualFileSystem.h"
-#include "llvm/ADT/IntrusiveRefCntPtr.h"
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/Option/OptSpecifier.h"
+#include "llvm/Support/Timer.h"
 #include <cstdint>
 #include <memory>
 #include <string>
@@ -234,6 +235,34 @@
   BuryPointer(Ptr.release());
 }
 
+// Frontend timing utils
+
+/// If the user specifies the -ftime-report argument on an Clang command line
+/// then the value of this boolean will be true, otherwise false.
+extern bool FrontendTimesIsEnabled;
+void startFrontendTimer(llvm::Timer *T, int *TimerLevel, const char *TimerName,
+                        const char *TimerDsc, llvm::TimerGroup *TG);
+void stopFrontendTimer(llvm::Timer *T, int *TimerLevel);
+
+static llvm::TimerGroup *TG = nullptr;
+
+class FrontendTimeRAII {
+  llvm::Timer *T;
+  int *Level;
+
+public:
+  FrontendTimeRAII(llvm::Timer *Timer, int *L, const char *TName,
+                   const char *TDsc)
+      : T(Timer), Level(L) {
+    if (FrontendTimesIsEnabled) {
+      if (!TG)
+        TG = new llvm::TimerGroup("fetimers", "Frontend Recursive Timers");
+      startFrontendTimer(T, Level, TName, TDsc, TG);
+    }
+  }
+  ~FrontendTimeRAII() { stopFrontendTimer(T, Level); }
+};
+
 } // namespace clang
 
 #endif // LLVM_CLANG_FRONTEND_UTILS_H
Index: include/clang/Frontend/FrontendAction.h
===================================================================
--- include/clang/Frontend/FrontendAction.h
+++ include/clang/Frontend/FrontendAction.h
@@ -45,6 +45,9 @@
                                                         StringRef InFile);
 
 protected:
+  static constexpr const char *GroupName = "factions";
+  static constexpr const char *GroupDescription =
+      "===== Frontend Actions =====";
   /// @name Implementation Action Interface
   /// @{
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to