diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -252,7 +252,8 @@ 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 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2005,7 +2005,12 @@ 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 --- a/clang/include/clang/Frontend/FrontendOptions.h +++ b/clang/include/clang/Frontend/FrontendOptions.h @@ -239,9 +239,6 @@ /// 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: 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 --- a/clang/include/clang/Frontend/Utils.h +++ b/clang/include/clang/Frontend/Utils.h @@ -227,10 +227,6 @@ // 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 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -907,7 +907,7 @@ 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 @@ /// `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 --- a/clang/lib/CodeGen/CodeGenAction.cpp +++ b/clang/lib/CodeGen/CodeGenAction.cpp @@ -122,6 +122,8 @@ /// 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ Context = &Ctx; - if (FrontendTimesIsEnabled) + if (TimerIsEnabled) LLVMIRGeneration.startTimer(); Gen->Initialize(Ctx); - if (FrontendTimesIsEnabled) + if (TimerIsEnabled) LLVMIRGeneration.stopTimer(); } @@ -206,7 +209,7 @@ "LLVM IR generation of declaration"); // Recurse. - if (FrontendTimesIsEnabled) { + if (TimerIsEnabled) { LLVMIRGenerationRefCount += 1; if (LLVMIRGenerationRefCount == 1) LLVMIRGeneration.startTimer(); @@ -214,7 +217,7 @@ Gen->HandleTopLevelDecl(D); - if (FrontendTimesIsEnabled) { + if (TimerIsEnabled) { LLVMIRGenerationRefCount -= 1; if (LLVMIRGenerationRefCount == 0) LLVMIRGeneration.stopTimer(); @@ -227,12 +230,12 @@ 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 @@ { 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 @@ Gen->HandleTranslationUnit(C); - if (FrontendTimesIsEnabled) { + if (TimerIsEnabled) { LLVMIRGenerationRefCount -= 1; if (LLVMIRGenerationRefCount == 0) LLVMIRGeneration.stopTimer(); @@ -967,8 +970,8 @@ 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 @@ 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 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -5501,6 +5501,7 @@ 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 --- a/clang/lib/Frontend/CMakeLists.txt +++ b/clang/lib/Frontend/CMakeLists.txt @@ -23,7 +23,6 @@ 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 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -975,7 +975,7 @@ << " 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 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1046,6 +1046,26 @@ 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 --- 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 --- /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 --- /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 --- a/llvm/include/llvm/IR/PassTimingInfo.h +++ b/llvm/include/llvm/IR/PassTimingInfo.h @@ -38,11 +38,6 @@ /// 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 @@ 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 --- a/llvm/include/llvm/Pass.h +++ b/llvm/include/llvm/Pass.h @@ -309,6 +309,12 @@ /// 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 --- a/llvm/lib/IR/PassTimingInfo.cpp +++ b/llvm/lib/IR/PassTimingInfo.cpp @@ -35,11 +35,17 @@ 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 @@ /// 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 @@ 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 --- 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() {