diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -111,6 +111,21 @@ llvm::StringRef mapFile; llvm::StringRef outputFile; llvm::StringRef optRemarksFilename; + + // The minimum hotness value a diagnostic needs in order to be included in + // optimization diagnostics. + // + // The threshold is an Optional value, which maps to one of the 3 states: + // 1. 0 => threshold disabled. All emarks will be printed. + // 2. positive int => manual threshold by user. Remarks with hotness exceed + // threshold will be printed. + // 3. None => 'auto' threshold by user. The actual value is not + // available at command line, but will be synced with + // hotness threhold from profile summary during + // compilation. + // + // If threshold option is not specified, it is disabled by default. + llvm::Optional optRemarksHotnessThreshold = 0; llvm::StringRef optRemarksPasses; llvm::StringRef optRemarksFormat; llvm::StringRef progName; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -48,6 +48,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/LTO/LTO.h" +#include "llvm/Remarks/HotnessThresholdParser.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compression.h" #include "llvm/Support/GlobPattern.h" @@ -985,6 +986,17 @@ config->oFormatBinary = isOutputFormatBinary(args); config->omagic = args.hasFlag(OPT_omagic, OPT_no_omagic, false); config->optRemarksFilename = args.getLastArgValue(OPT_opt_remarks_filename); + + // Parse remarks hotness threshold. Valid value is either integer or 'auto'. + if (auto *arg = args.getLastArg(OPT_opt_remarks_hotness_threshold)) { + auto resultOrErr = remarks::parseHotnessThresholdOption(arg->getValue()); + if (!resultOrErr) + error(arg->getSpelling() + ": invalid argument '" + arg->getValue() + + "', only integer or 'auto' is supported."); + else + config->optRemarksHotnessThreshold = *resultOrErr; + } + 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 @@ -545,6 +545,10 @@ 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." + " Use 'auto' to apply the threshold from profile summary.">, + 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">, @@ -593,6 +597,21 @@ def: J<"plugin-opt=obj-path=">, Alias, HelpText<"Alias for --lto-obj-path=">; +def: J<"plugin-opt=opt-remarks-filename=">, + Alias, + HelpText<"Alias for --opt-remarks-filename">; +def: J<"plugin-opt=opt-remarks-passes=">, + Alias, + HelpText<"Alias for --opt-remarks-passes">; +def: J<"plugin-opt=opt-remarks-format=">, + Alias, + HelpText<"Alias for --opt-remarks-format">; +def: F<"plugin-opt=opt-remarks-with-hotness">, + Alias, + HelpText<"Alias for --opt-remarks-with_hotness">; +def: J<"plugin-opt=opt-remarks-hotness-threshold=">, + Alias, + HelpText<"Alias for --opt-remarks-hotness-threshold">; def: J<"plugin-opt=sample-profile=">, Alias, HelpText<"Alias for --lto-sample-profile">; def: F<"plugin-opt=save-temps">, Alias, HelpText<"Alias for --save-temps">; 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: FileCheck %s -check-prefix=YAML < %t1.yaml ; Check that @tinkywinky is inlined after optimizations. ; CHECK-LABEL: define i32 @main diff --git a/llvm/include/llvm/IR/LLVMContext.h b/llvm/include/llvm/IR/LLVMContext.h --- a/llvm/include/llvm/IR/LLVMContext.h +++ b/llvm/include/llvm/IR/LLVMContext.h @@ -222,13 +222,20 @@ void setDiagnosticsHotnessRequested(bool Requested); /// Return the minimum hotness value a diagnostic would need in order - /// to be included in optimization diagnostics. If there is no minimum, this - /// returns None. + /// to be included in optimization diagnostics. + /// + /// Three possible return values: + /// 0 - threshold is disabled. Everything will be printed out. + /// positive int - threshold is set. + /// UINT64_MAX - threshold is not yet set, and needs to be synced from + /// profile summary. Note that in case of missing profile + /// summary, threshold will be kept at "MAX", effectively + /// suppresses all remarks output. uint64_t getDiagnosticsHotnessThreshold() const; /// Set the minimum hotness value a diagnostic needs in order to be /// included in optimization diagnostics. - void setDiagnosticsHotnessThreshold(uint64_t Threshold); + void setDiagnosticsHotnessThreshold(Optional Threshold); /// The "main remark streamer" used by all the specialized remark streamers. /// This streamer keeps generic remark metadata in memory throughout the life diff --git a/llvm/include/llvm/IR/LLVMRemarkStreamer.h b/llvm/include/llvm/IR/LLVMRemarkStreamer.h --- a/llvm/include/llvm/IR/LLVMRemarkStreamer.h +++ b/llvm/include/llvm/IR/LLVMRemarkStreamer.h @@ -79,16 +79,15 @@ setupLLVMOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename, StringRef RemarksPasses, StringRef RemarksFormat, bool RemarksWithHotness, - unsigned RemarksHotnessThreshold = 0); + Optional RemarksHotnessThreshold = 0); /// Setup optimization remarks that output directly to a raw_ostream. /// \p OS is managed by the caller and should be open for writing as long as \p /// Context is streaming remarks to it. -Error setupLLVMOptimizationRemarks(LLVMContext &Context, raw_ostream &OS, - StringRef RemarksPasses, - StringRef RemarksFormat, - bool RemarksWithHotness, - unsigned RemarksHotnessThreshold = 0); +Error setupLLVMOptimizationRemarks( + LLVMContext &Context, raw_ostream &OS, StringRef RemarksPasses, + StringRef RemarksFormat, bool RemarksWithHotness, + Optional RemarksHotnessThreshold = 0); } // end namespace llvm 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,21 @@ /// Whether to emit optimization remarks with hotness informations. bool RemarksWithHotness = false; + /// The minimum hotness value a diagnostic needs in order to be included in + /// optimization diagnostics. + /// + /// The threshold is an Optional value, which maps to one of the 3 states: + /// 1. 0 => threshold disabled. All emarks will be printed. + /// 2. positive int => manual threshold by user. Remarks with hotness exceed + /// threshold will be printed. + /// 3. None => 'auto' threshold by user. The actual value is not + /// available at command line, but will be synced with + /// hotness threhold from profile summary during + /// compilation. + /// + /// If threshold option is not specified, it is disabled by default. + llvm::Optional 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, + Optional RemarksHotnessThreshold = 0, int Count = -1); /// Setups the output file for saving statistics. Expected> diff --git a/llvm/include/llvm/Remarks/HotnessThresholdParser.h b/llvm/include/llvm/Remarks/HotnessThresholdParser.h new file mode 100644 --- /dev/null +++ b/llvm/include/llvm/Remarks/HotnessThresholdParser.h @@ -0,0 +1,62 @@ +//===- HotnessThresholdParser.h - Parser for hotness threshold --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file implements a simple parser to decode commandline option for +/// remarks hotness threshold that supports both int and a special 'auto' value. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_REMARKS_HOTNESSTHRESHOLDPARSER_H +#define LLVM_REMARKS_HOTNESSTHRESHOLDPARSER_H + +#include "llvm/ADT/Optional.h" +#include "llvm/Support/CommandLine.h" +namespace llvm { +namespace remarks { + +// Parse remarks hotness threshold argument value. +// Valid option values are +// 1. integer: manually specified threshold; or +// 2. string 'auto': automatically get threshold from profile summary. +// +// Return None Optional if 'auto' is specified, indicating the value will +// be filled later during PSI. +inline Expected> parseHotnessThresholdOption(StringRef Arg) { + if (Arg == "auto") + return None; + + int64_t Val; + if (Arg.getAsInteger(10, Val)) + return createStringError(llvm::inconvertibleErrorCode(), + "Not an integer: %s", Arg.data()); + + // Negative integer effectively means no threshold + return Val < 0 ? 0 : Val; +} + +// A simple CL parser for '*-remarks-hotness-threshold=' +class HotnessThresholdParser : public cl::parser> { +public: + HotnessThresholdParser(cl::Option &O) : cl::parser>(O) {} + + bool parse(cl::Option &O, StringRef ArgName, StringRef Arg, + Optional &V) { + auto ResultOrErr = parseHotnessThresholdOption(Arg); + if (!ResultOrErr) + return O.error("Invalid argument '" + Arg + + "', only integer or 'auto' is supported."); + + V = *ResultOrErr; + return false; + } +}; + +} // namespace remarks +} // namespace llvm +#endif // LLVM_REMARKS_HOTNESSTHRESHOLDPARSER_H diff --git a/llvm/include/llvm/Support/CommandLine.h b/llvm/include/llvm/Support/CommandLine.h --- a/llvm/include/llvm/Support/CommandLine.h +++ b/llvm/include/llvm/Support/CommandLine.h @@ -1481,7 +1481,7 @@ template explicit opt(const Mods &... Ms) - : Option(Optional, NotHidden), Parser(*this) { + : Option(llvm::cl::Optional, NotHidden), Parser(*this) { apply(this, Ms...); done(); } diff --git a/llvm/lib/IR/LLVMContext.cpp b/llvm/lib/IR/LLVMContext.cpp --- a/llvm/lib/IR/LLVMContext.cpp +++ b/llvm/lib/IR/LLVMContext.cpp @@ -146,11 +146,11 @@ return pImpl->DiagnosticsHotnessRequested; } -void LLVMContext::setDiagnosticsHotnessThreshold(uint64_t Threshold) { +void LLVMContext::setDiagnosticsHotnessThreshold(Optional Threshold) { pImpl->DiagnosticsHotnessThreshold = Threshold; } uint64_t LLVMContext::getDiagnosticsHotnessThreshold() const { - return pImpl->DiagnosticsHotnessThreshold; + return pImpl->DiagnosticsHotnessThreshold.getValueOr(UINT64_MAX); } remarks::RemarkStreamer *LLVMContext::getMainRemarkStreamer() { diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -1276,7 +1276,26 @@ std::unique_ptr DiagHandler; bool RespectDiagnosticFilters = false; bool DiagnosticsHotnessRequested = false; - uint64_t DiagnosticsHotnessThreshold = 0; + /// The minimum hotness value a diagnostic needs in order to be included in + /// optimization diagnostics. + /// + /// The threshold is an Optional value, which maps to one of the 3 states: + /// 1). 0 => threshold disabled. All emarks will be printed. + /// 2). positive int => manual threshold by user. Remarks with hotness exceed + /// threshold will be printed. + /// 3). None => 'auto' threshold by user. The actual value is not + /// available at command line, but will be synced with + /// hotness threhold from profile summary during + /// compilation. + /// + /// State 1 and 2 are considered as terminal states. State transition is + /// only allowed from 3 to 2, when the threshold is first synced with profile + /// summary. This ensures that the threshold is set only once and stays + /// constant. + /// + /// If threshold option is not specified, it is disabled (0) by default. + Optional DiagnosticsHotnessThreshold = 0; + /// The specialized remark streamer used by LLVM's OptimizationRemarkEmitter. std::unique_ptr LLVMRS; diff --git a/llvm/lib/IR/LLVMRemarkStreamer.cpp b/llvm/lib/IR/LLVMRemarkStreamer.cpp --- a/llvm/lib/IR/LLVMRemarkStreamer.cpp +++ b/llvm/lib/IR/LLVMRemarkStreamer.cpp @@ -92,7 +92,7 @@ Expected> llvm::setupLLVMOptimizationRemarks( LLVMContext &Context, StringRef RemarksFilename, StringRef RemarksPasses, StringRef RemarksFormat, bool RemarksWithHotness, - unsigned RemarksHotnessThreshold) { + Optional RemarksHotnessThreshold) { if (RemarksWithHotness) Context.setDiagnosticsHotnessRequested(true); @@ -137,11 +137,10 @@ return std::move(RemarksFile); } -Error llvm::setupLLVMOptimizationRemarks(LLVMContext &Context, raw_ostream &OS, - StringRef RemarksPasses, - StringRef RemarksFormat, - bool RemarksWithHotness, - unsigned RemarksHotnessThreshold) { +Error llvm::setupLLVMOptimizationRemarks( + LLVMContext &Context, raw_ostream &OS, StringRef RemarksPasses, + StringRef RemarksFormat, bool RemarksWithHotness, + Optional RemarksHotnessThreshold) { if (RemarksWithHotness) Context.setDiagnosticsHotnessRequested(true); 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, + Optional 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 @@ -43,6 +43,7 @@ #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/SubtargetFeature.h" +#include "llvm/Remarks/HotnessThresholdParser.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Host.h" @@ -87,6 +88,14 @@ cl::desc("With PGO, include profile count in optimization remarks"), cl::Hidden); +cl::opt, false, remarks::HotnessThresholdParser> + RemarksHotnessThreshold( + "lto-pass-remarks-hotness-threshold", + cl::desc("Minimum profile count required for an " + "optimization remark to be output." + " Use 'auto' to apply the threshold from profile summary."), + cl::value_desc("uint or 'auto'"), cl::init(0), cl::Hidden); + cl::opt RemarksFilename("lto-pass-remarks-output", cl::desc("Output filename for pass remarks"), @@ -528,9 +537,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 @@ -21,6 +21,7 @@ #include "llvm/LTO/Caching.h" #include "llvm/LTO/LTO.h" #include "llvm/Object/Error.h" +#include "llvm/Remarks/HotnessThresholdParser.h" #include "llvm/Support/CachePruning.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" @@ -213,6 +214,7 @@ static std::string RemarksFilename; static std::string RemarksPasses; static bool RemarksWithHotness = false; + static Optional RemarksHotnessThreshold = 0; static std::string RemarksFormat; // Context sensitive PGO options. @@ -297,6 +299,12 @@ RemarksPasses = std::string(opt); } else if (opt == "opt-remarks-with-hotness") { RemarksWithHotness = true; + } else if (opt.consume_front("opt-remarks-hotness-threshold=")) { + auto ResultOrErr = remarks::parseHotnessThresholdOption(opt); + if (!ResultOrErr) + message(LDPL_FATAL, "Invalid remarks hotness threshold: %s", opt); + else + RemarksHotnessThreshold = *ResultOrErr; } else if (opt.consume_front("opt-remarks-format=")) { RemarksFormat = std::string(opt); } else if (opt.consume_front("stats-file=")) { @@ -931,6 +939,7 @@ 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/llc/llc.cpp b/llvm/tools/llc/llc.cpp --- a/llvm/tools/llc/llc.cpp +++ b/llvm/tools/llc/llc.cpp @@ -37,6 +37,7 @@ #include "llvm/InitializePasses.h" #include "llvm/MC/SubtargetFeature.h" #include "llvm/Pass.h" +#include "llvm/Remarks/HotnessThresholdParser.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileSystem.h" @@ -142,11 +143,13 @@ 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::Hidden); +static cl::opt, false, remarks::HotnessThresholdParser> + RemarksHotnessThreshold( + "pass-remarks-hotness-threshold", + cl::desc("Minimum profile count required for " + "an optimization remark to be output. " + "Use 'auto' to apply the threshold from profile summary."), + cl::value_desc("N or 'auto'"), cl::init(0), cl::Hidden); static cl::opt RemarksFilename("pass-remarks-output", 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 @@ -21,6 +21,7 @@ #include "llvm/LTO/Caching.h" #include "llvm/LTO/LTO.h" #include "llvm/Passes/PassPlugin.h" +#include "llvm/Remarks/HotnessThresholdParser.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/InitLLVM.h" @@ -103,6 +104,14 @@ cl::desc("With PGO, include profile count in optimization remarks"), cl::Hidden); +cl::opt, false, remarks::HotnessThresholdParser> + RemarksHotnessThreshold( + "pass-remarks-hotness-threshold", + cl::desc("Minimum profile count required for an " + "optimization remark to be output." + " Use 'auto' to apply the threshold from profile summary."), + cl::value_desc("uint or 'auto'"), cl::init(0), cl::Hidden); + static cl::opt RemarksFilename("pass-remarks-output", cl::desc("Output filename for pass remarks"), @@ -246,6 +255,7 @@ Conf.RemarksFilename = RemarksFilename; Conf.RemarksPasses = RemarksPasses; Conf.RemarksWithHotness = RemarksWithHotness; + Conf.RemarksHotnessThreshold = RemarksHotnessThreshold; Conf.RemarksFormat = RemarksFormat; Conf.SampleProfile = SamplePGOFile; diff --git a/llvm/tools/opt/opt.cpp b/llvm/tools/opt/opt.cpp --- a/llvm/tools/opt/opt.cpp +++ b/llvm/tools/opt/opt.cpp @@ -38,6 +38,7 @@ #include "llvm/LinkAllIR.h" #include "llvm/LinkAllPasses.h" #include "llvm/MC/SubtargetFeature.h" +#include "llvm/Remarks/HotnessThresholdParser.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Host.h" @@ -272,11 +273,13 @@ 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::Hidden); +static cl::opt, false, remarks::HotnessThresholdParser> + RemarksHotnessThreshold( + "pass-remarks-hotness-threshold", + cl::desc("Minimum profile count required for " + "an optimization remark to be output. " + "Use 'auto' to apply the threshold from profile summary."), + cl::value_desc("N or 'auto'"), cl::init(0), cl::Hidden); static cl::opt RemarksFilename("pass-remarks-output",