File: | llvm/include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h |
Warning: | line 35, column 40 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===- llvm/CodeGen/GlobalISel/InstructionSelect.cpp - InstructionSelect ---==// | ||||
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 | /// This file implements the InstructionSelect class. | ||||
10 | //===----------------------------------------------------------------------===// | ||||
11 | |||||
12 | #include "llvm/CodeGen/GlobalISel/InstructionSelect.h" | ||||
13 | #include "llvm/ADT/PostOrderIterator.h" | ||||
14 | #include "llvm/ADT/ScopeExit.h" | ||||
15 | #include "llvm/ADT/Twine.h" | ||||
16 | #include "llvm/Analysis/BlockFrequencyInfo.h" | ||||
17 | #include "llvm/Analysis/LazyBlockFrequencyInfo.h" | ||||
18 | #include "llvm/Analysis/ProfileSummaryInfo.h" | ||||
19 | #include "llvm/CodeGen/GlobalISel/GISelKnownBits.h" | ||||
20 | #include "llvm/CodeGen/GlobalISel/InstructionSelector.h" | ||||
21 | #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" | ||||
22 | #include "llvm/CodeGen/GlobalISel/Utils.h" | ||||
23 | #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" | ||||
24 | #include "llvm/CodeGen/MachineFrameInfo.h" | ||||
25 | #include "llvm/CodeGen/MachineRegisterInfo.h" | ||||
26 | #include "llvm/CodeGen/TargetInstrInfo.h" | ||||
27 | #include "llvm/CodeGen/TargetLowering.h" | ||||
28 | #include "llvm/CodeGen/TargetPassConfig.h" | ||||
29 | #include "llvm/CodeGen/TargetSubtargetInfo.h" | ||||
30 | #include "llvm/Config/config.h" | ||||
31 | #include "llvm/IR/Constants.h" | ||||
32 | #include "llvm/IR/Function.h" | ||||
33 | #include "llvm/Support/CommandLine.h" | ||||
34 | #include "llvm/Support/Debug.h" | ||||
35 | #include "llvm/Support/TargetRegistry.h" | ||||
36 | #include "llvm/Target/TargetMachine.h" | ||||
37 | |||||
38 | #define DEBUG_TYPE"instruction-select" "instruction-select" | ||||
39 | |||||
40 | using namespace llvm; | ||||
41 | |||||
42 | #ifdef LLVM_GISEL_COV_PREFIX | ||||
43 | static cl::opt<std::string> | ||||
44 | CoveragePrefix("gisel-coverage-prefix", cl::init(LLVM_GISEL_COV_PREFIX), | ||||
45 | cl::desc("Record GlobalISel rule coverage files of this " | ||||
46 | "prefix if instrumentation was generated")); | ||||
47 | #else | ||||
48 | static const std::string CoveragePrefix; | ||||
49 | #endif | ||||
50 | |||||
51 | char InstructionSelect::ID = 0; | ||||
52 | INITIALIZE_PASS_BEGIN(InstructionSelect, DEBUG_TYPE,static void *initializeInstructionSelectPassOnce(PassRegistry &Registry) { | ||||
53 | "Select target instructions out of generic instructions",static void *initializeInstructionSelectPassOnce(PassRegistry &Registry) { | ||||
54 | false, false)static void *initializeInstructionSelectPassOnce(PassRegistry &Registry) { | ||||
55 | INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)initializeTargetPassConfigPass(Registry); | ||||
56 | INITIALIZE_PASS_DEPENDENCY(GISelKnownBitsAnalysis)initializeGISelKnownBitsAnalysisPass(Registry); | ||||
57 | INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass)initializeProfileSummaryInfoWrapperPassPass(Registry); | ||||
58 | INITIALIZE_PASS_DEPENDENCY(LazyBlockFrequencyInfoPass)initializeLazyBlockFrequencyInfoPassPass(Registry); | ||||
59 | INITIALIZE_PASS_END(InstructionSelect, DEBUG_TYPE,PassInfo *PI = new PassInfo( "Select target instructions out of generic instructions" , "instruction-select", &InstructionSelect::ID, PassInfo:: NormalCtor_t(callDefaultCtor<InstructionSelect>), false , false); Registry.registerPass(*PI, true); return PI; } static llvm::once_flag InitializeInstructionSelectPassFlag; void llvm ::initializeInstructionSelectPass(PassRegistry &Registry) { llvm::call_once(InitializeInstructionSelectPassFlag, initializeInstructionSelectPassOnce , std::ref(Registry)); } | ||||
60 | "Select target instructions out of generic instructions",PassInfo *PI = new PassInfo( "Select target instructions out of generic instructions" , "instruction-select", &InstructionSelect::ID, PassInfo:: NormalCtor_t(callDefaultCtor<InstructionSelect>), false , false); Registry.registerPass(*PI, true); return PI; } static llvm::once_flag InitializeInstructionSelectPassFlag; void llvm ::initializeInstructionSelectPass(PassRegistry &Registry) { llvm::call_once(InitializeInstructionSelectPassFlag, initializeInstructionSelectPassOnce , std::ref(Registry)); } | ||||
61 | false, false)PassInfo *PI = new PassInfo( "Select target instructions out of generic instructions" , "instruction-select", &InstructionSelect::ID, PassInfo:: NormalCtor_t(callDefaultCtor<InstructionSelect>), false , false); Registry.registerPass(*PI, true); return PI; } static llvm::once_flag InitializeInstructionSelectPassFlag; void llvm ::initializeInstructionSelectPass(PassRegistry &Registry) { llvm::call_once(InitializeInstructionSelectPassFlag, initializeInstructionSelectPassOnce , std::ref(Registry)); } | ||||
62 | |||||
63 | InstructionSelect::InstructionSelect(CodeGenOpt::Level OL) | ||||
64 | : MachineFunctionPass(ID), OptLevel(OL) {} | ||||
65 | |||||
66 | // In order not to crash when calling getAnalysis during testing with -run-pass | ||||
67 | // we use the default opt level here instead of None, so that the addRequired() | ||||
68 | // calls are made in getAnalysisUsage(). | ||||
69 | InstructionSelect::InstructionSelect() | ||||
70 | : MachineFunctionPass(ID), OptLevel(CodeGenOpt::Default) {} | ||||
71 | |||||
72 | void InstructionSelect::getAnalysisUsage(AnalysisUsage &AU) const { | ||||
73 | AU.addRequired<TargetPassConfig>(); | ||||
74 | if (OptLevel != CodeGenOpt::None) { | ||||
75 | AU.addRequired<GISelKnownBitsAnalysis>(); | ||||
76 | AU.addPreserved<GISelKnownBitsAnalysis>(); | ||||
77 | AU.addRequired<ProfileSummaryInfoWrapperPass>(); | ||||
78 | LazyBlockFrequencyInfoPass::getLazyBFIAnalysisUsage(AU); | ||||
79 | } | ||||
80 | getSelectionDAGFallbackAnalysisUsage(AU); | ||||
81 | MachineFunctionPass::getAnalysisUsage(AU); | ||||
82 | } | ||||
83 | |||||
84 | bool InstructionSelect::runOnMachineFunction(MachineFunction &MF) { | ||||
85 | // If the ISel pipeline failed, do not bother running that pass. | ||||
86 | if (MF.getProperties().hasProperty( | ||||
87 | MachineFunctionProperties::Property::FailedISel)) | ||||
88 | return false; | ||||
89 | |||||
90 | LLVM_DEBUG(dbgs() << "Selecting function: " << MF.getName() << '\n')do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("instruction-select")) { dbgs() << "Selecting function: " << MF.getName() << '\n'; } } while (false); | ||||
| |||||
91 | |||||
92 | const TargetPassConfig &TPC = getAnalysis<TargetPassConfig>(); | ||||
93 | InstructionSelector *ISel = MF.getSubtarget().getInstructionSelector(); | ||||
94 | |||||
95 | CodeGenOpt::Level OldOptLevel = OptLevel; | ||||
96 | auto RestoreOptLevel = make_scope_exit([=]() { OptLevel = OldOptLevel; }); | ||||
97 | OptLevel = MF.getFunction().hasOptNone() ? CodeGenOpt::None | ||||
98 | : MF.getTarget().getOptLevel(); | ||||
99 | |||||
100 | GISelKnownBits *KB = nullptr; | ||||
101 | if (OptLevel
| ||||
102 | KB = &getAnalysis<GISelKnownBitsAnalysis>().get(MF); | ||||
103 | PSI = &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI(); | ||||
104 | if (PSI && PSI->hasProfileSummary()) | ||||
105 | BFI = &getAnalysis<LazyBlockFrequencyInfoPass>().getBFI(); | ||||
106 | } | ||||
107 | |||||
108 | CodeGenCoverage CoverageInfo; | ||||
109 | assert(ISel && "Cannot work without InstructionSelector")(static_cast <bool> (ISel && "Cannot work without InstructionSelector" ) ? void (0) : __assert_fail ("ISel && \"Cannot work without InstructionSelector\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp" , 109, __extension__ __PRETTY_FUNCTION__)); | ||||
110 | ISel->setupMF(MF, KB, CoverageInfo, PSI, BFI); | ||||
111 | |||||
112 | // An optimization remark emitter. Used to report failures. | ||||
113 | MachineOptimizationRemarkEmitter MORE(MF, /*MBFI=*/nullptr); | ||||
114 | |||||
115 | // FIXME: There are many other MF/MFI fields we need to initialize. | ||||
116 | |||||
117 | MachineRegisterInfo &MRI = MF.getRegInfo(); | ||||
118 | #ifndef NDEBUG | ||||
119 | // Check that our input is fully legal: we require the function to have the | ||||
120 | // Legalized property, so it should be. | ||||
121 | // FIXME: This should be in the MachineVerifier, as the RegBankSelected | ||||
122 | // property check already is. | ||||
123 | if (!DisableGISelLegalityCheck) | ||||
124 | if (const MachineInstr *MI = machineFunctionIsIllegal(MF)) { | ||||
125 | reportGISelFailure(MF, TPC, MORE, "gisel-select", | ||||
126 | "instruction is not legal", *MI); | ||||
127 | return false; | ||||
128 | } | ||||
129 | // FIXME: We could introduce new blocks and will need to fix the outer loop. | ||||
130 | // Until then, keep track of the number of blocks to assert that we don't. | ||||
131 | const size_t NumBlocks = MF.size(); | ||||
132 | #endif | ||||
133 | |||||
134 | for (MachineBasicBlock *MBB : post_order(&MF)) { | ||||
135 | ISel->CurMBB = MBB; | ||||
136 | if (MBB->empty()) | ||||
137 | continue; | ||||
138 | |||||
139 | // Select instructions in reverse block order. We permit erasing so have | ||||
140 | // to resort to manually iterating and recognizing the begin (rend) case. | ||||
141 | bool ReachedBegin = false; | ||||
142 | for (auto MII = std::prev(MBB->end()), Begin = MBB->begin(); | ||||
143 | !ReachedBegin;) { | ||||
144 | #ifndef NDEBUG | ||||
145 | // Keep track of the insertion range for debug printing. | ||||
146 | const auto AfterIt = std::next(MII); | ||||
147 | #endif | ||||
148 | // Select this instruction. | ||||
149 | MachineInstr &MI = *MII; | ||||
150 | |||||
151 | // And have our iterator point to the next instruction, if there is one. | ||||
152 | if (MII == Begin) | ||||
153 | ReachedBegin = true; | ||||
154 | else | ||||
155 | --MII; | ||||
156 | |||||
157 | LLVM_DEBUG(dbgs() << "Selecting: \n " << MI)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("instruction-select")) { dbgs() << "Selecting: \n " << MI; } } while (false); | ||||
158 | |||||
159 | // We could have folded this instruction away already, making it dead. | ||||
160 | // If so, erase it. | ||||
161 | if (isTriviallyDead(MI, MRI)) { | ||||
162 | LLVM_DEBUG(dbgs() << "Is dead; erasing.\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("instruction-select")) { dbgs() << "Is dead; erasing.\n" ; } } while (false); | ||||
163 | MI.eraseFromParentAndMarkDBGValuesForRemoval(); | ||||
164 | continue; | ||||
165 | } | ||||
166 | |||||
167 | // Eliminate hints. | ||||
168 | if (isPreISelGenericOptimizationHint(MI.getOpcode())) { | ||||
169 | Register DstReg = MI.getOperand(0).getReg(); | ||||
170 | Register SrcReg = MI.getOperand(1).getReg(); | ||||
171 | |||||
172 | // At this point, the destination register class of the hint may have | ||||
173 | // been decided. | ||||
174 | // | ||||
175 | // Propagate that through to the source register. | ||||
176 | const TargetRegisterClass *DstRC = MRI.getRegClassOrNull(DstReg); | ||||
177 | if (DstRC) | ||||
178 | MRI.setRegClass(SrcReg, DstRC); | ||||
179 | assert(canReplaceReg(DstReg, SrcReg, MRI) &&(static_cast <bool> (canReplaceReg(DstReg, SrcReg, MRI) && "Must be able to replace dst with src!") ? void ( 0) : __assert_fail ("canReplaceReg(DstReg, SrcReg, MRI) && \"Must be able to replace dst with src!\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp" , 180, __extension__ __PRETTY_FUNCTION__)) | ||||
180 | "Must be able to replace dst with src!")(static_cast <bool> (canReplaceReg(DstReg, SrcReg, MRI) && "Must be able to replace dst with src!") ? void ( 0) : __assert_fail ("canReplaceReg(DstReg, SrcReg, MRI) && \"Must be able to replace dst with src!\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp" , 180, __extension__ __PRETTY_FUNCTION__)); | ||||
181 | MI.eraseFromParent(); | ||||
182 | MRI.replaceRegWith(DstReg, SrcReg); | ||||
183 | continue; | ||||
184 | } | ||||
185 | |||||
186 | if (!ISel->select(MI)) { | ||||
187 | // FIXME: It would be nice to dump all inserted instructions. It's | ||||
188 | // not obvious how, esp. considering select() can insert after MI. | ||||
189 | reportGISelFailure(MF, TPC, MORE, "gisel-select", "cannot select", MI); | ||||
190 | return false; | ||||
191 | } | ||||
192 | |||||
193 | // Dump the range of instructions that MI expanded into. | ||||
194 | LLVM_DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("instruction-select")) { { auto InsertedBegin = ReachedBegin ? MBB->begin() : std::next(MII); dbgs() << "Into:\n" ; for (auto &InsertedMI : make_range(InsertedBegin, AfterIt )) dbgs() << " " << InsertedMI; dbgs() << '\n' ; }; } } while (false) | ||||
195 | auto InsertedBegin = ReachedBegin ? MBB->begin() : std::next(MII);do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("instruction-select")) { { auto InsertedBegin = ReachedBegin ? MBB->begin() : std::next(MII); dbgs() << "Into:\n" ; for (auto &InsertedMI : make_range(InsertedBegin, AfterIt )) dbgs() << " " << InsertedMI; dbgs() << '\n' ; }; } } while (false) | ||||
196 | dbgs() << "Into:\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("instruction-select")) { { auto InsertedBegin = ReachedBegin ? MBB->begin() : std::next(MII); dbgs() << "Into:\n" ; for (auto &InsertedMI : make_range(InsertedBegin, AfterIt )) dbgs() << " " << InsertedMI; dbgs() << '\n' ; }; } } while (false) | ||||
197 | for (auto &InsertedMI : make_range(InsertedBegin, AfterIt))do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("instruction-select")) { { auto InsertedBegin = ReachedBegin ? MBB->begin() : std::next(MII); dbgs() << "Into:\n" ; for (auto &InsertedMI : make_range(InsertedBegin, AfterIt )) dbgs() << " " << InsertedMI; dbgs() << '\n' ; }; } } while (false) | ||||
198 | dbgs() << " " << InsertedMI;do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("instruction-select")) { { auto InsertedBegin = ReachedBegin ? MBB->begin() : std::next(MII); dbgs() << "Into:\n" ; for (auto &InsertedMI : make_range(InsertedBegin, AfterIt )) dbgs() << " " << InsertedMI; dbgs() << '\n' ; }; } } while (false) | ||||
199 | dbgs() << '\n';do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("instruction-select")) { { auto InsertedBegin = ReachedBegin ? MBB->begin() : std::next(MII); dbgs() << "Into:\n" ; for (auto &InsertedMI : make_range(InsertedBegin, AfterIt )) dbgs() << " " << InsertedMI; dbgs() << '\n' ; }; } } while (false) | ||||
200 | })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("instruction-select")) { { auto InsertedBegin = ReachedBegin ? MBB->begin() : std::next(MII); dbgs() << "Into:\n" ; for (auto &InsertedMI : make_range(InsertedBegin, AfterIt )) dbgs() << " " << InsertedMI; dbgs() << '\n' ; }; } } while (false); | ||||
201 | } | ||||
202 | } | ||||
203 | |||||
204 | for (MachineBasicBlock &MBB : MF) { | ||||
205 | if (MBB.empty()) | ||||
206 | continue; | ||||
207 | |||||
208 | // Try to find redundant copies b/w vregs of the same register class. | ||||
209 | bool ReachedBegin = false; | ||||
210 | for (auto MII = std::prev(MBB.end()), Begin = MBB.begin(); !ReachedBegin;) { | ||||
211 | // Select this instruction. | ||||
212 | MachineInstr &MI = *MII; | ||||
213 | |||||
214 | // And have our iterator point to the next instruction, if there is one. | ||||
215 | if (MII == Begin) | ||||
216 | ReachedBegin = true; | ||||
217 | else | ||||
218 | --MII; | ||||
219 | if (MI.getOpcode() != TargetOpcode::COPY) | ||||
220 | continue; | ||||
221 | Register SrcReg = MI.getOperand(1).getReg(); | ||||
222 | Register DstReg = MI.getOperand(0).getReg(); | ||||
223 | if (Register::isVirtualRegister(SrcReg) && | ||||
224 | Register::isVirtualRegister(DstReg)) { | ||||
225 | auto SrcRC = MRI.getRegClass(SrcReg); | ||||
226 | auto DstRC = MRI.getRegClass(DstReg); | ||||
227 | if (SrcRC == DstRC) { | ||||
228 | MRI.replaceRegWith(DstReg, SrcReg); | ||||
229 | MI.eraseFromParent(); | ||||
230 | } | ||||
231 | } | ||||
232 | } | ||||
233 | } | ||||
234 | |||||
235 | #ifndef NDEBUG | ||||
236 | const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo(); | ||||
237 | // Now that selection is complete, there are no more generic vregs. Verify | ||||
238 | // that the size of the now-constrained vreg is unchanged and that it has a | ||||
239 | // register class. | ||||
240 | for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) { | ||||
241 | unsigned VReg = Register::index2VirtReg(I); | ||||
242 | |||||
243 | MachineInstr *MI = nullptr; | ||||
244 | if (!MRI.def_empty(VReg)) | ||||
245 | MI = &*MRI.def_instr_begin(VReg); | ||||
246 | else if (!MRI.use_empty(VReg)) | ||||
247 | MI = &*MRI.use_instr_begin(VReg); | ||||
248 | if (!MI) | ||||
249 | continue; | ||||
250 | |||||
251 | const TargetRegisterClass *RC = MRI.getRegClassOrNull(VReg); | ||||
252 | if (!RC) { | ||||
253 | reportGISelFailure(MF, TPC, MORE, "gisel-select", | ||||
254 | "VReg has no regclass after selection", *MI); | ||||
255 | return false; | ||||
256 | } | ||||
257 | |||||
258 | const LLT Ty = MRI.getType(VReg); | ||||
259 | if (Ty.isValid() && Ty.getSizeInBits() > TRI.getRegSizeInBits(*RC)) { | ||||
260 | reportGISelFailure( | ||||
261 | MF, TPC, MORE, "gisel-select", | ||||
262 | "VReg's low-level type and register class have different sizes", *MI); | ||||
263 | return false; | ||||
264 | } | ||||
265 | } | ||||
266 | |||||
267 | if (MF.size() != NumBlocks) { | ||||
268 | MachineOptimizationRemarkMissed R("gisel-select", "GISelFailure", | ||||
269 | MF.getFunction().getSubprogram(), | ||||
270 | /*MBB=*/nullptr); | ||||
271 | R << "inserting blocks is not supported yet"; | ||||
272 | reportGISelFailure(MF, TPC, MORE, R); | ||||
273 | return false; | ||||
274 | } | ||||
275 | #endif | ||||
276 | // Determine if there are any calls in this machine function. Ported from | ||||
277 | // SelectionDAG. | ||||
278 | MachineFrameInfo &MFI = MF.getFrameInfo(); | ||||
279 | for (const auto &MBB : MF) { | ||||
280 | if (MFI.hasCalls() && MF.hasInlineAsm()) | ||||
281 | break; | ||||
282 | |||||
283 | for (const auto &MI : MBB) { | ||||
284 | if ((MI.isCall() && !MI.isReturn()) || MI.isStackAligningInlineAsm()) | ||||
285 | MFI.setHasCalls(true); | ||||
286 | if (MI.isInlineAsm()) | ||||
287 | MF.setHasInlineAsm(true); | ||||
288 | } | ||||
289 | } | ||||
290 | |||||
291 | // FIXME: FinalizeISel pass calls finalizeLowering, so it's called twice. | ||||
292 | auto &TLI = *MF.getSubtarget().getTargetLowering(); | ||||
293 | TLI.finalizeLowering(MF); | ||||
294 | |||||
295 | LLVM_DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("instruction-select")) { { dbgs() << "Rules covered by selecting function: " << MF.getName() << ":"; for (auto RuleID : CoverageInfo .covered()) dbgs() << " id" << RuleID; dbgs() << "\n\n"; }; } } while (false) | ||||
296 | dbgs() << "Rules covered by selecting function: " << MF.getName() << ":";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("instruction-select")) { { dbgs() << "Rules covered by selecting function: " << MF.getName() << ":"; for (auto RuleID : CoverageInfo .covered()) dbgs() << " id" << RuleID; dbgs() << "\n\n"; }; } } while (false) | ||||
297 | for (auto RuleID : CoverageInfo.covered())do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("instruction-select")) { { dbgs() << "Rules covered by selecting function: " << MF.getName() << ":"; for (auto RuleID : CoverageInfo .covered()) dbgs() << " id" << RuleID; dbgs() << "\n\n"; }; } } while (false) | ||||
298 | dbgs() << " id" << RuleID;do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("instruction-select")) { { dbgs() << "Rules covered by selecting function: " << MF.getName() << ":"; for (auto RuleID : CoverageInfo .covered()) dbgs() << " id" << RuleID; dbgs() << "\n\n"; }; } } while (false) | ||||
299 | dbgs() << "\n\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("instruction-select")) { { dbgs() << "Rules covered by selecting function: " << MF.getName() << ":"; for (auto RuleID : CoverageInfo .covered()) dbgs() << " id" << RuleID; dbgs() << "\n\n"; }; } } while (false) | ||||
300 | })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("instruction-select")) { { dbgs() << "Rules covered by selecting function: " << MF.getName() << ":"; for (auto RuleID : CoverageInfo .covered()) dbgs() << " id" << RuleID; dbgs() << "\n\n"; }; } } while (false); | ||||
301 | CoverageInfo.emit(CoveragePrefix, | ||||
302 | TLI.getTargetMachine().getTarget().getBackendName()); | ||||
303 | |||||
304 | // If we successfully selected the function nothing is going to use the vreg | ||||
305 | // types after us (otherwise MIRPrinter would need them). Make sure the types | ||||
306 | // disappear. | ||||
307 | MRI.clearVirtRegTypes(); | ||||
308 | |||||
309 | // FIXME: Should we accurately track changes? | ||||
310 | return true; | ||||
311 | } |
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 | ||||
21 | namespace llvm { | |||
22 | class MachineBasicBlock; | |||
23 | class MachineBlockFrequencyInfo; | |||
24 | class MachineInstr; | |||
25 | ||||
26 | /// Common features for diagnostics dealing with optimization remarks | |||
27 | /// that are used by machine passes. | |||
28 | class DiagnosticInfoMIROptimization : public DiagnosticInfoOptimizationBase { | |||
29 | public: | |||
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), | |||
| ||||
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 | ||||
51 | private: | |||
52 | const MachineBasicBlock *MBB; | |||
53 | }; | |||
54 | ||||
55 | /// Diagnostic information for applied optimization remarks. | |||
56 | class MachineOptimizationRemark : public DiagnosticInfoMIROptimization { | |||
57 | public: | |||
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. | |||
82 | class MachineOptimizationRemarkMissed : public DiagnosticInfoMIROptimization { | |||
83 | public: | |||
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) {} | |||
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. | |||
108 | class MachineOptimizationRemarkAnalysis : public DiagnosticInfoMIROptimization { | |||
109 | public: | |||
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 | MachineOptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName, | |||
122 | const MachineInstr *MI) | |||
123 | : DiagnosticInfoMIROptimization(DK_MachineOptimizationRemarkAnalysis, | |||
124 | PassName, RemarkName, MI->getDebugLoc(), | |||
125 | MI->getParent()) {} | |||
126 | ||||
127 | static bool classof(const DiagnosticInfo *DI) { | |||
128 | return DI->getKind() == DK_MachineOptimizationRemarkAnalysis; | |||
129 | } | |||
130 | ||||
131 | /// \see DiagnosticInfoOptimizationBase::isEnabled. | |||
132 | bool isEnabled() const override { | |||
133 | const Function &Fn = getFunction(); | |||
134 | LLVMContext &Ctx = Fn.getContext(); | |||
135 | return Ctx.getDiagHandlerPtr()->isAnalysisRemarkEnabled(getPassName()); | |||
136 | } | |||
137 | }; | |||
138 | ||||
139 | /// Extend llvm::ore:: with MI-specific helper names. | |||
140 | namespace ore { | |||
141 | using MNV = DiagnosticInfoMIROptimization::MachineArgument; | |||
142 | } | |||
143 | ||||
144 | /// The optimization diagnostic interface. | |||
145 | /// | |||
146 | /// It allows reporting when optimizations are performed and when they are not | |||
147 | /// along with the reasons for it. Hotness information of the corresponding | |||
148 | /// code region can be included in the remark if DiagnosticsHotnessRequested is | |||
149 | /// enabled in the LLVM context. | |||
150 | class MachineOptimizationRemarkEmitter { | |||
151 | public: | |||
152 | MachineOptimizationRemarkEmitter(MachineFunction &MF, | |||
153 | MachineBlockFrequencyInfo *MBFI) | |||
154 | : MF(MF), MBFI(MBFI) {} | |||
155 | ||||
156 | /// Emit an optimization remark. | |||
157 | void emit(DiagnosticInfoOptimizationBase &OptDiag); | |||
158 | ||||
159 | /// Whether we allow for extra compile-time budget to perform more | |||
160 | /// analysis to be more informative. | |||
161 | /// | |||
162 | /// This is useful to enable additional missed optimizations to be reported | |||
163 | /// that are normally too noisy. In this mode, we can use the extra analysis | |||
164 | /// (1) to filter trivial false positives or (2) to provide more context so | |||
165 | /// that non-trivial false positives can be quickly detected by the user. | |||
166 | bool allowExtraAnalysis(StringRef PassName) const { | |||
167 | return ( | |||
168 | MF.getFunction().getContext().getLLVMRemarkStreamer() || | |||
169 | MF.getFunction().getContext().getDiagHandlerPtr()->isAnyRemarkEnabled( | |||
170 | PassName)); | |||
171 | } | |||
172 | ||||
173 | /// Take a lambda that returns a remark which will be emitted. Second | |||
174 | /// argument is only used to restrict this to functions. | |||
175 | template <typename T> | |||
176 | void emit(T RemarkBuilder, decltype(RemarkBuilder()) * = nullptr) { | |||
177 | // Avoid building the remark unless we know there are at least *some* | |||
178 | // remarks enabled. We can't currently check whether remarks are requested | |||
179 | // for the calling pass since that requires actually building the remark. | |||
180 | ||||
181 | if (MF.getFunction().getContext().getLLVMRemarkStreamer() || | |||
182 | MF.getFunction() | |||
183 | .getContext() | |||
184 | .getDiagHandlerPtr() | |||
185 | ->isAnyRemarkEnabled()) { | |||
186 | auto R = RemarkBuilder(); | |||
187 | emit((DiagnosticInfoOptimizationBase &)R); | |||
188 | } | |||
189 | } | |||
190 | ||||
191 | MachineBlockFrequencyInfo *getBFI() { | |||
192 | return MBFI; | |||
193 | } | |||
194 | ||||
195 | private: | |||
196 | MachineFunction &MF; | |||
197 | ||||
198 | /// MBFI is only set if hotness is requested. | |||
199 | MachineBlockFrequencyInfo *MBFI; | |||
200 | ||||
201 | /// Compute hotness from IR value (currently assumed to be a block) if PGO is | |||
202 | /// available. | |||
203 | Optional<uint64_t> computeHotness(const MachineBasicBlock &MBB); | |||
204 | ||||
205 | /// Similar but use value from \p OptDiag and update hotness there. | |||
206 | void computeHotness(DiagnosticInfoMIROptimization &Remark); | |||
207 | ||||
208 | /// Only allow verbose messages if we know we're filtering by hotness | |||
209 | /// (BFI is only set in this case). | |||
210 | bool shouldEmitVerbose() { return MBFI != nullptr; } | |||
211 | }; | |||
212 | ||||
213 | /// The analysis pass | |||
214 | /// | |||
215 | /// Note that this pass shouldn't generally be marked as preserved by other | |||
216 | /// passes. It's holding onto BFI, so if the pass does not preserve BFI, BFI | |||
217 | /// could be freed. | |||
218 | class MachineOptimizationRemarkEmitterPass : public MachineFunctionPass { | |||
219 | std::unique_ptr<MachineOptimizationRemarkEmitter> ORE; | |||
220 | ||||
221 | public: | |||
222 | MachineOptimizationRemarkEmitterPass(); | |||
223 | ||||
224 | bool runOnMachineFunction(MachineFunction &MF) override; | |||
225 | ||||
226 | void getAnalysisUsage(AnalysisUsage &AU) const override; | |||
227 | ||||
228 | MachineOptimizationRemarkEmitter &getORE() { | |||
229 | assert(ORE && "pass not run yet")(static_cast <bool> (ORE && "pass not run yet") ? void (0) : __assert_fail ("ORE && \"pass not run yet\"" , "/build/llvm-toolchain-snapshot-14~++20210828111110+16086d47c0d0/llvm/include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h" , 229, __extension__ __PRETTY_FUNCTION__)); | |||
230 | return *ORE; | |||
231 | } | |||
232 | ||||
233 | static char ID; | |||
234 | }; | |||
235 | } | |||
236 | ||||
237 | #endif |