weiwang updated this revision to Diff 281077.
weiwang added a comment.
Fix msvc build failure
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D84246/new/
https://reviews.llvm.org/D84246
Files:
clang/include/clang/Basic/CodeGenOptions.def
clang/include/clang/Basic/CodeGenOptions.h
clang/include/clang/Basic/DiagnosticDriverKinds.td
clang/include/clang/Driver/Driver.h
clang/include/clang/Driver/Options.td
clang/lib/Driver/Driver.cpp
clang/lib/Driver/ToolChains/CommonArgs.cpp
clang/lib/Frontend/CompilerInvocation.cpp
clang/test/Driver/remarks-pass-through.c
lld/ELF/Config.h
lld/ELF/Driver.cpp
lld/ELF/LTO.cpp
lld/ELF/Options.td
lld/test/ELF/lto/opt-remarks.ll
llvm/include/llvm/Analysis/ProfileSummaryInfo.h
llvm/include/llvm/IR/LLVMContext.h
llvm/include/llvm/IR/LLVMRemarkStreamer.h
llvm/include/llvm/IR/Module.h
llvm/include/llvm/LTO/Config.h
llvm/include/llvm/LTO/LTO.h
llvm/include/llvm/Remarks/HotnessThresholdParser.h
llvm/lib/Analysis/OptimizationRemarkEmitter.cpp
llvm/lib/IR/LLVMContext.cpp
llvm/lib/IR/LLVMContextImpl.h
llvm/lib/IR/LLVMRemarkStreamer.cpp
llvm/lib/IR/Module.cpp
llvm/lib/LTO/LTO.cpp
llvm/lib/LTO/LTOBackend.cpp
llvm/lib/LTO/LTOCodeGenerator.cpp
llvm/lib/LTO/ThinLTOCodeGenerator.cpp
llvm/test/LTO/X86/diagnostic-handler-remarks-with-hotness.ll
llvm/test/Other/optimization-remarks-auto.ll
llvm/test/Transforms/SampleProfile/Inputs/remarks-hotness.prof
llvm/test/Transforms/SampleProfile/remarks-hotness.ll
llvm/tools/llc/llc.cpp
llvm/tools/opt/opt.cpp
Index: llvm/tools/opt/opt.cpp
===================================================================
--- llvm/tools/opt/opt.cpp
+++ 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<unsigned>
- RemarksHotnessThreshold("pass-remarks-hotness-threshold",
- cl::desc("Minimum profile count required for "
- "an optimization remark to be output"),
- cl::Hidden);
+static cl::opt<Optional<uint64_t>, 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<std::string>
RemarksFilename("pass-remarks-output",
Index: llvm/tools/llc/llc.cpp
===================================================================
--- llvm/tools/llc/llc.cpp
+++ 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<unsigned>
- RemarksHotnessThreshold("pass-remarks-hotness-threshold",
- cl::desc("Minimum profile count required for "
- "an optimization remark to be output"),
- cl::Hidden);
+static cl::opt<Optional<uint64_t>, 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<std::string>
RemarksFilename("pass-remarks-output",
Index: llvm/test/Transforms/SampleProfile/remarks-hotness.ll
===================================================================
--- /dev/null
+++ llvm/test/Transforms/SampleProfile/remarks-hotness.ll
@@ -0,0 +1,96 @@
+;; This test verifies 'auto' hotness threshold when profile file is provided.
+;;
+;; new PM
+; RUN: rm -f %t.yaml %t.hot.yaml
+; RUN: opt %s --enable-new-pm --passes='sample-profile,cgscc(inline)' \
+; RUN: --sample-profile-file=%S/Inputs/remarks-hotness.prof \
+; RUN: -S --pass-remarks-filter=inline --pass-remarks-output=%t.yaml \
+; RUN: -pass-remarks-with-hotness --disable-output
+; RUN: FileCheck %s -check-prefix=YAML-PASS < %t.yaml
+; RUN: FileCheck %s -check-prefix=YAML-MISS < %t.yaml
+
+;; test 'auto' threshold
+; RUN: opt %s --enable-new-pm --passes='sample-profile,cgscc(inline)' \
+; RUN: --sample-profile-file=%S/Inputs/remarks-hotness.prof \
+; RUN: -S --pass-remarks-filter=inline --pass-remarks-output=%t.hot.yaml \
+; RUN: --pass-remarks-with-hotness --pass-remarks-hotness-threshold=auto --disable-output
+; RUN: FileCheck %s -check-prefix=YAML-PASS < %t.hot.yaml
+; RUN: not FileCheck %s -check-prefix=YAML-MISS < %t.hot.yaml
+
+; RUN: opt %s --enable-new-pm --passes='sample-profile,cgscc(inline)' \
+; RUN: --sample-profile-file=%S/Inputs/remarks-hotness.prof \
+; RUN: -S --pass-remarks=inline --pass-remarks-missed=inline --pass-remarks-analysis=inline \
+; RUN: --pass-remarks-with-hotness --pass-remarks-hotness-threshold=auto --disable-output 2>&1 | FileCheck %s -check-prefix=CHECK-RPASS
+
+; YAML-PASS: --- !Passed
+; YAML-PASS-NEXT: Pass: inline
+; YAML-PASS-NEXT: Name: Inlined
+; YAML-PASS-NEXT: DebugLoc: { File: remarks-hotness.cpp, Line: 10, Column: 10 }
+; YAML-PASS-NEXT: Function: _Z7caller1v
+; YAML-PASS-NEXT: Hotness: 401
+
+; YAML-MISS: --- !Missed
+; YAML-MISS-NEXT: Pass: inline
+; YAML-MISS-NEXT: Name: NeverInline
+; YAML-MISS-NEXT: DebugLoc: { File: remarks-hotness.cpp, Line: 14, Column: 10 }
+; YAML-MISS-NEXT: Function: _Z7caller2v
+; YAML-MISS-NEXT: Hotness: 2
+
+; CHECK-RPASS: _Z7callee1v inlined into _Z7caller1v with (cost=-30, threshold=4500) at callsite _Z7caller1v:1 (hotness: 401)
+; CHECK-RPASS-NOT: _Z7callee2v not inlined into _Z7caller2v because it should never be inlined (cost=never): noinline function attribute (hotness: 2)
+
+; ModuleID = 'remarks-hotness.cpp'
+source_filename = "remarks-hotness.cpp"
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Function Attrs: use-sample-profile
+define dso_local i32 @_Z7callee1v() #0 !dbg !7 {
+ ret i32 1, !dbg !11
+}
+
+; Function Attrs: noinline nounwind uwtable use-sample-profile
+define dso_local i32 @_Z7callee2v() #1 !dbg !12 {
+ ret i32 2, !dbg !13
+}
+
+; Function Attrs: use-sample-profile
+define dso_local i32 @_Z7caller1v() #0 !dbg !14 {
+ %1 = call i32 @_Z7callee1v(), !dbg !15
+ ret i32 %1, !dbg !16
+}
+
+; Function Attrs: use-sample-profile
+define dso_local i32 @_Z7caller2v() #0 !dbg !17 {
+ %1 = call i32 @_Z7callee2v(), !dbg !18
+ ret i32 %1, !dbg !19
+}
+
+attributes #0 = { "use-sample-profile" }
+attributes #1 = { noinline nounwind uwtable "use-sample-profile" }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5}
+!llvm.ident = !{!6}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, debugInfoForProfiling: true, nameTableKind: None)
+!1 = !DIFile(filename: "remarks-hotness.cpp", directory: ".")
+!2 = !{}
+!3 = !{i32 7, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"wchar_size", i32 4}
+!6 = !{!"clang version 11.0.0"}
+!7 = distinct !DISubprogram(name: "callee1", linkageName: "_Z7callee1v", scope: !1, file: !1, line: 1, type: !8, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
+!8 = !DISubroutineType(types: !9)
+!9 = !{!10}
+!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!11 = !DILocation(line: 2, column: 3, scope: !7)
+!12 = distinct !DISubprogram(name: "callee2", linkageName: "_Z7callee2v", scope: !1, file: !1, line: 5, type: !8, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
+!13 = !DILocation(line: 6, column: 3, scope: !12)
+!14 = distinct !DISubprogram(name: "caller1", linkageName: "_Z7caller1v", scope: !1, file: !1, line: 9, type: !8, scopeLine: 9, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
+!15 = !DILocation(line: 10, column: 10, scope: !14)
+!16 = !DILocation(line: 10, column: 3, scope: !14)
+!17 = distinct !DISubprogram(name: "caller2", linkageName: "_Z7caller2v", scope: !1, file: !1, line: 13, type: !8, scopeLine: 13, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
+!18 = !DILocation(line: 14, column: 10, scope: !17)
+!19 = !DILocation(line: 14, column: 3, scope: !17)
+
Index: llvm/test/Transforms/SampleProfile/Inputs/remarks-hotness.prof
===================================================================
--- /dev/null
+++ llvm/test/Transforms/SampleProfile/Inputs/remarks-hotness.prof
@@ -0,0 +1,8 @@
+_Z7callee1v:600:600
+ 1: 600
+_Z7callee2v:1:1
+ 1: 1
+_Z7caller1v:400:400
+ 1: 400
+_Z7caller2v:1:1
+ 1: 1
Index: llvm/test/Other/optimization-remarks-auto.ll
===================================================================
--- /dev/null
+++ llvm/test/Other/optimization-remarks-auto.ll
@@ -0,0 +1,85 @@
+;; This test verifies 'auto' hotness threshold when profile summary is available.
+;;
+;; new PM
+; RUN: rm -f %t.yaml %t.hot.yaml
+; RUN: opt < %s --disable-output --enable-new-pm \
+; RUN: --passes='inline' \
+; RUN: --pass-remarks-output=%t.yaml --pass-remarks-filter='inline' \
+; RUN: --pass-remarks-with-hotness
+; RUN: FileCheck %s -check-prefix=YAML-PASS < %t.yaml
+; RUN: FileCheck %s -check-prefix=YAML-MISS < %t.yaml
+
+;; test 'auto' threshold
+; RUN: opt < %s --disable-output --enable-new-pm \
+; RUN: --passes='module(print-profile-summary,cgscc(inline))' \
+; RUN: --pass-remarks-output=%t.hot.yaml --pass-remarks-filter='inline' \
+; RUN: --pass-remarks-with-hotness --pass-remarks-hotness-threshold=auto 2>&1 | FileCheck %s
+; RUN: FileCheck %s -check-prefix=YAML-PASS < %t.hot.yaml
+; RUN: not FileCheck %s -check-prefix=YAML-MISS < %t.hot.yaml
+
+; RUN: opt < %s --disable-output --enable-new-pm \
+; RUN: --passes='module(print-profile-summary,cgscc(inline))' \
+; RUN: --pass-remarks=inline --pass-remarks-missed=inline --pass-remarks-analysis=inline \
+; RUN: --pass-remarks-with-hotness --pass-remarks-hotness-threshold=auto 2>&1 | FileCheck %s -check-prefix=CHECK-RPASS
+
+; YAML-PASS: --- !Passed
+; YAML-PASS-NEXT: Pass: inline
+; YAML-PASS-NEXT: Name: Inlined
+; YAML-PASS-NEXT: Function: caller1
+; YAML-PASS-NEXT: Hotness: 400
+
+; YAML-MISS: --- !Missed
+; YAML-MISS-NEXT: Pass: inline
+; YAML-MISS-NEXT: Name: NeverInline
+; YAML-MISS-NEXT: Function: caller2
+; YAML-MISS-NEXT: Hotness: 1
+
+; CHECK-RPASS: callee1 inlined into caller1 with (cost=-30, threshold=4500) (hotness: 400)
+; CHECK-RPASS-NOT: callee2 not inlined into caller2 because it should never be inlined (cost=never): noinline function attribute (hotness: 1)
+
+define void @callee1() !prof !20 {
+; CHECK: callee1 :hot
+entry:
+ ret void
+}
+
+; Function Attrs: noinline
+define void @callee2() noinline !prof !21 {
+; CHECK: callee2 :cold
+entry:
+ ret void
+}
+
+define void @caller1() !prof !20 {
+; CHECK: caller1 :hot
+entry:
+ call void @callee1()
+ ret void
+}
+
+define void @caller2() !prof !21 {
+; CHECK: caller2 :cold
+entry:
+ call void @callee2()
+ ret void
+}
+
+!llvm.module.flags = !{!1}
+!20 = !{!"function_entry_count", i64 400}
+!21 = !{!"function_entry_count", i64 1}
+
+!1 = !{i32 1, !"ProfileSummary", !2}
+!2 = !{!3, !4, !5, !6, !7, !8, !9, !10}
+!3 = !{!"ProfileFormat", !"InstrProf"}
+!4 = !{!"TotalCount", i64 10000}
+!5 = !{!"MaxCount", i64 10}
+!6 = !{!"MaxInternalCount", i64 1}
+!7 = !{!"MaxFunctionCount", i64 1000}
+!8 = !{!"NumCounts", i64 3}
+!9 = !{!"NumFunctions", i64 3}
+!10 = !{!"DetailedSummary", !11}
+!11 = !{!12, !13, !14}
+!12 = !{i32 10000, i64 100, i32 1}
+!13 = !{i32 999000, i64 100, i32 1}
+!14 = !{i32 999999, i64 1, i32 2}
+
Index: llvm/test/LTO/X86/diagnostic-handler-remarks-with-hotness.ll
===================================================================
--- llvm/test/LTO/X86/diagnostic-handler-remarks-with-hotness.ll
+++ 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: cat %t.t300.yaml | FileCheck -check-prefix=YAML %s
+
+; 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: cat %t.t301.yaml | not FileCheck -check-prefix=YAML %s
+
; YAML: --- !Passed
; YAML-NEXT: Pass: inline
; YAML-NEXT: Name: Inlined
Index: llvm/lib/LTO/ThinLTOCodeGenerator.cpp
===================================================================
--- llvm/lib/LTO/ThinLTOCodeGenerator.cpp
+++ llvm/lib/LTO/ThinLTOCodeGenerator.cpp
@@ -75,6 +75,7 @@
extern cl::opt<std::string> RemarksFilename;
extern cl::opt<std::string> RemarksPasses;
extern cl::opt<bool> RemarksWithHotness;
+extern cl::opt<Optional<uint64_t>> RemarksHotnessThreshold;
extern cl::opt<std::string> 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 "
Index: llvm/lib/LTO/LTOCodeGenerator.cpp
===================================================================
--- llvm/lib/LTO/LTOCodeGenerator.cpp
+++ 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,15 @@
cl::desc("With PGO, include profile count in optimization remarks"),
cl::Hidden);
+cl::opt<Optional<uint64_t>, 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(Optional<uint64_t>(0)),
+ cl::Hidden);
+
cl::opt<std::string>
RemarksFilename("lto-pass-remarks-output",
cl::desc("Output filename for pass remarks"),
@@ -528,9 +538,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");
Index: llvm/lib/LTO/LTOBackend.cpp
===================================================================
--- llvm/lib/LTO/LTOBackend.cpp
+++ 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);
Index: llvm/lib/LTO/LTO.cpp
===================================================================
--- llvm/lib/LTO/LTO.cpp
+++ 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<std::unique_ptr<ToolOutputFile>> lto::setupLLVMOptimizationRemarks(
LLVMContext &Context, StringRef RemarksFilename, StringRef RemarksPasses,
- StringRef RemarksFormat, bool RemarksWithHotness, int Count) {
+ StringRef RemarksFormat, bool RemarksWithHotness,
+ Optional<uint64_t> RemarksHotnessThreshold, int Count) {
std::string Filename = std::string(RemarksFilename);
// For ThinLTO, file.opt.<format> becomes
// file.opt.<format>.thin.<num>.<format>.
@@ -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);
Index: llvm/lib/IR/Module.cpp
===================================================================
--- llvm/lib/IR/Module.cpp
+++ llvm/lib/IR/Module.cpp
@@ -582,7 +582,7 @@
setModuleFlag(ModFlagBehavior::Error, "ProfileSummary", M);
}
-Metadata *Module::getProfileSummary(bool IsCS) {
+Metadata *Module::getProfileSummary(bool IsCS) const {
return (IsCS ? getModuleFlag("CSProfileSummary")
: getModuleFlag("ProfileSummary"));
}
Index: llvm/lib/IR/LLVMRemarkStreamer.cpp
===================================================================
--- llvm/lib/IR/LLVMRemarkStreamer.cpp
+++ llvm/lib/IR/LLVMRemarkStreamer.cpp
@@ -92,12 +92,11 @@
Expected<std::unique_ptr<ToolOutputFile>> llvm::setupLLVMOptimizationRemarks(
LLVMContext &Context, StringRef RemarksFilename, StringRef RemarksPasses,
StringRef RemarksFormat, bool RemarksWithHotness,
- unsigned RemarksHotnessThreshold) {
+ Optional<uint64_t> RemarksHotnessThreshold) {
if (RemarksWithHotness)
Context.setDiagnosticsHotnessRequested(true);
- if (RemarksHotnessThreshold)
- Context.setDiagnosticsHotnessThreshold(RemarksHotnessThreshold);
+ Context.setDiagnosticsHotnessThreshold(RemarksHotnessThreshold);
if (RemarksFilename.empty())
return nullptr;
@@ -137,16 +136,14 @@
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<uint64_t> RemarksHotnessThreshold) {
if (RemarksWithHotness)
Context.setDiagnosticsHotnessRequested(true);
- if (RemarksHotnessThreshold)
- Context.setDiagnosticsHotnessThreshold(RemarksHotnessThreshold);
+ Context.setDiagnosticsHotnessThreshold(RemarksHotnessThreshold);
Expected<remarks::Format> Format = remarks::parseFormat(RemarksFormat);
if (Error E = Format.takeError())
Index: llvm/lib/IR/LLVMContextImpl.h
===================================================================
--- llvm/lib/IR/LLVMContextImpl.h
+++ llvm/lib/IR/LLVMContextImpl.h
@@ -1296,7 +1296,26 @@
std::unique_ptr<DiagnosticHandler> 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<uint64_t> DiagnosticsHotnessThreshold = 0;
+
/// The specialized remark streamer used by LLVM's OptimizationRemarkEmitter.
std::unique_ptr<LLVMRemarkStreamer> LLVMRS;
Index: llvm/lib/IR/LLVMContext.cpp
===================================================================
--- llvm/lib/IR/LLVMContext.cpp
+++ llvm/lib/IR/LLVMContext.cpp
@@ -146,11 +146,16 @@
return pImpl->DiagnosticsHotnessRequested;
}
-void LLVMContext::setDiagnosticsHotnessThreshold(uint64_t Threshold) {
+void LLVMContext::setDiagnosticsHotnessThreshold(Optional<uint64_t> Threshold) {
pImpl->DiagnosticsHotnessThreshold = Threshold;
}
+
uint64_t LLVMContext::getDiagnosticsHotnessThreshold() const {
- return pImpl->DiagnosticsHotnessThreshold;
+ return pImpl->DiagnosticsHotnessThreshold.getValueOr(UINT64_MAX);
+}
+
+bool LLVMContext::isDiagnosticsHotnessThresholdSetFromPSI() const {
+ return !pImpl->DiagnosticsHotnessThreshold.hasValue();
}
remarks::RemarkStreamer *LLVMContext::getMainRemarkStreamer() {
Index: llvm/lib/Analysis/OptimizationRemarkEmitter.cpp
===================================================================
--- llvm/lib/Analysis/OptimizationRemarkEmitter.cpp
+++ llvm/lib/Analysis/OptimizationRemarkEmitter.cpp
@@ -15,6 +15,7 @@
#include "llvm/Analysis/BranchProbabilityInfo.h"
#include "llvm/Analysis/LazyBlockFrequencyInfo.h"
#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/ProfileSummaryInfo.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/LLVMContext.h"
@@ -96,9 +97,17 @@
bool OptimizationRemarkEmitterWrapperPass::runOnFunction(Function &Fn) {
BlockFrequencyInfo *BFI;
- if (Fn.getContext().getDiagnosticsHotnessRequested())
+ auto &Context = Fn.getContext();
+ if (Context.getDiagnosticsHotnessRequested()) {
BFI = &getAnalysis<LazyBlockFrequencyInfoPass>().getBFI();
- else
+ // Get hotness threshold from PSI. This should only happen once.
+ if (Context.isDiagnosticsHotnessThresholdSetFromPSI()) {
+ if (ProfileSummaryInfo *PSI =
+ &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI())
+ Context.setDiagnosticsHotnessThreshold(
+ PSI->getOrCompHotCountThreshold());
+ }
+ } else
BFI = nullptr;
ORE = std::make_unique<OptimizationRemarkEmitter>(&Fn, BFI);
@@ -117,10 +126,19 @@
OptimizationRemarkEmitterAnalysis::run(Function &F,
FunctionAnalysisManager &AM) {
BlockFrequencyInfo *BFI;
+ auto &Context = F.getContext();
- if (F.getContext().getDiagnosticsHotnessRequested())
+ if (Context.getDiagnosticsHotnessRequested()) {
BFI = &AM.getResult<BlockFrequencyAnalysis>(F);
- else
+ // Get hotness threshold from PSI. This should only happen once.
+ if (Context.isDiagnosticsHotnessThresholdSetFromPSI()) {
+ auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
+ if (ProfileSummaryInfo *PSI =
+ MAMProxy.getCachedResult<ProfileSummaryAnalysis>(*F.getParent()))
+ Context.setDiagnosticsHotnessThreshold(
+ PSI->getOrCompHotCountThreshold());
+ }
+ } else
BFI = nullptr;
return OptimizationRemarkEmitter(&F, BFI);
@@ -133,5 +151,6 @@
INITIALIZE_PASS_BEGIN(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name,
false, true)
INITIALIZE_PASS_DEPENDENCY(LazyBFIPass)
+INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass)
INITIALIZE_PASS_END(OptimizationRemarkEmitterWrapperPass, ORE_NAME, ore_name,
false, true)
Index: llvm/include/llvm/Remarks/HotnessThresholdParser.h
===================================================================
--- /dev/null
+++ llvm/include/llvm/Remarks/HotnessThresholdParser.h
@@ -0,0 +1,65 @@
+//===- 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.
+//
+//===----------------------------------------------------------------------===//
+
+#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 is
+// 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<Optional<uint64_t>> 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 '-pass-remarks-hotness-threshold='
+class HotnessThresholdParser : public cl::parser<Optional<uint64_t>> {
+public:
+ HotnessThresholdParser(cl::Option &O) : cl::parser<Optional<uint64_t>>(O) {}
+
+ bool parse(cl::Option &O, StringRef ArgName, StringRef Arg,
+ Optional<uint64_t> &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
Index: llvm/include/llvm/LTO/LTO.h
===================================================================
--- llvm/include/llvm/LTO/LTO.h
+++ llvm/include/llvm/LTO/LTO.h
@@ -82,10 +82,10 @@
const std::string &NewPrefix);
/// Setup optimization remarks.
-Expected<std::unique_ptr<ToolOutputFile>>
-setupLLVMOptimizationRemarks(LLVMContext &Context, StringRef RemarksFilename,
- StringRef RemarksPasses, StringRef RemarksFormat,
- bool RemarksWithHotness, int Count = -1);
+Expected<std::unique_ptr<ToolOutputFile>> setupLLVMOptimizationRemarks(
+ LLVMContext &Context, StringRef RemarksFilename, StringRef RemarksPasses,
+ StringRef RemarksFormat, bool RemarksWithHotness,
+ Optional<uint64_t> RemarksHotnessThreshold = 0, int Count = -1);
/// Setups the output file for saving statistics.
Expected<std::unique_ptr<ToolOutputFile>>
Index: llvm/include/llvm/LTO/Config.h
===================================================================
--- llvm/include/llvm/LTO/Config.h
+++ 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<uint64_t> RemarksHotnessThreshold = 0;
+
/// The format used for serializing remarks (default: YAML).
std::string RemarksFormat = "";
Index: llvm/include/llvm/IR/Module.h
===================================================================
--- llvm/include/llvm/IR/Module.h
+++ llvm/include/llvm/IR/Module.h
@@ -854,7 +854,7 @@
/// Returns profile summary metadata. When IsCS is true, use the context
/// sensitive profile summary.
- Metadata *getProfileSummary(bool IsCS);
+ Metadata *getProfileSummary(bool IsCS) const;
/// @}
/// Returns whether semantic interposition is to be respected.
Index: llvm/include/llvm/IR/LLVMRemarkStreamer.h
===================================================================
--- llvm/include/llvm/IR/LLVMRemarkStreamer.h
+++ 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<uint64_t> 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<uint64_t> RemarksHotnessThreshold = 0);
} // end namespace llvm
Index: llvm/include/llvm/IR/LLVMContext.h
===================================================================
--- llvm/include/llvm/IR/LLVMContext.h
+++ llvm/include/llvm/IR/LLVMContext.h
@@ -222,13 +222,23 @@
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<uint64_t> Threshold);
+
+ /// Return if hotness threshold is requested from PSI.
+ bool isDiagnosticsHotnessThresholdSetFromPSI() const;
/// The "main remark streamer" used by all the specialized remark streamers.
/// This streamer keeps generic remark metadata in memory throughout the life
Index: llvm/include/llvm/Analysis/ProfileSummaryInfo.h
===================================================================
--- llvm/include/llvm/Analysis/ProfileSummaryInfo.h
+++ llvm/include/llvm/Analysis/ProfileSummaryInfo.h
@@ -38,7 +38,7 @@
// units. This would require making this depend on BFI.
class ProfileSummaryInfo {
private:
- Module &M;
+ const Module &M;
std::unique_ptr<ProfileSummary> Summary;
void computeThresholds();
// Count thresholds to answer isHotCount and isColdCount queries.
@@ -58,7 +58,8 @@
mutable DenseMap<int, uint64_t> ThresholdCache;
public:
- ProfileSummaryInfo(Module &M) : M(M) { refresh(); }
+ ProfileSummaryInfo(const Module &M) : M(M) { refresh(); }
+
ProfileSummaryInfo(ProfileSummaryInfo &&Arg) = default;
/// If no summary is present, attempt to refresh.
Index: lld/test/ELF/lto/opt-remarks.ll
===================================================================
--- lld/test/ELF/lto/opt-remarks.ll
+++ 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: cat %t.t300.yaml | FileCheck %s -check-prefix=YAML-HOT
+; 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: cat %t1.yaml | FileCheck %s -check-prefix=YAML
; Check that @tinkywinky is inlined after optimizations.
; CHECK-LABEL: define i32 @main
Index: lld/ELF/Options.td
===================================================================
--- lld/ELF/Options.td
+++ lld/ELF/Options.td
@@ -538,6 +538,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<"<value>">;
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">,
Index: lld/ELF/LTO.cpp
===================================================================
--- lld/ELF/LTO.cpp
+++ 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);
Index: lld/ELF/Driver.cpp
===================================================================
--- lld/ELF/Driver.cpp
+++ 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"
@@ -978,6 +979,16 @@
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);
Index: lld/ELF/Config.h
===================================================================
--- lld/ELF/Config.h
+++ lld/ELF/Config.h
@@ -260,6 +260,21 @@
unsigned timeTraceGranularity;
int32_t splitStackAdjustSize;
+ // 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<uint64_t> optRemarksHotnessThreshold = 0;
+
// The following config options do not directly correspond to any
// particular command line options.
Index: clang/test/Driver/remarks-pass-through.c
===================================================================
--- /dev/null
+++ clang/test/Driver/remarks-pass-through.c
@@ -0,0 +1,38 @@
+// This test verifies remarks options pass-through into linker(lld)
+
+// no pass-through if lto is disabled
+// RUN: %clang -### -o FOO -fdiagnostics-hotness-threshold=auto -fsave-optimization-record %s 2>&1 | not FileCheck %s
+
+// no pass-through if linker is not lld
+// RUN: %clang -### -o FOO -fuse-ld=gold -fdiagnostics-hotness-threshold=auto -fsave-optimization-record %s 2>&1 | not FileCheck %s
+
+// pass-through cases
+// RUN: %clang -### -o FOO -fuse-ld=lld -flto -fdiagnostics-hotness-threshold=100 -fsave-optimization-record -foptimization-record-passes=inline %s 2>&1 | FileCheck %s
+// RUN: %clang -### -o FOO -fuse-ld=lld -flto -fdiagnostics-hotness-threshold=100 -fsave-optimization-record -foptimization-record-passes=inline %s 2>&1 | FileCheck %s -check-prefix=CHECK-MANUAL
+
+// RUN: %clang -### -o FOO -fuse-ld=lld -flto -fdiagnostics-hotness-threshold=auto -fsave-optimization-record -foptimization-record-passes=inline %s 2>&1 | FileCheck %s
+// RUN: %clang -### -o FOO -fuse-ld=lld -flto -fdiagnostics-hotness-threshold=auto -fsave-optimization-record -foptimization-record-passes=inline %s 2>&1 | FileCheck %s -check-prefix=CHECK-AUTO
+//
+// RUN: %clang -### -o FOO -fuse-ld=lld -flto=thin -fdiagnostics-hotness-threshold=auto -fsave-optimization-record -foptimization-record-passes=inline %s 2>&1 | FileCheck %s
+// RUN: %clang -### -o FOO -fuse-ld=lld -flto=thin -fdiagnostics-hotness-threshold=auto -fsave-optimization-record -foptimization-record-passes=inline %s 2>&1 | FileCheck %s -check-prefix=CHECK-AUTO
+//
+// RUN: %clang -### -o FOO -fuse-ld=lld -flto=thin -fdiagnostics-hotness-threshold=auto -fsave-optimization-record=some-format -foptimization-record-file=FOO.txt %s 2>&1 | FileCheck %s -check-prefix=CHECK-CUSTOM
+//
+// RUN: %clang -### -o FOO -fuse-ld=lld -flto=thin -fdiagnostics-hotness-threshold=auto -Rpass=inline -Rpass-missed=inline -Rpass-analysis=inline %s 2>&1 | FileCheck %s -check-prefix=CHECK-RPASS
+//
+// CHECK: "--opt-remarks-filename" "FOO.opt.ld.yaml"
+// CHECK: "--opt-remarks-passes" "inline"
+// CHECK: "--opt-remarks-format" "yaml"
+//
+// CHECK-MANUAL: "--opt-remarks-hotness-threshold=100"
+//
+// CHECK-AUTO: "--opt-remarks-hotness-threshold=auto"
+//
+// CHECK-CUSTOM: "--opt-remarks-filename" "FOO.txt.opt.ld.some-format"
+// CHECK-CUSTOM: "--opt-remarks-format" "some-format"
+// CHECK-CUSTOM: "--opt-remarks-hotness-threshold=auto"
+//
+// CHECK-RPASS: "-mllvm" "-pass-remarks=inline"
+// CHECK-RPASS: "-mllvm" "-pass-remarks-missed=inline"
+// CHECK-RPASS: "-mllvm" "-pass-remarks-analysis=inline"
+// CHECK-RPASS: "--opt-remarks-hotness-threshold=auto"
Index: clang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- clang/lib/Frontend/CompilerInvocation.cpp
+++ clang/lib/Frontend/CompilerInvocation.cpp
@@ -14,6 +14,7 @@
#include "clang/Basic/CommentOptions.h"
#include "clang/Basic/DebugInfoOptions.h"
#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticDriver.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileSystemOptions.h"
#include "clang/Basic/LLVM.h"
@@ -66,6 +67,7 @@
#include "llvm/Option/OptTable.h"
#include "llvm/Option/Option.h"
#include "llvm/ProfileData/InstrProfReader.h"
+#include "llvm/Remarks/HotnessThresholdParser.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Error.h"
@@ -1390,11 +1392,24 @@
Diags.Report(diag::warn_drv_diagnostics_hotness_requires_pgo)
<< "-fdiagnostics-show-hotness";
- Opts.DiagnosticsHotnessThreshold = getLastArgUInt64Value(
- Args, options::OPT_fdiagnostics_hotness_threshold_EQ, 0);
- if (Opts.DiagnosticsHotnessThreshold > 0 && !UsingProfile)
- Diags.Report(diag::warn_drv_diagnostics_hotness_requires_pgo)
- << "-fdiagnostics-hotness-threshold=";
+ // Parse remarks hotness threshold. Valid value is either integer or 'auto'.
+ if (auto *arg =
+ Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ)) {
+ auto ResultOrErr =
+ llvm::remarks::parseHotnessThresholdOption(arg->getValue());
+
+ if (!ResultOrErr) {
+ Diags.Report(diag::err_drv_invalid_diagnotics_hotness_threshold)
+ << "-fdiagnostics-hotness-threshold=";
+ } else {
+ Opts.DiagnosticsHotnessThreshold = *ResultOrErr;
+ if ((!Opts.DiagnosticsHotnessThreshold.hasValue() ||
+ Opts.DiagnosticsHotnessThreshold.getValue() > 0) &&
+ !UsingProfile)
+ Diags.Report(diag::warn_drv_diagnostics_hotness_requires_pgo)
+ << "-fdiagnostics-hotness-threshold=";
+ }
+ }
// If the user requested to use a sample profile for PGO, then the
// backend will need to track source location information so the profile
Index: clang/lib/Driver/ToolChains/CommonArgs.cpp
===================================================================
--- clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -60,6 +60,95 @@
using namespace clang;
using namespace llvm::opt;
+// Remarks option pass-through only happens when
+// 1). single arch target
+// 2). linker is lld
+static bool checkRemarksOptions(StringRef LinkerPath, const ArgList &Args,
+ const llvm::Triple &Triple) {
+ bool hasMultipleArchs =
+ Triple.isOSDarwin() && Args.getAllArgValues(options::OPT_arch).size() > 1;
+
+ bool isLLD = llvm::sys::path::filename(LinkerPath) == "ld.lld" ||
+ llvm::sys::path::stem(LinkerPath) != "ld.lld";
+ if (hasMultipleArchs || !isLLD)
+ return false;
+ return true;
+}
+
+static void renderRpassOptions(const ArgList &Args, ArgStringList &CmdArgs) {
+ if (const Arg *A = Args.getLastArg(options::OPT_Rpass_EQ)) {
+ CmdArgs.push_back("-mllvm");
+ std::string Passes = std::string("-pass-remarks=") + A->getValue();
+ CmdArgs.push_back(Args.MakeArgString(Passes));
+ }
+
+ if (const Arg *A = Args.getLastArg(options::OPT_Rpass_missed_EQ)) {
+ CmdArgs.push_back("-mllvm");
+ std::string Passes = std::string("-pass-remarks-missed=") + A->getValue();
+ CmdArgs.push_back(Args.MakeArgString(Passes));
+ }
+
+ if (const Arg *A = Args.getLastArg(options::OPT_Rpass_analysis_EQ)) {
+ CmdArgs.push_back("-mllvm");
+ std::string Passes = std::string("-pass-remarks-analysis=") + A->getValue();
+ CmdArgs.push_back(Args.MakeArgString(Passes));
+ }
+}
+
+static void renderRemarksOptions(const ArgList &Args, ArgStringList &CmdArgs,
+ const llvm::Triple &Triple,
+ const InputInfo &Input,
+ const InputInfo &Output) {
+ StringRef Format = "yaml";
+ if (const Arg *A = Args.getLastArg(options::OPT_fsave_optimization_record_EQ))
+ Format = A->getValue();
+
+ CmdArgs.push_back("--opt-remarks-filename");
+
+ SmallString<128> F;
+ const Arg *A = Args.getLastArg(options::OPT_foptimization_record_file_EQ);
+ if (A) {
+ F = A->getValue();
+ } else {
+ if (Output.isFilename())
+ F = Output.getFilename();
+
+ if (F.empty()) {
+ // Use the input filename.
+ F = llvm::sys::path::stem(Input.getBaseInput());
+ }
+ }
+ // Append "opt.ld.<format>" to the end of the file name.
+ SmallString<32> Extension;
+ Extension += ".opt.ld.";
+ Extension += Format;
+
+ CmdArgs.push_back(Args.MakeArgString(F + Extension));
+
+ if (const Arg *A =
+ Args.getLastArg(options::OPT_foptimization_record_passes_EQ)) {
+ CmdArgs.push_back("--opt-remarks-passes");
+ CmdArgs.push_back(A->getValue());
+ }
+
+ CmdArgs.push_back("--opt-remarks-format");
+ CmdArgs.push_back(Format.data());
+}
+
+static void renderRemarksHotnessOptions(const ArgList &Args,
+ ArgStringList &CmdArgs) {
+ if (Args.hasFlag(options::OPT_fdiagnostics_show_hotness,
+ options::OPT_fno_diagnostics_show_hotness, false))
+ CmdArgs.push_back("--opt-remarks-with-hotness");
+
+ if (const Arg *A =
+ Args.getLastArg(options::OPT_fdiagnostics_hotness_threshold_EQ)) {
+ std::string Opt =
+ std::string("--opt-remarks-hotness-threshold=") + A->getValue();
+ CmdArgs.push_back(Args.MakeArgString(Opt));
+ }
+}
+
void tools::addPathIfExists(const Driver &D, const Twine &Path,
ToolChain::path_list &Paths) {
if (D.getVFS().exists(Path))
@@ -531,6 +620,23 @@
Args.MakeArgString(Twine("-plugin-opt=stats-file=") + StatsFile));
addX86AlignBranchArgs(D, Args, CmdArgs, /*IsLTO=*/true);
+
+ if (checkRemarksOptions(Linker, Args, ToolChain.getEffectiveTriple())) {
+ // handle remark diagnostics on screen options: '-Rpass-*'
+ if (hasRpassOptions(Args)) {
+ renderRpassOptions(Args, CmdArgs);
+ }
+
+ // handle serialized remarks options: '-fsave-optimization-record'
+ // and '-foptimization-record-*'
+ if (willEmitRemarks(Args)) {
+ renderRemarksOptions(Args, CmdArgs, ToolChain.getEffectiveTriple(), Input,
+ Output);
+ }
+
+ // handle remarks hotness/threshold related options
+ renderRemarksHotnessOptions(Args, CmdArgs);
+ }
}
void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args,
Index: clang/lib/Driver/Driver.cpp
===================================================================
--- clang/lib/Driver/Driver.cpp
+++ clang/lib/Driver/Driver.cpp
@@ -5204,3 +5204,19 @@
return true;
return false;
}
+
+bool clang::driver::hasRpassOptions(const ArgList &Args) {
+ // -Rpass=<format> enables it.
+ if (Args.getLastArg(options::OPT_Rpass_EQ))
+ return true;
+
+ // -Rpass-missed=<format> alone enables it too.
+ if (Args.getLastArg(options::OPT_Rpass_missed_EQ))
+ return true;
+
+ // -Rpass-analysis=<format> alone enables it too.
+ if (Args.getLastArg(options::OPT_Rpass_analysis_EQ))
+ return true;
+
+ return false;
+}
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -908,8 +908,9 @@
def fdiagnostics_show_hotness : Flag<["-"], "fdiagnostics-show-hotness">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Enable profile hotness information in diagnostic line">;
def fdiagnostics_hotness_threshold_EQ : Joined<["-"], "fdiagnostics-hotness-threshold=">,
- Group<f_Group>, Flags<[CC1Option]>, MetaVarName<"<number>">,
- HelpText<"Prevent optimization remarks from being output if they do not have at least this profile count">;
+ Group<f_Group>, Flags<[CC1Option]>, MetaVarName<"<value>">,
+ HelpText<"Prevent optimization remarks from being output if they do not have at least this profile count. "
+ "Use 'auto' to apply the threshold from profile summary">;
def fdiagnostics_show_option : Flag<["-"], "fdiagnostics-show-option">, Group<f_Group>,
HelpText<"Print option name with mappable diagnostics">;
def fdiagnostics_show_note_include_stack : Flag<["-"], "fdiagnostics-show-note-include-stack">,
Index: clang/include/clang/Driver/Driver.h
===================================================================
--- clang/include/clang/Driver/Driver.h
+++ clang/include/clang/Driver/Driver.h
@@ -632,6 +632,11 @@
/// \return True if the argument combination will end up generating remarks.
bool willEmitRemarks(const llvm::opt::ArgList &Args);
+/// \return True if the argument combination will end up outputing remarks
+/// onto screen.
+/// This checks for clang specific R-value ('-Rpass-*') group.
+bool hasRpassOptions(const llvm::opt::ArgList &Args);
+
} // end namespace driver
} // end namespace clang
Index: clang/include/clang/Basic/DiagnosticDriverKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -108,6 +108,8 @@
"unable to execute command: %0">;
def err_drv_invalid_darwin_version : Error<
"invalid Darwin version number: %0">;
+def err_drv_invalid_diagnotics_hotness_threshold : Error<
+ "invalid argument in '%0', only integer or 'auto' is supported">;
def err_drv_missing_argument : Error<
"argument to '%0' is missing (expected %1 value%s1)">;
def err_drv_invalid_Xarch_argument_with_args : Error<
Index: clang/include/clang/Basic/CodeGenOptions.h
===================================================================
--- clang/include/clang/Basic/CodeGenOptions.h
+++ clang/include/clang/Basic/CodeGenOptions.h
@@ -337,6 +337,21 @@
const char *Argv0 = nullptr;
ArrayRef<const char *> CommandLineArgs;
+ /// 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.
+ Optional<uint64_t> DiagnosticsHotnessThreshold = 0;
+
public:
// Define accessors/mutators for code generation options of enumeration type.
#define CODEGENOPT(Name, Bits, Default)
Index: clang/include/clang/Basic/CodeGenOptions.def
===================================================================
--- clang/include/clang/Basic/CodeGenOptions.def
+++ clang/include/clang/Basic/CodeGenOptions.def
@@ -352,10 +352,6 @@
/// Whether to report the hotness of the code region for optimization remarks.
CODEGENOPT(DiagnosticsWithHotness, 1, 0)
-/// The minimum hotness value a diagnostic needs in order to be included in
-/// optimization diagnostics.
-VALUE_CODEGENOPT(DiagnosticsHotnessThreshold, 32, 0)
-
/// Whether copy relocations support is available when building as PIE.
CODEGENOPT(PIECopyRelocations, 1, 0)
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits