diff options
32 files changed, 162 insertions, 10 deletions
diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index fc284f8c677..200706fda7c 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -238,6 +238,10 @@ public: /// records. std::string OptRecordFile; + /// The regex that filters the passes that should be saved to the optimization + /// records. + std::string OptRecordPasses; + /// Regular expression to select optimizations for which we should enable /// optimization remarks. Transformation passes whose name matches this /// expression (and support this feature), will emit a diagnostic diff --git a/clang/include/clang/Driver/CC1Options.td b/clang/include/clang/Driver/CC1Options.td index f4f8fae39e3..2825a927797 100644 --- a/clang/include/clang/Driver/CC1Options.td +++ b/clang/include/clang/Driver/CC1Options.td @@ -603,6 +603,8 @@ def arcmt_migrate : Flag<["-"], "arcmt-migrate">, 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 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 81e4ce75b02..0f05effe278 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1715,6 +1715,10 @@ def fno_save_optimization_record : Flag<["-"], "fno-save-optimization-record">, def foptimization_record_file_EQ : Joined<["-"], "foptimization-record-file=">, Group<f_Group>, HelpText<"Specify the file name of any generated YAML optimization record">; +def foptimization_record_passes_EQ : Joined<["-"], "foptimization-record-passes=">, + Group<f_Group>, + HelpText<"Only include passes which match a specified regular expression in the generated optimization record (by default, include all passes)">; + def ftest_coverage : Flag<["-"], "ftest-coverage">, Group<f_Group>; def fvectorize : Flag<["-"], "fvectorize">, Group<f_Group>, diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 30a3dc830f6..34705ad8ff8 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -1340,6 +1340,7 @@ static void runThinLTOBackend(ModuleSummaryIndex *CombinedIndex, Module *M, Conf.DebugPassManager = CGOpts.DebugPassManager; Conf.RemarksWithHotness = CGOpts.DiagnosticsWithHotness; Conf.RemarksFilename = CGOpts.OptRecordFile; + Conf.RemarksPasses = CGOpts.OptRecordPasses; Conf.DwoPath = CGOpts.SplitDwarfFile; switch (Action) { case Backend_EmitNothing: diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp index f59adcd3fb9..cab3a6bc32b 100644 --- a/clang/lib/CodeGen/CodeGenAction.cpp +++ b/clang/lib/CodeGen/CodeGenAction.cpp @@ -19,6 +19,7 @@ #include "clang/Basic/TargetInfo.h" #include "clang/CodeGen/BackendUtil.h" #include "clang/CodeGen/ModuleBuilder.h" +#include "clang/Driver/DriverDiagnostic.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Lex/Preprocessor.h" @@ -280,6 +281,12 @@ namespace clang { Ctx.setRemarkStreamer(llvm::make_unique<RemarkStreamer>( CodeGenOpts.OptRecordFile, OptRecordFile->os())); + if (!CodeGenOpts.OptRecordPasses.empty()) + if (Error E = Ctx.getRemarkStreamer()->setFilter( + CodeGenOpts.OptRecordPasses)) + Diags.Report(diag::err_drv_optimization_remark_pattern) + << toString(std::move(E)) << CodeGenOpts.OptRecordPasses; + if (CodeGenOpts.getProfileUse() != CodeGenOptions::ProfileNone) Ctx.setDiagnosticsHotnessRequested(true); } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 3bc7412911b..bf9ab9dd107 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -5032,8 +5032,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_apple_pragma_pack, false)) CmdArgs.push_back("-fapple-pragma-pack"); + // Remarks can be enabled with any of the `-f.*optimization-record.*` flags. 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_foptimization_record_passes_EQ, options::OPT_fno_save_optimization_record, false)) { CmdArgs.push_back("-opt-record-file"); @@ -5068,6 +5071,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, llvm::sys::path::replace_extension(F, "opt.yaml"); CmdArgs.push_back(Args.MakeArgString(F)); } + if (const Arg *A = + Args.getLastArg(options::OPT_foptimization_record_passes_EQ)) { + CmdArgs.push_back("-opt-record-passes"); + 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 ea93fadcdc2..f91ab1946f5 100644 --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -483,6 +483,14 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(Args.MakeArgString(Opt)); } } + + if (const Arg *A = + Args.getLastArg(options::OPT_foptimization_record_passes_EQ)) { + CmdArgs.push_back("-mllvm"); + std::string Passes = + std::string("-lto-pass-remarks-filter=") + A->getValue(); + CmdArgs.push_back(Args.MakeArgString(Passes)); + } } // Propagate the -moutline flag to the linker in LTO. diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 1cd1cb1ff47..b5872b961cc 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1218,6 +1218,11 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, if (!Opts.OptRecordFile.empty()) NeedLocTracking = true; + if (Arg *A = Args.getLastArg(OPT_opt_record_passes)) { + Opts.OptRecordPasses = 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 37239281e9e..f9b4e745805 100644 --- a/clang/test/CodeGen/opt-record-MIR.c +++ b/clang/test/CodeGen/opt-record-MIR.c @@ -3,6 +3,8 @@ // RUN: %clang_cc1 -triple arm64-apple-ios -S -o /dev/null %s -O2 -dwarf-column-info 2>&1 | FileCheck -allow-empty -check-prefix=NO_REMARK %s // RUN: %clang_cc1 -triple arm64-apple-ios -S -o /dev/null %s -O2 -dwarf-column-info -opt-record-file %t.yaml // 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 void bar(float); @@ -15,15 +17,15 @@ void foo(float *p, int i) { } } -// REMARK: opt-record-MIR.c:10:11: remark: {{.}} spills {{.}} reloads generated in loop +// REMARK: opt-record-MIR.c:{{[1-9][0-9]*}}:{{[1-9][0-9]*}}: remark: {{.}} spills {{.}} reloads generated in loop // NO_REMARK-NOT: remark: // YAML: --- !Missed // YAML: Pass: regalloc // YAML: Name: LoopSpillReload // YAML: DebugLoc: { File: {{[^,]+}}, -// YAML: Line: 10, -// YAML: Column: 11 } +// YAML: Line: {{[1-9][0-9]*}} +// YAML: Column: {{[1-9][0-9]*}} } // YAML: Function: foo // YAML: Args: // YAML: - NumSpills: '{{.}}' @@ -32,3 +34,6 @@ void foo(float *p, int i) { // YAML: - String: ' reloads ' // YAML: - String: generated // YAML: ... + +// PASSES: Pass: asm-printer +// PASSES-NOT: regalloc diff --git a/clang/test/CodeGen/opt-record.c b/clang/test/CodeGen/opt-record.c index 3bc3c41f784..3f134854fe5 100644 --- a/clang/test/CodeGen/opt-record.c +++ b/clang/test/CodeGen/opt-record.c @@ -3,6 +3,8 @@ // RUN: llvm-profdata merge %S/Inputs/opt-record.proftext -o %t.profdata // RUN: %clang_cc1 -O3 -triple x86_64-unknown-linux-gnu -target-cpu x86-64 -fprofile-instrument-use-path=%t.profdata %s -o %t -dwarf-column-info -opt-record-file %t.yaml -emit-obj // RUN: cat %t.yaml | FileCheck -check-prefix=CHECK -check-prefix=CHECK-PGO %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-passes inline -emit-obj +// RUN: cat %t.yaml | FileCheck -check-prefix=CHECK-PASSES %s // REQUIRES: x86-registered-target void bar(); @@ -23,6 +25,7 @@ void Test(int *res, int *c, int *d, int *p, int n) { // CHECK: DebugLoc: // CHECK: Function: foo // CHECK-PGO: Hotness: +// CHECK-PASSES: Pass: inline // CHECK: --- !Passed // CHECK: Pass: loop-vectorize @@ -30,4 +33,4 @@ void Test(int *res, int *c, int *d, int *p, int n) { // CHECK: DebugLoc: // CHECK: Function: Test // CHECK-PGO: Hotness: - +// CHECK-PASSES-NOT: loop-vectorize diff --git a/clang/test/Driver/darwin-ld.c b/clang/test/Driver/darwin-ld.c index 181d4e324cc..b120bbe8a34 100644 --- a/clang/test/Driver/darwin-ld.c +++ b/clang/test/Driver/darwin-ld.c @@ -327,6 +327,10 @@ // RUN: FileCheck -check-prefix=PASS_REMARKS_WITH_HOTNESS_THRESHOLD %s < %t.log // PASS_REMARKS_WITH_HOTNESS_THRESHOLD: "-mllvm" "-lto-pass-remarks-output" "-mllvm" "foo/bar.out.opt.yaml" "-mllvm" "-lto-pass-remarks-with-hotness" "-mllvm" "-lto-pass-remarks-hotness-threshold=100" +// 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-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 // RUN: %clang -target x86_64-apple-darwin12 -fprofile-instr-generate -### %t.o 2> %t.log diff --git a/clang/test/Driver/opt-record.c b/clang/test/Driver/opt-record.c index 7b4ec48632e..44ad4a2a6b3 100644 --- a/clang/test/Driver/opt-record.c +++ b/clang/test/Driver/opt-record.c @@ -12,6 +12,10 @@ // RUN: %clang -### -S -o FOO -foptimization-record-file=BAR.txt %s 2>&1 | FileCheck %s -check-prefix=CHECK-EQ // RUN: %clang -### -S -o FOO -foptimization-record-file=BAR.txt -fno-save-optimization-record %s 2>&1 | FileCheck %s --check-prefix=CHECK-FOPT-DISABLE +// 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 +// // CHECK: "-cc1" // CHECK: "-opt-record-file" "FOO.opt.yaml" @@ -23,3 +27,8 @@ // CHECK-EQ: "-opt-record-file" "BAR.txt" // CHECK-FOPT-DISABLE-NOT: "-fno-save-optimization-record" + +// CHECK-EQ-PASSES: "-cc1" +// CHECK-EQ-PASSES: "-opt-record-passes" "inline" + +// CHECK-FOPT-DISABLE-PASSES-NOT: "-fno-save-optimization-record" diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 9981098eb6c..a6b96b40548 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -99,6 +99,7 @@ struct Configuration { llvm::StringRef MapFile; llvm::StringRef OutputFile; llvm::StringRef OptRemarksFilename; + llvm::StringRef OptRemarksPasses; llvm::StringRef ProgName; llvm::StringRef SoName; llvm::StringRef Sysroot; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 44f2293f199..c27e36f94a2 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -818,6 +818,7 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) { Config->OFormatBinary = isOutputFormatBinary(Args); Config->Omagic = Args.hasFlag(OPT_omagic, OPT_no_omagic, false); 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->Optimize = args::getInteger(Args, OPT_O, 1); Config->OrphanHandling = getOrphanHandling(Args); diff --git a/lld/ELF/LTO.cpp b/lld/ELF/LTO.cpp index b19996d5e9a..c97ff4d2476 100644 --- a/lld/ELF/LTO.cpp +++ b/lld/ELF/LTO.cpp @@ -97,6 +97,7 @@ static lto::Config createConfig() { // Set up optimization remarks if we've been asked to. C.RemarksFilename = Config->OptRemarksFilename; + C.RemarksPasses = Config->OptRemarksPasses; C.RemarksWithHotness = Config->OptRemarksWithHotness; C.SampleProfile = Config->LTOSampleProfile; diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td index 013235287b3..968cf1900b6 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -454,6 +454,8 @@ def disable_verify: F<"disable-verify">; defm mllvm: Eq<"mllvm", "Additional arguments to forward to LLVM's option processing">; def opt_remarks_filename: Separate<["--"], "opt-remarks-filename">, HelpText<"YAML output file for optimization remarks">; +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">; defm plugin_opt: Eq<"plugin-opt", "specifies LTO options for compatibility with GNU linkers">; diff --git a/lld/docs/ld.lld.1 b/lld/docs/ld.lld.1 index 2e499bac81e..d18914ca509 100644 --- a/lld/docs/ld.lld.1 +++ b/lld/docs/ld.lld.1 @@ -329,6 +329,9 @@ Set the text and data sections to be readable and writable. .It Fl -opt-remarks-filename Ar file Write optimization remarks in YAML format to .Ar file . +.It Fl -opt-remarks-passes Ar pass-regex +Filter optimization remarks by only allowing the passes matching +.Ar pass-regex . .It Fl -opt-remarks-with-hotness Include hotness information in the optimization remarks file. .It Fl -orphan-handling Ns = Ns Ar mode diff --git a/lld/test/ELF/lto/opt-remarks.ll b/lld/test/ELF/lto/opt-remarks.ll index bef7e016a1c..e37bfd345ac 100644 --- a/lld/test/ELF/lto/opt-remarks.ll +++ b/lld/test/ELF/lto/opt-remarks.ll @@ -8,6 +8,9 @@ ; RUN: %t.o -o %t -shared ; RUN: cat %t.yaml | FileCheck %s -check-prefix=YAML ; RUN: cat %t.hot.yaml | FileCheck %s -check-prefix=YAML-HOT +; 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 ; Check that @tinkywinky is inlined after optimizations. ; CHECK-LABEL: define i32 @main @@ -48,6 +51,8 @@ ; YAML-HOT-NEXT: - String: ')' ; YAML-HOT-NEXT: ... +; YAML-PASSES: Pass: inline + target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-scei-ps4" diff --git a/llvm/include/llvm/IR/RemarkStreamer.h b/llvm/include/llvm/IR/RemarkStreamer.h index 38baa2b3b4b..64de27e3726 100644 --- a/llvm/include/llvm/IR/RemarkStreamer.h +++ b/llvm/include/llvm/IR/RemarkStreamer.h @@ -14,8 +14,10 @@ #define LLVM_IR_REMARKSTREAMER_H #include "llvm/IR/DiagnosticInfo.h" +#include "llvm/Support/Error.h" #include "llvm/Support/YAMLTraits.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Regex.h" #include <string> #include <vector> @@ -26,6 +28,8 @@ class RemarkStreamer { const std::string Filename; /// The open raw_ostream that the remark diagnostics are emitted to. raw_ostream &OS; + /// The regex used to filter remarks based on the passes that emit them. + Optional<Regex> PassFilter; /// The YAML streamer. yaml::Output YAMLOutput; @@ -36,6 +40,9 @@ public: StringRef getFilename() const { return Filename; } /// Return stream that the remark diagnostics are emitted to. raw_ostream &getStream() { return OS; } + /// Set a pass filter based on a regex \p Filter. + /// Returns an error if the regex is invalid. + Error setFilter(StringRef Filter); /// Emit a diagnostic through the streamer. void emit(const DiagnosticInfoOptimizationBase &Diag); }; diff --git a/llvm/include/llvm/LTO/Config.h b/llvm/include/llvm/LTO/Config.h index bf8cc98ac4d..1e2eeab11c0 100644 --- a/llvm/include/llvm/LTO/Config.h +++ b/llvm/include/llvm/LTO/Config.h @@ -96,6 +96,9 @@ struct Config { /// Optimization remarks file path. std::string RemarksFilename = ""; + /// Optimization remarks pass filter. + std::string RemarksPasses = ""; + /// Whether to emit optimization remarks with hotness informations. bool RemarksWithHotness = false; diff --git a/llvm/include/llvm/LTO/LTO.h b/llvm/include/llvm/LTO/LTO.h index ab4d874b55e..be37dbd0c59 100644 --- a/llvm/include/llvm/LTO/LTO.h +++ b/llvm/include/llvm/LTO/LTO.h @@ -84,6 +84,7 @@ std::string getThinLTOOutputFile(const std::string &Path, /// Setup optimization remarks. Expected<std::unique_ptr<ToolOutputFile>> setupOptimizationRemarks(LLVMContext &Context, StringRef LTORemarksFilename, + StringRef LTORemarksPasses, bool LTOPassRemarksWithHotness, int Count = -1); class LTO; diff --git a/llvm/lib/IR/RemarkStreamer.cpp b/llvm/lib/IR/RemarkStreamer.cpp index 0b983408e46..022c17d6722 100644 --- a/llvm/lib/IR/RemarkStreamer.cpp +++ b/llvm/lib/IR/RemarkStreamer.cpp @@ -21,7 +21,21 @@ RemarkStreamer::RemarkStreamer(StringRef Filename, raw_ostream &OS) assert(!Filename.empty() && "This needs to be a real filename."); } +Error RemarkStreamer::setFilter(StringRef Filter) { + Regex R = Regex(Filter); + std::string RegexError; + if (!R.isValid(RegexError)) + return createStringError(std::make_error_code(std::errc::invalid_argument), + RegexError.data()); + PassFilter = std::move(R); + return Error::success(); +} + void RemarkStreamer::emit(const DiagnosticInfoOptimizationBase &Diag) { + if (Optional<Regex> &Filter = PassFilter) + if (!Filter->match(Diag.getPassName())) + return; + DiagnosticInfoOptimizationBase *DiagPtr = const_cast<DiagnosticInfoOptimizationBase *>(&Diag); YAMLOutput << DiagPtr; diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp index f6e34c5d061..99318c19a89 100644 --- a/llvm/lib/LTO/LTO.cpp +++ b/llvm/lib/LTO/LTO.cpp @@ -1312,6 +1312,7 @@ Error LTO::runThinLTO(AddStreamFn AddStream, NativeObjectCache Cache) { Expected<std::unique_ptr<ToolOutputFile>> lto::setupOptimizationRemarks(LLVMContext &Context, StringRef LTORemarksFilename, + StringRef LTORemarksPasses, bool LTOPassRemarksWithHotness, int Count) { if (LTOPassRemarksWithHotness) Context.setDiagnosticsHotnessRequested(true); @@ -1329,6 +1330,11 @@ lto::setupOptimizationRemarks(LLVMContext &Context, return errorCodeToError(EC); Context.setRemarkStreamer( llvm::make_unique<RemarkStreamer>(Filename, DiagnosticFile->os())); + + if (!LTORemarksPasses.empty()) + if (Error E = Context.getRemarkStreamer()->setFilter(LTORemarksPasses)) + return std::move(E); + DiagnosticFile->keep(); return std::move(DiagnosticFile); } diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp index 0595771bd00..64c596931fa 100644 --- a/llvm/lib/LTO/LTOBackend.cpp +++ b/llvm/lib/LTO/LTOBackend.cpp @@ -429,8 +429,9 @@ Error lto::backend(Config &C, AddStreamFn AddStream, std::unique_ptr<TargetMachine> TM = createTargetMachine(C, *TOrErr, *Mod); // Setup optimization remarks. - auto DiagFileOrErr = lto::setupOptimizationRemarks( - Mod->getContext(), C.RemarksFilename, C.RemarksWithHotness); + auto DiagFileOrErr = + lto::setupOptimizationRemarks(Mod->getContext(), C.RemarksFilename, + C.RemarksPasses, C.RemarksWithHotness); if (!DiagFileOrErr) return DiagFileOrErr.takeError(); auto DiagnosticOutputFile = std::move(*DiagFileOrErr); @@ -484,7 +485,8 @@ Error lto::thinBackend(Config &Conf, unsigned Task, AddStreamFn AddStream, // Setup optimization remarks. auto DiagFileOrErr = lto::setupOptimizationRemarks( - Mod.getContext(), Conf.RemarksFilename, Conf.RemarksWithHotness, Task); + Mod.getContext(), Conf.RemarksFilename, Conf.RemarksPasses, + Conf.RemarksWithHotness, Task); if (!DiagFileOrErr) return DiagFileOrErr.takeError(); auto DiagnosticOutputFile = std::move(*DiagFileOrErr); diff --git a/llvm/lib/LTO/LTOCodeGenerator.cpp b/llvm/lib/LTO/LTOCodeGenerator.cpp index 1b1de2ba187..f02907f7a86 100644 --- a/llvm/lib/LTO/LTOCodeGenerator.cpp +++ b/llvm/lib/LTO/LTOCodeGenerator.cpp @@ -85,6 +85,12 @@ cl::opt<std::string> cl::desc("Output filename for pass remarks"), cl::value_desc("filename")); +cl::opt<std::string> + LTORemarksPasses("lto-pass-remarks-filter", + cl::desc("Only record optimization remarks from passes " + "whose names match the given regular expression"), + cl::value_desc("regex")); + cl::opt<bool> LTOPassRemarksWithHotness( "lto-pass-remarks-with-hotness", cl::desc("With PGO, include profile count in optimization remarks"), @@ -505,7 +511,7 @@ bool LTOCodeGenerator::optimize(bool DisableVerify, bool DisableInline, return false; auto DiagFileOrErr = lto::setupOptimizationRemarks( - Context, LTORemarksFilename, LTOPassRemarksWithHotness); + Context, LTORemarksFilename, LTORemarksPasses, LTOPassRemarksWithHotness); if (!DiagFileOrErr) { errs() << "Error: " << toString(DiagFileOrErr.takeError()) << "\n"; report_fatal_error("Can't get an output file for the remarks"); diff --git a/llvm/lib/LTO/ThinLTOCodeGenerator.cpp b/llvm/lib/LTO/ThinLTOCodeGenerator.cpp index 557afd6c360..d4ee66a53e0 100644 --- a/llvm/lib/LTO/ThinLTOCodeGenerator.cpp +++ b/llvm/lib/LTO/ThinLTOCodeGenerator.cpp @@ -70,6 +70,7 @@ namespace llvm { // Flags -discard-value-names, defined in LTOCodeGenerator.cpp extern cl::opt<bool> LTODiscardValueNames; extern cl::opt<std::string> LTORemarksFilename; +extern cl::opt<std::string> LTORemarksPasses; extern cl::opt<bool> LTOPassRemarksWithHotness; } @@ -972,7 +973,8 @@ void ThinLTOCodeGenerator::run() { Context.setDiscardValueNames(LTODiscardValueNames); Context.enableDebugTypeODRUniquing(); auto DiagFileOrErr = lto::setupOptimizationRemarks( - Context, LTORemarksFilename, LTOPassRemarksWithHotness, count); + Context, LTORemarksFilename, LTORemarksPasses, + LTOPassRemarksWithHotness, count); if (!DiagFileOrErr) { errs() << "Error: " << toString(DiagFileOrErr.takeError()) << "\n"; report_fatal_error("ThinLTO: Can't get an output file for the " diff --git a/llvm/test/LTO/Resolution/X86/diagnostic-handler-remarks.ll b/llvm/test/LTO/Resolution/X86/diagnostic-handler-remarks.ll index 03db4a722b5..beb0f4fa49b 100644 --- a/llvm/test/LTO/Resolution/X86/diagnostic-handler-remarks.ll +++ b/llvm/test/LTO/Resolution/X86/diagnostic-handler-remarks.ll @@ -4,6 +4,7 @@ ; RUN: llvm-as < %s >%t.bc ; RUN: rm -f %t.yaml ; RUN: llvm-lto2 run -pass-remarks-output=%t.yaml \ +; RUN: -pass-remarks-filter=inline \ ; RUN: -r %t.bc,tinkywinky,p \ ; RUN: -r %t.bc,patatino,px \ ; RUN: -r %t.bc,main,px -o %t.o %t.bc @@ -13,6 +14,7 @@ ; RUN: opt -module-summary %s -o %t.bc ; RUN: rm -f %t.thin.1.yaml ; RUN: llvm-lto2 run -pass-remarks-output=%t \ +; RUN: -pass-remarks-filter=inline \ ; RUN: -r %t.bc,tinkywinky,p \ ; RUN: -r %t.bc,patatino,px \ ; RUN: -r %t.bc,main,px -o %t.o %t.bc diff --git a/llvm/test/ThinLTO/X86/diagnostic-handler-remarks.ll b/llvm/test/ThinLTO/X86/diagnostic-handler-remarks.ll index d4606ba999d..4c13fe804d6 100644 --- a/llvm/test/ThinLTO/X86/diagnostic-handler-remarks.ll +++ b/llvm/test/ThinLTO/X86/diagnostic-handler-remarks.ll @@ -5,6 +5,7 @@ ; RUN: rm -f %t.yaml.thin.0.yaml %t.yaml.thin.1.yaml ; RUN: llvm-lto -thinlto-action=run \ ; RUN: -lto-pass-remarks-output=%t.yaml \ +; RUN: -lto-pass-remarks-filter=inline \ ; RUN: -exported-symbol _func2 \ ; RUN: -exported-symbol _main %t1.bc %t2.bc 2>&1 | \ ; RUN: FileCheck %s -allow-empty diff --git a/llvm/tools/gold/gold-plugin.cpp b/llvm/tools/gold/gold-plugin.cpp index fbf78b02551..dc61ff925ce 100644 --- a/llvm/tools/gold/gold-plugin.cpp +++ b/llvm/tools/gold/gold-plugin.cpp @@ -205,8 +205,9 @@ namespace options { /// Statistics output filename. static std::string stats_file; - // Optimization remarks filename and hotness options + // Optimization remarks filename, accepted passes and hotness options static std::string OptRemarksFilename; + static std::string OptRemarksFilter; static bool OptRemarksWithHotness = false; // Context sensitive PGO options. @@ -285,6 +286,8 @@ namespace options { dwo_dir = opt.substr(strlen("dwo_dir=")); } else if (opt.startswith("opt-remarks-filename=")) { OptRemarksFilename = opt.substr(strlen("opt-remarks-filename=")); + } else if (opt.startswith("opt-remarks-passes=")) { + OptRemarksFilter = opt.substr(strlen("opt-remarks-passes=")); } else if (opt == "opt-remarks-with-hotness") { OptRemarksWithHotness = true; } else if (opt.startswith("stats-file=")) { @@ -908,6 +911,7 @@ static std::unique_ptr<LTO> createLTO(IndexWriteCallback OnIndexWrite, // Set up optimization remarks handling. Conf.RemarksFilename = options::OptRemarksFilename; + Conf.RemarksPasses = options::OptRemarksFilter; Conf.RemarksWithHotness = options::OptRemarksWithHotness; // Use new pass manager if set in driver diff --git a/llvm/tools/llc/llc.cpp b/llvm/tools/llc/llc.cpp index a566d15cd81..be103845e97 100644 --- a/llvm/tools/llc/llc.cpp +++ b/llvm/tools/llc/llc.cpp @@ -148,6 +148,12 @@ static cl::opt<std::string> cl::desc("YAML output filename for pass remarks"), cl::value_desc("filename")); +static cl::opt<std::string> + RemarksPasses("pass-remarks-filter", + cl::desc("Only record optimization remarks from passes whose " + "names match the given regular expression"), + cl::value_desc("regex")); + namespace { static ManagedStatic<std::vector<std::string>> RunPassNames; @@ -336,6 +342,12 @@ int main(int argc, char **argv) { } Context.setRemarkStreamer( llvm::make_unique<RemarkStreamer>(RemarksFilename, YamlFile->os())); + + if (!RemarksPasses.empty()) + if (Error E = Context.getRemarkStreamer()->setFilter(RemarksPasses)) { + WithColor::error(errs(), argv[0]) << E << '\n'; + return 1; + } } if (InputLanguage != "" && InputLanguage != "ir" && diff --git a/llvm/tools/llvm-lto2/llvm-lto2.cpp b/llvm/tools/llvm-lto2/llvm-lto2.cpp index 6cceb8e4cf8..df51921396a 100644 --- a/llvm/tools/llvm-lto2/llvm-lto2.cpp +++ b/llvm/tools/llvm-lto2/llvm-lto2.cpp @@ -101,6 +101,12 @@ static cl::opt<bool> OptRemarksWithHotness( "Has effect only if -pass-remarks-output is specified.")); static cl::opt<std::string> + OptRemarksPasses("pass-remarks-filter", + cl::desc("Only record optimization remarks from passes " + "whose names match the given regular expression"), + cl::value_desc("regex")); + +static cl::opt<std::string> SamplePGOFile("lto-sample-profile-file", cl::desc("Specify a SamplePGO profile file")); @@ -220,6 +226,7 @@ static int run(int argc, char **argv) { // Optimization remarks. Conf.RemarksFilename = OptRemarksOutput; + Conf.RemarksPasses = OptRemarksPasses; Conf.RemarksWithHotness = OptRemarksWithHotness; Conf.SampleProfile = SamplePGOFile; diff --git a/llvm/tools/opt/opt.cpp b/llvm/tools/opt/opt.cpp index 06745b0cca0..b4c39e2fca8 100644 --- a/llvm/tools/opt/opt.cpp +++ b/llvm/tools/opt/opt.cpp @@ -275,6 +275,12 @@ static cl::opt<std::string> cl::desc("YAML output filename for pass remarks"), cl::value_desc("filename")); +static cl::opt<std::string> + RemarksPasses("pass-remarks-filter", + cl::desc("Only record optimization remarks from passes whose " + "names match the given regular expression"), + cl::value_desc("regex")); + cl::opt<PGOKind> PGOKindFlag("pgo-kind", cl::init(NoPGO), cl::Hidden, cl::desc("The kind of profile guided optimization"), @@ -566,6 +572,12 @@ int main(int argc, char **argv) { } Context.setRemarkStreamer(llvm::make_unique<RemarkStreamer>( RemarksFilename, OptRemarkFile->os())); + + if (!RemarksPasses.empty()) + if (Error E = Context.getRemarkStreamer()->setFilter(RemarksPasses)) { + errs() << E << '\n'; + return 1; + } } // Load the input module... |