diff --git a/llvm/include/llvm/IR/LLVMContext.h b/llvm/include/llvm/IR/LLVMContext.h index c8ff90e3b083..b27abad618c9 100644 --- a/llvm/include/llvm/IR/LLVMContext.h +++ b/llvm/include/llvm/IR/LLVMContext.h @@ -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. diff --git a/llvm/lib/Analysis/OptimizationDiagnosticInfo.cpp b/llvm/lib/Analysis/OptimizationDiagnosticInfo.cpp index e16500408801..eb259fd7a384 100644 --- a/llvm/lib/Analysis/OptimizationDiagnosticInfo.cpp +++ b/llvm/lib/Analysis/OptimizationDiagnosticInfo.cpp @@ -155,6 +155,13 @@ void OptimizationRemarkEmitter::emit( DiagnosticInfoOptimizationBase &OptDiagBase) { auto &OptDiag = cast(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) { diff --git a/llvm/lib/CodeGen/MachineOptimizationRemarkEmitter.cpp b/llvm/lib/CodeGen/MachineOptimizationRemarkEmitter.cpp index 957028fe0394..73c3428a6e53 100644 --- a/llvm/lib/CodeGen/MachineOptimizationRemarkEmitter.cpp +++ b/llvm/lib/CodeGen/MachineOptimizationRemarkEmitter.cpp @@ -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(OptDiagCommon); diff --git a/llvm/lib/IR/LLVMContext.cpp b/llvm/lib/IR/LLVMContext.cpp index ed3f10601bf4..2e13f362344d 100644 --- a/llvm/lib/IR/LLVMContext.cpp +++ b/llvm/lib/IR/LLVMContext.cpp @@ -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(); } diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h index 8f4450e92784..395beb57fe37 100644 --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -1170,6 +1170,7 @@ public: void *DiagnosticContext = nullptr; bool RespectDiagnosticFilters = false; bool DiagnosticsHotnessRequested = false; + uint64_t DiagnosticsHotnessThreshold = 0; std::unique_ptr DiagnosticsOutputFile; LLVMContext::YieldCallbackTy YieldCallback = nullptr; diff --git a/llvm/test/CodeGen/AArch64/arm64-spill-remarks.ll b/llvm/test/CodeGen/AArch64/arm64-spill-remarks.ll index bc9340352d75..cfebeb496e18 100644 --- a/llvm/test/CodeGen/AArch64/arm64-spill-remarks.ll +++ b/llvm/test/CodeGen/AArch64/arm64-spill-remarks.ll @@ -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 diff --git a/llvm/test/Transforms/Inline/optimization-remarks-yaml.ll b/llvm/test/Transforms/Inline/optimization-remarks-yaml.ll index 532e443e2170..16783634484f 100644 --- a/llvm/test/Transforms/Inline/optimization-remarks-yaml.ll +++ b/llvm/test/Transforms/Inline/optimization-remarks-yaml.ll @@ -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" diff --git a/llvm/tools/llc/llc.cpp b/llvm/tools/llc/llc.cpp index cd2481bcf467..f13a19213c69 100644 --- a/llvm/tools/llc/llc.cpp +++ b/llvm/tools/llc/llc.cpp @@ -149,6 +149,11 @@ static cl::opt PassRemarksWithHotness( cl::desc("With PGO, include profile count in optimization remarks"), cl::Hidden); +static cl::opt PassRemarksHotnessThreshold( + "pass-remarks-hotness-threshold", + cl::desc("Minimum profile count required for an optimization remark to be output"), + cl::Hidden); + static cl::opt 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 YamlFile; if (RemarksFilename != "") { std::error_code EC; diff --git a/llvm/tools/opt/opt.cpp b/llvm/tools/opt/opt.cpp index 480deac02018..24cce58047f1 100644 --- a/llvm/tools/opt/opt.cpp +++ b/llvm/tools/opt/opt.cpp @@ -242,6 +242,11 @@ static cl::opt PassRemarksWithHotness( cl::desc("With PGO, include profile count in optimization remarks"), cl::Hidden); +static cl::opt PassRemarksHotnessThreshold( + "pass-remarks-hotness-threshold", + cl::desc("Minimum profile count required for an optimization remark to be output"), + cl::Hidden); + static cl::opt 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 YamlFile; if (RemarksFilename != "") { std::error_code EC;