1 //===- OptimizationRemarkEmitter.cpp - Optimization Diagnostic --*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // Optimization diagnostic interfaces. It's packaged as an analysis pass so
10 // that by using this service passes become dependent on BFI as well. BFI is
11 // used to compute the "hotness" of the diagnostic message.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/Analysis/OptimizationRemarkEmitter.h"
15 #include "llvm/Analysis/BranchProbabilityInfo.h"
16 #include "llvm/Analysis/LazyBlockFrequencyInfo.h"
17 #include "llvm/Analysis/LoopInfo.h"
18 #include "llvm/Analysis/ProfileSummaryInfo.h"
19 #include "llvm/IR/DiagnosticInfo.h"
20 #include "llvm/IR/Dominators.h"
21 #include "llvm/IR/LLVMContext.h"
22 #include "llvm/InitializePasses.h"
27 OptimizationRemarkEmitter::OptimizationRemarkEmitter(const Function
*F
)
28 : F(F
), BFI(nullptr) {
29 if (!F
->getContext().getDiagnosticsHotnessRequested())
32 // First create a dominator tree.
34 DT
.recalculate(*const_cast<Function
*>(F
));
36 // Generate LoopInfo from it.
40 // Then compute BranchProbabilityInfo.
41 BranchProbabilityInfo
BPI(*F
, LI
, nullptr, &DT
, nullptr);
43 // Finally compute BFI.
44 OwnedBFI
= std::make_unique
<BlockFrequencyInfo
>(*F
, BPI
, LI
);
48 bool OptimizationRemarkEmitter::invalidate(
49 Function
&F
, const PreservedAnalyses
&PA
,
50 FunctionAnalysisManager::Invalidator
&Inv
) {
55 // This analysis has no state and so can be trivially preserved but it needs
56 // a fresh view of BFI if it was constructed with one.
57 if (BFI
&& Inv
.invalidate
<BlockFrequencyAnalysis
>(F
, PA
))
60 // Otherwise this analysis result remains valid.
64 std::optional
<uint64_t>
65 OptimizationRemarkEmitter::computeHotness(const Value
*V
) {
69 return BFI
->getBlockProfileCount(cast
<BasicBlock
>(V
));
72 void OptimizationRemarkEmitter::computeHotness(
73 DiagnosticInfoIROptimization
&OptDiag
) {
74 const Value
*V
= OptDiag
.getCodeRegion();
76 OptDiag
.setHotness(computeHotness(V
));
79 void OptimizationRemarkEmitter::emit(
80 DiagnosticInfoOptimizationBase
&OptDiagBase
) {
81 auto &OptDiag
= cast
<DiagnosticInfoIROptimization
>(OptDiagBase
);
82 computeHotness(OptDiag
);
84 // Only emit it if its hotness meets the threshold.
85 if (OptDiag
.getHotness().value_or(0) <
86 F
->getContext().getDiagnosticsHotnessThreshold()) {
90 F
->getContext().diagnose(OptDiag
);
93 OptimizationRemarkEmitterWrapperPass::OptimizationRemarkEmitterWrapperPass()
95 initializeOptimizationRemarkEmitterWrapperPassPass(
96 *PassRegistry::getPassRegistry());
99 bool OptimizationRemarkEmitterWrapperPass::runOnFunction(Function
&Fn
) {
100 BlockFrequencyInfo
*BFI
;
102 auto &Context
= Fn
.getContext();
103 if (Context
.getDiagnosticsHotnessRequested()) {
104 BFI
= &getAnalysis
<LazyBlockFrequencyInfoPass
>().getBFI();
105 // Get hotness threshold from PSI. This should only happen once.
106 if (Context
.isDiagnosticsHotnessThresholdSetFromPSI()) {
107 if (ProfileSummaryInfo
*PSI
=
108 &getAnalysis
<ProfileSummaryInfoWrapperPass
>().getPSI())
109 Context
.setDiagnosticsHotnessThreshold(
110 PSI
->getOrCompHotCountThreshold());
115 ORE
= std::make_unique
<OptimizationRemarkEmitter
>(&Fn
, BFI
);
119 void OptimizationRemarkEmitterWrapperPass::getAnalysisUsage(
120 AnalysisUsage
&AU
) const {
121 LazyBlockFrequencyInfoPass::getLazyBFIAnalysisUsage(AU
);
122 AU
.addRequired
<ProfileSummaryInfoWrapperPass
>();
123 AU
.setPreservesAll();
126 AnalysisKey
OptimizationRemarkEmitterAnalysis::Key
;
128 OptimizationRemarkEmitter
129 OptimizationRemarkEmitterAnalysis::run(Function
&F
,
130 FunctionAnalysisManager
&AM
) {
131 BlockFrequencyInfo
*BFI
;
132 auto &Context
= F
.getContext();
134 if (Context
.getDiagnosticsHotnessRequested()) {
135 BFI
= &AM
.getResult
<BlockFrequencyAnalysis
>(F
);
136 // Get hotness threshold from PSI. This should only happen once.
137 if (Context
.isDiagnosticsHotnessThresholdSetFromPSI()) {
138 auto &MAMProxy
= AM
.getResult
<ModuleAnalysisManagerFunctionProxy
>(F
);
139 if (ProfileSummaryInfo
*PSI
=
140 MAMProxy
.getCachedResult
<ProfileSummaryAnalysis
>(*F
.getParent()))
141 Context
.setDiagnosticsHotnessThreshold(
142 PSI
->getOrCompHotCountThreshold());
147 return OptimizationRemarkEmitter(&F
, BFI
);
150 char OptimizationRemarkEmitterWrapperPass::ID
= 0;
151 static const char ore_name
[] = "Optimization Remark Emitter";
152 #define ORE_NAME "opt-remark-emitter"
154 INITIALIZE_PASS_BEGIN(OptimizationRemarkEmitterWrapperPass
, ORE_NAME
, ore_name
,
156 INITIALIZE_PASS_DEPENDENCY(LazyBFIPass
)
157 INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass
)
158 INITIALIZE_PASS_END(OptimizationRemarkEmitterWrapperPass
, ORE_NAME
, ore_name
,