diff options
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; |