summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/docs/UsersManual.rst18
-rw-r--r--clang/include/clang/Basic/CodeGenOptions.h3
-rw-r--r--clang/include/clang/Basic/DiagnosticDriverKinds.td2
-rw-r--r--clang/include/clang/Driver/CC1Options.td2
-rw-r--r--clang/include/clang/Driver/Options.td2
-rw-r--r--clang/lib/CodeGen/BackendUtil.cpp1
-rw-r--r--clang/lib/CodeGen/CodeGenAction.cpp5
-rw-r--r--clang/lib/Driver/ToolChains/Clang.cpp8
-rw-r--r--clang/lib/Driver/ToolChains/Darwin.cpp9
-rw-r--r--clang/lib/Frontend/CompilerInvocation.cpp5
-rw-r--r--clang/test/CodeGen/opt-record-MIR.c2
-rw-r--r--clang/test/CodeGen/opt-record.c5
-rw-r--r--clang/test/Driver/darwin-ld.c4
-rw-r--r--clang/test/Driver/opt-record.c8
-rw-r--r--lld/ELF/Config.h1
-rw-r--r--lld/ELF/Driver.cpp1
-rw-r--r--lld/ELF/LTO.cpp1
-rw-r--r--lld/ELF/Options.td2
-rw-r--r--lld/test/ELF/lto/opt-remarks.ll3
-rw-r--r--llvm/include/llvm/IR/RemarkStreamer.h12
-rw-r--r--llvm/include/llvm/LTO/Config.h3
-rw-r--r--llvm/include/llvm/LTO/LTO.h5
-rw-r--r--llvm/lib/IR/RemarkStreamer.cpp37
-rw-r--r--llvm/lib/LTO/LTO.cpp6
-rw-r--r--llvm/lib/LTO/LTOBackend.cpp8
-rw-r--r--llvm/lib/LTO/LTOCodeGenerator.cpp10
-rw-r--r--llvm/lib/LTO/ThinLTOCodeGenerator.cpp3
-rw-r--r--llvm/test/ThinLTO/X86/diagnostic-handler-remarks.ll1
-rw-r--r--llvm/test/tools/gold/X86/opt-remarks.ll2
-rw-r--r--llvm/tools/gold/gold-plugin.cpp4
-rw-r--r--llvm/tools/llc/llc.cpp8
-rw-r--r--llvm/tools/llvm-lto2/llvm-lto2.cpp6
-rw-r--r--llvm/tools/opt/opt.cpp8
33 files changed, 172 insertions, 23 deletions
diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst
index 54ff02cce1d..0e2d1c82e92 100644
--- a/clang/docs/UsersManual.rst
+++ b/clang/docs/UsersManual.rst
@@ -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:
diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h
index 7c936c49d3e..2ece9e7f146 100644
--- a/clang/include/clang/Basic/CodeGenOptions.h
+++ b/clang/include/clang/Basic/CodeGenOptions.h
@@ -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;
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index b66aa22964d..dd86ca49b7a 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -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<
diff --git a/clang/include/clang/Driver/CC1Options.td b/clang/include/clang/Driver/CC1Options.td
index 1d96f1e1ee1..062aae1f112 100644
--- a/clang/include/clang/Driver/CC1Options.td
+++ b/clang/include/clang/Driver/CC1Options.td
@@ -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">;
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index c9c9984ffa4..628fa4435d1 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -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=">,
diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index 46b075ff126..2a904d54346 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -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) {
diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp
index e8022c0e637..0ae9ea427d6 100644
--- a/clang/lib/CodeGen/CodeGenAction.cpp
+++ b/clang/lib/CodeGen/CodeGenAction.cpp
@@ -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;
}
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 91993a44007..9ec6f7d9a95 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -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,
diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp
index 478e1111e18..fbdc0b50189 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -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.
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index da7ed04bc4c..fc49aa6f86b 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -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);
diff --git a/clang/test/CodeGen/opt-record-MIR.c b/clang/test/CodeGen/opt-record-MIR.c
index f9b4e745805..731c6591c23 100644
--- a/clang/test/CodeGen/opt-record-MIR.c
+++ b/clang/test/CodeGen/opt-record-MIR.c
@@ -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);
diff --git a/clang/test/CodeGen/opt-record.c b/clang/test/CodeGen/opt-record.c
index da32f357282..481b45d9e95 100644
--- a/clang/test/CodeGen/opt-record.c
+++ b/clang/test/CodeGen/opt-record.c
@@ -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'
diff --git a/clang/test/Driver/darwin-ld.c b/clang/test/Driver/darwin-ld.c
index 6886fbad254..9dc31297e8b 100644
--- a/clang/test/Driver/darwin-ld.c
+++ b/clang/test/Driver/darwin-ld.c
@@ -330,6 +330,10 @@
// 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
diff --git a/clang/test/Driver/opt-record.c b/clang/test/Driver/opt-record.c
index 44ad4a2a6b3..f7dd5eb740c 100644
--- a/clang/test/Driver/opt-record.c
+++ b/clang/test/Driver/opt-record.c
@@ -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"
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index ac5087cf589..3b3087987e6 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -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;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index e4c1b79244f..008a6cd7954 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -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);
diff --git a/lld/ELF/LTO.cpp b/lld/ELF/LTO.cpp
index eb0f75e6cc4..361205973c0 100644
--- a/lld/ELF/LTO.cpp
+++ b/lld/ELF/LTO.cpp
@@ -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;
diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index 6c6222c23fe..d45d9aaad9a 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -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=">,
diff --git a/lld/test/ELF/lto/opt-remarks.ll b/lld/test/ELF/lto/opt-remarks.ll
index cce886c6371..013e28e79bf 100644
--- a/lld/test/ELF/lto/opt-remarks.ll
+++ b/lld/test/ELF/lto/opt-remarks.ll
@@ -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
diff --git a/llvm/include/llvm/IR/RemarkStreamer.h b/llvm/include/llvm/IR/RemarkStreamer.h
index 4ba8491a9b4..9b6d82ee30c 100644
--- a/llvm/include/llvm/IR/RemarkStreamer.h
+++ b/llvm/include/llvm/IR/RemarkStreamer.h
@@ -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
diff --git a/llvm/include/llvm/LTO/Config.h b/llvm/include/llvm/LTO/Config.h
index 25c423715f1..fb107e3fbe0 100644
--- a/llvm/include/llvm/LTO/Config.h
+++ b/llvm/include/llvm/LTO/Config.h
@@ -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;
diff --git a/llvm/include/llvm/LTO/LTO.h b/llvm/include/llvm/LTO/LTO.h
index cbddede66c0..ca0a8b64523 100644
--- a/llvm/include/llvm/LTO/LTO.h
+++ b/llvm/include/llvm/LTO/LTO.h
@@ -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>>
diff --git a/llvm/lib/IR/RemarkStreamer.cpp b/llvm/lib/IR/RemarkStreamer.cpp
index e0f9a9d70c3..2c3bc8406e5 100644
--- a/llvm/lib/IR/RemarkStreamer.cpp
+++ b/llvm/lib/IR/RemarkStreamer.cpp
@@ -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))
diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp
index fe1bdfcaa96..4ed13701aa9 100644
--- a/llvm/lib/LTO/LTO.cpp
+++ b/llvm/lib/LTO/LTO.cpp
@@ -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);
diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp
index b0a7c434b67..7456e717516 100644
--- a/llvm/lib/LTO/LTOBackend.cpp
+++ b/llvm/lib/LTO/LTOBackend.cpp
@@ -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);
diff --git a/llvm/lib/LTO/LTOCodeGenerator.cpp b/llvm/lib/LTO/LTOCodeGenerator.cpp
index ebc4cc5794a..6bb3bfaefc9 100644
--- a/llvm/lib/LTO/LTOCodeGenerator.cpp
+++ b/llvm/lib/LTO/LTOCodeGenerator.cpp
@@ -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");
diff --git a/llvm/lib/LTO/ThinLTOCodeGenerator.cpp b/llvm/lib/LTO/ThinLTOCodeGenerator.cpp
index 5d9aa8e571b..b5dbab0ca8f 100644
--- a/llvm/lib/LTO/ThinLTOCodeGenerator.cpp
+++ b/llvm/lib/LTO/ThinLTOCodeGenerator.cpp
@@ -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";
diff --git a/llvm/test/ThinLTO/X86/diagnostic-handler-remarks.ll b/llvm/test/ThinLTO/X86/diagnostic-handler-remarks.ll
index 4c13fe804d6..f0ff9542ee1 100644
--- a/llvm/test/ThinLTO/X86/diagnostic-handler-remarks.ll
+++ b/llvm/test/ThinLTO/X86/diagnostic-handler-remarks.ll
@@ -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
diff --git a/llvm/test/tools/gold/X86/opt-remarks.ll b/llvm/test/tools/gold/X86/opt-remarks.ll
index 4f8ae2c843c..c95447f0b55 100644
--- a/llvm/test/tools/gold/X86/opt-remarks.ll
+++ b/llvm/test/tools/gold/X86/opt-remarks.ll
@@ -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
diff --git a/llvm/tools/gold/gold-plugin.cpp b/llvm/tools/gold/gold-plugin.cpp
index 314d8637623..1cd287cb668 100644
--- a/llvm/tools/gold/gold-plugin.cpp
+++ b/llvm/tools/gold/gold-plugin.cpp
@@ -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;
diff --git a/llvm/tools/llc/llc.cpp b/llvm/tools/llc/llc.cpp
index 48a810cf6eb..76da843f065 100644
--- a/llvm/tools/llc/llc.cpp
+++ b/llvm/tools/llc/llc.cpp
@@ -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;
diff --git a/llvm/tools/llvm-lto2/llvm-lto2.cpp b/llvm/tools/llvm-lto2/llvm-lto2.cpp
index 7f8b5beb716..0bd9289dc93 100644
--- a/llvm/tools/llvm-lto2/llvm-lto2.cpp
+++ b/llvm/tools/llvm-lto2/llvm-lto2.cpp
@@ -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;
diff --git a/llvm/tools/opt/opt.cpp b/llvm/tools/opt/opt.cpp
index dde1d776fef..ccf8b073b82 100644
--- a/llvm/tools/opt/opt.cpp
+++ b/llvm/tools/opt/opt.cpp
@@ -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;
OpenPOWER on IntegriCloud