1 ///===- MachineOptimizationRemarkEmitter.h - Opt Diagnostics -*- 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 for machine passes. It's packaged as an
10 /// analysis pass so that by using this service passes become dependent on MBFI
11 /// as well. MBFI is used to compute the "hotness" of the diagnostic message.
13 ///===---------------------------------------------------------------------===//
15 #ifndef LLVM_CODEGEN_MACHINEOPTIMIZATIONREMARKEMITTER_H
16 #define LLVM_CODEGEN_MACHINEOPTIMIZATIONREMARKEMITTER_H
18 #include "llvm/Analysis/OptimizationRemarkEmitter.h"
19 #include "llvm/CodeGen/MachineFunctionPass.h"
22 class MachineBasicBlock
;
23 class MachineBlockFrequencyInfo
;
26 /// Common features for diagnostics dealing with optimization remarks
27 /// that are used by machine passes.
28 class DiagnosticInfoMIROptimization
: public DiagnosticInfoOptimizationBase
{
30 DiagnosticInfoMIROptimization(enum DiagnosticKind Kind
, const char *PassName
,
32 const DiagnosticLocation
&Loc
,
33 const MachineBasicBlock
*MBB
)
34 : DiagnosticInfoOptimizationBase(Kind
, DS_Remark
, PassName
, RemarkName
,
35 MBB
->getParent()->getFunction(), Loc
),
38 /// MI-specific kinds of diagnostic Arguments.
39 struct MachineArgument
: public DiagnosticInfoOptimizationBase::Argument
{
40 /// Print an entire MachineInstr.
41 MachineArgument(StringRef Key
, const MachineInstr
&MI
);
44 static bool classof(const DiagnosticInfo
*DI
) {
45 return DI
->getKind() >= DK_FirstMachineRemark
&&
46 DI
->getKind() <= DK_LastMachineRemark
;
49 const MachineBasicBlock
*getBlock() const { return MBB
; }
52 const MachineBasicBlock
*MBB
;
55 /// Diagnostic information for applied optimization remarks.
56 class MachineOptimizationRemark
: public DiagnosticInfoMIROptimization
{
58 /// \p PassName is the name of the pass emitting this diagnostic. If this name
59 /// matches the regular expression given in -Rpass=, then the diagnostic will
60 /// be emitted. \p RemarkName is a textual identifier for the remark. \p
61 /// Loc is the debug location and \p MBB is the block that the optimization
63 MachineOptimizationRemark(const char *PassName
, StringRef RemarkName
,
64 const DiagnosticLocation
&Loc
,
65 const MachineBasicBlock
*MBB
)
66 : DiagnosticInfoMIROptimization(DK_MachineOptimizationRemark
, PassName
,
67 RemarkName
, Loc
, MBB
) {}
69 static bool classof(const DiagnosticInfo
*DI
) {
70 return DI
->getKind() == DK_MachineOptimizationRemark
;
73 /// \see DiagnosticInfoOptimizationBase::isEnabled.
74 bool isEnabled() const override
{
75 const Function
&Fn
= getFunction();
76 LLVMContext
&Ctx
= Fn
.getContext();
77 return Ctx
.getDiagHandlerPtr()->isPassedOptRemarkEnabled(getPassName());
81 /// Diagnostic information for missed-optimization remarks.
82 class MachineOptimizationRemarkMissed
: public DiagnosticInfoMIROptimization
{
84 /// \p PassName is the name of the pass emitting this diagnostic. If this name
85 /// matches the regular expression given in -Rpass-missed=, then the
86 /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
87 /// remark. \p Loc is the debug location and \p MBB is the block that the
88 /// optimization operates in.
89 MachineOptimizationRemarkMissed(const char *PassName
, StringRef RemarkName
,
90 const DiagnosticLocation
&Loc
,
91 const MachineBasicBlock
*MBB
)
92 : DiagnosticInfoMIROptimization(DK_MachineOptimizationRemarkMissed
,
93 PassName
, RemarkName
, Loc
, MBB
) {}
95 static bool classof(const DiagnosticInfo
*DI
) {
96 return DI
->getKind() == DK_MachineOptimizationRemarkMissed
;
99 /// \see DiagnosticInfoOptimizationBase::isEnabled.
100 bool isEnabled() const override
{
101 const Function
&Fn
= getFunction();
102 LLVMContext
&Ctx
= Fn
.getContext();
103 return Ctx
.getDiagHandlerPtr()->isMissedOptRemarkEnabled(getPassName());
107 /// Diagnostic information for optimization analysis remarks.
108 class MachineOptimizationRemarkAnalysis
: public DiagnosticInfoMIROptimization
{
110 /// \p PassName is the name of the pass emitting this diagnostic. If this name
111 /// matches the regular expression given in -Rpass-analysis=, then the
112 /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
113 /// remark. \p Loc is the debug location and \p MBB is the block that the
114 /// optimization operates in.
115 MachineOptimizationRemarkAnalysis(const char *PassName
, StringRef RemarkName
,
116 const DiagnosticLocation
&Loc
,
117 const MachineBasicBlock
*MBB
)
118 : DiagnosticInfoMIROptimization(DK_MachineOptimizationRemarkAnalysis
,
119 PassName
, RemarkName
, Loc
, MBB
) {}
121 static bool classof(const DiagnosticInfo
*DI
) {
122 return DI
->getKind() == DK_MachineOptimizationRemarkAnalysis
;
125 /// \see DiagnosticInfoOptimizationBase::isEnabled.
126 bool isEnabled() const override
{
127 const Function
&Fn
= getFunction();
128 LLVMContext
&Ctx
= Fn
.getContext();
129 return Ctx
.getDiagHandlerPtr()->isAnalysisRemarkEnabled(getPassName());
133 /// Extend llvm::ore:: with MI-specific helper names.
135 using MNV
= DiagnosticInfoMIROptimization::MachineArgument
;
138 /// The optimization diagnostic interface.
140 /// It allows reporting when optimizations are performed and when they are not
141 /// along with the reasons for it. Hotness information of the corresponding
142 /// code region can be included in the remark if DiagnosticsHotnessRequested is
143 /// enabled in the LLVM context.
144 class MachineOptimizationRemarkEmitter
{
146 MachineOptimizationRemarkEmitter(MachineFunction
&MF
,
147 MachineBlockFrequencyInfo
*MBFI
)
148 : MF(MF
), MBFI(MBFI
) {}
150 /// Emit an optimization remark.
151 void emit(DiagnosticInfoOptimizationBase
&OptDiag
);
153 /// Whether we allow for extra compile-time budget to perform more
154 /// analysis to be more informative.
156 /// This is useful to enable additional missed optimizations to be reported
157 /// that are normally too noisy. In this mode, we can use the extra analysis
158 /// (1) to filter trivial false positives or (2) to provide more context so
159 /// that non-trivial false positives can be quickly detected by the user.
160 bool allowExtraAnalysis(StringRef PassName
) const {
162 MF
.getFunction().getContext().getRemarkStreamer() ||
163 MF
.getFunction().getContext().getDiagHandlerPtr()->isAnyRemarkEnabled(
167 /// Take a lambda that returns a remark which will be emitted. Second
168 /// argument is only used to restrict this to functions.
169 template <typename T
>
170 void emit(T RemarkBuilder
, decltype(RemarkBuilder()) * = nullptr) {
171 // Avoid building the remark unless we know there are at least *some*
172 // remarks enabled. We can't currently check whether remarks are requested
173 // for the calling pass since that requires actually building the remark.
175 if (MF
.getFunction().getContext().getRemarkStreamer() ||
179 ->isAnyRemarkEnabled()) {
180 auto R
= RemarkBuilder();
181 emit((DiagnosticInfoOptimizationBase
&)R
);
188 /// MBFI is only set if hotness is requested.
189 MachineBlockFrequencyInfo
*MBFI
;
191 /// Compute hotness from IR value (currently assumed to be a block) if PGO is
193 Optional
<uint64_t> computeHotness(const MachineBasicBlock
&MBB
);
195 /// Similar but use value from \p OptDiag and update hotness there.
196 void computeHotness(DiagnosticInfoMIROptimization
&Remark
);
198 /// Only allow verbose messages if we know we're filtering by hotness
199 /// (BFI is only set in this case).
200 bool shouldEmitVerbose() { return MBFI
!= nullptr; }
203 /// The analysis pass
205 /// Note that this pass shouldn't generally be marked as preserved by other
206 /// passes. It's holding onto BFI, so if the pass does not preserve BFI, BFI
208 class MachineOptimizationRemarkEmitterPass
: public MachineFunctionPass
{
209 std::unique_ptr
<MachineOptimizationRemarkEmitter
> ORE
;
212 MachineOptimizationRemarkEmitterPass();
214 bool runOnMachineFunction(MachineFunction
&MF
) override
;
216 void getAnalysisUsage(AnalysisUsage
&AU
) const override
;
218 MachineOptimizationRemarkEmitter
&getORE() {
219 assert(ORE
&& "pass not run yet");