]> granicus.if.org Git - llvm/commitdiff
Reland "[Remarks] Add -foptimization-record-passes to filter remark emission"
authorFrancis Visoiu Mistrih <francisvm@yahoo.com>
Tue, 12 Mar 2019 21:22:27 +0000 (21:22 +0000)
committerFrancis Visoiu Mistrih <francisvm@yahoo.com>
Tue, 12 Mar 2019 21:22:27 +0000 (21:22 +0000)
Currently we have -Rpass for filtering the remarks that are displayed as
diagnostics, but when using -fsave-optimization-record, there is no way
to filter the remarks while generating them.

This adds support for filtering remarks by passes using a regex.
Ex: `clang -fsave-optimization-record -foptimization-record-passes=inline`

will only emit the remarks coming from the pass `inline`.

This adds:

* `-fsave-optimization-record` to the driver
* `-opt-record-passes` to cc1
* `-lto-pass-remarks-filter` to the LTOCodeGenerator
* `--opt-remarks-passes` to lld
* `-pass-remarks-filter` to llc, opt, llvm-lto, llvm-lto2
* `-opt-remarks-passes` to gold-plugin

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

Original llvm-svn: 355964

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

14 files changed:
include/llvm/IR/RemarkStreamer.h
include/llvm/LTO/Config.h
include/llvm/LTO/LTO.h
lib/IR/RemarkStreamer.cpp
lib/LTO/LTO.cpp
lib/LTO/LTOBackend.cpp
lib/LTO/LTOCodeGenerator.cpp
lib/LTO/ThinLTOCodeGenerator.cpp
test/LTO/Resolution/X86/diagnostic-handler-remarks.ll
test/ThinLTO/X86/diagnostic-handler-remarks.ll
tools/gold/gold-plugin.cpp
tools/llc/llc.cpp
tools/llvm-lto2/llvm-lto2.cpp
tools/opt/opt.cpp

index 38baa2b3b4b3a6be046553f40a72d0d26a829cd0..64de27e372600b62025eafce4ad8871cdfab2850 100644 (file)
 #define LLVM_IR_REMARKSTREAMER_H
 
 #include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/Support/Error.h"
 #include "llvm/Support/YAMLTraits.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Regex.h"
 #include <string>
 #include <vector>
 
@@ -26,6 +28,8 @@ class RemarkStreamer {
   const std::string Filename;
   /// The open raw_ostream that the remark diagnostics are emitted to.
   raw_ostream &OS;
+  /// The regex used to filter remarks based on the passes that emit them.
+  Optional<Regex> PassFilter;
 
   /// The YAML streamer.
   yaml::Output YAMLOutput;
@@ -36,6 +40,9 @@ public:
   StringRef getFilename() const { return Filename; }
   /// Return stream that the remark diagnostics are emitted to.
   raw_ostream &getStream() { return OS; }
+  /// Set a pass filter based on a regex \p Filter.
+  /// Returns an error if the regex is invalid.
+  Error setFilter(StringRef Filter);
   /// Emit a diagnostic through the streamer.
   void emit(const DiagnosticInfoOptimizationBase &Diag);
 };
index bf8cc98ac4da2389d265501b965c50aa80405a45..1e2eeab11c0a29ce38c29b13e73d5187fd265063 100644 (file)
@@ -96,6 +96,9 @@ struct Config {
   /// Optimization remarks file path.
   std::string RemarksFilename = "";
 
+  /// Optimization remarks pass filter.
+  std::string RemarksPasses = "";
+
   /// Whether to emit optimization remarks with hotness informations.
   bool RemarksWithHotness = false;
 
index ab4d874b55e3793629ffb12b415ba8aeed1d9664..be37dbd0c59249f3dab7a192276e56f5e6b1ad37 100644 (file)
@@ -84,6 +84,7 @@ std::string getThinLTOOutputFile(const std::string &Path,
 /// Setup optimization remarks.
 Expected<std::unique_ptr<ToolOutputFile>>
 setupOptimizationRemarks(LLVMContext &Context, StringRef LTORemarksFilename,
+                         StringRef LTORemarksPasses,
                          bool LTOPassRemarksWithHotness, int Count = -1);
 
 class LTO;
index 0b983408e46668605df8e9eef1bf1da2d7d931ce..022c17d6722bf61b1450aaed065e917ca27c8414 100644 (file)
@@ -21,7 +21,21 @@ RemarkStreamer::RemarkStreamer(StringRef Filename, raw_ostream &OS)
   assert(!Filename.empty() && "This needs to be a real filename.");
 }
 
+Error RemarkStreamer::setFilter(StringRef Filter) {
+  Regex R = Regex(Filter);
+  std::string RegexError;
+  if (!R.isValid(RegexError))
+    return createStringError(std::make_error_code(std::errc::invalid_argument),
+                             RegexError.data());
+  PassFilter = std::move(R);
+  return Error::success();
+}
+
 void RemarkStreamer::emit(const DiagnosticInfoOptimizationBase &Diag) {
+  if (Optional<Regex> &Filter = PassFilter)
+    if (!Filter->match(Diag.getPassName()))
+      return;
+
   DiagnosticInfoOptimizationBase *DiagPtr =
       const_cast<DiagnosticInfoOptimizationBase *>(&Diag);
   YAMLOutput << DiagPtr;
index f6e34c5d0614ebd1dee4cf75221150d90e85c9ad..99318c19a89cf9c8e9738c9e89df75a253216df5 100644 (file)
@@ -1312,6 +1312,7 @@ Error LTO::runThinLTO(AddStreamFn AddStream, NativeObjectCache Cache) {
 Expected<std::unique_ptr<ToolOutputFile>>
 lto::setupOptimizationRemarks(LLVMContext &Context,
                               StringRef LTORemarksFilename,
+                              StringRef LTORemarksPasses,
                               bool LTOPassRemarksWithHotness, int Count) {
   if (LTOPassRemarksWithHotness)
     Context.setDiagnosticsHotnessRequested(true);
@@ -1329,6 +1330,11 @@ lto::setupOptimizationRemarks(LLVMContext &Context,
     return errorCodeToError(EC);
   Context.setRemarkStreamer(
       llvm::make_unique<RemarkStreamer>(Filename, DiagnosticFile->os()));
+
+  if (!LTORemarksPasses.empty())
+    if (Error E = Context.getRemarkStreamer()->setFilter(LTORemarksPasses))
+      return std::move(E);
+
   DiagnosticFile->keep();
   return std::move(DiagnosticFile);
 }
index 0595771bd008f72cd860a61c739edb0abbdbbd7a..64c596931fab1a1eb0669c314bc94c4f77c65698 100644 (file)
@@ -429,8 +429,9 @@ Error lto::backend(Config &C, AddStreamFn AddStream,
   std::unique_ptr<TargetMachine> TM = createTargetMachine(C, *TOrErr, *Mod);
 
   // Setup optimization remarks.
-  auto DiagFileOrErr = lto::setupOptimizationRemarks(
-      Mod->getContext(), C.RemarksFilename, C.RemarksWithHotness);
+  auto DiagFileOrErr =
+      lto::setupOptimizationRemarks(Mod->getContext(), C.RemarksFilename,
+                                    C.RemarksPasses, C.RemarksWithHotness);
   if (!DiagFileOrErr)
     return DiagFileOrErr.takeError();
   auto DiagnosticOutputFile = std::move(*DiagFileOrErr);
@@ -484,7 +485,8 @@ Error lto::thinBackend(Config &Conf, unsigned Task, AddStreamFn AddStream,
 
   // Setup optimization remarks.
   auto DiagFileOrErr = lto::setupOptimizationRemarks(
-      Mod.getContext(), Conf.RemarksFilename, Conf.RemarksWithHotness, Task);
+      Mod.getContext(), Conf.RemarksFilename, Conf.RemarksPasses,
+      Conf.RemarksWithHotness, Task);
   if (!DiagFileOrErr)
     return DiagFileOrErr.takeError();
   auto DiagnosticOutputFile = std::move(*DiagFileOrErr);
index 1b1de2ba187fa2de0bea52e876b4e817baa1eac8..f02907f7a86189aa3478cda0f3dcd533d637d293 100644 (file)
@@ -85,6 +85,12 @@ cl::opt<std::string>
                        cl::desc("Output filename for pass remarks"),
                        cl::value_desc("filename"));
 
+cl::opt<std::string>
+    LTORemarksPasses("lto-pass-remarks-filter",
+                     cl::desc("Only record optimization remarks from passes "
+                              "whose names match the given regular expression"),
+                     cl::value_desc("regex"));
+
 cl::opt<bool> LTOPassRemarksWithHotness(
     "lto-pass-remarks-with-hotness",
     cl::desc("With PGO, include profile count in optimization remarks"),
@@ -505,7 +511,7 @@ bool LTOCodeGenerator::optimize(bool DisableVerify, bool DisableInline,
     return false;
 
   auto DiagFileOrErr = lto::setupOptimizationRemarks(
-      Context, LTORemarksFilename, LTOPassRemarksWithHotness);
+      Context, LTORemarksFilename, LTORemarksPasses, LTOPassRemarksWithHotness);
   if (!DiagFileOrErr) {
     errs() << "Error: " << toString(DiagFileOrErr.takeError()) << "\n";
     report_fatal_error("Can't get an output file for the remarks");
index 557afd6c36030d6428e81a1679ecbb5173ce1de8..d4ee66a53e057db5ad500c81561a39f7a95a2088 100644 (file)
@@ -70,6 +70,7 @@ namespace llvm {
 // Flags -discard-value-names, defined in LTOCodeGenerator.cpp
 extern cl::opt<bool> LTODiscardValueNames;
 extern cl::opt<std::string> LTORemarksFilename;
+extern cl::opt<std::string> LTORemarksPasses;
 extern cl::opt<bool> LTOPassRemarksWithHotness;
 }
 
@@ -972,7 +973,8 @@ void ThinLTOCodeGenerator::run() {
         Context.setDiscardValueNames(LTODiscardValueNames);
         Context.enableDebugTypeODRUniquing();
         auto DiagFileOrErr = lto::setupOptimizationRemarks(
-            Context, LTORemarksFilename, LTOPassRemarksWithHotness, count);
+            Context, LTORemarksFilename, LTORemarksPasses,
+            LTOPassRemarksWithHotness, count);
         if (!DiagFileOrErr) {
           errs() << "Error: " << toString(DiagFileOrErr.takeError()) << "\n";
           report_fatal_error("ThinLTO: Can't get an output file for the "
index 03db4a722b5d566d08efc9c2d3c882a6a4a8e1c7..beb0f4fa49b8663364e3457f744828dd5ef173ec 100644 (file)
@@ -4,6 +4,7 @@
 ; RUN: llvm-as < %s >%t.bc
 ; RUN: rm -f %t.yaml
 ; RUN: llvm-lto2 run -pass-remarks-output=%t.yaml \
+; RUN:           -pass-remarks-filter=inline \
 ; RUN:           -r %t.bc,tinkywinky,p \
 ; RUN:           -r %t.bc,patatino,px \
 ; RUN:           -r %t.bc,main,px -o %t.o %t.bc
@@ -13,6 +14,7 @@
 ; RUN: opt -module-summary %s -o %t.bc
 ; RUN: rm -f %t.thin.1.yaml
 ; RUN: llvm-lto2 run -pass-remarks-output=%t \
+; RUN:           -pass-remarks-filter=inline \
 ; RUN:           -r %t.bc,tinkywinky,p \
 ; RUN:           -r %t.bc,patatino,px \
 ; RUN:           -r %t.bc,main,px -o %t.o %t.bc
index d4606ba999d48a8046724efb2318c69df532a2d0..4c13fe804d6a37f8f1b8281465cc5bd0a6a321f1 100644 (file)
@@ -5,6 +5,7 @@
 ; RUN: rm -f %t.yaml.thin.0.yaml %t.yaml.thin.1.yaml
 ; RUN: llvm-lto -thinlto-action=run \
 ; RUN:          -lto-pass-remarks-output=%t.yaml \
+; RUN:          -lto-pass-remarks-filter=inline \
 ; RUN:          -exported-symbol _func2 \
 ; RUN:          -exported-symbol _main %t1.bc %t2.bc 2>&1 | \
 ; RUN:     FileCheck %s -allow-empty
index fbf78b02551be8b2cb1423d00cee0c9276a44dea..dc61ff925ceaba21822342910bb96d5d020113db 100644 (file)
@@ -205,8 +205,9 @@ namespace options {
   /// Statistics output filename.
   static std::string stats_file;
 
-  // Optimization remarks filename and hotness options
+  // Optimization remarks filename, accepted passes and hotness options
   static std::string OptRemarksFilename;
+  static std::string OptRemarksFilter;
   static bool OptRemarksWithHotness = false;
 
   // Context sensitive PGO options.
@@ -285,6 +286,8 @@ namespace options {
       dwo_dir = opt.substr(strlen("dwo_dir="));
     } else if (opt.startswith("opt-remarks-filename=")) {
       OptRemarksFilename = opt.substr(strlen("opt-remarks-filename="));
+    } else if (opt.startswith("opt-remarks-passes=")) {
+      OptRemarksFilter = opt.substr(strlen("opt-remarks-passes="));
     } else if (opt == "opt-remarks-with-hotness") {
       OptRemarksWithHotness = true;
     } else if (opt.startswith("stats-file=")) {
@@ -908,6 +911,7 @@ static std::unique_ptr<LTO> createLTO(IndexWriteCallback OnIndexWrite,
 
   // Set up optimization remarks handling.
   Conf.RemarksFilename = options::OptRemarksFilename;
+  Conf.RemarksPasses = options::OptRemarksFilter;
   Conf.RemarksWithHotness = options::OptRemarksWithHotness;
 
   // Use new pass manager if set in driver
index a566d15cd81ac7d5913e7a046715e7fc00ef4473..be103845e97796312cb83e982ddb330732870960 100644 (file)
@@ -148,6 +148,12 @@ static cl::opt<std::string>
                     cl::desc("YAML output filename for pass remarks"),
                     cl::value_desc("filename"));
 
+static cl::opt<std::string>
+    RemarksPasses("pass-remarks-filter",
+                  cl::desc("Only record optimization remarks from passes whose "
+                           "names match the given regular expression"),
+                  cl::value_desc("regex"));
+
 namespace {
 static ManagedStatic<std::vector<std::string>> RunPassNames;
 
@@ -336,6 +342,12 @@ int main(int argc, char **argv) {
     }
     Context.setRemarkStreamer(
         llvm::make_unique<RemarkStreamer>(RemarksFilename, YamlFile->os()));
+
+    if (!RemarksPasses.empty())
+      if (Error E = Context.getRemarkStreamer()->setFilter(RemarksPasses)) {
+        WithColor::error(errs(), argv[0]) << E << '\n';
+        return 1;
+      }
   }
 
   if (InputLanguage != "" && InputLanguage != "ir" &&
index 6cceb8e4cf8113a76c3235ebcb9edccb73147a07..df51921396abce6a9d343d4cdb8d7083d920ba1d 100644 (file)
@@ -100,6 +100,12 @@ static cl::opt<bool> OptRemarksWithHotness(
     cl::desc("Whether to include hotness informations in the remarks.\n"
              "Has effect only if -pass-remarks-output is specified."));
 
+static cl::opt<std::string>
+    OptRemarksPasses("pass-remarks-filter",
+                     cl::desc("Only record optimization remarks from passes "
+                              "whose names match the given regular expression"),
+                     cl::value_desc("regex"));
+
 static cl::opt<std::string>
     SamplePGOFile("lto-sample-profile-file",
                   cl::desc("Specify a SamplePGO profile file"));
@@ -220,6 +226,7 @@ static int run(int argc, char **argv) {
 
   // Optimization remarks.
   Conf.RemarksFilename = OptRemarksOutput;
+  Conf.RemarksPasses = OptRemarksPasses;
   Conf.RemarksWithHotness = OptRemarksWithHotness;
 
   Conf.SampleProfile = SamplePGOFile;
index 06745b0cca078791091c3baf312d3a961d221e02..b4c39e2fca8afa03fe6596debd89b5839b94d33f 100644 (file)
@@ -275,6 +275,12 @@ static cl::opt<std::string>
                     cl::desc("YAML output filename for pass remarks"),
                     cl::value_desc("filename"));
 
+static cl::opt<std::string>
+    RemarksPasses("pass-remarks-filter",
+                  cl::desc("Only record optimization remarks from passes whose "
+                           "names match the given regular expression"),
+                  cl::value_desc("regex"));
+
 cl::opt<PGOKind>
     PGOKindFlag("pgo-kind", cl::init(NoPGO), cl::Hidden,
                 cl::desc("The kind of profile guided optimization"),
@@ -566,6 +572,12 @@ int main(int argc, char **argv) {
     }
     Context.setRemarkStreamer(llvm::make_unique<RemarkStreamer>(
         RemarksFilename, OptRemarkFile->os()));
+
+    if (!RemarksPasses.empty())
+      if (Error E = Context.getRemarkStreamer()->setFilter(RemarksPasses)) {
+        errs() << E << '\n';
+        return 1;
+      }
   }
 
   // Load the input module...