[Remarks] Extend -fsave-optimization-record to specify the format
authorFrancis Visoiu Mistrih <francisvm@yahoo.com>
Mon, 17 Jun 2019 16:06:00 +0000 (16:06 +0000)
committerFrancis Visoiu Mistrih <francisvm@yahoo.com>
Mon, 17 Jun 2019 16:06:00 +0000 (16:06 +0000)
Use -fsave-optimization-record=<format> to specify a different format
than the default, which is YAML.

For now, only YAML is supported.

llvm-svn: 363573

33 files changed:
clang/docs/UsersManual.rst
clang/include/clang/Basic/CodeGenOptions.h
clang/include/clang/Basic/DiagnosticDriverKinds.td
clang/include/clang/Driver/CC1Options.td
clang/include/clang/Driver/Options.td
clang/lib/CodeGen/BackendUtil.cpp
clang/lib/CodeGen/CodeGenAction.cpp
clang/lib/Driver/ToolChains/Clang.cpp
clang/lib/Driver/ToolChains/Darwin.cpp
clang/lib/Frontend/CompilerInvocation.cpp
clang/test/CodeGen/opt-record-MIR.c
clang/test/CodeGen/opt-record.c
clang/test/Driver/darwin-ld.c
clang/test/Driver/opt-record.c
lld/ELF/Config.h
lld/ELF/Driver.cpp
lld/ELF/LTO.cpp
lld/ELF/Options.td
lld/test/ELF/lto/opt-remarks.ll
llvm/include/llvm/IR/RemarkStreamer.h
llvm/include/llvm/LTO/Config.h
llvm/include/llvm/LTO/LTO.h
llvm/lib/IR/RemarkStreamer.cpp
llvm/lib/LTO/LTO.cpp
llvm/lib/LTO/LTOBackend.cpp
llvm/lib/LTO/LTOCodeGenerator.cpp
llvm/lib/LTO/ThinLTOCodeGenerator.cpp
llvm/test/ThinLTO/X86/diagnostic-handler-remarks.ll
llvm/test/tools/gold/X86/opt-remarks.ll
llvm/tools/gold/gold-plugin.cpp
llvm/tools/llc/llc.cpp
llvm/tools/llvm-lto2/llvm-lto2.cpp
llvm/tools/opt/opt.cpp

index 54ff02cce1d40d339767398579d8112e8dff8812..0e2d1c82e92e9f29a59c8962d444ec00d618b5f8 100644 (file)
@@ -324,13 +324,21 @@ output format of the diagnostics that it generates.
 
 .. _opt_fsave-optimization-record:
 
-**-fsave-optimization-record**
-   Write optimization remarks to a YAML file.
+.. option:: -fsave-optimization-record[=<format>]
+
+   Write optimization remarks to a separate file.
 
    This option, which defaults to off, controls whether Clang writes
-   optimization reports to a YAML file. By recording diagnostics in a file,
-   using a structured YAML format, users can parse or sort the remarks in a
-   convenient way.
+   optimization reports to a separate file. By recording diagnostics in a file,
+   users can parse or sort the remarks in a convenient way.
+
+   By default, the serialization format is YAML.
+
+   The supported serialization formats are:
+
+   -  .. _opt_fsave_optimization_record_yaml:
+
+      ``-fsave-optimization-record=yaml``: A structured YAML format.
 
 .. _opt_foptimization-record-file:
 
index 7c936c49d3e5c3a3aa4eabdcd9b2f50a29c71934..2ece9e7f146f53d20bb063de89d40b20efe9f93e 100644 (file)
@@ -246,6 +246,9 @@ public:
   /// records.
   std::string OptRecordPasses;
 
+  /// The format used for serializing remarks (default: YAML)
+  std::string OptRecordFormat;
+
   /// The name of the partition that symbols are assigned to, specified with
   /// -fsymbol-partition (see https://lld.llvm.org/Partitions.html).
   std::string SymbolPartition;
index b66aa22964d3239e723037919d3b25ffc2f5ce9e..dd86ca49b7a288e7f60ccd49accf345eb8c5dc98 100644 (file)
@@ -230,6 +230,8 @@ def err_drv_emit_llvm_link : Error<
    "-emit-llvm cannot be used when linking">;
 def err_drv_optimization_remark_pattern : Error<
   "in pattern '%1': %0">;
+def err_drv_optimization_remark_format : Error<
+  "unknown remark serializer format: '%0'">;
 def err_drv_no_neon_modifier : Error<"[no]neon is not accepted as modifier, please use [no]simd instead">;
 def err_drv_invalid_omp_target : Error<"OpenMP target is invalid: '%0'">;
 def err_drv_omp_host_ir_file_not_found : Error<
index 1d96f1e1ee1c3ad05bfa48d3c8b4e3e1d6090d74..062aae1f1129fa9bc868a8b8c58d11856ae26f86 100644 (file)
@@ -636,6 +636,8 @@ def opt_record_file : Separate<["-"], "opt-record-file">,
   HelpText<"File name to use for YAML optimization record output">;
 def opt_record_passes : Separate<["-"], "opt-record-passes">,
   HelpText<"Only record remark information for passes whose names match the given regular expression">;
+def opt_record_format : Separate<["-"], "opt-record-format">,
+  HelpText<"The format used for serializing remarks (default: YAML)">;
 
 def print_stats : Flag<["-"], "print-stats">,
   HelpText<"Print performance metrics and statistics">;
index c9c9984ffa41474325a53ce2c7570efa61cd017b..628fa4435d1396e2260a46e6bb36e43d3d555036 100644 (file)
@@ -1717,6 +1717,8 @@ def foperator_arrow_depth_EQ : Joined<["-"], "foperator-arrow-depth=">,
 
 def fsave_optimization_record : Flag<["-"], "fsave-optimization-record">,
   Group<f_Group>, HelpText<"Generate a YAML optimization record file">;
+def fsave_optimization_record_EQ : Joined<["-"], "fsave-optimization-record=">,
+  Group<f_Group>, HelpText<"Generate an optimization record file in a specific format (default: YAML)">;
 def fno_save_optimization_record : Flag<["-"], "fno-save-optimization-record">,
   Group<f_Group>, Flags<[NoArgumentUnused]>;
 def foptimization_record_file_EQ : Joined<["-"], "foptimization-record-file=">,
index 46b075ff1264b9c25cf56eb9c032f00da3ced49f..2a904d543467123069f07405b920cff9660f7844 100644 (file)
@@ -1428,6 +1428,7 @@ static void runThinLTOBackend(ModuleSummaryIndex *CombinedIndex, Module *M,
   Conf.RemarksWithHotness = CGOpts.DiagnosticsWithHotness;
   Conf.RemarksFilename = CGOpts.OptRecordFile;
   Conf.RemarksPasses = CGOpts.OptRecordPasses;
+  Conf.RemarksFormat = CGOpts.OptRecordFormat;
   Conf.SplitDwarfFile = CGOpts.SplitDwarfFile;
   Conf.SplitDwarfOutput = CGOpts.SplitDwarfOutput;
   switch (Action) {
index e8022c0e637ff0438b7c1c0de1174448f1576f20..0ae9ea427d65904dbbf578b6e133f9e963a4cc6b 100644 (file)
@@ -266,6 +266,7 @@ namespace clang {
       Expected<std::unique_ptr<llvm::ToolOutputFile>> OptRecordFileOrErr =
           setupOptimizationRemarks(Ctx, CodeGenOpts.OptRecordFile,
                                    CodeGenOpts.OptRecordPasses,
+                                   CodeGenOpts.OptRecordFormat,
                                    CodeGenOpts.DiagnosticsWithHotness,
                                    CodeGenOpts.DiagnosticsHotnessThreshold);
 
@@ -279,6 +280,10 @@ namespace clang {
             [&](const RemarkSetupPatternError &E) {
               Diags.Report(diag::err_drv_optimization_remark_pattern)
                   << E.message() << CodeGenOpts.OptRecordPasses;
+            },
+            [&](const RemarkSetupFormatError &E) {
+              Diags.Report(diag::err_drv_optimization_remark_format)
+                  << CodeGenOpts.OptRecordFormat;
             });
         return;
       }
index 91993a44007ec316aeb632fa0e97611ddedf57d1..9ec6f7d9a95025e0d8eb6027eeed63a3362c00f1 100644 (file)
@@ -5079,6 +5079,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
   if (Args.hasFlag(options::OPT_fsave_optimization_record,
                    options::OPT_foptimization_record_file_EQ,
                    options::OPT_fno_save_optimization_record, false) ||
+      Args.hasFlag(options::OPT_fsave_optimization_record_EQ,
+                   options::OPT_fno_save_optimization_record, false) ||
       Args.hasFlag(options::OPT_foptimization_record_passes_EQ,
                    options::OPT_fno_save_optimization_record, false)) {
     CmdArgs.push_back("-opt-record-file");
@@ -5119,6 +5121,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
       CmdArgs.push_back("-opt-record-passes");
       CmdArgs.push_back(A->getValue());
     }
+
+    if (const Arg *A =
+            Args.getLastArg(options::OPT_fsave_optimization_record_EQ)) {
+      CmdArgs.push_back("-opt-record-format");
+      CmdArgs.push_back(A->getValue());
+    }
   }
 
   bool RewriteImports = Args.hasFlag(options::OPT_frewrite_imports,
index 478e1111e18dc392245d03ec5be32fcd388db592..fbdc0b50189b4dbd3897443dad910cb36da32604 100644 (file)
@@ -462,6 +462,7 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
   // For LTO, pass the name of the optimization record file and other
   // opt-remarks flags.
   if (Args.hasFlag(options::OPT_fsave_optimization_record,
+                   options::OPT_fsave_optimization_record_EQ,
                    options::OPT_fno_save_optimization_record, false)) {
     CmdArgs.push_back("-mllvm");
     CmdArgs.push_back("-lto-pass-remarks-output");
@@ -492,6 +493,14 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
           std::string("-lto-pass-remarks-filter=") + A->getValue();
       CmdArgs.push_back(Args.MakeArgString(Passes));
     }
+
+    if (const Arg *A =
+            Args.getLastArg(options::OPT_fsave_optimization_record_EQ)) {
+      CmdArgs.push_back("-mllvm");
+      std::string Format =
+          std::string("-lto-pass-remarks-format=") + A->getValue();
+      CmdArgs.push_back(Args.MakeArgString(Format));
+    }
   }
 
   // Propagate the -moutline flag to the linker in LTO.
index da7ed04bc4c9a4b10e156fbab8d1c950225d3bb4..fc49aa6f86b10627557bb79a69baebd17ab7f0a7 100644 (file)
@@ -1237,6 +1237,11 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
     NeedLocTracking = true;
   }
 
+  if (Arg *A = Args.getLastArg(OPT_opt_record_format)) {
+    Opts.OptRecordFormat = A->getValue();
+    NeedLocTracking = true;
+  }
+
   if (Arg *A = Args.getLastArg(OPT_Rpass_EQ)) {
     Opts.OptimizationRemarkPattern =
         GenerateOptimizationRemarkRegex(Diags, Args, A);
index f9b4e7458059543c4130f50454db4e2c6565e268..731c6591c23720877a0fd1d94deed9afc63e000d 100644 (file)
@@ -5,6 +5,8 @@
 // RUN: cat %t.yaml | FileCheck -check-prefix=YAML %s
 // RUN: %clang_cc1 -triple arm64-apple-ios -S -o /dev/null %s -O2 -dwarf-column-info -opt-record-file %t.yaml -opt-record-passes asm-printer
 // RUN: cat %t.yaml | FileCheck -check-prefix=PASSES %s
+// RUN: %clang_cc1 -triple arm64-apple-ios -S -o /dev/null %s -O2 -dwarf-column-info -opt-record-file %t.yaml -opt-record-format yaml
+// RUN: cat %t.yaml | FileCheck -check-prefix=YAML %s
 
 void bar(float);
 
index da32f3572820e1bc05e19d32a9c9997f7c1ed42f..481b45d9e95898f5d69a4f809f24460e3c0eda18 100644 (file)
@@ -6,6 +6,9 @@
 // RUN: %clang_cc1 -O3 -triple x86_64-unknown-linux-gnu -target-cpu x86-64 %s -o %t -dwarf-column-info -opt-record-file %t.yaml -opt-record-passes inline -emit-obj
 // RUN: cat %t.yaml | FileCheck -check-prefix=CHECK-PASSES %s
 // RUN: not %clang_cc1 -O3 -triple x86_64-unknown-linux-gnu -target-cpu x86-64 %s -o %t -dwarf-column-info -opt-record-file %t.yaml -opt-record-passes "(foo" -emit-obj 2>&1 | FileCheck -check-prefix=CHECK-PATTERN-ERROR %s
+// RUN: %clang_cc1 -O3 -triple x86_64-unknown-linux-gnu -target-cpu x86-64 %s -o %t -dwarf-column-info -opt-record-file %t.yaml -opt-record-format yaml -emit-obj
+// RUN: cat %t.yaml | FileCheck %s
+// RUN: not %clang_cc1 -O3 -triple x86_64-unknown-linux-gnu -target-cpu x86-64 %s -o %t -dwarf-column-info -opt-record-file %t.yaml -opt-record-format "unknown-format" -emit-obj 2>&1 | FileCheck -check-prefix=CHECK-FORMAT-ERROR %s
 // REQUIRES: x86-registered-target
 
 void bar();
@@ -37,3 +40,5 @@ void Test(int *res, int *c, int *d, int *p, int n) {
 // CHECK-PASSES-NOT: loop-vectorize
 
 // CHECK-PATTERN-ERROR: error: in pattern '(foo': parentheses not balanced
+
+// CHECK-FORMAT-ERROR: error: unknown remark serializer format: 'unknown-format'
index 6886fbad2540982a9e4d5f3170bdf3cfdd08f11d..9dc31297e8bc14ba27dab469be13fcb56695e46a 100644 (file)
 // RUN: %clang -target x86_64-apple-darwin12 %t.o -fsave-optimization-record -foptimization-record-passes=inline -### -o foo/bar.out 2> %t.log
 // RUN: FileCheck -check-prefix=PASS_REMARKS_WITH_PASSES %s < %t.log
 // PASS_REMARKS_WITH_PASSES: "-mllvm" "-lto-pass-remarks-output" "-mllvm" "foo/bar.out.opt.yaml" "-mllvm" "-lto-pass-remarks-filter=inline"
+//
+// RUN: %clang -target x86_64-apple-darwin12 %t.o -fsave-optimization-record=some-format -### -o foo/bar.out 2> %t.log
+// RUN: FileCheck -check-prefix=PASS_REMARKS_WITH_FORMAT %s < %t.log
+// PASS_REMARKS_WITH_FORMAT: "-mllvm" "-lto-pass-remarks-output" "-mllvm" "foo/bar.out.opt.yaml" "-mllvm" "-lto-pass-remarks-format=some-format"
 
 // RUN: %clang -target x86_64-apple-ios6.0 -miphoneos-version-min=6.0 -fprofile-instr-generate -### %t.o 2> %t.log
 // RUN: FileCheck -check-prefix=LINK_PROFILE_FIRST %s < %t.log
index 44ad4a2a6b328aa587fcf597aac0438ec9fc98ab..f7dd5eb740cb616095bd3f6ca6ac0b83eee7ebf9 100644 (file)
@@ -15,6 +15,9 @@
 // RUN: %clang -### -S -o FOO -fsave-optimization-record -foptimization-record-passes=inline %s 2>&1 | FileCheck %s -check-prefix=CHECK-EQ-PASSES
 // RUN: %clang -### -S -o FOO -foptimization-record-passes=inline %s 2>&1 | FileCheck %s -check-prefix=CHECK-EQ-PASSES
 // RUN: %clang -### -S -o FOO -foptimization-record-passes=inline -fno-save-optimization-record %s 2>&1 | FileCheck %s --check-prefix=CHECK-FOPT-DISABLE-PASSES
+// RUN: %clang -### -S -o FOO -fsave-optimization-record -fsave-optimization-record=some-format %s 2>&1 | FileCheck %s -check-prefix=CHECK-EQ-FORMAT
+// RUN: %clang -### -S -o FOO -fsave-optimization-record=some-format %s 2>&1 | FileCheck %s -check-prefix=CHECK-EQ-FORMAT
+// RUN: %clang -### -S -o FOO -fsave-optimization-record=some-format -fno-save-optimization-record %s 2>&1 | FileCheck %s --check-prefix=CHECK-FOPT-DISABLE-FORMAT
 //
 // CHECK: "-cc1"
 // CHECK: "-opt-record-file" "FOO.opt.yaml"
@@ -32,3 +35,8 @@
 // CHECK-EQ-PASSES: "-opt-record-passes" "inline"
 
 // CHECK-FOPT-DISABLE-PASSES-NOT: "-fno-save-optimization-record"
+
+// CHECK-EQ-FORMAT: "-cc1"
+// CHECK-EQ-FORMAT: "-opt-record-format" "some-format"
+
+// CHECK-FOPT-DISABLE-FORMAT-NOT: "-fno-save-optimization-record"
index ac5087cf5899b46502fdb05ec7a0a855e29ba7bc..3b3087987e6f6979b8de27aa08f3d224680602c6 100644 (file)
@@ -100,6 +100,7 @@ struct Configuration {
   llvm::StringRef OutputFile;
   llvm::StringRef OptRemarksFilename;
   llvm::StringRef OptRemarksPasses;
+  llvm::StringRef OptRemarksFormat;
   llvm::StringRef ProgName;
   llvm::StringRef PrintSymbolOrder;
   llvm::StringRef SoName;
index e4c1b79244f5c93d223e6a0929bce7ca3f328809..008a6cd7954b40736a04b78ad8fd4a958fc8b62d 100644 (file)
@@ -857,6 +857,7 @@ static void readConfigs(opt::InputArgList &Args) {
   Config->OptRemarksFilename = Args.getLastArgValue(OPT_opt_remarks_filename);
   Config->OptRemarksPasses = Args.getLastArgValue(OPT_opt_remarks_passes);
   Config->OptRemarksWithHotness = Args.hasArg(OPT_opt_remarks_with_hotness);
+  Config->OptRemarksFormat = Args.getLastArgValue(OPT_opt_remarks_format);
   Config->Optimize = args::getInteger(Args, OPT_O, 1);
   Config->OrphanHandling = getOrphanHandling(Args);
   Config->OutputFile = Args.getLastArgValue(OPT_o);
index eb0f75e6cc4000b7fbfbc51d31e3a98a9f5b35fe..361205973c08f57a3f875792e88aac22bf6a7f1d 100644 (file)
@@ -99,6 +99,7 @@ static lto::Config createConfig() {
   C.RemarksFilename = Config->OptRemarksFilename;
   C.RemarksPasses = Config->OptRemarksPasses;
   C.RemarksWithHotness = Config->OptRemarksWithHotness;
+  C.RemarksFormat = Config->OptRemarksFormat;
 
   C.SampleProfile = Config->LTOSampleProfile;
   C.UseNewPM = Config->LTONewPassManager;
index 6c6222c23fef69f287314cd7db1e09d01fdd4472..d45d9aaad9af9bfe833522d6edd4bfc0217b9307 100644 (file)
@@ -485,6 +485,8 @@ def opt_remarks_passes: Separate<["--"], "opt-remarks-passes">,
   HelpText<"Regex for the passes that need to be serialized to the output file">;
 def opt_remarks_with_hotness: Flag<["--"], "opt-remarks-with-hotness">,
   HelpText<"Include hotness information in the optimization remarks file">;
+def opt_remarks_format: Separate<["--"], "opt-remarks-format">,
+  HelpText<"The format used for serializing remarks (default: YAML)">;
 defm plugin_opt: Eq<"plugin-opt", "specifies LTO options for compatibility with GNU linkers">;
 def save_temps: F<"save-temps">;
 def thinlto_cache_dir: J<"thinlto-cache-dir=">,
index cce886c637190ab8f7e6a1ee7ae7bc84c7262464..013e28e79bf4611a60b1342128cc379a0a70f99f 100644 (file)
@@ -11,6 +11,9 @@
 ; RUN: ld.lld --opt-remarks-filename %t1.yaml --opt-remarks-passes inline %t.o \
 ; RUN: -o /dev/null -shared
 ; RUN: cat %t1.yaml | FileCheck %s -check-prefix=YAML-PASSES
+; RUN: ld.lld --opt-remarks-filename %t1.yaml --opt-remarks-format yaml %t.o \
+; RUN: -o /dev/null -shared
+; RUN: cat %t.yaml | FileCheck %s -check-prefix=YAML
 
 ; Check that @tinkywinky is inlined after optimizations.
 ; CHECK-LABEL: define i32 @main
index 4ba8491a9b4dd0844c15dc769c77dd4007d9dfc7..9b6d82ee30c0c6a9608539c55e0b3f90021bb326 100644 (file)
@@ -85,10 +85,20 @@ struct RemarkSetupPatternError : RemarkSetupErrorInfo<RemarkSetupPatternError> {
   using RemarkSetupErrorInfo<RemarkSetupPatternError>::RemarkSetupErrorInfo;
 };
 
+struct RemarkSetupFormatError : RemarkSetupErrorInfo<RemarkSetupFormatError> {
+  static char ID;
+  using RemarkSetupErrorInfo<RemarkSetupFormatError>::RemarkSetupErrorInfo;
+};
+
+enum class RemarksSerializerFormat { Unknown, YAML };
+
+Expected<RemarksSerializerFormat> parseSerializerFormat(StringRef Format);
+
 /// Setup optimization remarks.
 Expected<std::unique_ptr<ToolOutputFile>>
 setupOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename,
-                         StringRef RemarksPasses, bool RemarksWithHotness,
+                         StringRef RemarksPasses, StringRef RemarksFormat,
+                         bool RemarksWithHotness,
                          unsigned RemarksHotnessThreshold = 0);
 
 } // end namespace llvm
index 25c423715f1651c87e03ce6ff54dff0c09b4a13f..fb107e3fbe024d88d9440ce2ba152bfeffc1723a 100644 (file)
@@ -108,6 +108,9 @@ struct Config {
   /// Whether to emit optimization remarks with hotness informations.
   bool RemarksWithHotness = false;
 
+  /// The format used for serializing remarks (default: YAML).
+  std::string RemarksFormat = "";
+
   /// Whether to emit the pass manager debuggging informations.
   bool DebugPassManager = false;
 
index cbddede66c07ccbcfe8ece233a9342eaba86ff49..ca0a8b64523aca8eb082c464f3b7e2299e7a3a2c 100644 (file)
@@ -20,6 +20,7 @@
 #include "llvm/ADT/StringSet.h"
 #include "llvm/IR/DiagnosticInfo.h"
 #include "llvm/IR/ModuleSummaryIndex.h"
+#include "llvm/IR/RemarkStreamer.h"
 #include "llvm/LTO/Config.h"
 #include "llvm/Linker/IRMover.h"
 #include "llvm/Object/IRSymtab.h"
@@ -85,8 +86,8 @@ std::string getThinLTOOutputFile(const std::string &Path,
 /// Setup optimization remarks.
 Expected<std::unique_ptr<ToolOutputFile>>
 setupOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename,
-                         StringRef RemarksPasses, bool RemarksWithHotness,
-                         int Count = -1);
+                         StringRef RemarksPasses, StringRef RemarksFormat,
+                         bool RemarksWithHotness, int Count = -1);
 
 /// Setups the output file for saving statistics.
 Expected<std::unique_ptr<ToolOutputFile>>
index e0f9a9d70c36d9a0a2e788132454557415de9c00..2c3bc8406e55ef4f0a3862f48b0e0a03749f022d 100644 (file)
@@ -109,10 +109,37 @@ void RemarkStreamer::emit(const DiagnosticInfoOptimizationBase &Diag) {
 
 char RemarkSetupFileError::ID = 0;
 char RemarkSetupPatternError::ID = 0;
+char RemarkSetupFormatError::ID = 0;
+
+static std::unique_ptr<remarks::Serializer>
+formatToSerializer(RemarksSerializerFormat RemarksFormat, raw_ostream &OS) {
+  switch (RemarksFormat) {
+  default:
+    llvm_unreachable("Unknown remark serializer format.");
+    return nullptr;
+  case RemarksSerializerFormat::YAML:
+    return llvm::make_unique<remarks::YAMLSerializer>(OS);
+  };
+}
+
+Expected<RemarksSerializerFormat>
+llvm::parseSerializerFormat(StringRef StrFormat) {
+  auto Format = StringSwitch<RemarksSerializerFormat>(StrFormat)
+                    .Cases("", "yaml", RemarksSerializerFormat::YAML)
+                    .Default(RemarksSerializerFormat::Unknown);
+
+  if (Format == RemarksSerializerFormat::Unknown)
+    return createStringError(std::make_error_code(std::errc::invalid_argument),
+                             "Unknown remark serializer format: '%s'",
+                             StrFormat.data());
+
+  return Format;
+}
 
 Expected<std::unique_ptr<ToolOutputFile>>
 llvm::setupOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename,
-                               StringRef RemarksPasses, bool RemarksWithHotness,
+                               StringRef RemarksPasses, StringRef RemarksFormat,
+                               bool RemarksWithHotness,
                                unsigned RemarksHotnessThreshold) {
   if (RemarksWithHotness)
     Context.setDiagnosticsHotnessRequested(true);
@@ -131,9 +158,13 @@ llvm::setupOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename,
   if (EC)
     return make_error<RemarkSetupFileError>(errorCodeToError(EC));
 
+  Expected<RemarksSerializerFormat> Format =
+      parseSerializerFormat(RemarksFormat);
+  if (Error E = Format.takeError())
+    return make_error<RemarkSetupFormatError>(std::move(E));
+
   Context.setRemarkStreamer(llvm::make_unique<RemarkStreamer>(
-      RemarksFilename,
-      llvm::make_unique<remarks::YAMLSerializer>(RemarksFile->os())));
+      RemarksFilename, formatToSerializer(*Format, RemarksFile->os())));
 
   if (!RemarksPasses.empty())
     if (Error E = Context.getRemarkStreamer()->setFilter(RemarksPasses))
index fe1bdfcaa96c33ed27fa1b654829027d959822f6..4ed13701aa9e104ca792d44c75d28a4a79258a52 100644 (file)
@@ -1339,14 +1339,14 @@ Error LTO::runThinLTO(AddStreamFn AddStream, NativeObjectCache Cache,
 
 Expected<std::unique_ptr<ToolOutputFile>>
 lto::setupOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename,
-                              StringRef RemarksPasses, bool RemarksWithHotness,
-                              int Count) {
+                              StringRef RemarksPasses, StringRef RemarksFormat,
+                              bool RemarksWithHotness, int Count) {
   std::string Filename = RemarksFilename;
   if (!Filename.empty() && Count != -1)
     Filename += ".thin." + llvm::utostr(Count) + ".yaml";
 
   auto ResultOrErr = llvm::setupOptimizationRemarks(
-      Context, Filename, RemarksPasses, RemarksWithHotness);
+      Context, Filename, RemarksPasses, RemarksFormat, RemarksWithHotness);
   if (Error E = ResultOrErr.takeError())
     return std::move(E);
 
index b0a7c434b6772141d982256087dbe46785a121ab..7456e71751638d9d1e5bf941508c09a3838b953e 100644 (file)
@@ -431,9 +431,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.RemarksPasses, C.RemarksWithHotness);
+  auto DiagFileOrErr = lto::setupOptimizationRemarks(
+      Mod->getContext(), C.RemarksFilename, C.RemarksPasses, C.RemarksFormat,
+      C.RemarksWithHotness);
   if (!DiagFileOrErr)
     return DiagFileOrErr.takeError();
   auto DiagnosticOutputFile = std::move(*DiagFileOrErr);
@@ -488,7 +488,7 @@ Error lto::thinBackend(Config &Conf, unsigned Task, AddStreamFn AddStream,
   // Setup optimization remarks.
   auto DiagFileOrErr = lto::setupOptimizationRemarks(
       Mod.getContext(), Conf.RemarksFilename, Conf.RemarksPasses,
-      Conf.RemarksWithHotness, Task);
+      Conf.RemarksFormat, Conf.RemarksWithHotness, Task);
   if (!DiagFileOrErr)
     return DiagFileOrErr.takeError();
   auto DiagnosticOutputFile = std::move(*DiagFileOrErr);
index ebc4cc5794aa6625d69c0c748c756ea6d057de07..6bb3bfaefc9c605a198d4d2ab99e4b6e95a2c8a2 100644 (file)
@@ -97,6 +97,11 @@ cl::opt<std::string>
                            "names match the given regular expression"),
                   cl::value_desc("regex"));
 
+cl::opt<std::string> RemarksFormat(
+    "lto-pass-remarks-format",
+    cl::desc("The format used for serializing remarks (default: YAML)"),
+    cl::value_desc("format"), cl::init("yaml"));
+
 cl::opt<std::string> LTOStatsFile(
     "lto-stats-file",
     cl::desc("Save statistics to the specified file"),
@@ -517,8 +522,9 @@ bool LTOCodeGenerator::optimize(bool DisableVerify, bool DisableInline,
   if (!this->determineTarget())
     return false;
 
-  auto DiagFileOrErr = lto::setupOptimizationRemarks(
-      Context, RemarksFilename, RemarksPasses, RemarksWithHotness);
+  auto DiagFileOrErr =
+      lto::setupOptimizationRemarks(Context, RemarksFilename, RemarksPasses,
+                                    RemarksFormat, RemarksWithHotness);
   if (!DiagFileOrErr) {
     errs() << "Error: " << toString(DiagFileOrErr.takeError()) << "\n";
     report_fatal_error("Can't get an output file for the remarks");
index 5d9aa8e571bd361f3ffbb5ac4345e2ab01e7b76b..b5dbab0ca8fcac758a40054c5015b6f5e3b3ea67 100644 (file)
@@ -73,6 +73,7 @@ extern cl::opt<bool> LTODiscardValueNames;
 extern cl::opt<std::string> RemarksFilename;
 extern cl::opt<std::string> RemarksPasses;
 extern cl::opt<bool> RemarksWithHotness;
+extern cl::opt<std::string> RemarksFormat;
 }
 
 namespace {
@@ -1020,7 +1021,7 @@ void ThinLTOCodeGenerator::run() {
         Context.setDiscardValueNames(LTODiscardValueNames);
         Context.enableDebugTypeODRUniquing();
         auto DiagFileOrErr = lto::setupOptimizationRemarks(
-            Context, RemarksFilename, RemarksPasses,
+            Context, RemarksFilename, RemarksPasses, RemarksFormat,
             RemarksWithHotness, count);
         if (!DiagFileOrErr) {
           errs() << "Error: " << toString(DiagFileOrErr.takeError()) << "\n";
index 4c13fe804d6a37f8f1b8281465cc5bd0a6a321f1..f0ff9542ee1b3ceb4fdb7f362ad2f17a92163168 100644 (file)
@@ -6,6 +6,7 @@
 ; RUN: llvm-lto -thinlto-action=run \
 ; RUN:          -lto-pass-remarks-output=%t.yaml \
 ; RUN:          -lto-pass-remarks-filter=inline \
+; RUN:          -lto-pass-remarks-format=yaml \
 ; RUN:          -exported-symbol _func2 \
 ; RUN:          -exported-symbol _main %t1.bc %t2.bc 2>&1 | \
 ; RUN:     FileCheck %s -allow-empty
index 4f8ae2c843c8b35c188b29c0a3e5a44b97524b06..c95447f0b552234a31ee4008d598cdc90e85736c 100644 (file)
@@ -3,10 +3,12 @@
 ; RUN: %gold -m elf_x86_64 -plugin %llvmshlibdir/LLVMgold%shlibext -shared \
 ; RUN:   -plugin-opt=save-temps \
 ; RUN:    -plugin-opt=opt-remarks-passes=inline \
+; RUN:    -plugin-opt=opt-remarks-format=yaml \
 ; RUN:    -plugin-opt=opt-remarks-filename=%t.yaml %t.o -o %t2.o 2>&1
 ; RUN: llvm-dis %t2.o.0.4.opt.bc -o - | FileCheck %s
 ; RUN: %gold -m elf_x86_64 -plugin %llvmshlibdir/LLVMgold%shlibext -shared \
 ; RUN:    -plugin-opt=opt-remarks-passes=inline \
+; RUN:    -plugin-opt=opt-remarks-format=yaml \
 ; RUN:    -plugin-opt=opt-remarks-with-hotness \
 ; RUN:   -plugin-opt=opt-remarks-filename=%t.hot.yaml %t.o -o %t2.o 2>&1
 ; RUN: cat %t.yaml | FileCheck %s -check-prefix=YAML
index 314d86376234ae07d729b15dead4acf7304b336b..1cd287cb66812b0dc5f5478c4a70a90dbaa48570 100644 (file)
@@ -209,6 +209,7 @@ namespace options {
   static std::string RemarksFilename;
   static std::string RemarksPasses;
   static bool RemarksWithHotness = false;
+  static std::string RemarksFormat;
 
   // Context sensitive PGO options.
   static std::string cs_profile_path;
@@ -290,6 +291,8 @@ namespace options {
       RemarksPasses = opt.substr(strlen("opt-remarks-passes="));
     } else if (opt == "opt-remarks-with-hotness") {
       RemarksWithHotness = true;
+    } else if (opt.startswith("opt-remarks-format=")) {
+      RemarksFormat = opt.substr(strlen("opt-remarks-format="));
     } else if (opt.startswith("stats-file=")) {
       stats_file = opt.substr(strlen("stats-file="));
     } else {
@@ -913,6 +916,7 @@ static std::unique_ptr<LTO> createLTO(IndexWriteCallback OnIndexWrite,
   Conf.RemarksFilename = options::RemarksFilename;
   Conf.RemarksPasses = options::RemarksPasses;
   Conf.RemarksWithHotness = options::RemarksWithHotness;
+  Conf.RemarksFormat = options::RemarksFormat;
 
   // Use new pass manager if set in driver
   Conf.UseNewPM = options::new_pass_manager;
index 48a810cf6eb94e6631bc6142f1f2579849186996..76da843f065e6906bd3b2dd727709a64196fc050 100644 (file)
@@ -155,6 +155,11 @@ static cl::opt<std::string>
                            "names match the given regular expression"),
                   cl::value_desc("regex"));
 
+static cl::opt<std::string> RemarksFormat(
+    "pass-remarks-format",
+    cl::desc("The format used for serializing remarks (default: YAML)"),
+    cl::value_desc("format"), cl::init("yaml"));
+
 namespace {
 static ManagedStatic<std::vector<std::string>> RunPassNames;
 
@@ -329,7 +334,8 @@ int main(int argc, char **argv) {
 
   Expected<std::unique_ptr<ToolOutputFile>> RemarksFileOrErr =
       setupOptimizationRemarks(Context, RemarksFilename, RemarksPasses,
-                               RemarksWithHotness, RemarksHotnessThreshold);
+                               RemarksFormat, RemarksWithHotness,
+                               RemarksHotnessThreshold);
   if (Error E = RemarksFileOrErr.takeError()) {
     WithColor::error(errs(), argv[0]) << toString(std::move(E)) << '\n';
     return 1;
index 7f8b5beb716853df1228d5daa2eb667236d88b52..0bd9289dc938debb2bd521b34800f036ab6fc0cd 100644 (file)
@@ -107,6 +107,11 @@ static cl::opt<std::string>
                            "names match the given regular expression"),
                   cl::value_desc("regex"));
 
+static cl::opt<std::string> RemarksFormat(
+    "pass-remarks-format",
+    cl::desc("The format used for serializing remarks (default: YAML)"),
+    cl::value_desc("format"), cl::init("yaml"));
+
 static cl::opt<std::string>
     SamplePGOFile("lto-sample-profile-file",
                   cl::desc("Specify a SamplePGO profile file"));
@@ -229,6 +234,7 @@ static int run(int argc, char **argv) {
   Conf.RemarksFilename = RemarksFilename;
   Conf.RemarksPasses = RemarksPasses;
   Conf.RemarksWithHotness = RemarksWithHotness;
+  Conf.RemarksFormat = RemarksFormat;
 
   Conf.SampleProfile = SamplePGOFile;
   Conf.CSIRProfile = CSPGOFile;
index dde1d776fef4373289d1c305bc50e77388f9b72b..ccf8b073b82b654735d26e29109b589df0bd6fe4 100644 (file)
@@ -273,6 +273,11 @@ static cl::opt<std::string>
                            "names match the given regular expression"),
                   cl::value_desc("regex"));
 
+static cl::opt<std::string> RemarksFormat(
+    "pass-remarks-format",
+    cl::desc("The format used for serializing remarks (default: YAML)"),
+    cl::value_desc("format"), cl::init("yaml"));
+
 cl::opt<PGOKind>
     PGOKindFlag("pgo-kind", cl::init(NoPGO), cl::Hidden,
                 cl::desc("The kind of profile guided optimization"),
@@ -552,7 +557,8 @@ int main(int argc, char **argv) {
 
   Expected<std::unique_ptr<ToolOutputFile>> RemarksFileOrErr =
       setupOptimizationRemarks(Context, RemarksFilename, RemarksPasses,
-                               RemarksWithHotness, RemarksHotnessThreshold);
+                               RemarksFormat, RemarksWithHotness,
+                               RemarksHotnessThreshold);
   if (Error E = RemarksFileOrErr.takeError()) {
     errs() << toString(std::move(E)) << '\n';
     return 1;