From: Yuanfang Chen Date: Wed, 2 Dec 2020 18:18:18 +0000 (-0800) Subject: [Time-report] Add a flag -ftime-report={per-pass,per-pass-run} to control the pass... X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=1821265db681cd2289fce9331e3aed26bdf814e3;p=android-x86%2Fexternal-llvm-project.git [Time-report] Add a flag -ftime-report={per-pass,per-pass-run} to control the pass timing aggregation Currently, -ftime-report + new pass manager emits one line of report for each pass run. This potentially causes huge output text especially with regular LTO or large single file (Obeserved in private tests and was reported in D51276). The behaviour of -ftime-report + legacy pass manager is emitting one line of report for each pass object which has relatively reasonable text output size. This patch adds a flag `-ftime-report=` to control time report aggregation for new pass manager. The flag is for new pass manager only. Using it with legacy pass manager gives an error. It is a driver and cc1 flag. `per-pass` is the new default so `-ftime-report` is aliased to `-ftime-report=per-pass`. Before this patch, functionality-wise `-ftime-report` is aliased to `-ftime-report=per-pass-run`. * Adds an boolean variable TimePassesHandler::PerRun to control per-pass vs per-pass-run. * Adds a new clang CodeGen flag CodeGenOptions::TimePassesPerRun to work with the existing CodeGenOptions::TimePasses. * Remove FrontendOptions::ShowTimers, its uses are replaced by the existing CodeGenOptions::TimePasses. * Remove FrontendTimesIsEnabled (It was introduced in D45619 which was largely reverted.) Differential Revision: https://reviews.llvm.org/D92436 --- diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index d4bbdbfa13b..9c3b4f8289f 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -252,7 +252,8 @@ CODEGENOPT(SpeculativeLoadHardening, 1, 0) ///< Enable speculative load hardenin CODEGENOPT(FineGrainedBitfieldAccesses, 1, 0) ///< Enable fine-grained bitfield accesses. CODEGENOPT(StrictEnums , 1, 0) ///< Optimize based on strict enum definition. CODEGENOPT(StrictVTablePointers, 1, 0) ///< Optimize based on the strict vtable pointers -CODEGENOPT(TimePasses , 1, 0) ///< Set when -ftime-report is enabled. +CODEGENOPT(TimePasses , 1, 0) ///< Set when -ftime-report or -ftime-report= is enabled. +CODEGENOPT(TimePassesPerRun , 1, 0) ///< Set when -ftime-report=per-pass-run is enabled. CODEGENOPT(TimeTrace , 1, 0) ///< Set when -ftime-trace is enabled. VALUE_CODEGENOPT(TimeTraceGranularity, 32, 500) ///< Minimum time granularity (in microseconds), ///< traced by time profiler diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 794aa24f997..8cabcd67116 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2005,7 +2005,12 @@ def Wframe_larger_than_EQ : Joined<["-"], "Wframe-larger-than=">, Group def : Flag<["-"], "fterminated-vtables">, Alias; def fthreadsafe_statics : Flag<["-"], "fthreadsafe-statics">, Group; def ftime_report : Flag<["-"], "ftime-report">, Group, Flags<[CC1Option]>, - MarshallingInfoFlag<"FrontendOpts.ShowTimers">; + MarshallingInfoFlag<"CodeGenOpts.TimePasses">; +def ftime_report_EQ: Joined<["-"], "ftime-report=">, Group, + Flags<[CC1Option]>, Values<"per-pass,per-pass-run">, + MarshallingInfoFlag<"CodeGenOpts.TimePassesPerRun">, + HelpText<"(For new pass manager) \"per-pass\": one report for each pass; " + "\"per-pass-run\": one report for each pass invocation">; def ftime_trace : Flag<["-"], "ftime-trace">, Group, HelpText<"Turn on time profiler. Generates JSON file based on output filename.">, DocBrief<[{ diff --git a/clang/include/clang/Frontend/FrontendOptions.h b/clang/include/clang/Frontend/FrontendOptions.h index b06ad5203e7..223c1e05d05 100644 --- a/clang/include/clang/Frontend/FrontendOptions.h +++ b/clang/include/clang/Frontend/FrontendOptions.h @@ -239,9 +239,6 @@ public: /// Show frontend performance metrics and statistics. unsigned ShowStats : 1; - /// Show timers for individual actions. - unsigned ShowTimers : 1; - /// print the supported cpus for the current target unsigned PrintSupportedCPUs : 1; @@ -453,15 +450,15 @@ public: public: FrontendOptions() : DisableFree(false), RelocatablePCH(false), ShowHelp(false), - ShowStats(false), ShowTimers(false), TimeTrace(false), - ShowVersion(false), FixWhatYouCan(false), FixOnlyWarnings(false), - FixAndRecompile(false), FixToTemporaries(false), - ARCMTMigrateEmitARCErrors(false), SkipFunctionBodies(false), - UseGlobalModuleIndex(true), GenerateGlobalModuleIndex(true), - ASTDumpDecls(false), ASTDumpLookups(false), - BuildingImplicitModule(false), ModulesEmbedAllFiles(false), - IncludeTimestamps(true), UseTemporary(true), - AllowPCMWithCompilerErrors(false), TimeTraceGranularity(500) {} + ShowStats(false), TimeTrace(false), ShowVersion(false), + FixWhatYouCan(false), FixOnlyWarnings(false), FixAndRecompile(false), + FixToTemporaries(false), ARCMTMigrateEmitARCErrors(false), + SkipFunctionBodies(false), UseGlobalModuleIndex(true), + GenerateGlobalModuleIndex(true), ASTDumpDecls(false), + ASTDumpLookups(false), BuildingImplicitModule(false), + ModulesEmbedAllFiles(false), IncludeTimestamps(true), + UseTemporary(true), AllowPCMWithCompilerErrors(false), + TimeTraceGranularity(500) {} /// getInputKindForExtension - Return the appropriate input kind for a file /// extension. For example, "c" would return Language::C. diff --git a/clang/include/clang/Frontend/Utils.h b/clang/include/clang/Frontend/Utils.h index b5834921b9e..9386873db17 100644 --- a/clang/include/clang/Frontend/Utils.h +++ b/clang/include/clang/Frontend/Utils.h @@ -227,10 +227,6 @@ std::unique_ptr createInvocationFromCommandLine( // 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; - } // namespace clang #endif // LLVM_CLANG_FRONTEND_UTILS_H diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 724e2ec16fc..c5a8a3df216 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -907,7 +907,7 @@ bool EmitAssemblyHelper::AddEmitPasses(legacy::PassManager &CodeGenPasses, void EmitAssemblyHelper::EmitAssembly(BackendAction Action, std::unique_ptr OS) { - TimeRegion Region(FrontendTimesIsEnabled ? &CodeGenerationTime : nullptr); + TimeRegion Region(CodeGenOpts.TimePasses ? &CodeGenerationTime : nullptr); setCommandLineOpts(CodeGenOpts); @@ -1064,7 +1064,7 @@ static PassBuilder::OptimizationLevel mapToLevel(const CodeGenOptions &Opts) { /// `EmitAssembly` at some point in the future when the default switches. void EmitAssemblyHelper::EmitAssemblyWithNewPassManager( BackendAction Action, std::unique_ptr OS) { - TimeRegion Region(FrontendTimesIsEnabled ? &CodeGenerationTime : nullptr); + TimeRegion Region(CodeGenOpts.TimePasses ? &CodeGenerationTime : nullptr); setCommandLineOpts(CodeGenOpts); bool RequiresCodeGen = (Action != Backend_EmitNothing && diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp index 1e935bbeeca..5b23b6d2b7f 100644 --- a/clang/lib/CodeGen/CodeGenAction.cpp +++ b/clang/lib/CodeGen/CodeGenAction.cpp @@ -122,6 +122,8 @@ namespace clang { /// can happen when Clang plugins trigger additional AST deserialization. bool IRGenFinished = false; + bool TimerIsEnabled = false; + std::unique_ptr Gen; SmallVector LinkModules; @@ -136,8 +138,7 @@ namespace clang { const PreprocessorOptions &PPOpts, const CodeGenOptions &CodeGenOpts, const TargetOptions &TargetOpts, - const LangOptions &LangOpts, bool TimePasses, - const std::string &InFile, + const LangOptions &LangOpts, const std::string &InFile, SmallVector LinkModules, std::unique_ptr OS, LLVMContext &C, CoverageSourceInfo *CoverageInfo = nullptr) @@ -149,8 +150,9 @@ namespace clang { Gen(CreateLLVMCodeGen(Diags, InFile, HeaderSearchOpts, PPOpts, CodeGenOpts, C, CoverageInfo)), LinkModules(std::move(LinkModules)) { - FrontendTimesIsEnabled = TimePasses; - llvm::TimePassesIsEnabled = TimePasses; + TimerIsEnabled = CodeGenOpts.TimePasses; + llvm::TimePassesIsEnabled = CodeGenOpts.TimePasses; + llvm::TimePassesPerRun = CodeGenOpts.TimePassesPerRun; } // This constructor is used in installing an empty BackendConsumer @@ -161,7 +163,7 @@ namespace clang { const PreprocessorOptions &PPOpts, const CodeGenOptions &CodeGenOpts, const TargetOptions &TargetOpts, - const LangOptions &LangOpts, bool TimePasses, + const LangOptions &LangOpts, SmallVector LinkModules, LLVMContext &C, CoverageSourceInfo *CoverageInfo = nullptr) : Diags(Diags), Action(Action), HeaderSearchOpts(HeaderSearchOpts), @@ -172,8 +174,9 @@ namespace clang { Gen(CreateLLVMCodeGen(Diags, "", HeaderSearchOpts, PPOpts, CodeGenOpts, C, CoverageInfo)), LinkModules(std::move(LinkModules)) { - FrontendTimesIsEnabled = TimePasses; - llvm::TimePassesIsEnabled = TimePasses; + TimerIsEnabled = CodeGenOpts.TimePasses; + llvm::TimePassesIsEnabled = CodeGenOpts.TimePasses; + llvm::TimePassesPerRun = CodeGenOpts.TimePassesPerRun; } llvm::Module *getModule() const { return Gen->GetModule(); } std::unique_ptr takeModule() { @@ -191,12 +194,12 @@ namespace clang { Context = &Ctx; - if (FrontendTimesIsEnabled) + if (TimerIsEnabled) LLVMIRGeneration.startTimer(); Gen->Initialize(Ctx); - if (FrontendTimesIsEnabled) + if (TimerIsEnabled) LLVMIRGeneration.stopTimer(); } @@ -206,7 +209,7 @@ namespace clang { "LLVM IR generation of declaration"); // Recurse. - if (FrontendTimesIsEnabled) { + if (TimerIsEnabled) { LLVMIRGenerationRefCount += 1; if (LLVMIRGenerationRefCount == 1) LLVMIRGeneration.startTimer(); @@ -214,7 +217,7 @@ namespace clang { Gen->HandleTopLevelDecl(D); - if (FrontendTimesIsEnabled) { + if (TimerIsEnabled) { LLVMIRGenerationRefCount -= 1; if (LLVMIRGenerationRefCount == 0) LLVMIRGeneration.stopTimer(); @@ -227,12 +230,12 @@ namespace clang { PrettyStackTraceDecl CrashInfo(D, SourceLocation(), Context->getSourceManager(), "LLVM IR generation of inline function"); - if (FrontendTimesIsEnabled) + if (TimerIsEnabled) LLVMIRGeneration.startTimer(); Gen->HandleInlineFunctionDefinition(D); - if (FrontendTimesIsEnabled) + if (TimerIsEnabled) LLVMIRGeneration.stopTimer(); } @@ -280,7 +283,7 @@ namespace clang { { llvm::TimeTraceScope TimeScope("Frontend"); PrettyStackTraceString CrashInfo("Per-file LLVM IR generation"); - if (FrontendTimesIsEnabled) { + if (TimerIsEnabled) { LLVMIRGenerationRefCount += 1; if (LLVMIRGenerationRefCount == 1) LLVMIRGeneration.startTimer(); @@ -288,7 +291,7 @@ namespace clang { Gen->HandleTranslationUnit(C); - if (FrontendTimesIsEnabled) { + if (TimerIsEnabled) { LLVMIRGenerationRefCount -= 1; if (LLVMIRGenerationRefCount == 0) LLVMIRGeneration.stopTimer(); @@ -967,8 +970,8 @@ CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { std::unique_ptr Result(new BackendConsumer( BA, CI.getDiagnostics(), CI.getHeaderSearchOpts(), CI.getPreprocessorOpts(), CI.getCodeGenOpts(), CI.getTargetOpts(), - CI.getLangOpts(), CI.getFrontendOpts().ShowTimers, std::string(InFile), - std::move(LinkModules), std::move(OS), *VMContext, CoverageInfo)); + CI.getLangOpts(), std::string(InFile), std::move(LinkModules), + std::move(OS), *VMContext, CoverageInfo)); BEConsumer = Result.get(); // Enable generating macro debug info only when debug info is not disabled and @@ -1115,7 +1118,6 @@ void CodeGenAction::ExecuteAction() { BackendConsumer Result(BA, CI.getDiagnostics(), CI.getHeaderSearchOpts(), CI.getPreprocessorOpts(), CI.getCodeGenOpts(), CI.getTargetOpts(), CI.getLangOpts(), - CI.getFrontendOpts().ShowTimers, std::move(LinkModules), *VMContext, nullptr); // PR44896: Force DiscardValueNames as false. DiscardValueNames cannot be // true here because the valued names are needed for reading textual IR. diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 86d4c5a8658..baf7d5c58e4 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -5501,6 +5501,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_print_source_range_info); Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_parseable_fixits); Args.AddLastArg(CmdArgs, options::OPT_ftime_report); + Args.AddLastArg(CmdArgs, options::OPT_ftime_report_EQ); Args.AddLastArg(CmdArgs, options::OPT_ftime_trace); Args.AddLastArg(CmdArgs, options::OPT_ftime_trace_granularity_EQ); Args.AddLastArg(CmdArgs, options::OPT_ftrapv); diff --git a/clang/lib/Frontend/CMakeLists.txt b/clang/lib/Frontend/CMakeLists.txt index af5446618b0..90422855bd0 100644 --- a/clang/lib/Frontend/CMakeLists.txt +++ b/clang/lib/Frontend/CMakeLists.txt @@ -23,7 +23,6 @@ add_clang_library(clangFrontend FrontendAction.cpp FrontendActions.cpp FrontendOptions.cpp - FrontendTiming.cpp HeaderIncludeGen.cpp InitHeaderSearch.cpp InitPreprocessor.cpp diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index 5c82878d8e2..fa3d50aeedf 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -975,7 +975,7 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) { << " based upon " << BACKEND_PACKAGE_STRING << " default target " << llvm::sys::getDefaultTargetTriple() << "\n"; - if (getFrontendOpts().ShowTimers) + if (getCodeGenOpts().TimePasses) createFrontendTimer(); if (getFrontendOpts().ShowStats || !getFrontendOpts().StatsFile.empty()) diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 547dadd3793..6d4e677f026 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1046,6 +1046,26 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.setFramePointer(FP); } + if (const Arg *A = Args.getLastArg(OPT_ftime_report, OPT_ftime_report_EQ)) { + Opts.TimePasses = true; + + // -ftime-report= is only for new pass manager. + if (A->getOption().getID() == OPT_ftime_report_EQ) { + if (!Opts.ExperimentalNewPassManager) + Diags.Report(diag::err_drv_argument_only_allowed_with) + << A->getAsString(Args) << "-fexperimental-new-pass-manager"; + + StringRef Val = A->getValue(); + if (Val == "per-pass") + Opts.TimePassesPerRun = false; + else if (Val == "per-pass-run") + Opts.TimePassesPerRun = true; + else + Diags.Report(diag::err_drv_invalid_value) + << A->getAsString(Args) << A->getValue(); + } + } + Opts.DisableFree = Args.hasArg(OPT_disable_free); Opts.DiscardValueNames = Args.hasArg(OPT_discard_value_names); Opts.DisableTailCalls = Args.hasArg(OPT_mdisable_tail_calls); diff --git a/clang/lib/Frontend/FrontendTiming.cpp b/clang/lib/Frontend/FrontendTiming.cpp deleted file mode 100644 index e3f44c9999f..00000000000 --- a/clang/lib/Frontend/FrontendTiming.cpp +++ /dev/null @@ -1,19 +0,0 @@ -//===- FrontendTiming.cpp - Implements Frontend timing utils -------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file keps implementation of frontend timing utils. -// -//===----------------------------------------------------------------------===// - -#include "clang/Frontend/Utils.h" - -namespace clang { - -bool FrontendTimesIsEnabled = false; - -} diff --git a/clang/test/Driver/time-report.c b/clang/test/Driver/time-report.c new file mode 100644 index 00000000000..72fb6f4550b --- /dev/null +++ b/clang/test/Driver/time-report.c @@ -0,0 +1,11 @@ +// Check that -ftime-report flag is passed to compiler. The value of the flag +// is only diagnosed in the compiler for simplicity since this is a dev option. +// RUN: %clang -### -c -ftime-report %s 2>&1 | FileCheck %s +// RUN: %clang -### -c -ftime-report=per-pass %s 2>&1 | FileCheck %s -check-prefix=PER-PASS +// RUN: %clang -### -c -ftime-report=per-pass-run %s 2>&1 | FileCheck %s -check-prefix=PER-PASS-INVOKE +// RUN: %clang -### -c -ftime-report=unknown %s 2>&1 | FileCheck %s -check-prefix=UNKNOWN + +// CHECK: "-ftime-report" +// PER-PASS: "-ftime-report=per-pass" +// PER-PASS-INVOKE: "-ftime-report=per-pass-run" +// UNKNOWN: "-ftime-report=unknown" diff --git a/clang/test/Misc/time-passes.c b/clang/test/Misc/time-passes.c new file mode 100644 index 00000000000..7347cf5a047 --- /dev/null +++ b/clang/test/Misc/time-passes.c @@ -0,0 +1,41 @@ +// Check that legacy pass manager could only use -ftime-report +// RUN: %clang_cc1 -fno-experimental-new-pass-manager -emit-obj -O1 \ +// RUN: -ftime-report %s -o /dev/null 2>&1 | \ +// RUN: FileCheck %s --check-prefixes=TIME,LPM +// RUN: not %clang_cc1 -fno-experimental-new-pass-manager -emit-obj -O1 \ +// RUN: -ftime-report=per-pass %s -o /dev/null 2>&1 | \ +// RUN: FileCheck %s --check-prefixes=ERROR +// RUN: not %clang_cc1 -fno-experimental-new-pass-manager -emit-obj -O1 \ +// RUN: -ftime-report=per-pass-run %s -o /dev/null 2>&1 | \ +// RUN: FileCheck %s --check-prefixes=ERROR + +// Check -ftime-report/-ftime-report= output for the new pass manager +// RUN: %clang_cc1 -emit-obj -O1 -fexperimental-new-pass-manager \ +// RUN: -ftime-report %s -o /dev/null 2>&1 | \ +// RUN: FileCheck %s --check-prefixes=TIME,NPM +// RUN: %clang_cc1 -emit-obj -O1 -fexperimental-new-pass-manager \ +// RUN: -ftime-report=per-pass %s -o /dev/null 2>&1 | \ +// RUN: FileCheck %s --check-prefixes=TIME,NPM +// RUN: %clang_cc1 -emit-obj -O1 -fexperimental-new-pass-manager \ +// RUN: -ftime-report=per-pass-run %s -o /dev/null 2>&1 | \ +// RUN: FileCheck %s --check-prefixes=TIME,NPM-PER-INVOKE + +// TIME: Pass execution timing report +// TIME: Total Execution Time: +// TIME: Name +// LPM-DAG: Dominator Tree Construction # +// LPM-DAG: Dominator Tree Construction # +// LPM-DAG: Dominator Tree Construction # +// NPM-PER-INVOKE-DAG: InstCombinePass # +// NPM-PER-INVOKE-DAG: InstCombinePass # +// NPM-PER-INVOKE-DAG: InstCombinePass # +// NPM-NOT: InstCombinePass # +// NPM: InstCombinePass{{$}} +// NPM-NOT: InstCombinePass # +// TIME: Total{{$}} +// LPM-NOT: Pass execution timing report +// NPM: Pass execution timing report + +// ERROR: error: invalid argument '-ftime-report={{.*}}' only allowed with '-fexperimental-new-pass-manager' + +int foo(int x, int y) { return x + y; } diff --git a/llvm/include/llvm/IR/PassTimingInfo.h b/llvm/include/llvm/IR/PassTimingInfo.h index a3608971217..e44321b4af6 100644 --- a/llvm/include/llvm/IR/PassTimingInfo.h +++ b/llvm/include/llvm/IR/PassTimingInfo.h @@ -38,11 +38,6 @@ void reportAndResetTimings(raw_ostream *OutStream = nullptr); /// Request the timer for this legacy-pass-manager's pass instance. Timer *getPassTimer(Pass *); -/// If the user specifies the -time-passes argument on an LLVM tool command line -/// then the value of this boolean will be true, otherwise false. -/// This is the storage for the -time-passes option. -extern bool TimePassesIsEnabled; - /// This class implements -time-passes functionality for new pass manager. /// It provides the pass-instrumentation callbacks that measure the pass /// execution time. They collect timing info into individual timers as @@ -70,9 +65,11 @@ class TimePassesHandler { raw_ostream *OutStream = nullptr; bool Enabled; + bool PerRun; public: - TimePassesHandler(bool Enabled = TimePassesIsEnabled); + TimePassesHandler(); + TimePassesHandler(bool Enabled, bool PerRun = false); /// Destructor handles the print action if it has not been handled before. ~TimePassesHandler() { print(); } diff --git a/llvm/include/llvm/Pass.h b/llvm/include/llvm/Pass.h index 2fe7aee2e37..af583dae58b 100644 --- a/llvm/include/llvm/Pass.h +++ b/llvm/include/llvm/Pass.h @@ -309,6 +309,12 @@ protected: /// then the value of this boolean will be true, otherwise false. /// This is the storage for the -time-passes option. extern bool TimePassesIsEnabled; +/// If TimePassesPerRun is true, there would be one line of report for +/// each pass invocation. +/// If TimePassesPerRun is false, there would be only one line of +/// report for each pass (even there are more than one pass objects). +/// (For new pass manager only) +extern bool TimePassesPerRun; } // end namespace llvm diff --git a/llvm/lib/IR/PassTimingInfo.cpp b/llvm/lib/IR/PassTimingInfo.cpp index fa3296cc134..d0c1517f480 100644 --- a/llvm/lib/IR/PassTimingInfo.cpp +++ b/llvm/lib/IR/PassTimingInfo.cpp @@ -35,11 +35,17 @@ using namespace llvm; namespace llvm { bool TimePassesIsEnabled = false; +bool TimePassesPerRun = false; static cl::opt EnableTiming( "time-passes", cl::location(TimePassesIsEnabled), cl::Hidden, cl::desc("Time each pass, printing elapsed time for each on exit")); +static cl::opt EnableTimingPerRun( + "time-passes-per-run", cl::location(TimePassesPerRun), cl::Hidden, + cl::desc("Time each pass run, printing elapsed time for each run on exit"), + cl::callback([](const bool &) { TimePassesIsEnabled = true; })); + namespace { namespace legacy { @@ -165,6 +171,13 @@ void reportAndResetTimings(raw_ostream *OutStream) { /// Returns the timer for the specified pass invocation of \p PassID. /// Each time it creates a new timer. Timer &TimePassesHandler::getPassTimer(StringRef PassID) { + if (!PerRun) { + TimerVector &Timers = TimingData[PassID]; + if (Timers.size() == 0) + Timers.emplace_back(new Timer(PassID, PassID, TG)); + return *Timers.front(); + } + // Take a vector of Timers created for this \p PassID and append // one more timer to it. TimerVector &Timers = TimingData[PassID]; @@ -179,8 +192,12 @@ Timer &TimePassesHandler::getPassTimer(StringRef PassID) { return *T; } -TimePassesHandler::TimePassesHandler(bool Enabled) - : TG("pass", "... Pass execution timing report ..."), Enabled(Enabled) {} +TimePassesHandler::TimePassesHandler(bool Enabled, bool PerRun) + : TG("pass", "... Pass execution timing report ..."), Enabled(Enabled), + PerRun(PerRun) {} + +TimePassesHandler::TimePassesHandler() + : TimePassesHandler(TimePassesIsEnabled, TimePassesPerRun) {} void TimePassesHandler::setOutStream(raw_ostream &Out) { OutStream = &Out; diff --git a/llvm/test/Other/time-passes.ll b/llvm/test/Other/time-passes.ll index e3b5a003703..b9c85b7917b 100644 --- a/llvm/test/Other/time-passes.ll +++ b/llvm/test/Other/time-passes.ll @@ -1,9 +1,15 @@ ; RUN: opt -enable-new-pm=0 < %s -disable-output -instcombine -instcombine -licm -time-passes 2>&1 | FileCheck %s --check-prefix=TIME --check-prefix=TIME-LEGACY ; RUN: opt -enable-new-pm=0 < %s -disable-output -instcombine -instcombine -licm -licm -time-passes 2>&1 | FileCheck %s --check-prefix=TIME --check-prefix=TIME-LEGACY --check-prefix=TIME-DOUBLE-LICM-LEGACY -; RUN: opt < %s -disable-output -passes='instcombine,instcombine,loop(licm)' -time-passes 2>&1 | FileCheck %s --check-prefix=TIME --check-prefix=TIME-NEW -; RUN: opt < %s -disable-output -passes='instcombine,loop(licm),instcombine,loop(licm)' -time-passes 2>&1 | FileCheck %s --check-prefix=TIME --check-prefix=TIME-NEW -check-prefix=TIME-DOUBLE-LICM-NEW ; RUN: opt < %s -disable-output -passes='default' -time-passes 2>&1 | FileCheck %s --check-prefix=TIME ; +; For new pass manager, check that -time-passes-per-run emit one report for each pass run. +; RUN: opt < %s -disable-output -passes='instcombine,instcombine,loop(licm)' -time-passes-per-run 2>&1 | FileCheck %s --check-prefix=TIME --check-prefix=TIME-NEW +; RUN: opt < %s -disable-output -passes='instcombine,loop(licm),instcombine,loop(licm)' -time-passes-per-run 2>&1 | FileCheck %s --check-prefix=TIME --check-prefix=TIME-NEW -check-prefix=TIME-DOUBLE-LICM-NEW +; +; For new pass manager, check that -time-passes emit one report for each pass. +; RUN: opt < %s -disable-output -passes='instcombine,instcombine,loop(licm)' -time-passes 2>&1 | FileCheck %s --check-prefixes=TIME,TIME-NEW-PER-PASS +; RUN: opt < %s -disable-output -passes='instcombine,loop(licm),instcombine,loop(licm)' -time-passes 2>&1 | FileCheck %s --check-prefixes=TIME,TIME-NEW-PER-PASS +; ; The following 4 test runs verify -info-output-file interaction (default goes to stderr, '-' goes to stdout). ; RUN: opt -enable-new-pm=0 < %s -disable-output -O2 -time-passes -info-output-file='-' 2>/dev/null | FileCheck %s --check-prefix=TIME ; RUN: opt < %s -disable-output -passes='default' -time-passes -info-output-file='-' 2>/dev/null | FileCheck %s --check-prefix=TIME @@ -46,6 +52,24 @@ ; TIME-NEW-DAG: VerifierPass ; TIME-NEW-DAG: DominatorTreeAnalysis ; TIME-NEW-DAG: TargetLibraryAnalysis +; TIME-NEW-PER-PASS-DAG: InstCombinePass +; TIME-NEW-PER-PASS-DAG: LICMPass +; TIME-NEW-PER-PASS-DAG: LCSSAPass +; TIME-NEW-PER-PASS-DAG: LoopSimplifyPass +; TIME-NEW-PER-PASS-DAG: ScalarEvolutionAnalysis +; TIME-NEW-PER-PASS-DAG: LoopAnalysis +; TIME-NEW-PER-PASS-DAG: VerifierPass +; TIME-NEW-PER-PASS-DAG: DominatorTreeAnalysis +; TIME-NEW-PER-PASS-DAG: TargetLibraryAnalysis +; TIME-NEW-PER-PASS-NOT: InstCombinePass # +; TIME-NEW-PER-PASS-NOT: LICMPass # +; TIME-NEW-PER-PASS-NOT: LCSSAPass # +; TIME-NEW-PER-PASS-NOT: LoopSimplifyPass # +; TIME-NEW-PER-PASS-NOT: ScalarEvolutionAnalysis # +; TIME-NEW-PER-PASS-NOT: LoopAnalysis # +; TIME-NEW-PER-PASS-NOT: VerifierPass # +; TIME-NEW-PER-PASS-NOT: DominatorTreeAnalysis # +; TIME-NEW-PER-PASS-NOT: TargetLibraryAnalysis # ; TIME: Total{{$}} define i32 @foo() {