mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 20:23:11 +01:00
Reland "[Remarks] Add -foptimization-record-passes to filter remark emission"
Currently we have -Rpass for filtering the remarks that are displayed as diagnostics, but when using -fsave-optimization-record, there is no way to filter the remarks while generating them. This adds support for filtering remarks by passes using a regex. Ex: `clang -fsave-optimization-record -foptimization-record-passes=inline` will only emit the remarks coming from the pass `inline`. This adds: * `-fsave-optimization-record` to the driver * `-opt-record-passes` to cc1 * `-lto-pass-remarks-filter` to the LTOCodeGenerator * `--opt-remarks-passes` to lld * `-pass-remarks-filter` to llc, opt, llvm-lto, llvm-lto2 * `-opt-remarks-passes` to gold-plugin Differential Revision: https://reviews.llvm.org/D59268 Original llvm-svn: 355964 llvm-svn: 355984
This commit is contained in:
parent
4b3cf34091
commit
14e47fc8be
@ -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);
|
||||
};
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
@ -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 "
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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" &&
|
||||
|
@ -100,6 +100,12 @@ static cl::opt<bool> OptRemarksWithHotness(
|
||||
cl::desc("Whether to include hotness informations in the remarks.\n"
|
||||
"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;
|
||||
|
@ -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...
|
||||
|
Loading…
Reference in New Issue
Block a user