avt77 updated this revision to Diff 154802. avt77 added a comment. I fixed all issues raised by efriedma: GlobalDecl(FD), function body, class names, etc. Many tnx for your help.
https://reviews.llvm.org/D47196 Files: include/clang/Frontend/Utils.h lib/CodeGen/CodeGenAction.cpp lib/CodeGen/CodeGenFunction.cpp lib/CodeGen/CodeGenModule.cpp lib/Frontend/FrontendTiming.cpp lib/Parse/CMakeLists.txt lib/Parse/ParseTemplate.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaLambda.cpp lib/Sema/TreeTransform.h test/Frontend/ftime-report-template-decl.cpp test/Headers/opencl-c-header.cl
Index: test/Headers/opencl-c-header.cl =================================================================== --- test/Headers/opencl-c-header.cl +++ test/Headers/opencl-c-header.cl @@ -71,4 +71,5 @@ } #endif //__OPENCL_C_VERSION__ -// CHECK-MOD: Reading modules +// CHECK-DAG-MOD: Clang Timers: CodeGen Functions +// CHECK-DAG-MOD: Reading modules Index: test/Frontend/ftime-report-template-decl.cpp =================================================================== --- test/Frontend/ftime-report-template-decl.cpp +++ test/Frontend/ftime-report-template-decl.cpp @@ -3,9 +3,15 @@ // Template function declarations template <typename T> -void foo(); +T foo(T bar) { + T Result = bar * bar + bar / 1.2 + bar; + return Result; +}; template <typename T, typename U> -void foo(); +T foo(T bar, U bar2) { + T Result = bar2 * bar + bar / 1.2 + bar2; + return Result; +}; // Template function definitions. template <typename T> @@ -130,9 +136,15 @@ template <typename U> oneT L<0>::O<char>::Fun(U) { return one; } -void Instantiate() { +double Instantiate() { sassert(sizeof(L<0>::O<int>::Fun(0)) == sizeof(one)); sassert(sizeof(L<0>::O<char>::Fun(0)) == sizeof(one)); + int R1 = foo<int>(123) + foo<double>(177.2) - foo<double>(331.442); + char R2 = foo<char, int>('d', 1234) * foo<double>(1.26); + int R3 = foo<double>(1.2) + foo<double>(11.22) / foo<double>(66.77); + double R4 = foo<double, int>(34.56, 1234); + double R5 = R1 + R2 * R3 - R4 + one[0]*foo<double>(15.52) - two[1]/foo<double>(51.25); + return R5 * R1 + R4 / R3 + R2; } } @@ -150,7 +162,10 @@ }; _Wrap_alloc<int>::rebind<int> w; -// CHECK: Miscellaneous Ungrouped Timers +// FIXME: We need more complex test to increase the compilation time; +// otherwise we see the foolowing message from time to time only. +// VIOLATILE-CHECK: Clang Timers: CodeGen Functions +// CHECK-DAG: Miscellaneous Ungrouped Timers // CHECK-DAG: LLVM IR Generation Time // CHECK-DAG: Code Generation Time // CHECK: Total Index: lib/Sema/TreeTransform.h =================================================================== --- lib/Sema/TreeTransform.h +++ lib/Sema/TreeTransform.h @@ -27,6 +27,7 @@ #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" #include "clang/AST/StmtOpenMP.h" +#include "clang/Frontend/Utils.h" #include "clang/Sema/Designator.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Ownership.h" @@ -10951,6 +10952,11 @@ LSI->CallOperator = NewCallOperator; + if (FrontendTimesIsEnabled) { + getFrontendFunctionTimeCtx<const FunctionDecl *>()->startFrontendTimer( + {NewCallOperator, 0.0}); + } + for (unsigned I = 0, NumParams = NewCallOperator->getNumParams(); I != NumParams; ++I) { auto *P = NewCallOperator->getParamDecl(I); Index: lib/Sema/SemaLambda.cpp =================================================================== --- lib/Sema/SemaLambda.cpp +++ lib/Sema/SemaLambda.cpp @@ -10,17 +10,18 @@ // This file implements semantic analysis for C++ lambda expressions. // //===----------------------------------------------------------------------===// -#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/SemaLambda.h" #include "TypeLocBuilder.h" #include "clang/AST/ASTLambda.h" #include "clang/AST/ExprCXX.h" #include "clang/Basic/TargetInfo.h" +#include "clang/Frontend/Utils.h" +#include "clang/Sema/DeclSpec.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaInternal.h" -#include "clang/Sema/SemaLambda.h" using namespace clang; using namespace sema; @@ -1433,6 +1434,11 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, Scope *CurScope) { LambdaScopeInfo LSI = *cast<LambdaScopeInfo>(FunctionScopes.back()); + + if (FrontendTimesIsEnabled) { + getFrontendFunctionTimeCtx<const FunctionDecl *>()->startFrontendTimer( + {LSI.CallOperator, 0.0}); + } ActOnFinishFunctionBody(LSI.CallOperator, Body); return BuildLambdaExpr(StartLoc, Body->getLocEnd(), &LSI); } 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 @@ -8287,6 +8288,10 @@ isVirtualOkay); if (!NewFD) return nullptr; + FrontendTimeRAII<const FunctionDecl *> FTRAII( + FrontendTimesIsEnabled, + getFrontendFunctionTimeCtx<const FunctionDecl *>(), {NewFD, 0}); + if (OriginalLexicalContext && OriginalLexicalContext->isObjCContainer()) NewFD->setTopLevelDeclInObjCContainer(); @@ -12429,6 +12434,11 @@ else FD = cast<FunctionDecl>(D); + if (FrontendTimesIsEnabled) { + getFrontendFunctionTimeCtx<const FunctionDecl *>()->startFrontendTimer( + {FD, 0.0}); + } + // Check for defining attributes before the check for redefinition. if (const auto *Attr = FD->getAttr<AliasAttr>()) { Diag(Attr->getLocation(), diag::err_alias_is_definition) << FD << 0; @@ -12934,6 +12944,14 @@ DiscardCleanupsInEvaluationContext(); } + if (FrontendTimesIsEnabled) { + assert(getFrontendFunctionTimeCtx<const FunctionDecl *>() + ->ChildStack.back() + .first == FD && + "Invalid FD"); + getFrontendFunctionTimeCtx<const FunctionDecl *>()->stopFrontendTimer(); + } + return dcl; } Index: lib/Parse/ParseTemplate.cpp =================================================================== --- lib/Parse/ParseTemplate.cpp +++ lib/Parse/ParseTemplate.cpp @@ -13,30 +13,60 @@ #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" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" using namespace clang; +#define DEBUG_TYPE "parsetemplate" + /// Parse a template declaration, explicit instantiation, or /// explicit specialization. Decl * Parser::ParseDeclarationStartingWithTemplate(DeclaratorContext Context, SourceLocation &DeclEnd, AccessSpecifier AS, AttributeList *AccessAttrs) { ObjCDeclContextSwitch ObjCDC(*this); - + Decl *Result; + + if (FrontendTimesIsEnabled) { + LLVM_DEBUG(getFrontendFunctionTimeCtx<const FunctionDecl *>()->debugPrint( + "ParseDeclarationStartingWithTemplate: ", nullptr)); + getFrontendFunctionTimeCtx<const FunctionDecl *>()->startFrontendTimer( + {nullptr, 0.0}); + } if (Tok.is(tok::kw_template) && NextToken().isNot(tok::less)) { - return ParseExplicitInstantiation(Context, - SourceLocation(), ConsumeToken(), - DeclEnd, AS); + Result = ParseExplicitInstantiation(Context, SourceLocation(), + ConsumeToken(), DeclEnd, AS); + } else + Result = ParseTemplateDeclarationOrSpecialization(Context, DeclEnd, AS, + AccessAttrs); + if (FrontendTimesIsEnabled) { + bool Done = false; + if (const auto *F = dyn_cast_or_null<FunctionDecl>(Result)) { + if (F->isFunctionOrFunctionTemplate() && F->hasBody()) { + LLVM_DEBUG( + getFrontendFunctionTimeCtx<const FunctionDecl *>()->debugPrint( + "stopFrontendTimer(ParseDeclarationStartingWithTemplate): ", + F)); + getFrontendFunctionTimeCtx<const FunctionDecl *>()->stopFrontendTimer( + true, {F, 0.0}); + Done = true; + } + } + if (!Done) { + getFrontendFunctionTimeCtx<const FunctionDecl *>()->stopFrontendTimer( + true, {nullptr, -1.0}); + LLVM_DEBUG(llvm::dbgs() << "ParseDeclarationStartingWithTemplate: simply " + "remove the non-func time slot from times\n"); + } } - return ParseTemplateDeclarationOrSpecialization(Context, DeclEnd, AS, - AccessAttrs); + return Result; } Index: lib/Parse/CMakeLists.txt =================================================================== --- lib/Parse/CMakeLists.txt +++ lib/Parse/CMakeLists.txt @@ -24,6 +24,7 @@ LINK_LIBS clangAST clangBasic + clangFrontend clangLex clangSema ) Index: lib/Frontend/FrontendTiming.cpp =================================================================== --- lib/Frontend/FrontendTiming.cpp +++ lib/Frontend/FrontendTiming.cpp @@ -11,10 +11,38 @@ // //===----------------------------------------------------------------------===// +#include "clang/AST/Decl.h" #include "clang/Frontend/Utils.h" +#include "llvm/ADT/StringRef.h" namespace clang { bool FrontendTimesIsEnabled = false; +llvm::TimerGroup *FDefTimeGroup = nullptr; +using FTimeBase = const FunctionDecl *; +FrontendTimeCtx<FTimeBase> FuncTimeCtx; + +template <> +FrontendTimeCtx<FTimeBase> *getFrontendFunctionTimeCtx<FTimeBase>() { + if (FrontendTimesIsEnabled && !FuncTimeCtx.IsValid) + FuncTimeCtx.init("cftimer", "Clang Function Timer", + FuncTimeCtx.getFrontendDefaultTimerGroup()); + return &FuncTimeCtx; +} + +template <> bool isFirstValid<FTimeBase>(FTimeBase First) { + assert(First && "Invalid First"); + if (FrontendTimesIsEnabled && FuncTimeCtx.IsValid && + !First->isInvalidDecl() && First->getIdentifier()) { + if (First->getVisibility() == DefaultVisibility && First->hasBody()) + return true; + } + return false; +} + +template <> bool isFirstValid<llvm::StringRef>(llvm::StringRef First) { + assert(!First.empty() && "Invalid First"); + return FrontendTimesIsEnabled; +} } Index: lib/CodeGen/CodeGenModule.cpp =================================================================== --- lib/CodeGen/CodeGenModule.cpp +++ lib/CodeGen/CodeGenModule.cpp @@ -43,6 +43,7 @@ #include "clang/Basic/Version.h" #include "clang/CodeGen/ConstantInitBuilder.h" #include "clang/Frontend/CodeGenOptions.h" +#include "clang/Frontend/Utils.h" #include "clang/Sema/SemaDiagnostic.h" #include "llvm/ADT/Triple.h" #include "llvm/Analysis/TargetLibraryInfo.h" @@ -4453,13 +4454,17 @@ switch (D->getKind()) { case Decl::CXXConversion: case Decl::CXXMethod: - case Decl::Function: + case Decl::Function: { + FrontendTimeRAII<const FunctionDecl *> FTRAII( + FrontendTimesIsEnabled, + getFrontendFunctionTimeCtx<const FunctionDecl *>(), + {cast<FunctionDecl>(D), 0}); EmitGlobal(cast<FunctionDecl>(D)); // Always provide some coverage mapping // even for the functions that aren't emitted. AddDeferredUnusedCoverageMapping(D); break; - + } case Decl::CXXDeductionGuide: // Function-like, but does not result in code emission. break; Index: lib/CodeGen/CodeGenFunction.cpp =================================================================== --- lib/CodeGen/CodeGenFunction.cpp +++ lib/CodeGen/CodeGenFunction.cpp @@ -13,9 +13,9 @@ #include "CodeGenFunction.h" #include "CGBlocks.h" -#include "CGCleanup.h" #include "CGCUDARuntime.h" #include "CGCXXABI.h" +#include "CGCleanup.h" #include "CGDebugInfo.h" #include "CGOpenMPRuntime.h" #include "CodeGenModule.h" @@ -31,6 +31,7 @@ #include "clang/Basic/TargetInfo.h" #include "clang/CodeGen/CGFunctionInfo.h" #include "clang/Frontend/CodeGenOptions.h" +#include "clang/Frontend/Utils.h" #include "clang/Sema/SemaDiagnostic.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Dominators.h" @@ -109,6 +110,8 @@ Builder.setFastMathFlags(FMF); } +using FTimeBase = const FunctionDecl *; + CodeGenFunction::~CodeGenFunction() { assert(LifetimeExtendedCleanupStack.empty() && "failed to emit a cleanup"); @@ -120,6 +123,9 @@ if (getLangOpts().OpenMP && CurFn) CGM.getOpenMPRuntime().functionFinished(*this); + if (FrontendTimesIsEnabled && CurFuncDecl) { + getFrontendFunctionTimeCtx<FTimeBase>()->stopFrontendTimer(); + } } CharUnits CodeGenFunction::getNaturalPointeeTypeAlignment(QualType T, @@ -836,9 +842,13 @@ DidCallStackSave = false; CurCodeDecl = D; - if (const auto *FD = dyn_cast_or_null<FunctionDecl>(D)) + if (const auto *FD = dyn_cast_or_null<FunctionDecl>(D)) { if (FD->usesSEHTry()) CurSEHParent = FD; + if (FrontendTimesIsEnabled) { + getFrontendFunctionTimeCtx<FTimeBase>()->startFrontendTimer({FD, 0.0}); + } + } CurFuncDecl = (D ? D->getNonClosureContext() : nullptr); FnRetTy = RetTy; CurFn = Fn; Index: lib/CodeGen/CodeGenAction.cpp =================================================================== --- lib/CodeGen/CodeGenAction.cpp +++ lib/CodeGen/CodeGenAction.cpp @@ -22,7 +22,9 @@ #include "clang/CodeGen/ModuleBuilder.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Frontend/Utils.h" #include "clang/Lex/Preprocessor.h" +#include "llvm/ADT/Statistic.h" #include "llvm/Bitcode/BitcodeReader.h" #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" #include "llvm/IR/DebugInfo.h" @@ -36,7 +38,6 @@ #include "llvm/Pass.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SourceMgr.h" -#include "llvm/Support/Timer.h" #include "llvm/Support/ToolOutputFile.h" #include "llvm/Support/YAMLTraits.h" #include "llvm/Transforms/IPO/Internalize.h" @@ -107,6 +108,18 @@ // refers to. llvm::Module *CurLinkModule = nullptr; + using FTimeMark = StringRef; + using FTP = std::pair<FTimeMark, double>; + using FTPIterator = std::vector<FTP>::iterator; + + class BCSortClassName { + public: + bool operator()(FTP i, FTP j) { return i.first.compare(j.first) < 0; } + StringRef getName(FTP E) { return E.first; } + }; + + FrontendTimeCtx<FTimeMark> BCTimerCtx; + public: BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags, const HeaderSearchOptions &HeaderSearchOpts, @@ -128,6 +141,12 @@ LinkModules(std::move(LinkModules)) { FrontendTimesIsEnabled = TimePasses; } + + ~BackendConsumer() { + if (FrontendTimesIsEnabled) + BCTimerCtx.print<BCSortClassName>(BCSortClassName(), "BackendConsumer"); + } + llvm::Module *getModule() const { return Gen->GetModule(); } std::unique_ptr<llvm::Module> takeModule() { return std::unique_ptr<llvm::Module>(Gen->ReleaseModule()); @@ -177,6 +196,9 @@ } void HandleInlineFunctionDefinition(FunctionDecl *D) override { + FrontendTimeRAII<const FunctionDecl *> FTRAII( + FrontendTimesIsEnabled, + getFrontendFunctionTimeCtx<const FunctionDecl *>(), {D, 0}); PrettyStackTraceDecl CrashInfo(D, SourceLocation(), Context->getSourceManager(), "LLVM IR generation of inline function"); @@ -805,11 +827,37 @@ bool CodeGenAction::hasIRSupport() const { return true; } +static StringRef getFDName(CodeGen::CodeGenModule &CGM, + const FunctionDecl *FD) { + assert(isFirstValid<const FunctionDecl *>(FD) && "Invalid FD"); + return CGM.getMangledName(GlobalDecl(FD)); +} + +using FTimeBase = const FunctionDecl *; +using FTP = std::pair<FTimeBase, double>; + +class CGSortClassName { + CodeGen::CodeGenModule &CGM; + +public: + CGSortClassName(CodeGen::CodeGenModule &_CGM) : CGM(_CGM) {} + bool operator()(FTP i, FTP j) { + StringRef NameI = getFDName(CGM, i.first); + StringRef NameJ = getFDName(CGM, j.first); + return NameI.compare(NameJ) < 0; + } + + StringRef getName(FTP E) { return getFDName(CGM, E.first); } +}; + void CodeGenAction::EndSourceFileAction() { // If the consumer creation failed, do nothing. if (!getCompilerInstance().hasASTConsumer()) return; - + if (FrontendTimesIsEnabled) + getFrontendFunctionTimeCtx<FTimeBase>()->print<CGSortClassName>( + CGSortClassName(BEConsumer->getCodeGenerator()->CGM()), + "CodeGen Functions", " (*)"); // Steal the module from the consumer. TheModule = BEConsumer->takeModule(); } Index: include/clang/Frontend/Utils.h =================================================================== --- include/clang/Frontend/Utils.h +++ include/clang/Frontend/Utils.h @@ -17,12 +17,15 @@ #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/Statistic.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" #include "llvm/Option/OptSpecifier.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/Timer.h" #include <cstdint> #include <memory> #include <string> @@ -239,7 +242,228 @@ /// 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; +extern llvm::TimerGroup *FDefTimeGroup; + +template <typename T> bool isFirstValid(T First); + +template <typename T> struct FrontendTimeCtx { + using FTimePair = std::pair<T, double>; + std::vector<FTimePair> FrontendTimes; + llvm::Timer FrontendTimer; + llvm::TimerGroup *TGroup = nullptr; + bool DeleteTGroup = false; + double ChildTime; + std::vector<FTimePair> ChildStack; + + static double getCurProcessTime(llvm::Timer &FT) { + assert(FT.isRunning() && "FrontendTimer must be running"); + FT.stopTimer(); + return FT.getTotalTime().getProcessTime(); + } + + static llvm::TimerGroup *getFrontendDefaultTimerGroup() { + if (!FDefTimeGroup) + FDefTimeGroup = (llvm::TimerGroup *)new llvm::TimerGroup( + "clangdeftg", "Clang Timers Group"); + return FDefTimeGroup; + } + +public: + bool IsValid; + FrontendTimeCtx() : IsValid(false){}; + void init(llvm::StringRef TimerName, llvm::StringRef TimerDsc, + llvm::StringRef GroupName, llvm::StringRef GroupDsc) { + if (FrontendTimesIsEnabled) { + TGroup = (llvm::TimerGroup *)new llvm::TimerGroup(GroupName, GroupDsc); + DeleteTGroup = true; + init(TimerName, TimerDsc, TGroup); + } else + IsValid = false; + }; + + void init(llvm::StringRef TimerName, llvm::StringRef TimerDsc, + llvm::TimerGroup *TG) { + if (FrontendTimesIsEnabled) { + FrontendTimer.init(TimerName, TimerDsc, *TG); + TGroup = TG; + ChildStack.clear(); + ChildTime = 0.0; + IsValid = true; + } else + IsValid = false; + }; + + ~FrontendTimeCtx() { + if (FrontendTimesIsEnabled && IsValid && DeleteTGroup) + delete TGroup; + } + + void startFrontendTimer(FTimePair TDsc) { + if (FrontendTimesIsEnabled) { + assert(IsValid && "Time Context must be initialized"); + if (FrontendTimer.isRunning()) + // It stops the timer as a side effect + TDsc.second = getCurProcessTime(FrontendTimer); + else + TDsc.second = FrontendTimer.getTotalTime().getProcessTime(); + ChildStack.push_back(TDsc); + FrontendTimer.startTimer(); + } + } + + bool stopFrontendTimer(bool UseEl = false, FTimePair El = FTimePair()) { + if (FrontendTimesIsEnabled) { + assert(IsValid && "Time Context must be initialized"); + assert(FrontendTimer.isRunning() && "FrontendTimer must be running"); + assert(!ChildStack.empty() && + "There should be at least one running time slice"); + FTimePair Result = ChildStack.back(); + ChildStack.pop_back(); + // As side effect getCurProcessTime does stopTimer(). + // Should we fix such a side effect? + double CurProcTime = getCurProcessTime(FrontendTimer) - Result.second; + Result.second = CurProcTime - ChildTime; + if (ChildStack.empty()) + ChildTime = 0; + else { + ChildTime += Result.second; + FrontendTimer.startTimer(); + } + if (UseEl) { + if (El.second > 0) + Result.first = El.first; + else + return false; + } + if (isFirstValid(Result.first) && Result.second > 0.00001) { + FrontendTimes.push_back(Result); + return true; + } + } + return false; + } + + using FTimePair2 = std::pair<FTimePair, unsigned>; + static bool ftimeSort2(FTimePair2 I, FTimePair2 J) { + return I.first.second < J.first.second; + } + + static bool ftimeSort(FTimePair I, FTimePair J) { + return I.second < J.second; + } + + llvm::TimerGroup *getTimerGroup() { + assert(IsValid && "Time Context must be initialized"); + return TGroup; + } + llvm::Timer *getFrontendTimer() { return &FrontendTimer; } + + std::vector<FTimePair> *getFrontendTimes() { return &FrontendTimes; } + + template <typename Compare> + void print(Compare SortName, StringRef SubGroup, StringRef Mark = " (+)") { + if (FrontendTimesIsEnabled && !FrontendTimes.empty()) { + std::unique_ptr<llvm::raw_ostream> OutStream = + llvm::CreateInfoOutputFile(); + llvm::sort(FrontendTimes.begin(), FrontendTimes.end(), SortName); + using FTPIterator = typename std::vector<FTimePair>::iterator; + std::pair<FTPIterator, FTPIterator> range; + + std::vector<FTimePair2> FinalTimes; + + *OutStream << "===------------ Clang Timers: " << SubGroup + << " ------------==\n"; + for (unsigned i = 0; i < FrontendTimes.size();) { + range = std::equal_range(FrontendTimes.begin() + i, FrontendTimes.end(), + FrontendTimes[i], SortName); + auto dist = std::distance(range.first, range.second); + FTimePair E = {FrontendTimes[i].first, 0}; + while (range.first != range.second) { + E.second += range.first->second; + range.first++; + } + FinalTimes.push_back({E, dist}); + i += dist; + } + llvm::sort(FinalTimes.begin(), FinalTimes.end(), ftimeSort2); + double TimeThreshold = + (FinalTimes.front().first.second + FinalTimes.back().first.second) / + 2; + for (auto E : FinalTimes) { + if ((E.first.second > TimeThreshold) || (E.second > 1)) + *OutStream << llvm::format("%7.4f (%d) ", E.second, E.first.second) + << SortName.getName(E.first) << Mark << "\n"; + } + } + } + void debugPrint(StringRef H, const void *P) { + llvm::dbgs() << H << P + << llvm::format("FrontendTimes.size=%d,ChildStack.size=%d," + "ChildTime=%7.4f, ProcessTime=%7.4f\n", + FrontendTimes.size(), ChildStack.size(), + ChildTime, + FrontendTimer.getTotalTime().getProcessTime()); + } +}; + +template <typename T> FrontendTimeCtx<T> *getFrontendFunctionTimeCtx(); + +template <typename T> class FrontendTimeRAII { + using FTimePair = std::pair<T, double>; + FrontendTimeCtx<T> *Ctx = nullptr; + void init(FTimePair E, llvm::StringRef TName, llvm::StringRef TDsc, + llvm::StringRef GName, llvm::StringRef GDsc) { + if (Ctx) { + if (!Ctx->IsValid) + Ctx->init(TName, TDsc, GName, GDsc); + Ctx->startFrontendTimer(E); + } + } + + void init(FTimePair E, llvm::StringRef TName, llvm::StringRef TDsc, + llvm::TimerGroup *TG) { + if (Ctx) { + if (!Ctx->IsValid) + Ctx->init(TName, TDsc, TG); + Ctx->startFrontendTimer(E); + } + } + +public: + FrontendTimeRAII(bool Enabled, FrontendTimeCtx<T> *FTC, FTimePair E, + llvm::StringRef TName, llvm::StringRef TDsc, + llvm::TimerGroup *TG) { + if (Enabled) { + Ctx = FTC; + init(E, TName, TDsc); + } + } + + FrontendTimeRAII(bool Enabled, FrontendTimeCtx<T> *FTC, FTimePair E, + llvm::StringRef TName, llvm::StringRef TDsc, + llvm::StringRef GName, llvm::StringRef GDsc) { + if (Enabled) { + Ctx = FTC; + init(E, TName, TDsc, GName, GDsc); + } + } + + FrontendTimeRAII(bool Enabled, FrontendTimeCtx<T> *FTC, FTimePair E) { + if (Enabled) { + Ctx = FTC; + init(E, "clangtimer", "Clang Func Timer", + FrontendTimeCtx<T>::getFrontendDefaultTimerGroup()); + } + } + + ~FrontendTimeRAII() { + if (Ctx && Ctx->IsValid) { + // Ctx->stopFrontendTimer(true, {T(), -1.0}); + Ctx->stopFrontendTimer(); + } + } +}; } // namespace clang #endif // LLVM_CLANG_FRONTEND_UTILS_H
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits