Skip to content

Commit

Permalink
[ORE] Add diagnostics hotness threshold
Browse files Browse the repository at this point in the history
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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@306912 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
modocache committed Jun 30, 2017
1 parent 14a125c commit e330528
Show file tree
Hide file tree
Showing 9 changed files with 92 additions and 1 deletion.
9 changes: 9 additions & 0 deletions include/llvm/IR/LLVMContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,15 @@ class LLVMContext {
/// 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.
Expand Down
7 changes: 7 additions & 0 deletions lib/Analysis/OptimizationDiagnosticInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
8 changes: 8 additions & 0 deletions lib/CodeGen/MachineOptimizationRemarkEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
7 changes: 7 additions & 0 deletions lib/IR/LLVMContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down
1 change: 1 addition & 0 deletions lib/IR/LLVMContextImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1170,6 +1170,7 @@ class LLVMContextImpl {
void *DiagnosticContext = nullptr;
bool RespectDiagnosticFilters = false;
bool DiagnosticsHotnessRequested = false;
uint64_t DiagnosticsHotnessThreshold = 0;
std::unique_ptr<yaml::Output> DiagnosticsOutputFile;

LLVMContext::YieldCallbackTy YieldCallback = nullptr;
Expand Down
27 changes: 27 additions & 0 deletions test/CodeGen/AArch64/arm64-spill-remarks.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
18 changes: 17 additions & 1 deletion test/Transforms/Inline/optimization-remarks-yaml.ll
Original file line number Diff line number Diff line change
@@ -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:
;
Expand Down Expand Up @@ -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"
Expand Down
8 changes: 8 additions & 0 deletions tools/llc/llc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
Expand Down Expand Up @@ -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;
Expand Down
8 changes: 8 additions & 0 deletions tools/opt/opt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit e330528

Please sign in to comment.