forked from OSchip/llvm-project
[ORE] Add diagnostics hotness threshold
Summary: Add an option to prevent diagnostics that do not meet a minimum hotness threshold from being output. When generating optimization remarks for large codebases with a ton of cold code paths, this option can be used to limit the optimization remark output at a reasonable size. Discussion of this change can be read here: http://lists.llvm.org/pipermail/llvm-dev/2017-June/114377.html Reviewers: anemet, davidxl, hfinkel Reviewed By: anemet Subscribers: qcolombet, javed.absar, fhahn, eraman, llvm-commits Differential Revision: https://reviews.llvm.org/D34867 llvm-svn: 306912
This commit is contained in:
parent
4fcfc19976
commit
4ef3daafef
|
@ -193,6 +193,15 @@ public:
|
|||
/// diagnostics.
|
||||
void setDiagnosticsHotnessRequested(bool Requested);
|
||||
|
||||
/// \brief 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.
|
||||
uint64_t getDiagnosticsHotnessThreshold() const;
|
||||
|
||||
/// \brief Set the minimum hotness value a diagnostic needs in order to be
|
||||
/// included in optimization diagnostics.
|
||||
void setDiagnosticsHotnessThreshold(uint64_t Threshold);
|
||||
|
||||
/// \brief Return the YAML file used by the backend to save optimization
|
||||
/// diagnostics. If null, diagnostics are not saved in a file but only
|
||||
/// emitted via the diagnostic handler.
|
||||
|
|
|
@ -155,6 +155,13 @@ void OptimizationRemarkEmitter::emit(
|
|||
DiagnosticInfoOptimizationBase &OptDiagBase) {
|
||||
auto &OptDiag = cast<DiagnosticInfoIROptimization>(OptDiagBase);
|
||||
computeHotness(OptDiag);
|
||||
// If a diagnostic has a hotness value, then only emit it if its hotness
|
||||
// meets the threshold.
|
||||
if (OptDiag.getHotness() &&
|
||||
*OptDiag.getHotness() <
|
||||
F->getContext().getDiagnosticsHotnessThreshold()) {
|
||||
return;
|
||||
}
|
||||
|
||||
yaml::Output *Out = F->getContext().getDiagnosticsOutputFile();
|
||||
if (Out) {
|
||||
|
|
|
@ -52,6 +52,14 @@ void MachineOptimizationRemarkEmitter::emit(
|
|||
computeHotness(OptDiag);
|
||||
|
||||
LLVMContext &Ctx = MF.getFunction()->getContext();
|
||||
|
||||
// If a diagnostic has a hotness value, then only emit it if its hotness
|
||||
// meets the threshold.
|
||||
if (OptDiag.getHotness() &&
|
||||
*OptDiag.getHotness() < Ctx.getDiagnosticsHotnessThreshold()) {
|
||||
return;
|
||||
}
|
||||
|
||||
yaml::Output *Out = Ctx.getDiagnosticsOutputFile();
|
||||
if (Out) {
|
||||
auto *P = &const_cast<DiagnosticInfoOptimizationBase &>(OptDiagCommon);
|
||||
|
|
|
@ -132,6 +132,13 @@ bool LLVMContext::getDiagnosticsHotnessRequested() const {
|
|||
return pImpl->DiagnosticsHotnessRequested;
|
||||
}
|
||||
|
||||
void LLVMContext::setDiagnosticsHotnessThreshold(uint64_t Threshold) {
|
||||
pImpl->DiagnosticsHotnessThreshold = Threshold;
|
||||
}
|
||||
uint64_t LLVMContext::getDiagnosticsHotnessThreshold() const {
|
||||
return pImpl->DiagnosticsHotnessThreshold;
|
||||
}
|
||||
|
||||
yaml::Output *LLVMContext::getDiagnosticsOutputFile() {
|
||||
return pImpl->DiagnosticsOutputFile.get();
|
||||
}
|
||||
|
|
|
@ -1170,6 +1170,7 @@ public:
|
|||
void *DiagnosticContext = nullptr;
|
||||
bool RespectDiagnosticFilters = false;
|
||||
bool DiagnosticsHotnessRequested = false;
|
||||
uint64_t DiagnosticsHotnessThreshold = 0;
|
||||
std::unique_ptr<yaml::Output> DiagnosticsOutputFile;
|
||||
|
||||
LLVMContext::YieldCallbackTy YieldCallback = nullptr;
|
||||
|
|
|
@ -3,6 +3,15 @@
|
|||
; RUN: llc < %s -mtriple=arm64-apple-ios7.0 -aarch64-neon-syntax=apple 2>&1 | FileCheck -check-prefix=NO_REMARK %s
|
||||
; RUN: llc < %s -mtriple=arm64-apple-ios7.0 -aarch64-neon-syntax=apple -pass-remarks-output=%t.yaml -pass-remarks-with-hotness 2>&1 | FileCheck -check-prefix=NO_REMARK %s
|
||||
; RUN: cat %t.yaml | FileCheck -check-prefix=YAML %s
|
||||
;
|
||||
; Verify that remarks below the hotness threshold are not output.
|
||||
; RUN: llc < %s -mtriple=arm64-apple-ios7.0 -aarch64-neon-syntax=apple -pass-remarks-missed=regalloc \
|
||||
; RUN: -pass-remarks-with-hotness -pass-remarks-hotness-threshold=500 \
|
||||
; RUN: 2>&1 | FileCheck -check-prefix=THRESHOLD %s
|
||||
; RUN: llc < %s -mtriple=arm64-apple-ios7.0 -aarch64-neon-syntax=apple -pass-remarks-output=%t.threshold.yaml \
|
||||
; RUN: -pass-remarks-with-hotness -pass-remarks-hotness-threshold=500 \
|
||||
; RUN: 2>&1 | FileCheck -check-prefix=NO_REMARK %s
|
||||
; RUN: cat %t.threshold.yaml | FileCheck -check-prefix=THRESHOLD_YAML %s
|
||||
|
||||
; This has two nested loops, each with one value that has to be spilled and
|
||||
; then reloaded.
|
||||
|
@ -23,6 +32,9 @@
|
|||
|
||||
; NO_REMARK-NOT: remark
|
||||
|
||||
; THRESHOLD-NOT: (hotness: 300)
|
||||
; THRESHOLD: remark: /tmp/kk.c:2:20: 1 spills 1 reloads generated in loop (hotness: 30000)
|
||||
|
||||
; YAML: --- !Missed
|
||||
; YAML: Pass: regalloc
|
||||
; YAML: Name: LoopSpillReload
|
||||
|
@ -63,6 +75,21 @@
|
|||
; YAML: - String: generated in loop
|
||||
; YAML: ...
|
||||
|
||||
; THRESHOLD_YAML-NOT: Hotness: 300{{$}}
|
||||
; THRESHOLD_YAML: --- !Missed
|
||||
; THRESHOLD_YAML: Pass: regalloc
|
||||
; THRESHOLD_YAML: Name: LoopSpillReload
|
||||
; THRESHOLD_YAML: DebugLoc: { File: /tmp/kk.c, Line: 2, Column: 20 }
|
||||
; THRESHOLD_YAML: Function: fpr128
|
||||
; THRESHOLD_YAML: Hotness: 30000
|
||||
; THRESHOLD_YAML: Args:
|
||||
; THRESHOLD_YAML: - NumSpills: '1'
|
||||
; THRESHOLD_YAML: - String: ' spills '
|
||||
; THRESHOLD_YAML: - NumReloads: '1'
|
||||
; THRESHOLD_YAML: - String: ' reloads '
|
||||
; THRESHOLD_YAML: - String: generated in loop
|
||||
; THRESHOLD_YAML: ...
|
||||
|
||||
define void @fpr128(<4 x float>* %p) nounwind ssp !prof !11 {
|
||||
entry:
|
||||
br label %loop, !dbg !8
|
||||
|
|
|
@ -1,8 +1,21 @@
|
|||
; RUN: opt < %s -S -inline -pass-remarks-missed=inline -pass-remarks-with-hotness \
|
||||
; RUN: opt < %s -S -inline -pass-remarks-missed=inline \
|
||||
; RUN: -pass-remarks-with-hotness -pass-remarks-hotness-threshold 15 \
|
||||
; RUN: -pass-remarks-output=%t 2>&1 | FileCheck %s
|
||||
; RUN: cat %t | FileCheck -check-prefix=YAML %s
|
||||
; RUN: opt < %s -S -inline -pass-remarks-with-hotness -pass-remarks-output=%t
|
||||
; RUN: cat %t | FileCheck -check-prefix=YAML %s
|
||||
;
|
||||
; Verify that remarks that don't meet the hotness threshold are not output.
|
||||
; RUN: opt < %s -S -inline -pass-remarks-missed=inline \
|
||||
; RUN: -pass-remarks-with-hotness -pass-remarks-hotness-threshold 100 \
|
||||
; RUN: -pass-remarks-output=%t.threshold 2>&1 | \
|
||||
; RUN: FileCheck -check-prefix=THRESHOLD %s
|
||||
; RUN: test ! -s %t.threshold
|
||||
; RUN: opt < %s -S -inline \
|
||||
; RUN: -pass-remarks-with-hotness -pass-remarks-hotness-threshold 100 \
|
||||
; RUN: -pass-remarks-output=%t.threshold
|
||||
; The remarks output file should be empty.
|
||||
; RUN: test ! -s %t.threshold
|
||||
|
||||
; Check the YAML file generated for inliner remarks for this program:
|
||||
;
|
||||
|
@ -43,6 +56,9 @@
|
|||
; YAML-NEXT: - String: ' because its definition is unavailable'
|
||||
; YAML-NEXT: ...
|
||||
|
||||
; No remarks should be output, since none meet the threshold.
|
||||
; THRESHOLD-NOT: remark
|
||||
|
||||
; ModuleID = '/tmp/s.c'
|
||||
source_filename = "/tmp/s.c"
|
||||
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
|
||||
|
|
|
@ -149,6 +149,11 @@ static cl::opt<bool> PassRemarksWithHotness(
|
|||
cl::desc("With PGO, include profile count in optimization remarks"),
|
||||
cl::Hidden);
|
||||
|
||||
static cl::opt<unsigned> PassRemarksHotnessThreshold(
|
||||
"pass-remarks-hotness-threshold",
|
||||
cl::desc("Minimum profile count required for an optimization remark to be output"),
|
||||
cl::Hidden);
|
||||
|
||||
static cl::opt<std::string>
|
||||
RemarksFilename("pass-remarks-output",
|
||||
cl::desc("YAML output filename for pass remarks"),
|
||||
|
@ -325,6 +330,9 @@ int main(int argc, char **argv) {
|
|||
if (PassRemarksWithHotness)
|
||||
Context.setDiagnosticsHotnessRequested(true);
|
||||
|
||||
if (PassRemarksHotnessThreshold)
|
||||
Context.setDiagnosticsHotnessThreshold(PassRemarksHotnessThreshold);
|
||||
|
||||
std::unique_ptr<tool_output_file> YamlFile;
|
||||
if (RemarksFilename != "") {
|
||||
std::error_code EC;
|
||||
|
|
|
@ -242,6 +242,11 @@ static cl::opt<bool> PassRemarksWithHotness(
|
|||
cl::desc("With PGO, include profile count in optimization remarks"),
|
||||
cl::Hidden);
|
||||
|
||||
static cl::opt<unsigned> PassRemarksHotnessThreshold(
|
||||
"pass-remarks-hotness-threshold",
|
||||
cl::desc("Minimum profile count required for an optimization remark to be output"),
|
||||
cl::Hidden);
|
||||
|
||||
static cl::opt<std::string>
|
||||
RemarksFilename("pass-remarks-output",
|
||||
cl::desc("YAML output filename for pass remarks"),
|
||||
|
@ -422,6 +427,9 @@ int main(int argc, char **argv) {
|
|||
if (PassRemarksWithHotness)
|
||||
Context.setDiagnosticsHotnessRequested(true);
|
||||
|
||||
if (PassRemarksHotnessThreshold)
|
||||
Context.setDiagnosticsHotnessThreshold(PassRemarksHotnessThreshold);
|
||||
|
||||
std::unique_ptr<tool_output_file> YamlFile;
|
||||
if (RemarksFilename != "") {
|
||||
std::error_code EC;
|
||||
|
|
Loading…
Reference in New Issue