]> granicus.if.org Git - clang/commitdiff
CC1: Add -save-stats option
authorMatthias Braun <matze@braunis.de>
Mon, 26 Sep 2016 18:53:34 +0000 (18:53 +0000)
committerMatthias Braun <matze@braunis.de>
Mon, 26 Sep 2016 18:53:34 +0000 (18:53 +0000)
This option behaves in a similar spirit as -save-temps and writes
internal llvm statistics in json format to a file.

Differential Revision: https://reviews.llvm.org/D24820

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@282426 91177308-0d34-0410-b5e6-96231b3b80d8

12 files changed:
docs/CommandGuide/clang.rst
include/clang/Basic/DiagnosticFrontendKinds.td
include/clang/Driver/CC1Options.td
include/clang/Driver/Options.td
include/clang/Frontend/FrontendOptions.h
lib/Driver/Tools.cpp
lib/Frontend/CompilerInstance.cpp
lib/Frontend/CompilerInvocation.cpp
lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
test/Driver/save-stats.c [new file with mode: 0644]
test/Frontend/stats-file.c [new file with mode: 0644]
test/Misc/warning-flags.c

index 7a616667dd40a59f606574d660b62fcf7c7208bf..b4b607d5a24b3fce6a7949f7c9ede20ec6ca96be 100644 (file)
@@ -408,6 +408,12 @@ Driver Options
 
   Save intermediate compilation results.
 
+.. option:: -save-stats, -save-stats=cwd, -save-stats=obj
+
+  Save internal code generation (LLVM) statistics to a file in the current
+  directory (:option:`-save-stats`/:option:`-save-stats=cwd`) or the directory
+  of the output file (:option:`-save-state=obj`).
+
 .. option:: -integrated-as, -no-integrated-as
 
   Used to enable and disable, respectively, the use of the integrated
index 43b5dfc83de6fb217e7d9ecbaa2d502e9df903b4..6be2f391863af09ce5b9c9e5ee4e39113ddb1626 100644 (file)
@@ -107,6 +107,8 @@ def warn_fe_cc_print_header_failure : Warning<
     "unable to open CC_PRINT_HEADERS file: %0 (using stderr)">;
 def warn_fe_cc_log_diagnostics_failure : Warning<
     "unable to open CC_LOG_DIAGNOSTICS file: %0 (using stderr)">;
+def warn_fe_unable_to_open_stats_file : Warning<
+    "unable to open statistics output file '%0': '%1'">;
 def err_fe_no_pch_in_dir : Error<
     "no suitable precompiled header file found in directory '%0'">;
 def err_fe_action_not_available : Error<
index 65abc8f2ab48f16b94b9bb5415cc81ceb9dbcd16..66e1ad6fc6e9889aa23a4b9fdb54c475685a7181 100644 (file)
@@ -509,6 +509,8 @@ def arcmt_migrate : Flag<["-"], "arcmt-migrate">,
 
 def print_stats : Flag<["-"], "print-stats">,
   HelpText<"Print performance metrics and statistics">;
+def stats_file : Joined<["-"], "stats-file=">,
+  HelpText<"Filename to write statistics to">;
 def fdump_record_layouts : Flag<["-"], "fdump-record-layouts">,
   HelpText<"Dump record layout information">;
 def fdump_record_layouts_simple : Flag<["-"], "fdump-record-layouts-simple">,
index d017b0b1b2d103a444d95552467171030d7bb5f6..a0e9a0d082acecc9ba3d96f11cd2e17226f15d93 100644 (file)
@@ -1876,6 +1876,11 @@ def save_temps_EQ : Joined<["-", "--"], "save-temps=">, Flags<[DriverOption]>,
 def save_temps : Flag<["-", "--"], "save-temps">, Flags<[DriverOption]>,
   Alias<save_temps_EQ>, AliasArgs<["cwd"]>,
   HelpText<"Save intermediate compilation results">;
+def save_stats_EQ : Joined<["-", "--"], "save-stats=">, Flags<[DriverOption]>,
+  HelpText<"Save llvm statistics.">;
+def save_stats : Flag<["-", "--"], "save-stats">, Flags<[DriverOption]>,
+  Alias<save_stats_EQ>, AliasArgs<["cwd"]>,
+  HelpText<"Save llvm statistics.">;
 def via_file_asm : Flag<["-", "--"], "via-file-asm">, InternalDebugOpt,
   HelpText<"Write assembly to file for input to assemble jobs">;
 def sectalign : MultiArg<["-"], "sectalign", 3>;
index 4df5e2bb9ba178ef382a36674333a3ef1adb9463..aad397526a038f7a83071e3c4a18eafa1a8be508 100644 (file)
@@ -273,6 +273,9 @@ public:
   // included by this file.
   std::string FindPchSource;
 
+  /// Filename to write statistics to.
+  std::string StatsFile;
+
 public:
   FrontendOptions() :
     DisableFree(false), RelocatablePCH(false), ShowHelp(false),
index dcdc92a1305192245ad5e4c671f5b03fda12dc54..d806efd9a2a107f5e81ad7d4bc2d87c854e0f6d3 100644 (file)
@@ -6107,6 +6107,33 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
     A->claim();
   }
 
+  // Setup statistics file output.
+  if (const Arg *A = Args.getLastArg(options::OPT_save_stats_EQ)) {
+    StringRef SaveStats = A->getValue();
+
+    SmallString<128> StatsFile;
+    bool DoSaveStats = false;
+    if (SaveStats == "obj") {
+      if (Output.isFilename()) {
+        StatsFile.assign(Output.getFilename());
+        llvm::sys::path::remove_filename(StatsFile);
+      }
+      DoSaveStats = true;
+    } else if (SaveStats == "cwd") {
+      DoSaveStats = true;
+    } else {
+      D.Diag(diag::err_drv_invalid_value) << A->getAsString(Args) << SaveStats;
+    }
+
+    if (DoSaveStats) {
+      StringRef BaseName = llvm::sys::path::filename(Input.getBaseInput());
+      llvm::sys::path::append(StatsFile, BaseName);
+      llvm::sys::path::replace_extension(StatsFile, "stats");
+      CmdArgs.push_back(Args.MakeArgString(Twine("-stats-file=") +
+                                           StatsFile));
+    }
+  }
+
   // Forward -Xclang arguments to -cc1, and -mllvm arguments to the LLVM option
   // parser.
   Args.AddAllArgValues(CmdArgs, options::OPT_Xclang);
index 627134e8dd16d0460f25326228f3689533fd9276..67b0c2e0746ba00fec03949abcd55dc453a1b349 100644 (file)
@@ -858,7 +858,7 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
   if (getFrontendOpts().ShowTimers)
     createFrontendTimer();
 
-  if (getFrontendOpts().ShowStats)
+  if (getFrontendOpts().ShowStats || !getFrontendOpts().StatsFile.empty())
     llvm::EnableStatistics();
 
   for (const FrontendInputFile &FIF : getFrontendOpts().Inputs) {
@@ -892,9 +892,24 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
       OS << " generated.\n";
   }
 
-  if (getFrontendOpts().ShowStats && hasFileManager()) {
-    getFileManager().PrintStats();
-    OS << "\n";
+  if (getFrontendOpts().ShowStats) {
+    if (hasFileManager()) {
+      getFileManager().PrintStats();
+      OS << '\n';
+    }
+    llvm::PrintStatistics(OS);
+  }
+  StringRef StatsFile = getFrontendOpts().StatsFile;
+  if (!StatsFile.empty()) {
+    std::error_code EC;
+    auto StatS = llvm::make_unique<llvm::raw_fd_ostream>(StatsFile, EC,
+                                                         llvm::sys::fs::F_Text);
+    if (EC) {
+      getDiagnostics().Report(diag::warn_fe_unable_to_open_stats_file)
+          << StatsFile << EC.message();
+    } else {
+      llvm::PrintStatisticsJSON(*StatS);
+    }
   }
 
   return !getDiagnostics().getClient()->getNumErrors();
index c3fbda114eff73df40be87fb70ed8f7ad20424fe..6b2df349f8b0bd8fe070cae6b38dc9f22f6e3b7d 100644 (file)
@@ -1252,6 +1252,7 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
   Opts.AuxTriple =
       llvm::Triple::normalize(Args.getLastArgValue(OPT_aux_triple));
   Opts.FindPchSource = Args.getLastArgValue(OPT_find_pch_source_EQ);
+  Opts.StatsFile = Args.getLastArgValue(OPT_stats_file);
 
   if (const Arg *A = Args.getLastArg(OPT_arcmt_check,
                                      OPT_arcmt_modify,
index 1dc490e1c70b95ce226101b668a38cd24b2cde5b..751053b62037aa2346d82f05574549e93f57f6f8 100644 (file)
@@ -194,8 +194,10 @@ public:
   }
 
   ~AnalysisConsumer() override {
-    if (Opts->PrintStats)
+    if (Opts->PrintStats) {
       delete TUTotalTimer;
+      llvm::PrintStatistics();
+    }
   }
 
   void DigestAnalyzerOptions() {
diff --git a/test/Driver/save-stats.c b/test/Driver/save-stats.c
new file mode 100644 (file)
index 0000000..19a9d6d
--- /dev/null
@@ -0,0 +1,20 @@
+// RUN: %clang -target x86_64-apple-darwin -save-stats %s -### 2>&1 | FileCheck %s
+// RUN: %clang -target x86_64-apple-darwin -save-stats=cwd %s -### 2>&1 | FileCheck %s
+// CHECK: "-stats-file=save-stats.stats"
+// CHECK: "{{.*}}save-stats.c"
+
+// RUN: %clang -target x86_64-apple-darwin -S %s -### 2>&1 | FileCheck %s -check-prefix=NO-STATS
+// NO-STATS-NO: -stats-file
+// NO-STATS: "{{.*}}save-stats.c"
+// NO-STATS-NO: -stats-file
+
+// RUN: %clang -target x86_64-apple-darwin -save-stats=obj -c -o obj/dir/save-stats.o %s -### 2>&1 | FileCheck %s -check-prefix=CHECK-OBJ
+// CHECK-OBJ: "-stats-file=obj/dir{{.}}save-stats.stats"
+// CHECK-OBJ: "-o" "obj/dir{{.}}save-stats.o"
+
+// RUN: %clang -target x86_64-apple-darwin -save-stats=obj -c %s -### 2>&1 | FileCheck %s -check-prefix=CHECK-OBJ-NOO
+// CHECK-OBJ-NOO: "-stats-file=save-stats.stats"
+// CHECK-OBJ-NOO: "-o" "save-stats.o"
+
+// RUN: %clang -target x86_64-apple-darwin -save-stats=bla -c %s -### 2>&1 | FileCheck %s -check-prefix=CHECK-INVALID
+// CHECK-INVALID: invalid value 'bla' in '-save-stats=bla'
diff --git a/test/Frontend/stats-file.c b/test/Frontend/stats-file.c
new file mode 100644 (file)
index 0000000..1869eb3
--- /dev/null
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -emit-llvm -o /dev/null -stats-file=%t %s
+// RUN: FileCheck -input-file=%t %s
+// CHECK: {
+//  ... here come some json values ...
+// CHECK: }
+
+// RUN: %clang_cc1 -emit-llvm -o %t -stats-file=%S/doesnotexist/bla %s 2>&1 | FileCheck -check-prefix=OUTPUTFAIL %s
+// OUTPUTFAIL: warning: unable to open statistics output file '{{.*}}doesnotexist{{.}}bla': '{{[Nn]}}o such file or directory'
index 69e820542ab71b416f5f859c2c253ba3aebcaf0b..1a216d59efe2c02ef47791258a9201e2001470ea 100644 (file)
@@ -18,7 +18,7 @@ This test serves two purposes:
 
 The list of warnings below should NEVER grow.  It should gradually shrink to 0.
 
-CHECK: Warnings without flags (84):
+CHECK: Warnings without flags (85):
 CHECK-NEXT:   ext_excess_initializers
 CHECK-NEXT:   ext_excess_initializers_in_char_array_initializer
 CHECK-NEXT:   ext_expected_semi_decl_list
@@ -66,6 +66,7 @@ CHECK-NEXT:   warn_extraneous_char_constant
 CHECK-NEXT:   warn_fe_cc_log_diagnostics_failure
 CHECK-NEXT:   warn_fe_cc_print_header_failure
 CHECK-NEXT:   warn_fe_macro_contains_embedded_newline
+CHECK-NEXT:   warn_fe_unable_to_open_stats_file
 CHECK-NEXT:   warn_file_asm_volatile
 CHECK-NEXT:   warn_ignoring_ftabstop_value
 CHECK-NEXT:   warn_implements_nscopying