Line data Source code
1 : ///===- MachineOptimizationRemarkEmitter.h - Opt Diagnostics -*- C++ -*----===//
2 : ///
3 : /// The LLVM Compiler Infrastructure
4 : ///
5 : /// This file is distributed under the University of Illinois Open Source
6 : /// License. See LICENSE.TXT for details.
7 : ///
8 : ///===---------------------------------------------------------------------===//
9 : /// \file
10 : /// Optimization diagnostic interfaces for machine passes. It's packaged as an
11 : /// analysis pass so that by using this service passes become dependent on MBFI
12 : /// as well. MBFI is used to compute the "hotness" of the diagnostic message.
13 : ///
14 : ///===---------------------------------------------------------------------===//
15 :
16 : #ifndef LLVM_CODEGEN_MACHINEOPTIMIZATIONREMARKEMITTER_H
17 : #define LLVM_CODEGEN_MACHINEOPTIMIZATIONREMARKEMITTER_H
18 :
19 : #include "llvm/Analysis/OptimizationRemarkEmitter.h"
20 : #include "llvm/CodeGen/MachineFunctionPass.h"
21 :
22 : namespace llvm {
23 : class MachineBasicBlock;
24 : class MachineBlockFrequencyInfo;
25 : class MachineInstr;
26 :
27 : /// Common features for diagnostics dealing with optimization remarks
28 : /// that are used by machine passes.
29 : class DiagnosticInfoMIROptimization : public DiagnosticInfoOptimizationBase {
30 : public:
31 : DiagnosticInfoMIROptimization(enum DiagnosticKind Kind, const char *PassName,
32 : StringRef RemarkName,
33 : const DiagnosticLocation &Loc,
34 : const MachineBasicBlock *MBB)
35 406036 : : DiagnosticInfoOptimizationBase(Kind, DS_Remark, PassName, RemarkName,
36 : MBB->getParent()->getFunction(), Loc),
37 406036 : MBB(MBB) {}
38 :
39 : /// MI-specific kinds of diagnostic Arguments.
40 24 : struct MachineArgument : public DiagnosticInfoOptimizationBase::Argument {
41 : /// Print an entire MachineInstr.
42 : MachineArgument(StringRef Key, const MachineInstr &MI);
43 : };
44 :
45 : static bool classof(const DiagnosticInfo *DI) {
46 : return DI->getKind() >= DK_FirstMachineRemark &&
47 : DI->getKind() <= DK_LastMachineRemark;
48 : }
49 :
50 0 : const MachineBasicBlock *getBlock() const { return MBB; }
51 :
52 : private:
53 : const MachineBasicBlock *MBB;
54 : };
55 :
56 : /// Diagnostic information for applied optimization remarks.
57 : class MachineOptimizationRemark : public DiagnosticInfoMIROptimization {
58 : public:
59 : /// \p PassName is the name of the pass emitting this diagnostic. If this name
60 : /// matches the regular expression given in -Rpass=, then the diagnostic will
61 : /// be emitted. \p RemarkName is a textual identifier for the remark. \p
62 : /// Loc is the debug location and \p MBB is the block that the optimization
63 : /// operates in.
64 : MachineOptimizationRemark(const char *PassName, StringRef RemarkName,
65 : const DiagnosticLocation &Loc,
66 : const MachineBasicBlock *MBB)
67 : : DiagnosticInfoMIROptimization(DK_MachineOptimizationRemark, PassName,
68 0 : RemarkName, Loc, MBB) {}
69 :
70 : static bool classof(const DiagnosticInfo *DI) {
71 : return DI->getKind() == DK_MachineOptimizationRemark;
72 : }
73 :
74 : /// \see DiagnosticInfoOptimizationBase::isEnabled.
75 33 : bool isEnabled() const override {
76 33 : const Function &Fn = getFunction();
77 33 : LLVMContext &Ctx = Fn.getContext();
78 66 : return Ctx.getDiagHandlerPtr()->isPassedOptRemarkEnabled(getPassName());
79 : }
80 : };
81 :
82 : /// Diagnostic information for missed-optimization remarks.
83 : class MachineOptimizationRemarkMissed : public DiagnosticInfoMIROptimization {
84 : public:
85 : /// \p PassName is the name of the pass emitting this diagnostic. If this name
86 : /// matches the regular expression given in -Rpass-missed=, then the
87 : /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
88 : /// remark. \p Loc is the debug location and \p MBB is the block that the
89 : /// optimization operates in.
90 : MachineOptimizationRemarkMissed(const char *PassName, StringRef RemarkName,
91 : const DiagnosticLocation &Loc,
92 : const MachineBasicBlock *MBB)
93 : : DiagnosticInfoMIROptimization(DK_MachineOptimizationRemarkMissed,
94 41 : PassName, RemarkName, Loc, MBB) {}
95 :
96 : static bool classof(const DiagnosticInfo *DI) {
97 : return DI->getKind() == DK_MachineOptimizationRemarkMissed;
98 : }
99 :
100 : /// \see DiagnosticInfoOptimizationBase::isEnabled.
101 73 : bool isEnabled() const override {
102 73 : const Function &Fn = getFunction();
103 73 : LLVMContext &Ctx = Fn.getContext();
104 146 : return Ctx.getDiagHandlerPtr()->isMissedOptRemarkEnabled(getPassName());
105 : }
106 : };
107 :
108 : /// Diagnostic information for optimization analysis remarks.
109 : class MachineOptimizationRemarkAnalysis : public DiagnosticInfoMIROptimization {
110 : public:
111 : /// \p PassName is the name of the pass emitting this diagnostic. If this name
112 : /// matches the regular expression given in -Rpass-analysis=, then the
113 : /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
114 : /// remark. \p Loc is the debug location and \p MBB is the block that the
115 : /// optimization operates in.
116 : MachineOptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName,
117 : const DiagnosticLocation &Loc,
118 : const MachineBasicBlock *MBB)
119 : : DiagnosticInfoMIROptimization(DK_MachineOptimizationRemarkAnalysis,
120 405995 : PassName, RemarkName, Loc, MBB) {}
121 :
122 : static bool classof(const DiagnosticInfo *DI) {
123 : return DI->getKind() == DK_MachineOptimizationRemarkAnalysis;
124 : }
125 :
126 : /// \see DiagnosticInfoOptimizationBase::isEnabled.
127 197431 : bool isEnabled() const override {
128 197431 : const Function &Fn = getFunction();
129 197431 : LLVMContext &Ctx = Fn.getContext();
130 394863 : return Ctx.getDiagHandlerPtr()->isAnalysisRemarkEnabled(getPassName());
131 : }
132 : };
133 :
134 : /// Extend llvm::ore:: with MI-specific helper names.
135 : namespace ore {
136 : using MNV = DiagnosticInfoMIROptimization::MachineArgument;
137 : }
138 :
139 : /// The optimization diagnostic interface.
140 : ///
141 : /// It allows reporting when optimizations are performed and when they are not
142 : /// along with the reasons for it. Hotness information of the corresponding
143 : /// code region can be included in the remark if DiagnosticsHotnessRequested is
144 : /// enabled in the LLVM context.
145 : class MachineOptimizationRemarkEmitter {
146 : public:
147 : MachineOptimizationRemarkEmitter(MachineFunction &MF,
148 : MachineBlockFrequencyInfo *MBFI)
149 1008827 : : MF(MF), MBFI(MBFI) {}
150 :
151 : /// Emit an optimization remark.
152 : void emit(DiagnosticInfoOptimizationBase &OptDiag);
153 :
154 : /// Whether we allow for extra compile-time budget to perform more
155 : /// analysis to be more informative.
156 : ///
157 : /// This is useful to enable additional missed optimizations to be reported
158 : /// that are normally too noisy. In this mode, we can use the extra analysis
159 : /// (1) to filter trivial false positives or (2) to provide more context so
160 : /// that non-trivial false positives can be quickly detected by the user.
161 0 : bool allowExtraAnalysis(StringRef PassName) const {
162 0 : return (MF.getFunction().getContext().getDiagnosticsOutputFile() ||
163 0 : MF.getFunction().getContext()
164 0 : .getDiagHandlerPtr()->isAnyRemarkEnabled(PassName));
165 : }
166 :
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 0 : 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.
174 :
175 0 : if (MF.getFunction().getContext().getDiagnosticsOutputFile() ||
176 0 : MF.getFunction().getContext().getDiagHandlerPtr()->isAnyRemarkEnabled()) {
177 0 : auto R = RemarkBuilder();
178 0 : emit((DiagnosticInfoOptimizationBase &)R);
179 : }
180 0 : }
181 0 :
182 : private:
183 : MachineFunction &MF;
184 :
185 : /// MBFI is only set if hotness is requested.
186 0 : MachineBlockFrequencyInfo *MBFI;
187 0 :
188 0 : /// Compute hotness from IR value (currently assumed to be a block) if PGO is
189 0 : /// available.
190 : Optional<uint64_t> computeHotness(const MachineBasicBlock &MBB);
191 0 :
192 0 : /// Similar but use value from \p OptDiag and update hotness there.
193 : void computeHotness(DiagnosticInfoMIROptimization &Remark);
194 :
195 : /// Only allow verbose messages if we know we're filtering by hotness
196 : /// (BFI is only set in this case).
197 0 : bool shouldEmitVerbose() { return MBFI != nullptr; }
198 0 : };
199 0 :
200 0 : /// The analysis pass
201 : ///
202 0 : /// Note that this pass shouldn't generally be marked as preserved by other
203 : /// passes. It's holding onto BFI, so if the pass does not preserve BFI, BFI
204 : /// could be freed.
205 : class MachineOptimizationRemarkEmitterPass : public MachineFunctionPass {
206 : std::unique_ptr<MachineOptimizationRemarkEmitter> ORE;
207 :
208 : public:
209 : MachineOptimizationRemarkEmitterPass();
210 :
211 : bool runOnMachineFunction(MachineFunction &MF) override;
212 :
213 : void getAnalysisUsage(AnalysisUsage &AU) const override;
214 :
215 : MachineOptimizationRemarkEmitter &getORE() {
216 : assert(ORE && "pass not run yet");
217 : return *ORE;
218 : }
219 :
220 : static char ID;
221 : };
222 : }
223 :
224 : #endif
|