Index: include/clang/Lex/Preprocessor.h =================================================================== --- include/clang/Lex/Preprocessor.h +++ include/clang/Lex/Preprocessor.h @@ -142,6 +142,8 @@ /// \brief External source of macros. ExternalPreprocessorSource *ExternalSource; + StringRef GroupName = "clangparser"; + StringRef GroupDescription = "===== Clang Parser ====="; /// An optional PTHManager object used for getting tokens from /// a token cache rather than lexing the original source file. Index: include/clang/Parse/Parser.h =================================================================== --- include/clang/Parse/Parser.h +++ include/clang/Parse/Parser.h @@ -76,6 +76,8 @@ unsigned short ParenCount = 0, BracketCount = 0, BraceCount = 0; unsigned short MisplacedModuleBeginCount = 0; + StringRef GroupName = "clangparser"; + StringRef GroupDescription = "===== Clang Parser ====="; /// Actions - These are the callbacks we invoke as we parse various constructs /// in the file. Index: lib/CodeGen/BackendUtil.cpp =================================================================== --- lib/CodeGen/BackendUtil.cpp +++ lib/CodeGen/BackendUtil.cpp @@ -75,7 +75,8 @@ const LangOptions &LangOpts; Module *TheModule; - Timer CodeGenerationTime; + StringRef GroupName = "frontend"; + StringRef GroupDescription = "===== Frontend ====="; std::unique_ptr OS; @@ -111,8 +112,7 @@ const clang::TargetOptions &TOpts, const LangOptions &LOpts, Module *M) : Diags(_Diags), HSOpts(HeaderSearchOpts), CodeGenOpts(CGOpts), - TargetOpts(TOpts), LangOpts(LOpts), TheModule(M), - CodeGenerationTime("codegen", "Code Generation Time") {} + TargetOpts(TOpts), LangOpts(LOpts), TheModule(M) {} ~EmitAssemblyHelper() { if (CodeGenOpts.DisableFree) @@ -716,7 +716,8 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action, std::unique_ptr OS) { - TimeRegion Region(llvm::TimePassesIsEnabled ? &CodeGenerationTime : nullptr); + NamedRegionTimer T("codegen", "Code Generation Time", GroupName, + GroupDescription, llvm::TimePassesIsEnabled); setCommandLineOpts(CodeGenOpts); @@ -846,7 +847,8 @@ /// `EmitAssembly` at some point in the future when the default switches. void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( BackendAction Action, std::unique_ptr OS) { - TimeRegion Region(llvm::TimePassesIsEnabled ? &CodeGenerationTime : nullptr); + NamedRegionTimer T("codegen", "Code Generation Time", GroupName, + GroupDescription, llvm::TimePassesIsEnabled); setCommandLineOpts(CodeGenOpts); // The new pass manager always makes a target machine available to passes 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 { @@ -91,8 +91,8 @@ std::unique_ptr AsmOutStream; ASTContext *Context; - Timer LLVMIRGeneration; - unsigned LLVMIRGenerationRefCount; + StringRef GroupName = "frontend"; + StringRef GroupDescription = "===== Frontend ====="; /// True if we've finished generating IR. This prevents us from generating /// additional LLVM IR after emitting output in HandleTranslationUnit. This @@ -121,8 +121,6 @@ : 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)) { @@ -141,38 +139,22 @@ void Initialize(ASTContext &Ctx) override { assert(!Context && "initialized multiple times"); - Context = &Ctx; - - if (llvm::TimePassesIsEnabled) - LLVMIRGeneration.startTimer(); - + NamedRegionTimer T("backendconsumer", "Backend Consumer actions", + GroupName, GroupDescription, + llvm::TimePassesIsEnabled); 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("backendconsumer", "Backend Consumer actions", + GroupName, GroupDescription, + llvm::TimePassesIsEnabled); Gen->HandleTopLevelDecl(D); - - if (llvm::TimePassesIsEnabled) { - LLVMIRGenerationRefCount -= 1; - if (LLVMIRGenerationRefCount == 0) - LLVMIRGeneration.stopTimer(); - } - return true; } @@ -180,13 +162,11 @@ PrettyStackTraceDecl CrashInfo(D, SourceLocation(), Context->getSourceManager(), "LLVM IR generation of inline function"); - if (llvm::TimePassesIsEnabled) - LLVMIRGeneration.startTimer(); + NamedRegionTimer T("backendconsumer", "Backend Consumer actions", + GroupName, GroupDescription, + llvm::TimePassesIsEnabled); Gen->HandleInlineFunctionDefinition(D); - - if (llvm::TimePassesIsEnabled) - LLVMIRGeneration.stopTimer(); } void HandleInterestingDecl(DeclGroupRef D) override { @@ -227,21 +207,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("backendconsumer", "Backend Consumer actions", + GroupName, GroupDescription, + llvm::TimePassesIsEnabled); 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. Index: lib/Lex/PPMacroExpansion.cpp =================================================================== --- lib/Lex/PPMacroExpansion.cpp +++ lib/Lex/PPMacroExpansion.cpp @@ -46,6 +46,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Timer.h" #include #include #include @@ -69,6 +70,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("clangparser20", "PP Macro Expansion", GroupName, + GroupDescription, llvm::TimePassesIsEnabled); MacroState &StoredMD = CurSubmoduleState->Macros[II]; auto *OldMD = StoredMD.getLatest(); @@ -131,6 +134,8 @@ MacroInfo *Macro, ArrayRef Overrides, bool &New) { + llvm::NamedRegionTimer NRT("clangparser20", "PP Macro Expansion", GroupName, + GroupDescription, llvm::TimePassesIsEnabled); llvm::FoldingSetNodeID ID; ModuleMacro::Profile(ID, Mod, II); @@ -182,6 +187,8 @@ assert(Info.ActiveModuleMacrosGeneration != CurSubmoduleState->VisibleModules.getGeneration() && "don't need to update this macro name info"); + llvm::NamedRegionTimer NRT("clangparser20", "PP Macro Expansion", GroupName, + GroupDescription, llvm::TimePassesIsEnabled); Info.ActiveModuleMacrosGeneration = CurSubmoduleState->VisibleModules.getGeneration(); @@ -754,6 +761,8 @@ MacroArgs *Preprocessor::ReadMacroCallArgumentList(Token &MacroName, MacroInfo *MI, SourceLocation &MacroEnd) { + llvm::NamedRegionTimer NRT("clangparser30", "PP Macro Call Args", GroupName, + GroupDescription, llvm::TimePassesIsEnabled); // The number of fixed arguments to parse. unsigned NumFixedArgsLeft = MI->getNumParams(); bool isVariadic = MI->isVariadic(); @@ -1654,6 +1663,8 @@ // Figure out which token this is. IdentifierInfo *II = Tok.getIdentifierInfo(); assert(II && "Can't be a macro without id info!"); + llvm::NamedRegionTimer NRT("clangparser20", "PP Macro Expansion", GroupName, + GroupDescription, llvm::TimePassesIsEnabled); // If this is an _Pragma or Microsoft __pragma directive, expand it, // invoke the pragma handler, then lex the token after it. Index: lib/Lex/Pragma.cpp =================================================================== --- lib/Lex/Pragma.cpp +++ lib/Lex/Pragma.cpp @@ -34,6 +34,7 @@ #include "clang/Lex/PTHLexer.h" #include "clang/Lex/Token.h" #include "clang/Lex/TokenLexer.h" +#include "llvm/Pass.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" @@ -44,6 +45,7 @@ #include "llvm/Support/CrashRecoveryContext.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Timer.h" #include #include #include @@ -54,6 +56,8 @@ #include using namespace clang; +StringRef GroupName = "clangparser"; +StringRef GroupDescription = "===== Clang Parser ====="; // Out-of-line destructor to provide a home for the class. PragmaHandler::~PragmaHandler() = default; @@ -82,6 +86,8 @@ /// the null handler isn't returned on failure to match. PragmaHandler *PragmaNamespace::FindHandler(StringRef Name, bool IgnoreNull) const { + llvm::NamedRegionTimer NRT("clangparser22", "PP Find Handler", GroupName, + GroupDescription, llvm::TimePassesIsEnabled); if (PragmaHandler *Handler = Handlers.lookup(Name)) return Handler; return IgnoreNull ? nullptr : Handlers.lookup(StringRef()); @@ -128,6 +134,8 @@ /// rest of the pragma, passing it to the registered pragma handlers. void Preprocessor::HandlePragmaDirective(SourceLocation IntroducerLoc, PragmaIntroducerKind Introducer) { + llvm::NamedRegionTimer NRT("clangparser21", "PP Pragma", GroupName, + GroupDescription, llvm::TimePassesIsEnabled); if (Callbacks) Callbacks->PragmaDirective(IntroducerLoc, Introducer); @@ -199,6 +207,8 @@ /// return the first token after the directive. The _Pragma token has just /// been read into 'Tok'. void Preprocessor::Handle_Pragma(Token &Tok) { + llvm::NamedRegionTimer NRT("clangparser21", "PP Pragma", GroupName, + GroupDescription, llvm::TimePassesIsEnabled); // This works differently if we are pre-expanding a macro argument. // In that case we don't actually "activate" the pragma now, we only lex it // until we are sure it is lexically correct and then we backtrack so that Index: lib/Parse/ParseDeclCXX.cpp =================================================================== --- lib/Parse/ParseDeclCXX.cpp +++ lib/Parse/ParseDeclCXX.cpp @@ -11,7 +11,6 @@ // //===----------------------------------------------------------------------===// -#include "clang/Parse/Parser.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclTemplate.h" #include "clang/Basic/Attributes.h" @@ -19,6 +18,7 @@ #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/TargetInfo.h" #include "clang/Parse/ParseDiagnostic.h" +#include "clang/Parse/Parser.h" #include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ParsedTemplate.h" Index: lib/Parse/ParseStmt.cpp =================================================================== --- lib/Parse/ParseStmt.cpp +++ lib/Parse/ParseStmt.cpp @@ -21,6 +21,7 @@ #include "clang/Sema/PrettyDeclStackTrace.h" #include "clang/Sema/Scope.h" #include "clang/Sema/TypoCorrection.h" +#include "llvm/Support/Timer.h" using namespace clang; //===----------------------------------------------------------------------===// @@ -99,7 +100,6 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts, AllowedConstructsKind Allowed, SourceLocation *TrailingElseLoc) { - ParenBraceBracketBalancer BalancerRAIIObj(*this); ParsedAttributesWithRange Attrs(AttrFactory); @@ -1955,6 +1955,10 @@ Decl *Parser::ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope) { assert(Tok.is(tok::l_brace)); + llvm::NamedRegionTimer NRT("clangparser2", "Parse Function Body", + GroupName, GroupDescription, + llvm::TimePassesIsEnabled); + SourceLocation LBraceLoc = Tok.getLocation(); PrettyDeclStackTraceEntry CrashInfo(Actions, Decl, LBraceLoc, @@ -2203,6 +2207,9 @@ } void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) { + llvm::NamedRegionTimer T("clangparser03", "Parse MS Statement", + GroupName, GroupDescription, + llvm::TimePassesIsEnabled); IfExistsCondition Result; if (ParseMicrosoftIfExistsCondition(Result)) return; Index: lib/Parse/ParseTemplate.cpp =================================================================== --- lib/Parse/ParseTemplate.cpp +++ lib/Parse/ParseTemplate.cpp @@ -19,6 +19,7 @@ #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" +#include "llvm/Support/Timer.h" using namespace clang; /// \brief Parse a template declaration, explicit instantiation, or @@ -28,6 +29,9 @@ SourceLocation &DeclEnd, AccessSpecifier AS, AttributeList *AccessAttrs) { + llvm::NamedRegionTimer NRT( + "clangparser10", "Parse Template", GroupName, + GroupDescription, llvm::TimePassesIsEnabled); ObjCDeclContextSwitch ObjCDC(*this); if (Tok.is(tok::kw_template) && NextToken().isNot(tok::less)) { Index: lib/Parse/Parser.cpp =================================================================== --- lib/Parse/Parser.cpp +++ lib/Parse/Parser.cpp @@ -20,6 +20,7 @@ #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" +#include "llvm/Support/Timer.h" using namespace clang; @@ -368,6 +369,8 @@ /// ExitScope - Pop a scope off the scope stack. void Parser::ExitScope() { assert(getCurScope() && "Scope imbalance!"); + llvm::NamedRegionTimer NRT("clangparser5", "Scope manipulation", GroupName, + GroupDescription, llvm::TimePassesIsEnabled); // Inform the actions module that this scope is going away if there are any // decls in it. @@ -1456,6 +1459,8 @@ /// declaration is finished. TemplateIdAnnotation *Parser::takeTemplateIdAnnotation(const Token &tok) { assert(tok.is(tok::annot_template_id) && "Expected template-id token"); + llvm::NamedRegionTimer NRT("clangparser7", "Annotation operations", GroupName, + GroupDescription, llvm::TimePassesIsEnabled); TemplateIdAnnotation * Id = static_cast(tok.getAnnotationValue()); return Id; @@ -1464,6 +1469,8 @@ void Parser::AnnotateScopeToken(CXXScopeSpec &SS, bool IsNewAnnotation) { // Push the current token back into the token stream (or revert it if it is // cached) and use an annotation scope token for current token. + llvm::NamedRegionTimer NRT("clangparser7", "Annotation operations", GroupName, + GroupDescription, llvm::TimePassesIsEnabled); if (PP.isBacktrackEnabled()) PP.RevertCachedTokens(1); else @@ -1659,7 +1666,6 @@ Tok.is(tok::kw_decltype) || Tok.is(tok::annot_template_id) || Tok.is(tok::kw___super)) && "Cannot be a type or scope token!"); - if (Tok.is(tok::kw_typename)) { // MSVC lets you do stuff like: // typename typedef T_::D D; @@ -1881,6 +1887,8 @@ (Tok.is(tok::annot_template_id) && NextToken().is(tok::coloncolon)) || Tok.is(tok::kw_decltype) || Tok.is(tok::kw___super)) && "Cannot be a type or scope token!"); + llvm::NamedRegionTimer NRT("clangparser7", "Annotation operations", GroupName, + GroupDescription, llvm::TimePassesIsEnabled); CXXScopeSpec SS; if (ParseOptionalCXXScopeSpecifier(SS, nullptr, EnteringContext)) @@ -1922,6 +1930,9 @@ SourceLocation Parser::handleUnexpectedCodeCompletionToken() { assert(Tok.is(tok::code_completion)); + llvm::NamedRegionTimer NRT("clangparser8", "Code completion operations", + GroupName, GroupDescription, + llvm::TimePassesIsEnabled); PrevTokLocation = Tok.getLocation(); for (Scope *S = getCurScope(); S; S = S->getParent()) { @@ -1947,29 +1958,47 @@ // Code-completion pass-through functions void Parser::CodeCompleteDirective(bool InConditional) { + llvm::NamedRegionTimer NRT("clangparser8", "Code completion operations", + GroupName, GroupDescription, + llvm::TimePassesIsEnabled); Actions.CodeCompletePreprocessorDirective(InConditional); } void Parser::CodeCompleteInConditionalExclusion() { + llvm::NamedRegionTimer NRT("clangparser8", "Code completion operations", + GroupName, GroupDescription, + llvm::TimePassesIsEnabled); Actions.CodeCompleteInPreprocessorConditionalExclusion(getCurScope()); } void Parser::CodeCompleteMacroName(bool IsDefinition) { + llvm::NamedRegionTimer NRT("clangparser8", "Code completion operations", + GroupName, GroupDescription, + llvm::TimePassesIsEnabled); Actions.CodeCompletePreprocessorMacroName(IsDefinition); } -void Parser::CodeCompletePreprocessorExpression() { +void Parser::CodeCompletePreprocessorExpression() { + llvm::NamedRegionTimer NRT("clangparser8", "Code completion operations", + GroupName, GroupDescription, + llvm::TimePassesIsEnabled); Actions.CodeCompletePreprocessorExpression(); } void Parser::CodeCompleteMacroArgument(IdentifierInfo *Macro, MacroInfo *MacroInfo, unsigned ArgumentIndex) { + llvm::NamedRegionTimer NRT("clangparser8", "Code completion operations", + GroupName, GroupDescription, + llvm::TimePassesIsEnabled); Actions.CodeCompletePreprocessorMacroArgument(getCurScope(), Macro, MacroInfo, ArgumentIndex); } void Parser::CodeCompleteNaturalLanguage() { + llvm::NamedRegionTimer NRT("clangparser8", "Code completion operations", + GroupName, GroupDescription, + llvm::TimePassesIsEnabled); Actions.CodeCompleteNaturalLanguage(); } @@ -2078,6 +2107,9 @@ /// /// Note that 'partition' is a context-sensitive keyword. Parser::DeclGroupPtrTy Parser::ParseModuleDecl() { + llvm::NamedRegionTimer NRT("clangparser9", "Module related operations", + GroupName, GroupDescription, + llvm::TimePassesIsEnabled); SourceLocation StartLoc = Tok.getLocation(); Sema::ModuleDeclKind MDK = TryConsumeToken(tok::kw_export) @@ -2123,6 +2155,9 @@ assert((AtLoc.isInvalid() ? Tok.is(tok::kw_import) : Tok.isObjCAtKeyword(tok::objc_import)) && "Improper start to module import"); + llvm::NamedRegionTimer NRT("clangparser9", "Module related operations", + GroupName, GroupDescription, + llvm::TimePassesIsEnabled); SourceLocation ImportLoc = ConsumeToken(); SourceLocation StartLoc = AtLoc.isInvalid() ? ImportLoc : AtLoc; @@ -2160,6 +2195,9 @@ SourceLocation UseLoc, SmallVectorImpl> &Path, bool IsImport) { + llvm::NamedRegionTimer NRT("clangparser9", "Module related operations", + GroupName, GroupDescription, + llvm::TimePassesIsEnabled); // Parse the module path. while (true) { if (!Tok.is(tok::identifier)) { @@ -2190,6 +2228,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("clangparser9", "Module related operations", + GroupName, GroupDescription, + llvm::TimePassesIsEnabled); while (true) { switch (Tok.getKind()) { case tok::annot_module_end: 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,130 @@ +// 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 void foo(); +template void foo(); + +// Template function definitions. +template void foo() { } + +// Template class (forward) declarations +template struct A; +template struct b; +template struct C; +template struct D; + +// Forward declarations with default parameters? +template class X1; +template class X2; + +// Forward declarations w/template template parameters +template