diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -263,6 +263,7 @@ StringRef thinLTOJobs; unsigned timeTraceGranularity; int32_t splitStackAdjustSize; + unsigned optRemarksHotnessThreshold; // The following config options do not directly correspond to any // particular command line options. diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -982,6 +982,8 @@ config->oFormatBinary = isOutputFormatBinary(args); config->omagic = args.hasFlag(OPT_omagic, OPT_no_omagic, false); config->optRemarksFilename = args.getLastArgValue(OPT_opt_remarks_filename); + config->optRemarksHotnessThreshold = + args::getInteger(args, OPT_opt_remarks_hotness_threshold, 0); 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); diff --git a/lld/ELF/LTO.cpp b/lld/ELF/LTO.cpp --- a/lld/ELF/LTO.cpp +++ b/lld/ELF/LTO.cpp @@ -130,6 +130,7 @@ c.RemarksFilename = std::string(config->optRemarksFilename); c.RemarksPasses = std::string(config->optRemarksPasses); c.RemarksWithHotness = config->optRemarksWithHotness; + c.RemarksHotnessThreshold = config->optRemarksHotnessThreshold; c.RemarksFormat = std::string(config->optRemarksFormat); c.SampleProfile = std::string(config->ltoSampleProfile); diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -541,6 +541,9 @@ 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">; +defm opt_remarks_hotness_threshold: EEq<"opt-remarks-hotness-threshold", + "Minimum profile count required for an optimization remark to be output">, + MetaVarName<"">; 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: FF<"opt-remarks-with-hotness">, diff --git a/lld/test/ELF/lto/opt-remarks.ll b/lld/test/ELF/lto/opt-remarks.ll --- a/lld/test/ELF/lto/opt-remarks.ll +++ b/lld/test/ELF/lto/opt-remarks.ll @@ -1,19 +1,25 @@ ; REQUIRES: x86 ; RUN: llvm-as %s -o %t.o -; RUN: rm -f %t.yaml +; RUN: rm -f %t.yaml %t1.yaml %t.hot.yaml %t.t300.yaml %t.t301.yaml ; RUN: ld.lld --opt-remarks-filename %t.yaml %t.o -o %t -shared -save-temps ; RUN: llvm-dis %t.0.4.opt.bc -o - | FileCheck %s ; RUN: ld.lld --opt-remarks-with-hotness --opt-remarks-filename %t.hot.yaml \ ; RUN: %t.o -o %t -shared +; RUN: ld.lld --opt-remarks-with-hotness --opt-remarks-hotness-threshold=300 \ +; RUN: --opt-remarks-filename %t.t300.yaml %t.o -o %t -shared +; RUN: ld.lld --opt-remarks-with-hotness --opt-remarks-hotness-threshold=301 \ +; RUN: --opt-remarks-filename %t.t301.yaml %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: FileCheck %s -check-prefix=YAML-HOT < %t.t300.yaml +; RUN: count 0 < %t.t301.yaml ; 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 +; RUN: cat %t1.yaml | FileCheck %s -check-prefix=YAML ; Check that @tinkywinky is inlined after optimizations. ; CHECK-LABEL: define i32 @main diff --git a/llvm/include/llvm/LTO/Config.h b/llvm/include/llvm/LTO/Config.h --- a/llvm/include/llvm/LTO/Config.h +++ b/llvm/include/llvm/LTO/Config.h @@ -121,6 +121,10 @@ /// Whether to emit optimization remarks with hotness informations. bool RemarksWithHotness = false; + /// Minimal number of hotness number for remarks to report. + /// "0 means no threshold". + unsigned RemarksHotnessThreshold = 0; + /// The format used for serializing remarks (default: YAML). std::string RemarksFormat = ""; diff --git a/llvm/include/llvm/LTO/LTO.h b/llvm/include/llvm/LTO/LTO.h --- a/llvm/include/llvm/LTO/LTO.h +++ b/llvm/include/llvm/LTO/LTO.h @@ -82,10 +82,10 @@ const std::string &NewPrefix); /// Setup optimization remarks. -Expected> -setupLLVMOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename, - StringRef RemarksPasses, StringRef RemarksFormat, - bool RemarksWithHotness, int Count = -1); +Expected> setupLLVMOptimizationRemarks( + LLVMContext &Context, StringRef RemarksFilename, StringRef RemarksPasses, + StringRef RemarksFormat, bool RemarksWithHotness, + unsigned RemarksHotnessThreshold = 0, int Count = -1); /// Setups the output file for saving statistics. Expected> diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp --- a/llvm/lib/LTO/LTO.cpp +++ b/llvm/lib/LTO/LTO.cpp @@ -983,7 +983,8 @@ // Setup optimization remarks. auto DiagFileOrErr = lto::setupLLVMOptimizationRemarks( RegularLTO.CombinedModule->getContext(), Conf.RemarksFilename, - Conf.RemarksPasses, Conf.RemarksFormat, Conf.RemarksWithHotness); + Conf.RemarksPasses, Conf.RemarksFormat, Conf.RemarksWithHotness, + Conf.RemarksHotnessThreshold); if (!DiagFileOrErr) return DiagFileOrErr.takeError(); @@ -1459,7 +1460,8 @@ Expected> lto::setupLLVMOptimizationRemarks( LLVMContext &Context, StringRef RemarksFilename, StringRef RemarksPasses, - StringRef RemarksFormat, bool RemarksWithHotness, int Count) { + StringRef RemarksFormat, bool RemarksWithHotness, + unsigned RemarksHotnessThreshold, int Count) { std::string Filename = std::string(RemarksFilename); // For ThinLTO, file.opt. becomes // file.opt..thin... @@ -1469,7 +1471,8 @@ .str(); auto ResultOrErr = llvm::setupLLVMOptimizationRemarks( - Context, Filename, RemarksPasses, RemarksFormat, RemarksWithHotness); + Context, Filename, RemarksPasses, RemarksFormat, RemarksWithHotness, + RemarksHotnessThreshold); if (Error E = ResultOrErr.takeError()) return std::move(E); diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp --- a/llvm/lib/LTO/LTOBackend.cpp +++ b/llvm/lib/LTO/LTOBackend.cpp @@ -542,7 +542,8 @@ // Setup optimization remarks. auto DiagFileOrErr = lto::setupLLVMOptimizationRemarks( Mod.getContext(), Conf.RemarksFilename, Conf.RemarksPasses, - Conf.RemarksFormat, Conf.RemarksWithHotness, Task); + Conf.RemarksFormat, Conf.RemarksWithHotness, Conf.RemarksHotnessThreshold, + 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 --- a/llvm/lib/LTO/LTOCodeGenerator.cpp +++ b/llvm/lib/LTO/LTOCodeGenerator.cpp @@ -87,6 +87,12 @@ cl::desc("With PGO, include profile count in optimization remarks"), cl::Hidden); +cl::opt + RemarksHotnessThreshold("lto-pass-remarks-hotness-threshold", + cl::desc("Minimum profile count required for an " + "optimization remark to be output"), + cl::init(0), cl::Hidden); + cl::opt RemarksFilename("lto-pass-remarks-output", cl::desc("Output filename for pass remarks"), @@ -528,9 +534,9 @@ if (!this->determineTarget()) return false; - auto DiagFileOrErr = - lto::setupLLVMOptimizationRemarks(Context, RemarksFilename, RemarksPasses, - RemarksFormat, RemarksWithHotness); + auto DiagFileOrErr = lto::setupLLVMOptimizationRemarks( + Context, RemarksFilename, RemarksPasses, RemarksFormat, + RemarksWithHotness, RemarksHotnessThreshold); 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 --- a/llvm/lib/LTO/ThinLTOCodeGenerator.cpp +++ b/llvm/lib/LTO/ThinLTOCodeGenerator.cpp @@ -75,6 +75,7 @@ extern cl::opt RemarksFilename; extern cl::opt RemarksPasses; extern cl::opt RemarksWithHotness; +extern cl::opt RemarksHotnessThreshold; extern cl::opt RemarksFormat; } @@ -1097,7 +1098,7 @@ Context.enableDebugTypeODRUniquing(); auto DiagFileOrErr = lto::setupLLVMOptimizationRemarks( Context, RemarksFilename, RemarksPasses, RemarksFormat, - RemarksWithHotness, count); + RemarksWithHotness, RemarksHotnessThreshold, 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-with-hotness.ll b/llvm/test/LTO/Resolution/X86/diagnostic-handler-remarks-with-hotness.ll --- a/llvm/test/LTO/Resolution/X86/diagnostic-handler-remarks-with-hotness.ll +++ b/llvm/test/LTO/Resolution/X86/diagnostic-handler-remarks-with-hotness.ll @@ -9,6 +9,26 @@ ; RUN: -r %t.bc,main,px -o %t.o %t.bc ; RUN: cat %t.yaml | FileCheck %s -check-prefix=YAML +; Check low threshold allows remarks to emit +; RUN: rm -f %t.t300.yaml +; RUN: llvm-lto2 run -pass-remarks-output=%t.t300.yaml \ +; RUN: -pass-remarks-with-hotness \ +; RUN: -pass-remarks-hotness-threshold=300 \ +; RUN: -r %t.bc,tinkywinky,p \ +; RUN: -r %t.bc,patatino,px \ +; RUN: -r %t.bc,main,px -o %t.o %t.bc +; RUN: FileCheck %s -check-prefix=YAML < %t.t300.yaml + +; Check high threshold disallows remarks to emit +; RUN: rm -f %t.t301.yaml +; RUN: llvm-lto2 run -pass-remarks-output=%t.t301.yaml \ +; RUN: -pass-remarks-with-hotness \ +; RUN: -pass-remarks-hotness-threshold=301 \ +; RUN: -r %t.bc,tinkywinky,p \ +; RUN: -r %t.bc,patatino,px \ +; RUN: -r %t.bc,main,px -o %t.o %t.bc +; RUN: not FileCheck %s -check-prefix=YAML < %t.t301.yaml + ; Check pass remarks emitted to stderr ; RUN: llvm-lto2 run -pass-remarks=inline \ ; RUN: -pass-remarks-with-hotness \ @@ -16,6 +36,22 @@ ; RUN: -r %t.bc,patatino,px \ ; RUN: -r %t.bc,main,px -o %t.o %t.bc 2>&1 | FileCheck %s +; Check low threshold allows remarks to emit +; RUN: llvm-lto2 run -pass-remarks=inline \ +; RUN: -pass-remarks-with-hotness \ +; RUN: -pass-remarks-hotness-threshold=300 \ +; RUN: -r %t.bc,tinkywinky,p \ +; RUN: -r %t.bc,patatino,px \ +; RUN: -r %t.bc,main,px -o %t.o %t.bc 2>&1 | FileCheck %s + +; Check high threshold disallows remarks to emit +; RUN: llvm-lto2 run -pass-remarks=inline \ +; RUN: -pass-remarks-with-hotness \ +; RUN: -pass-remarks-hotness-threshold=301 \ +; RUN: -r %t.bc,tinkywinky,p \ +; RUN: -r %t.bc,patatino,px \ +; RUN: -r %t.bc,main,px -o %t.o %t.bc 2>&1 | not FileCheck %s + ; YAML: --- !Passed ; YAML-NEXT: Pass: inline ; YAML-NEXT: Name: Inlined diff --git a/llvm/test/LTO/X86/diagnostic-handler-remarks-with-hotness.ll b/llvm/test/LTO/X86/diagnostic-handler-remarks-with-hotness.ll --- a/llvm/test/LTO/X86/diagnostic-handler-remarks-with-hotness.ll +++ b/llvm/test/LTO/X86/diagnostic-handler-remarks-with-hotness.ll @@ -2,12 +2,24 @@ ; with -lto-pass-remarks-with-hotness. ; RUN: llvm-as < %s >%t.bc -; RUN: rm -f %t.yaml +; RUN: rm -f %t.yaml %t.t300.yaml %t.t301.yaml ; RUN: llvm-lto -lto-pass-remarks-output=%t.yaml \ ; RUN: -lto-pass-remarks-with-hotness \ ; RUN: -exported-symbol _main -o %t.o %t.bc ; RUN: cat %t.yaml | FileCheck -check-prefix=YAML %s +; RUN: llvm-lto -lto-pass-remarks-output=%t.t300.yaml \ +; RUN: -lto-pass-remarks-with-hotness \ +; RUN: -lto-pass-remarks-hotness-threshold=300 \ +; RUN: -exported-symbol _main -o %t.o %t.bc +; RUN: FileCheck -check-prefix=YAML %s < %t.t300.yaml + +; RUN: llvm-lto -lto-pass-remarks-output=%t.t301.yaml \ +; RUN: -lto-pass-remarks-with-hotness \ +; RUN: -lto-pass-remarks-hotness-threshold=301 \ +; RUN: -exported-symbol _main -o %t.o %t.bc +; RUN: not FileCheck -check-prefix=YAML %s < %t.t301.yaml + ; YAML: --- !Passed ; YAML-NEXT: Pass: inline ; YAML-NEXT: Name: Inlined diff --git a/llvm/test/tools/gold/X86/opt-remarks.ll b/llvm/test/tools/gold/X86/opt-remarks.ll --- a/llvm/test/tools/gold/X86/opt-remarks.ll +++ b/llvm/test/tools/gold/X86/opt-remarks.ll @@ -11,8 +11,22 @@ ; 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: %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-hotness-threshold=300 \ +; RUN: -plugin-opt=opt-remarks-filename=%t.t300.yaml %t.o -o %t2.o 2>&1 +; 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-hotness-threshold=301 \ +; RUN: -plugin-opt=opt-remarks-filename=%t.t301.yaml %t.o -o %t2.o 2>&1 ; RUN: cat %t.yaml | FileCheck %s -check-prefix=YAML ; RUN: cat %t.hot.yaml | FileCheck %s -check-prefix=YAML-HOT +; RUN: FileCheck %s -check-prefix=YAML-HOT < %t.t300.yaml +; RUN: count 0 < %t.t301.yaml ; Check that @f is inlined after optimizations. ; CHECK-LABEL: define i32 @_start @@ -46,7 +60,6 @@ ; YAML-NEXT: - String: ')' ; YAML-NEXT: ... -; YAML-HOT: ... ; YAML-HOT: --- !Passed ; YAML-HOT: Pass: inline ; YAML-HOT-NEXT: Name: Inlined diff --git a/llvm/tools/gold/gold-plugin.cpp b/llvm/tools/gold/gold-plugin.cpp --- a/llvm/tools/gold/gold-plugin.cpp +++ b/llvm/tools/gold/gold-plugin.cpp @@ -213,6 +213,7 @@ static std::string RemarksFilename; static std::string RemarksPasses; static bool RemarksWithHotness = false; + static unsigned RemarksHotnessThreshold = 0; static std::string RemarksFormat; // Context sensitive PGO options. @@ -297,6 +298,10 @@ RemarksPasses = std::string(opt); } else if (opt == "opt-remarks-with-hotness") { RemarksWithHotness = true; + } else if (opt.consume_front("opt-remarks-hotness-threshold=")) { + if (opt.getAsInteger(10, RemarksHotnessThreshold)) { + message(LDPL_FATAL, "Invalid remarks hotness threshold: %s", opt); + } } else if (opt.consume_front("opt-remarks-format=")) { RemarksFormat = std::string(opt); } else if (opt.consume_front("stats-file=")) { @@ -931,6 +936,8 @@ Conf.RemarksFilename = options::RemarksFilename; Conf.RemarksPasses = options::RemarksPasses; Conf.RemarksWithHotness = options::RemarksWithHotness; + Conf.RemarksHotnessThreshold = options::RemarksHotnessThreshold; + ; Conf.RemarksFormat = options::RemarksFormat; // Use new pass manager if set in driver diff --git a/llvm/tools/llvm-lto2/llvm-lto2.cpp b/llvm/tools/llvm-lto2/llvm-lto2.cpp --- a/llvm/tools/llvm-lto2/llvm-lto2.cpp +++ b/llvm/tools/llvm-lto2/llvm-lto2.cpp @@ -103,6 +103,12 @@ cl::desc("With PGO, include profile count in optimization remarks"), cl::Hidden); +static cl::opt + RemarksHotnessThreshold("pass-remarks-hotness-threshold", + cl::desc("Minimum profile count required for an " + "optimization remark to be output"), + cl::init(0), cl::Hidden); + static cl::opt RemarksFilename("pass-remarks-output", cl::desc("Output filename for pass remarks"), @@ -246,6 +252,7 @@ Conf.RemarksFilename = RemarksFilename; Conf.RemarksPasses = RemarksPasses; Conf.RemarksWithHotness = RemarksWithHotness; + Conf.RemarksHotnessThreshold = RemarksHotnessThreshold; Conf.RemarksFormat = RemarksFormat; Conf.SampleProfile = SamplePGOFile;