Skip to content

[clang][timers][stats] Add a flag to enable timers in the stats file #149946

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

alanzhao1
Copy link
Contributor

As reported in #138173, enabling -ftime-report adds pass timing info to the stats file if -stats-file is specified. This was determined to be WAI. However, if one intentionally wants to put timer information in the stats file, using -ftime-report may lead to a lot of logspam (that can't be removed by directing stderr to /dev/null as that would also redirect compiler errors). To address this, this PR adds a flag -stats-file-timers that adds timer data to the stats file without outputting to stderr.

As reported in llvm#138173, enabling `-ftime-report` adds pass timing info
to the stats file if `-stats-file` is specified. This was determined to
be WAI. However, if one intentionally wants to put timer information in
the stats file, using `-ftime-report` may lead to a lot of logspam (that
can't be removed by directing stderr to `/dev/null` as that would also
redirect compiler errors). To address this, this PR adds a flag
`-stats-file-timers` that adds timer data to the stats file without
outputting to stderr.
@alanzhao1 alanzhao1 requested a review from aeubanks July 21, 2025 23:41
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Jul 21, 2025
@llvmbot
Copy link
Member

llvmbot commented Jul 21, 2025

@llvm/pr-subscribers-clang

Author: Alan Zhao (alanzhao1)

Changes

As reported in #138173, enabling -ftime-report adds pass timing info to the stats file if -stats-file is specified. This was determined to be WAI. However, if one intentionally wants to put timer information in the stats file, using -ftime-report may lead to a lot of logspam (that can't be removed by directing stderr to /dev/null as that would also redirect compiler errors). To address this, this PR adds a flag -stats-file-timers that adds timer data to the stats file without outputting to stderr.


Full diff: https://github.com/llvm/llvm-project/pull/149946.diff

5 Files Affected:

  • (modified) clang/include/clang/Basic/CodeGenOptions.def (+2-1)
  • (modified) clang/include/clang/Driver/Options.td (+3)
  • (modified) clang/lib/Frontend/CompilerInvocation.cpp (+4-3)
  • (modified) clang/test/Misc/time-passes.c (+4)
  • (modified) clang/tools/driver/cc1_main.cpp (+1-1)
diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def
index cfffeb71f09d1..e137738102544 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -313,9 +313,10 @@ CODEGENOPT(SpeculativeLoadHardening, 1, 0, Benign) ///< Enable speculative load
 CODEGENOPT(FineGrainedBitfieldAccesses, 1, 0, Benign) ///< Enable fine-grained bitfield accesses.
 CODEGENOPT(StrictEnums       , 1, 0, Benign) ///< Optimize based on strict enum definition.
 CODEGENOPT(StrictVTablePointers, 1, 0, Benign) ///< Optimize based on the strict vtable pointers
-CODEGENOPT(TimePasses        , 1, 0, Benign) ///< Set when -ftime-report or -ftime-report= or -ftime-report-json is enabled.
+CODEGENOPT(TimePasses        , 1, 0, Benign) ///< Set when -ftime-report, -ftime-report=, -ftime-report-json, or -stats-file-timers is enabled.
 CODEGENOPT(TimePassesPerRun  , 1, 0, Benign) ///< Set when -ftime-report=per-pass-run is enabled.
 CODEGENOPT(TimePassesJson    , 1, 0, Benign) ///< Set when -ftime-report-json is enabled.
+CODEGENOPT(TimePassesStatsFile     , 1, 0, Benign) ///< Set when -stats-file-timers is enabled.
 CODEGENOPT(TimeTrace         , 1, 0, Benign) ///< Set when -ftime-trace is enabled.
 VALUE_CODEGENOPT(TimeTraceGranularity, 32, 500, Benign) ///< 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 e30c152cbce2e..20def5dd0eb5e 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -8253,6 +8253,9 @@ def stats_file : Joined<["-"], "stats-file=">,
 def stats_file_append : Flag<["-"], "stats-file-append">,
   HelpText<"If stats should be appended to stats-file instead of overwriting it">,
   MarshallingInfoFlag<FrontendOpts<"AppendStats">>;
+def stats_file_timers : Flag<["-"], "stats-file-timers">,
+                        HelpText<"If stats should include timers.">,
+                        MarshallingInfoFlag<CodeGenOpts<"TimePassesStatsFile">>;
 def fdump_record_layouts_simple : Flag<["-"], "fdump-record-layouts-simple">,
   HelpText<"Dump record layout information in a simple form used for testing">,
   MarshallingInfoFlag<LangOpts<"DumpRecordLayoutsSimple">>;
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 3a36250da57a3..30bca9e72eae0 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -2013,8 +2013,9 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
             : llvm::codegenoptions::DebugTemplateNamesKind::Mangled);
   }
 
-  if (const Arg *A = Args.getLastArg(OPT_ftime_report, OPT_ftime_report_EQ,
-                                     OPT_ftime_report_json)) {
+  if (Args.hasArg(OPT_ftime_report, OPT_ftime_report_EQ,
+                  OPT_ftime_report_json) ||
+      Opts.TimePassesStatsFile) {
     Opts.TimePasses = true;
 
     // -ftime-report= is only for new pass manager.
@@ -2026,7 +2027,7 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
         Opts.TimePassesPerRun = true;
       else
         Diags.Report(diag::err_drv_invalid_value)
-            << A->getAsString(Args) << A->getValue();
+            << EQ->getAsString(Args) << EQ->getValue();
     }
 
     if (Args.getLastArg(OPT_ftime_report_json))
diff --git a/clang/test/Misc/time-passes.c b/clang/test/Misc/time-passes.c
index 370f52e4904fe..2f952d97b5967 100644
--- a/clang/test/Misc/time-passes.c
+++ b/clang/test/Misc/time-passes.c
@@ -19,6 +19,10 @@
 // RUN:     -ftime-report-json %s -o /dev/null \
 // RUN:     -mllvm -info-output-file=%t
 // RUN: cat %t | FileCheck %s --check-prefixes=JSON
+// RUN: %clang_cc1 -emit-obj -O1 \
+// RUN:     %s -o /dev/null \
+// RUN:     -stats-file=%t -stats-file-timers 2>&1 | count 0
+// RUN: FileCheck %s -input-file=%t -check-prefixes=JSON
 
 // TIME: Pass execution timing report
 // TIME: Total Execution Time:
diff --git a/clang/tools/driver/cc1_main.cpp b/clang/tools/driver/cc1_main.cpp
index 2c17f28621f5f..9b1e390cb0f34 100644
--- a/clang/tools/driver/cc1_main.cpp
+++ b/clang/tools/driver/cc1_main.cpp
@@ -304,7 +304,7 @@ int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
     *IOFile << "{\n";
     llvm::TimerGroup::printAllJSONValues(*IOFile, "");
     *IOFile << "\n}\n";
-  } else {
+  } else if (!Clang->getCodeGenOpts().TimePassesStatsFile) {
     llvm::TimerGroup::printAll(*IOFile);
   }
   llvm::TimerGroup::clearAll();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants