Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

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