Bug Summary

File:llvm/include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h
Warning:line 35, column 40
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name Legalizer.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mthread-model posix -mframe-pointer=none -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-10/lib/clang/10.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/build-llvm/lib/CodeGen/GlobalISel -I /build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/CodeGen/GlobalISel -I /build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/build-llvm/include -I /build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/include -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-10/lib/clang/10.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/build-llvm/lib/CodeGen/GlobalISel -fdebug-prefix-map=/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809=. -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -o /tmp/scan-build-2019-12-11-181444-25759-1 -x c++ /build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/CodeGen/GlobalISel/Legalizer.cpp

/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/CodeGen/GlobalISel/Legalizer.cpp

1//===-- llvm/CodeGen/GlobalISel/Legalizer.cpp -----------------------------===//
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//
9/// \file This file implements the LegalizerHelper class to legalize individual
10/// instructions and the LegalizePass wrapper pass for the primary
11/// legalization.
12//
13//===----------------------------------------------------------------------===//
14
15#include "llvm/CodeGen/GlobalISel/Legalizer.h"
16#include "llvm/ADT/PostOrderIterator.h"
17#include "llvm/ADT/SetVector.h"
18#include "llvm/CodeGen/GlobalISel/CSEInfo.h"
19#include "llvm/CodeGen/GlobalISel/CSEMIRBuilder.h"
20#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
21#include "llvm/CodeGen/GlobalISel/GISelWorkList.h"
22#include "llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h"
23#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
24#include "llvm/CodeGen/GlobalISel/Utils.h"
25#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
26#include "llvm/CodeGen/MachineRegisterInfo.h"
27#include "llvm/CodeGen/TargetPassConfig.h"
28#include "llvm/CodeGen/TargetSubtargetInfo.h"
29#include "llvm/Support/Debug.h"
30#include "llvm/Target/TargetMachine.h"
31
32#include <iterator>
33
34#define DEBUG_TYPE"legalizer" "legalizer"
35
36using namespace llvm;
37
38static cl::opt<bool>
39 EnableCSEInLegalizer("enable-cse-in-legalizer",
40 cl::desc("Should enable CSE in Legalizer"),
41 cl::Optional, cl::init(false));
42
43char Legalizer::ID = 0;
44INITIALIZE_PASS_BEGIN(Legalizer, DEBUG_TYPE,static void *initializeLegalizerPassOnce(PassRegistry &Registry
) {
45 "Legalize the Machine IR a function's Machine IR", false,static void *initializeLegalizerPassOnce(PassRegistry &Registry
) {
46 false)static void *initializeLegalizerPassOnce(PassRegistry &Registry
) {
47INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)initializeTargetPassConfigPass(Registry);
48INITIALIZE_PASS_DEPENDENCY(GISelCSEAnalysisWrapperPass)initializeGISelCSEAnalysisWrapperPassPass(Registry);
49INITIALIZE_PASS_END(Legalizer, DEBUG_TYPE,PassInfo *PI = new PassInfo( "Legalize the Machine IR a function's Machine IR"
, "legalizer", &Legalizer::ID, PassInfo::NormalCtor_t(callDefaultCtor
<Legalizer>), false, false); Registry.registerPass(*PI,
true); return PI; } static llvm::once_flag InitializeLegalizerPassFlag
; void llvm::initializeLegalizerPass(PassRegistry &Registry
) { llvm::call_once(InitializeLegalizerPassFlag, initializeLegalizerPassOnce
, std::ref(Registry)); }
50 "Legalize the Machine IR a function's Machine IR", false,PassInfo *PI = new PassInfo( "Legalize the Machine IR a function's Machine IR"
, "legalizer", &Legalizer::ID, PassInfo::NormalCtor_t(callDefaultCtor
<Legalizer>), false, false); Registry.registerPass(*PI,
true); return PI; } static llvm::once_flag InitializeLegalizerPassFlag
; void llvm::initializeLegalizerPass(PassRegistry &Registry
) { llvm::call_once(InitializeLegalizerPassFlag, initializeLegalizerPassOnce
, std::ref(Registry)); }
51 false)PassInfo *PI = new PassInfo( "Legalize the Machine IR a function's Machine IR"
, "legalizer", &Legalizer::ID, PassInfo::NormalCtor_t(callDefaultCtor
<Legalizer>), false, false); Registry.registerPass(*PI,
true); return PI; } static llvm::once_flag InitializeLegalizerPassFlag
; void llvm::initializeLegalizerPass(PassRegistry &Registry
) { llvm::call_once(InitializeLegalizerPassFlag, initializeLegalizerPassOnce
, std::ref(Registry)); }
52
53Legalizer::Legalizer() : MachineFunctionPass(ID) { }
54
55void Legalizer::getAnalysisUsage(AnalysisUsage &AU) const {
56 AU.addRequired<TargetPassConfig>();
57 AU.addRequired<GISelCSEAnalysisWrapperPass>();
58 AU.addPreserved<GISelCSEAnalysisWrapperPass>();
59 getSelectionDAGFallbackAnalysisUsage(AU);
60 MachineFunctionPass::getAnalysisUsage(AU);
61}
62
63void Legalizer::init(MachineFunction &MF) {
64}
65
66static bool isArtifact(const MachineInstr &MI) {
67 switch (MI.getOpcode()) {
68 default:
69 return false;
70 case TargetOpcode::G_TRUNC:
71 case TargetOpcode::G_ZEXT:
72 case TargetOpcode::G_ANYEXT:
73 case TargetOpcode::G_SEXT:
74 case TargetOpcode::G_MERGE_VALUES:
75 case TargetOpcode::G_UNMERGE_VALUES:
76 case TargetOpcode::G_CONCAT_VECTORS:
77 case TargetOpcode::G_BUILD_VECTOR:
78 case TargetOpcode::G_EXTRACT:
79 return true;
80 }
81}
82using InstListTy = GISelWorkList<256>;
83using ArtifactListTy = GISelWorkList<128>;
84
85namespace {
86class LegalizerWorkListManager : public GISelChangeObserver {
87 InstListTy &InstList;
88 ArtifactListTy &ArtifactList;
89#ifndef NDEBUG
90 SmallVector<MachineInstr *, 4> NewMIs;
91#endif
92
93public:
94 LegalizerWorkListManager(InstListTy &Insts, ArtifactListTy &Arts)
95 : InstList(Insts), ArtifactList(Arts) {}
96
97 void createdOrChangedInstr(MachineInstr &MI) {
98 // Only legalize pre-isel generic instructions.
99 // Legalization process could generate Target specific pseudo
100 // instructions with generic types. Don't record them
101 if (isPreISelGenericOpcode(MI.getOpcode())) {
102 if (isArtifact(MI))
103 ArtifactList.insert(&MI);
104 else
105 InstList.insert(&MI);
106 }
107 }
108
109 void createdInstr(MachineInstr &MI) override {
110 LLVM_DEBUG(dbgs() << ".. .. New MI: " << MI)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("legalizer")) { dbgs() << ".. .. New MI: " << MI
; } } while (false)
;
111 LLVM_DEBUG(NewMIs.push_back(&MI))do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("legalizer")) { NewMIs.push_back(&MI); } } while (false)
;
112 createdOrChangedInstr(MI);
113 }
114
115 void printNewInstrs() {
116 LLVM_DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("legalizer")) { { for (const auto *MI : NewMIs) dbgs() <<
".. .. New MI: " << *MI; NewMIs.clear(); }; } } while (
false)
117 for (const auto *MI : NewMIs)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("legalizer")) { { for (const auto *MI : NewMIs) dbgs() <<
".. .. New MI: " << *MI; NewMIs.clear(); }; } } while (
false)
118 dbgs() << ".. .. New MI: " << *MI;do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("legalizer")) { { for (const auto *MI : NewMIs) dbgs() <<
".. .. New MI: " << *MI; NewMIs.clear(); }; } } while (
false)
119 NewMIs.clear();do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("legalizer")) { { for (const auto *MI : NewMIs) dbgs() <<
".. .. New MI: " << *MI; NewMIs.clear(); }; } } while (
false)
120 })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("legalizer")) { { for (const auto *MI : NewMIs) dbgs() <<
".. .. New MI: " << *MI; NewMIs.clear(); }; } } while (
false)
;
121 }
122
123 void erasingInstr(MachineInstr &MI) override {
124 LLVM_DEBUG(dbgs() << ".. .. Erasing: " << MI)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("legalizer")) { dbgs() << ".. .. Erasing: " << MI
; } } while (false)
;
125 InstList.remove(&MI);
126 ArtifactList.remove(&MI);
127 }
128
129 void changingInstr(MachineInstr &MI) override {
130 LLVM_DEBUG(dbgs() << ".. .. Changing MI: " << MI)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("legalizer")) { dbgs() << ".. .. Changing MI: " <<
MI; } } while (false)
;
131 }
132
133 void changedInstr(MachineInstr &MI) override {
134 // When insts change, we want to revisit them to legalize them again.
135 // We'll consider them the same as created.
136 LLVM_DEBUG(dbgs() << ".. .. Changed MI: " << MI)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("legalizer")) { dbgs() << ".. .. Changed MI: " <<
MI; } } while (false)
;
137 createdOrChangedInstr(MI);
138 }
139};
140} // namespace
141
142bool Legalizer::runOnMachineFunction(MachineFunction &MF) {
143 // If the ISel pipeline failed, do not bother running that pass.
144 if (MF.getProperties().hasProperty(
1
Taking false branch
145 MachineFunctionProperties::Property::FailedISel))
146 return false;
147 LLVM_DEBUG(dbgs() << "Legalize Machine IR for: " << MF.getName() << '\n')do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("legalizer")) { dbgs() << "Legalize Machine IR for: " <<
MF.getName() << '\n'; } } while (false)
;
2
Assuming 'DebugFlag' is false
3
Loop condition is false. Exiting loop
148 init(MF);
149 const TargetPassConfig &TPC = getAnalysis<TargetPassConfig>();
150 GISelCSEAnalysisWrapper &Wrapper =
151 getAnalysis<GISelCSEAnalysisWrapperPass>().getCSEWrapper();
152 MachineOptimizationRemarkEmitter MORE(MF, /*MBFI=*/nullptr);
153
154 const size_t NumBlocks = MF.size();
155 MachineRegisterInfo &MRI = MF.getRegInfo();
156
157 // Populate Insts
158 InstListTy InstList;
159 ArtifactListTy ArtifactList;
160 ReversePostOrderTraversal<MachineFunction *> RPOT(&MF);
161 // Perform legalization bottom up so we can DCE as we legalize.
162 // Traverse BB in RPOT and within each basic block, add insts top down,
163 // so when we pop_back_val in the legalization process, we traverse bottom-up.
164 for (auto *MBB : RPOT) {
165 if (MBB->empty())
166 continue;
167 for (MachineInstr &MI : *MBB) {
168 // Only legalize pre-isel generic instructions: others don't have types
169 // and are assumed to be legal.
170 if (!isPreISelGenericOpcode(MI.getOpcode()))
171 continue;
172 if (isArtifact(MI))
173 ArtifactList.deferred_insert(&MI);
174 else
175 InstList.deferred_insert(&MI);
176 }
177 }
178 ArtifactList.finalize();
179 InstList.finalize();
180 std::unique_ptr<MachineIRBuilder> MIRBuilder;
181 GISelCSEInfo *CSEInfo = nullptr;
182 bool EnableCSE = EnableCSEInLegalizer.getNumOccurrences()
4
Assuming the condition is false
5
'?' condition is false
183 ? EnableCSEInLegalizer
184 : TPC.isGISelCSEEnabled();
185
186 if (EnableCSE) {
6
Assuming 'EnableCSE' is false
7
Taking false branch
187 MIRBuilder = std::make_unique<CSEMIRBuilder>();
188 CSEInfo = &Wrapper.get(TPC.getCSEConfig());
189 MIRBuilder->setCSEInfo(CSEInfo);
190 } else
191 MIRBuilder = std::make_unique<MachineIRBuilder>();
192 // This observer keeps the worklist updated.
193 LegalizerWorkListManager WorkListObserver(InstList, ArtifactList);
194 // We want both WorkListObserver as well as CSEInfo to observe all changes.
195 // Use the wrapper observer.
196 GISelObserverWrapper WrapperObserver(&WorkListObserver);
197 if (EnableCSE
7.1
'EnableCSE' is false
7.1
'EnableCSE' is false
&& CSEInfo)
198 WrapperObserver.addObserver(CSEInfo);
199 // Now install the observer as the delegate to MF.
200 // This will keep all the observers notified about new insertions/deletions.
201 RAIIDelegateInstaller DelInstall(MF, &WrapperObserver);
202 LegalizerHelper Helper(MF, WrapperObserver, *MIRBuilder.get());
203 const LegalizerInfo &LInfo(Helper.getLegalizerInfo());
204 LegalizationArtifactCombiner ArtCombiner(*MIRBuilder.get(), MF.getRegInfo(),
205 LInfo);
206 auto RemoveDeadInstFromLists = [&WrapperObserver](MachineInstr *DeadMI) {
207 WrapperObserver.erasingInstr(*DeadMI);
208 };
209 auto stopLegalizing = [&](MachineInstr &MI) {
210 Helper.MIRBuilder.stopObservingChanges();
211 reportGISelFailure(MF, TPC, MORE, "gisel-legalize",
212 "unable to legalize instruction", MI);
213 };
214 bool Changed = false;
215 SmallVector<MachineInstr *, 128> RetryList;
216 do {
15
Loop condition is false. Exiting loop
217 assert(RetryList.empty() && "Expected no instructions in RetryList")((RetryList.empty() && "Expected no instructions in RetryList"
) ? static_cast<void> (0) : __assert_fail ("RetryList.empty() && \"Expected no instructions in RetryList\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/CodeGen/GlobalISel/Legalizer.cpp"
, 217, __PRETTY_FUNCTION__))
;
8
'?' condition is true
218 unsigned NumArtifacts = ArtifactList.size();
219 while (!InstList.empty()) {
9
Assuming the condition is false
10
Loop condition is false. Execution continues on line 248
220 MachineInstr &MI = *InstList.pop_back_val();
221 assert(isPreISelGenericOpcode(MI.getOpcode()) && "Expecting generic opcode")((isPreISelGenericOpcode(MI.getOpcode()) && "Expecting generic opcode"
) ? static_cast<void> (0) : __assert_fail ("isPreISelGenericOpcode(MI.getOpcode()) && \"Expecting generic opcode\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/CodeGen/GlobalISel/Legalizer.cpp"
, 221, __PRETTY_FUNCTION__))
;
222 if (isTriviallyDead(MI, MRI)) {
223 LLVM_DEBUG(dbgs() << MI << "Is dead; erasing.\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("legalizer")) { dbgs() << MI << "Is dead; erasing.\n"
; } } while (false)
;
224 MI.eraseFromParentAndMarkDBGValuesForRemoval();
225 continue;
226 }
227
228 // Do the legalization for this instruction.
229 auto Res = Helper.legalizeInstrStep(MI);
230 // Error out if we couldn't legalize this instruction. We may want to
231 // fall back to DAG ISel instead in the future.
232 if (Res == LegalizerHelper::UnableToLegalize) {
233 // Move illegal artifacts to RetryList instead of aborting because
234 // legalizing InstList may generate artifacts that allow
235 // ArtifactCombiner to combine away them.
236 if (isArtifact(MI)) {
237 RetryList.push_back(&MI);
238 continue;
239 }
240 stopLegalizing(MI);
241 return false;
242 }
243 WorkListObserver.printNewInstrs();
244 Changed |= Res == LegalizerHelper::Legalized;
245 }
246 // Try to combine the instructions in RetryList again if there
247 // are new artifacts. If not, stop legalizing.
248 if (!RetryList.empty()) {
11
Taking false branch
249 if (ArtifactList.size() > NumArtifacts) {
250 while (!RetryList.empty())
251 ArtifactList.insert(RetryList.pop_back_val());
252 } else {
253 MachineInstr *MI = *RetryList.begin();
254 stopLegalizing(*MI);
255 return false;
256 }
257 }
258 while (!ArtifactList.empty()) {
12
Assuming the condition is false
13
Loop condition is false. Execution continues on line 285
259 MachineInstr &MI = *ArtifactList.pop_back_val();
260 assert(isPreISelGenericOpcode(MI.getOpcode()) && "Expecting generic opcode")((isPreISelGenericOpcode(MI.getOpcode()) && "Expecting generic opcode"
) ? static_cast<void> (0) : __assert_fail ("isPreISelGenericOpcode(MI.getOpcode()) && \"Expecting generic opcode\""
, "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/lib/CodeGen/GlobalISel/Legalizer.cpp"
, 260, __PRETTY_FUNCTION__))
;
261 if (isTriviallyDead(MI, MRI)) {
262 LLVM_DEBUG(dbgs() << MI << "Is dead\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("legalizer")) { dbgs() << MI << "Is dead\n"; } }
while (false)
;
263 RemoveDeadInstFromLists(&MI);
264 MI.eraseFromParentAndMarkDBGValuesForRemoval();
265 continue;
266 }
267 SmallVector<MachineInstr *, 4> DeadInstructions;
268 if (ArtCombiner.tryCombineInstruction(MI, DeadInstructions,
269 WrapperObserver)) {
270 WorkListObserver.printNewInstrs();
271 for (auto *DeadMI : DeadInstructions) {
272 LLVM_DEBUG(dbgs() << *DeadMI << "Is dead\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("legalizer")) { dbgs() << *DeadMI << "Is dead\n"
; } } while (false)
;
273 RemoveDeadInstFromLists(DeadMI);
274 DeadMI->eraseFromParentAndMarkDBGValuesForRemoval();
275 }
276 Changed = true;
277 continue;
278 }
279 // If this was not an artifact (that could be combined away), this might
280 // need special handling. Add it to InstList, so when it's processed
281 // there, it has to be legal or specially handled.
282 else
283 InstList.insert(&MI);
284 }
285 } while (!InstList.empty());
14
Assuming the condition is false
286
287 // For now don't support if new blocks are inserted - we would need to fix the
288 // outerloop for that.
289 if (MF.size() != NumBlocks) {
16
Assuming the condition is true
17
Taking true branch
290 MachineOptimizationRemarkMissed R("gisel-legalize", "GISelFailure",
19
Calling constructor for 'MachineOptimizationRemarkMissed'
291 MF.getFunction().getSubprogram(),
292 /*MBB=*/nullptr);
18
Passing null pointer value via 4th parameter 'MBB'
293 R << "inserting blocks is not supported yet";
294 reportGISelFailure(MF, TPC, MORE, R);
295 return false;
296 }
297
298 return Changed;
299}

/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h

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/Analysis/OptimizationRemarkEmitter.h"
19#include "llvm/CodeGen/MachineFunctionPass.h"
20
21namespace llvm {
22class MachineBasicBlock;
23class MachineBlockFrequencyInfo;
24class MachineInstr;
25
26/// Common features for diagnostics dealing with optimization remarks
27/// that are used by machine passes.
28class DiagnosticInfoMIROptimization : public DiagnosticInfoOptimizationBase {
29public:
30 DiagnosticInfoMIROptimization(enum DiagnosticKind Kind, const char *PassName,
31 StringRef RemarkName,
32 const DiagnosticLocation &Loc,
33 const MachineBasicBlock *MBB)
34 : DiagnosticInfoOptimizationBase(Kind, DS_Remark, PassName, RemarkName,
35 MBB->getParent()->getFunction(), Loc),
22
Called C++ object pointer is null
36 MBB(MBB) {}
37
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);
42 };
43
44 static bool classof(const DiagnosticInfo *DI) {
45 return DI->getKind() >= DK_FirstMachineRemark &&
46 DI->getKind() <= DK_LastMachineRemark;
47 }
48
49 const MachineBasicBlock *getBlock() const { return MBB; }
50
51private:
52 const MachineBasicBlock *MBB;
53};
54
55/// Diagnostic information for applied optimization remarks.
56class MachineOptimizationRemark : public DiagnosticInfoMIROptimization {
57public:
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
62 /// operates in.
63 MachineOptimizationRemark(const char *PassName, StringRef RemarkName,
64 const DiagnosticLocation &Loc,
65 const MachineBasicBlock *MBB)
66 : DiagnosticInfoMIROptimization(DK_MachineOptimizationRemark, PassName,
67 RemarkName, Loc, MBB) {}
68
69 static bool classof(const DiagnosticInfo *DI) {
70 return DI->getKind() == DK_MachineOptimizationRemark;
71 }
72
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());
78 }
79};
80
81/// Diagnostic information for missed-optimization remarks.
82class MachineOptimizationRemarkMissed : public DiagnosticInfoMIROptimization {
83public:
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,
21
Calling constructor for 'DiagnosticInfoMIROptimization'
93 PassName, RemarkName, Loc, MBB) {}
20
Passing null pointer value via 5th parameter 'MBB'
94
95 static bool classof(const DiagnosticInfo *DI) {
96 return DI->getKind() == DK_MachineOptimizationRemarkMissed;
97 }
98
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());
104 }
105};
106
107/// Diagnostic information for optimization analysis remarks.
108class MachineOptimizationRemarkAnalysis : public DiagnosticInfoMIROptimization {
109public:
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) {}
120
121 static bool classof(const DiagnosticInfo *DI) {
122 return DI->getKind() == DK_MachineOptimizationRemarkAnalysis;
123 }
124
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());
130 }
131};
132
133/// Extend llvm::ore:: with MI-specific helper names.
134namespace ore {
135using MNV = DiagnosticInfoMIROptimization::MachineArgument;
136}
137
138/// The optimization diagnostic interface.
139///
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.
144class MachineOptimizationRemarkEmitter {
145public:
146 MachineOptimizationRemarkEmitter(MachineFunction &MF,
147 MachineBlockFrequencyInfo *MBFI)
148 : MF(MF), MBFI(MBFI) {}
149
150 /// Emit an optimization remark.
151 void emit(DiagnosticInfoOptimizationBase &OptDiag);
152
153 /// Whether we allow for extra compile-time budget to perform more
154 /// analysis to be more informative.
155 ///
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 {
161 return (
162 MF.getFunction().getContext().getRemarkStreamer() ||
163 MF.getFunction().getContext().getDiagHandlerPtr()->isAnyRemarkEnabled(
164 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 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 if (MF.getFunction().getContext().getRemarkStreamer() ||
176 MF.getFunction()
177 .getContext()
178 .getDiagHandlerPtr()
179 ->isAnyRemarkEnabled()) {
180 auto R = RemarkBuilder();
181 emit((DiagnosticInfoOptimizationBase &)R);
182 }
183 }
184
185private:
186 MachineFunction &MF;
187
188 /// MBFI is only set if hotness is requested.
189 MachineBlockFrequencyInfo *MBFI;
190
191 /// Compute hotness from IR value (currently assumed to be a block) if PGO is
192 /// available.
193 Optional<uint64_t> computeHotness(const MachineBasicBlock &MBB);
194
195 /// Similar but use value from \p OptDiag and update hotness there.
196 void computeHotness(DiagnosticInfoMIROptimization &Remark);
197
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; }
201};
202
203/// The analysis pass
204///
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
207/// could be freed.
208class MachineOptimizationRemarkEmitterPass : public MachineFunctionPass {
209 std::unique_ptr<MachineOptimizationRemarkEmitter> ORE;
210
211public:
212 MachineOptimizationRemarkEmitterPass();
213
214 bool runOnMachineFunction(MachineFunction &MF) override;
215
216 void getAnalysisUsage(AnalysisUsage &AU) const override;
217
218 MachineOptimizationRemarkEmitter &getORE() {
219 assert(ORE && "pass not run yet")((ORE && "pass not run yet") ? static_cast<void>
(0) : __assert_fail ("ORE && \"pass not run yet\"", "/build/llvm-toolchain-snapshot-10~+201911111502510600c19528f1809/llvm/include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
, 219, __PRETTY_FUNCTION__))
;
220 return *ORE;
221 }
222
223 static char ID;
224};
225}
226
227#endif