Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 1 | //===- llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h --------*- 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 | // |
||
9 | /// \file This file declares the API for the instruction selector. |
||
10 | /// This class is responsible for selecting machine instructions. |
||
11 | /// It's implemented by the target. It's used by the InstructionSelect pass. |
||
12 | // |
||
13 | //===----------------------------------------------------------------------===// |
||
14 | |||
15 | #ifndef LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTORIMPL_H |
||
16 | #define LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTORIMPL_H |
||
17 | |||
18 | #include "llvm/ADT/SmallVector.h" |
||
19 | #include "llvm/CodeGen/GlobalISel/InstructionSelector.h" |
||
20 | #include "llvm/CodeGen/GlobalISel/Utils.h" |
||
21 | #include "llvm/CodeGen/MachineInstrBuilder.h" |
||
22 | #include "llvm/CodeGen/MachineOperand.h" |
||
23 | #include "llvm/CodeGen/MachineRegisterInfo.h" |
||
24 | #include "llvm/CodeGen/RegisterBankInfo.h" |
||
25 | #include "llvm/CodeGen/TargetInstrInfo.h" |
||
26 | #include "llvm/CodeGen/TargetOpcodes.h" |
||
27 | #include "llvm/CodeGen/TargetRegisterInfo.h" |
||
28 | #include "llvm/IR/Constants.h" |
||
29 | #include "llvm/IR/DataLayout.h" |
||
30 | #include "llvm/Support/CodeGenCoverage.h" |
||
31 | #include "llvm/Support/Debug.h" |
||
32 | #include "llvm/Support/ErrorHandling.h" |
||
33 | #include "llvm/Support/raw_ostream.h" |
||
34 | #include <cassert> |
||
35 | #include <cstddef> |
||
36 | #include <cstdint> |
||
37 | |||
38 | namespace llvm { |
||
39 | |||
40 | /// GlobalISel PatFrag Predicates |
||
41 | enum { |
||
42 | GIPFP_I64_Invalid = 0, |
||
43 | GIPFP_APInt_Invalid = 0, |
||
44 | GIPFP_APFloat_Invalid = 0, |
||
45 | GIPFP_MI_Invalid = 0, |
||
46 | }; |
||
47 | |||
48 | template <class TgtInstructionSelector, class PredicateBitset, |
||
49 | class ComplexMatcherMemFn, class CustomRendererFn> |
||
50 | bool InstructionSelector::executeMatchTable( |
||
51 | TgtInstructionSelector &ISel, NewMIVector &OutMIs, MatcherState &State, |
||
52 | const ISelInfoTy<PredicateBitset, ComplexMatcherMemFn, CustomRendererFn> |
||
53 | &ISelInfo, |
||
54 | const int64_t *MatchTable, const TargetInstrInfo &TII, |
||
55 | MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, |
||
56 | const RegisterBankInfo &RBI, const PredicateBitset &AvailableFeatures, |
||
57 | CodeGenCoverage &CoverageInfo) const { |
||
58 | |||
59 | uint64_t CurrentIdx = 0; |
||
60 | SmallVector<uint64_t, 4> OnFailResumeAt; |
||
61 | |||
62 | // Bypass the flag check on the instruction, and only look at the MCInstrDesc. |
||
63 | bool NoFPException = !State.MIs[0]->getDesc().mayRaiseFPException(); |
||
64 | |||
65 | const uint16_t Flags = State.MIs[0]->getFlags(); |
||
66 | |||
67 | enum RejectAction { RejectAndGiveUp, RejectAndResume }; |
||
68 | auto handleReject = [&]() -> RejectAction { |
||
69 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
70 | dbgs() << CurrentIdx << ": Rejected\n"); |
||
71 | if (OnFailResumeAt.empty()) |
||
72 | return RejectAndGiveUp; |
||
73 | CurrentIdx = OnFailResumeAt.pop_back_val(); |
||
74 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
75 | dbgs() << CurrentIdx << ": Resume at " << CurrentIdx << " (" |
||
76 | << OnFailResumeAt.size() << " try-blocks remain)\n"); |
||
77 | return RejectAndResume; |
||
78 | }; |
||
79 | |||
80 | auto propagateFlags = [=](NewMIVector &OutMIs) { |
||
81 | for (auto MIB : OutMIs) { |
||
82 | // Set the NoFPExcept flag when no original matched instruction could |
||
83 | // raise an FP exception, but the new instruction potentially might. |
||
84 | uint16_t MIBFlags = Flags; |
||
85 | if (NoFPException && MIB->mayRaiseFPException()) |
||
86 | MIBFlags |= MachineInstr::NoFPExcept; |
||
87 | MIB.setMIFlags(MIBFlags); |
||
88 | } |
||
89 | |||
90 | return true; |
||
91 | }; |
||
92 | |||
93 | while (true) { |
||
94 | assert(CurrentIdx != ~0u && "Invalid MatchTable index"); |
||
95 | int64_t MatcherOpcode = MatchTable[CurrentIdx++]; |
||
96 | switch (MatcherOpcode) { |
||
97 | case GIM_Try: { |
||
98 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
99 | dbgs() << CurrentIdx << ": Begin try-block\n"); |
||
100 | OnFailResumeAt.push_back(MatchTable[CurrentIdx++]); |
||
101 | break; |
||
102 | } |
||
103 | |||
104 | case GIM_RecordInsn: { |
||
105 | int64_t NewInsnID = MatchTable[CurrentIdx++]; |
||
106 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
107 | int64_t OpIdx = MatchTable[CurrentIdx++]; |
||
108 | |||
109 | // As an optimisation we require that MIs[0] is always the root. Refuse |
||
110 | // any attempt to modify it. |
||
111 | assert(NewInsnID != 0 && "Refusing to modify MIs[0]"); |
||
112 | |||
113 | MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx); |
||
114 | if (!MO.isReg()) { |
||
115 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
116 | dbgs() << CurrentIdx << ": Not a register\n"); |
||
117 | if (handleReject() == RejectAndGiveUp) |
||
118 | return false; |
||
119 | break; |
||
120 | } |
||
121 | if (MO.getReg().isPhysical()) { |
||
122 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
123 | dbgs() << CurrentIdx << ": Is a physical register\n"); |
||
124 | if (handleReject() == RejectAndGiveUp) |
||
125 | return false; |
||
126 | break; |
||
127 | } |
||
128 | |||
129 | MachineInstr *NewMI = MRI.getVRegDef(MO.getReg()); |
||
130 | if ((size_t)NewInsnID < State.MIs.size()) |
||
131 | State.MIs[NewInsnID] = NewMI; |
||
132 | else { |
||
133 | assert((size_t)NewInsnID == State.MIs.size() && |
||
134 | "Expected to store MIs in order"); |
||
135 | State.MIs.push_back(NewMI); |
||
136 | } |
||
137 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
138 | dbgs() << CurrentIdx << ": MIs[" << NewInsnID |
||
139 | << "] = GIM_RecordInsn(" << InsnID << ", " << OpIdx |
||
140 | << ")\n"); |
||
141 | break; |
||
142 | } |
||
143 | |||
144 | case GIM_CheckFeatures: { |
||
145 | int64_t ExpectedBitsetID = MatchTable[CurrentIdx++]; |
||
146 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
147 | dbgs() << CurrentIdx |
||
148 | << ": GIM_CheckFeatures(ExpectedBitsetID=" |
||
149 | << ExpectedBitsetID << ")\n"); |
||
150 | if ((AvailableFeatures & ISelInfo.FeatureBitsets[ExpectedBitsetID]) != |
||
151 | ISelInfo.FeatureBitsets[ExpectedBitsetID]) { |
||
152 | if (handleReject() == RejectAndGiveUp) |
||
153 | return false; |
||
154 | } |
||
155 | break; |
||
156 | } |
||
157 | |||
158 | case GIM_CheckOpcode: |
||
159 | case GIM_CheckOpcodeIsEither: { |
||
160 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
161 | int64_t Expected0 = MatchTable[CurrentIdx++]; |
||
162 | int64_t Expected1 = -1; |
||
163 | if (MatcherOpcode == GIM_CheckOpcodeIsEither) |
||
164 | Expected1 = MatchTable[CurrentIdx++]; |
||
165 | |||
166 | assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); |
||
167 | unsigned Opcode = State.MIs[InsnID]->getOpcode(); |
||
168 | |||
169 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
170 | dbgs() << CurrentIdx << ": GIM_CheckOpcode(MIs[" << InsnID |
||
171 | << "], ExpectedOpcode=" << Expected0; |
||
172 | if (MatcherOpcode == GIM_CheckOpcodeIsEither) |
||
173 | dbgs() << " || " << Expected1; |
||
174 | dbgs() << ") // Got=" << Opcode << "\n"; |
||
175 | ); |
||
176 | |||
177 | if (Opcode != Expected0 && Opcode != Expected1) { |
||
178 | if (handleReject() == RejectAndGiveUp) |
||
179 | return false; |
||
180 | } |
||
181 | break; |
||
182 | } |
||
183 | case GIM_SwitchOpcode: { |
||
184 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
185 | int64_t LowerBound = MatchTable[CurrentIdx++]; |
||
186 | int64_t UpperBound = MatchTable[CurrentIdx++]; |
||
187 | int64_t Default = MatchTable[CurrentIdx++]; |
||
188 | |||
189 | assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); |
||
190 | const int64_t Opcode = State.MIs[InsnID]->getOpcode(); |
||
191 | |||
192 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), { |
||
193 | dbgs() << CurrentIdx << ": GIM_SwitchOpcode(MIs[" << InsnID << "], [" |
||
194 | << LowerBound << ", " << UpperBound << "), Default=" << Default |
||
195 | << ", JumpTable...) // Got=" << Opcode << "\n"; |
||
196 | }); |
||
197 | if (Opcode < LowerBound || UpperBound <= Opcode) { |
||
198 | CurrentIdx = Default; |
||
199 | break; |
||
200 | } |
||
201 | CurrentIdx = MatchTable[CurrentIdx + (Opcode - LowerBound)]; |
||
202 | if (!CurrentIdx) { |
||
203 | CurrentIdx = Default; |
||
204 | break; |
||
205 | } |
||
206 | OnFailResumeAt.push_back(Default); |
||
207 | break; |
||
208 | } |
||
209 | |||
210 | case GIM_SwitchType: { |
||
211 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
212 | int64_t OpIdx = MatchTable[CurrentIdx++]; |
||
213 | int64_t LowerBound = MatchTable[CurrentIdx++]; |
||
214 | int64_t UpperBound = MatchTable[CurrentIdx++]; |
||
215 | int64_t Default = MatchTable[CurrentIdx++]; |
||
216 | |||
217 | assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); |
||
218 | MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx); |
||
219 | |||
220 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), { |
||
221 | dbgs() << CurrentIdx << ": GIM_SwitchType(MIs[" << InsnID |
||
222 | << "]->getOperand(" << OpIdx << "), [" << LowerBound << ", " |
||
223 | << UpperBound << "), Default=" << Default |
||
224 | << ", JumpTable...) // Got="; |
||
225 | if (!MO.isReg()) |
||
226 | dbgs() << "Not a VReg\n"; |
||
227 | else |
||
228 | dbgs() << MRI.getType(MO.getReg()) << "\n"; |
||
229 | }); |
||
230 | if (!MO.isReg()) { |
||
231 | CurrentIdx = Default; |
||
232 | break; |
||
233 | } |
||
234 | const LLT Ty = MRI.getType(MO.getReg()); |
||
235 | const auto TyI = ISelInfo.TypeIDMap.find(Ty); |
||
236 | if (TyI == ISelInfo.TypeIDMap.end()) { |
||
237 | CurrentIdx = Default; |
||
238 | break; |
||
239 | } |
||
240 | const int64_t TypeID = TyI->second; |
||
241 | if (TypeID < LowerBound || UpperBound <= TypeID) { |
||
242 | CurrentIdx = Default; |
||
243 | break; |
||
244 | } |
||
245 | CurrentIdx = MatchTable[CurrentIdx + (TypeID - LowerBound)]; |
||
246 | if (!CurrentIdx) { |
||
247 | CurrentIdx = Default; |
||
248 | break; |
||
249 | } |
||
250 | OnFailResumeAt.push_back(Default); |
||
251 | break; |
||
252 | } |
||
253 | |||
254 | case GIM_CheckNumOperands: { |
||
255 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
256 | int64_t Expected = MatchTable[CurrentIdx++]; |
||
257 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
258 | dbgs() << CurrentIdx << ": GIM_CheckNumOperands(MIs[" |
||
259 | << InsnID << "], Expected=" << Expected << ")\n"); |
||
260 | assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); |
||
261 | if (State.MIs[InsnID]->getNumOperands() != Expected) { |
||
262 | if (handleReject() == RejectAndGiveUp) |
||
263 | return false; |
||
264 | } |
||
265 | break; |
||
266 | } |
||
267 | case GIM_CheckI64ImmPredicate: |
||
268 | case GIM_CheckImmOperandPredicate: { |
||
269 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
270 | int64_t OpIdx = MatcherOpcode == GIM_CheckImmOperandPredicate |
||
271 | ? MatchTable[CurrentIdx++] |
||
272 | : 1; |
||
273 | int64_t Predicate = MatchTable[CurrentIdx++]; |
||
274 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
275 | dbgs() << CurrentIdx << ": GIM_CheckImmPredicate(MIs[" |
||
276 | << InsnID << "]->getOperand(" << OpIdx |
||
277 | << "), Predicate=" << Predicate << ")\n"); |
||
278 | assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); |
||
279 | assert((State.MIs[InsnID]->getOperand(OpIdx).isImm() || |
||
280 | State.MIs[InsnID]->getOperand(OpIdx).isCImm()) && |
||
281 | "Expected immediate operand"); |
||
282 | assert(Predicate > GIPFP_I64_Invalid && "Expected a valid predicate"); |
||
283 | int64_t Value = 0; |
||
284 | if (State.MIs[InsnID]->getOperand(OpIdx).isCImm()) |
||
285 | Value = State.MIs[InsnID]->getOperand(OpIdx).getCImm()->getSExtValue(); |
||
286 | else if (State.MIs[InsnID]->getOperand(OpIdx).isImm()) |
||
287 | Value = State.MIs[InsnID]->getOperand(OpIdx).getImm(); |
||
288 | else |
||
289 | llvm_unreachable("Expected Imm or CImm operand"); |
||
290 | |||
291 | if (!testImmPredicate_I64(Predicate, Value)) |
||
292 | if (handleReject() == RejectAndGiveUp) |
||
293 | return false; |
||
294 | break; |
||
295 | } |
||
296 | case GIM_CheckAPIntImmPredicate: { |
||
297 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
298 | int64_t Predicate = MatchTable[CurrentIdx++]; |
||
299 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
300 | dbgs() |
||
301 | << CurrentIdx << ": GIM_CheckAPIntImmPredicate(MIs[" |
||
302 | << InsnID << "], Predicate=" << Predicate << ")\n"); |
||
303 | assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); |
||
304 | assert(State.MIs[InsnID]->getOpcode() == TargetOpcode::G_CONSTANT && |
||
305 | "Expected G_CONSTANT"); |
||
306 | assert(Predicate > GIPFP_APInt_Invalid && "Expected a valid predicate"); |
||
307 | APInt Value; |
||
308 | if (State.MIs[InsnID]->getOperand(1).isCImm()) |
||
309 | Value = State.MIs[InsnID]->getOperand(1).getCImm()->getValue(); |
||
310 | else |
||
311 | llvm_unreachable("Expected Imm or CImm operand"); |
||
312 | |||
313 | if (!testImmPredicate_APInt(Predicate, Value)) |
||
314 | if (handleReject() == RejectAndGiveUp) |
||
315 | return false; |
||
316 | break; |
||
317 | } |
||
318 | case GIM_CheckAPFloatImmPredicate: { |
||
319 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
320 | int64_t Predicate = MatchTable[CurrentIdx++]; |
||
321 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
322 | dbgs() |
||
323 | << CurrentIdx << ": GIM_CheckAPFloatImmPredicate(MIs[" |
||
324 | << InsnID << "], Predicate=" << Predicate << ")\n"); |
||
325 | assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); |
||
326 | assert(State.MIs[InsnID]->getOpcode() == TargetOpcode::G_FCONSTANT && |
||
327 | "Expected G_FCONSTANT"); |
||
328 | assert(State.MIs[InsnID]->getOperand(1).isFPImm() && "Expected FPImm operand"); |
||
329 | assert(Predicate > GIPFP_APFloat_Invalid && "Expected a valid predicate"); |
||
330 | APFloat Value = State.MIs[InsnID]->getOperand(1).getFPImm()->getValueAPF(); |
||
331 | |||
332 | if (!testImmPredicate_APFloat(Predicate, Value)) |
||
333 | if (handleReject() == RejectAndGiveUp) |
||
334 | return false; |
||
335 | break; |
||
336 | } |
||
337 | case GIM_CheckIsBuildVectorAllOnes: |
||
338 | case GIM_CheckIsBuildVectorAllZeros: { |
||
339 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
340 | |||
341 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
342 | dbgs() << CurrentIdx |
||
343 | << ": GIM_CheckBuildVectorAll{Zeros|Ones}(MIs[" |
||
344 | << InsnID << "])\n"); |
||
345 | assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); |
||
346 | |||
347 | const MachineInstr *MI = State.MIs[InsnID]; |
||
348 | assert((MI->getOpcode() == TargetOpcode::G_BUILD_VECTOR || |
||
349 | MI->getOpcode() == TargetOpcode::G_BUILD_VECTOR_TRUNC) && |
||
350 | "Expected G_BUILD_VECTOR or G_BUILD_VECTOR_TRUNC"); |
||
351 | |||
352 | if (MatcherOpcode == GIM_CheckIsBuildVectorAllOnes) { |
||
353 | if (!isBuildVectorAllOnes(*MI, MRI)) { |
||
354 | if (handleReject() == RejectAndGiveUp) |
||
355 | return false; |
||
356 | } |
||
357 | } else { |
||
358 | if (!isBuildVectorAllZeros(*MI, MRI)) { |
||
359 | if (handleReject() == RejectAndGiveUp) |
||
360 | return false; |
||
361 | } |
||
362 | } |
||
363 | |||
364 | break; |
||
365 | } |
||
366 | case GIM_CheckCxxInsnPredicate: { |
||
367 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
368 | int64_t Predicate = MatchTable[CurrentIdx++]; |
||
369 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
370 | dbgs() |
||
371 | << CurrentIdx << ": GIM_CheckCxxPredicate(MIs[" |
||
372 | << InsnID << "], Predicate=" << Predicate << ")\n"); |
||
373 | assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); |
||
374 | assert(Predicate > GIPFP_MI_Invalid && "Expected a valid predicate"); |
||
375 | |||
376 | if (!testMIPredicate_MI(Predicate, *State.MIs[InsnID], |
||
377 | State.RecordedOperands)) |
||
378 | if (handleReject() == RejectAndGiveUp) |
||
379 | return false; |
||
380 | break; |
||
381 | } |
||
382 | case GIM_CheckHasNoUse: { |
||
383 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
384 | |||
385 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
386 | dbgs() << CurrentIdx << ": GIM_CheckHasNoUse(MIs[" |
||
387 | << InsnID << "]\n"); |
||
388 | |||
389 | const MachineInstr *MI = State.MIs[InsnID]; |
||
390 | assert(MI && "Used insn before defined"); |
||
391 | assert(MI->getNumDefs() > 0 && "No defs"); |
||
392 | const Register Res = MI->getOperand(0).getReg(); |
||
393 | |||
394 | if (!MRI.use_nodbg_empty(Res)) { |
||
395 | if (handleReject() == RejectAndGiveUp) |
||
396 | return false; |
||
397 | } |
||
398 | |||
399 | break; |
||
400 | } |
||
401 | case GIM_CheckAtomicOrdering: { |
||
402 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
403 | AtomicOrdering Ordering = (AtomicOrdering)MatchTable[CurrentIdx++]; |
||
404 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
405 | dbgs() << CurrentIdx << ": GIM_CheckAtomicOrdering(MIs[" |
||
406 | << InsnID << "], " << (uint64_t)Ordering << ")\n"); |
||
407 | assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); |
||
408 | if (!State.MIs[InsnID]->hasOneMemOperand()) |
||
409 | if (handleReject() == RejectAndGiveUp) |
||
410 | return false; |
||
411 | |||
412 | for (const auto &MMO : State.MIs[InsnID]->memoperands()) |
||
413 | if (MMO->getMergedOrdering() != Ordering) |
||
414 | if (handleReject() == RejectAndGiveUp) |
||
415 | return false; |
||
416 | break; |
||
417 | } |
||
418 | case GIM_CheckAtomicOrderingOrStrongerThan: { |
||
419 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
420 | AtomicOrdering Ordering = (AtomicOrdering)MatchTable[CurrentIdx++]; |
||
421 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
422 | dbgs() << CurrentIdx |
||
423 | << ": GIM_CheckAtomicOrderingOrStrongerThan(MIs[" |
||
424 | << InsnID << "], " << (uint64_t)Ordering << ")\n"); |
||
425 | assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); |
||
426 | if (!State.MIs[InsnID]->hasOneMemOperand()) |
||
427 | if (handleReject() == RejectAndGiveUp) |
||
428 | return false; |
||
429 | |||
430 | for (const auto &MMO : State.MIs[InsnID]->memoperands()) |
||
431 | if (!isAtLeastOrStrongerThan(MMO->getMergedOrdering(), Ordering)) |
||
432 | if (handleReject() == RejectAndGiveUp) |
||
433 | return false; |
||
434 | break; |
||
435 | } |
||
436 | case GIM_CheckAtomicOrderingWeakerThan: { |
||
437 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
438 | AtomicOrdering Ordering = (AtomicOrdering)MatchTable[CurrentIdx++]; |
||
439 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
440 | dbgs() << CurrentIdx |
||
441 | << ": GIM_CheckAtomicOrderingWeakerThan(MIs[" |
||
442 | << InsnID << "], " << (uint64_t)Ordering << ")\n"); |
||
443 | assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); |
||
444 | if (!State.MIs[InsnID]->hasOneMemOperand()) |
||
445 | if (handleReject() == RejectAndGiveUp) |
||
446 | return false; |
||
447 | |||
448 | for (const auto &MMO : State.MIs[InsnID]->memoperands()) |
||
449 | if (!isStrongerThan(Ordering, MMO->getMergedOrdering())) |
||
450 | if (handleReject() == RejectAndGiveUp) |
||
451 | return false; |
||
452 | break; |
||
453 | } |
||
454 | case GIM_CheckMemoryAddressSpace: { |
||
455 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
456 | int64_t MMOIdx = MatchTable[CurrentIdx++]; |
||
457 | // This accepts a list of possible address spaces. |
||
458 | const int NumAddrSpace = MatchTable[CurrentIdx++]; |
||
459 | |||
460 | if (State.MIs[InsnID]->getNumMemOperands() <= MMOIdx) { |
||
461 | if (handleReject() == RejectAndGiveUp) |
||
462 | return false; |
||
463 | break; |
||
464 | } |
||
465 | |||
466 | // Need to still jump to the end of the list of address spaces if we find |
||
467 | // a match earlier. |
||
468 | const uint64_t LastIdx = CurrentIdx + NumAddrSpace; |
||
469 | |||
470 | const MachineMemOperand *MMO |
||
471 | = *(State.MIs[InsnID]->memoperands_begin() + MMOIdx); |
||
472 | const unsigned MMOAddrSpace = MMO->getAddrSpace(); |
||
473 | |||
474 | bool Success = false; |
||
475 | for (int I = 0; I != NumAddrSpace; ++I) { |
||
476 | unsigned AddrSpace = MatchTable[CurrentIdx++]; |
||
477 | DEBUG_WITH_TYPE( |
||
478 | TgtInstructionSelector::getName(), |
||
479 | dbgs() << "addrspace(" << MMOAddrSpace << ") vs " |
||
480 | << AddrSpace << '\n'); |
||
481 | |||
482 | if (AddrSpace == MMOAddrSpace) { |
||
483 | Success = true; |
||
484 | break; |
||
485 | } |
||
486 | } |
||
487 | |||
488 | CurrentIdx = LastIdx; |
||
489 | if (!Success && handleReject() == RejectAndGiveUp) |
||
490 | return false; |
||
491 | break; |
||
492 | } |
||
493 | case GIM_CheckMemoryAlignment: { |
||
494 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
495 | int64_t MMOIdx = MatchTable[CurrentIdx++]; |
||
496 | unsigned MinAlign = MatchTable[CurrentIdx++]; |
||
497 | |||
498 | assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); |
||
499 | |||
500 | if (State.MIs[InsnID]->getNumMemOperands() <= MMOIdx) { |
||
501 | if (handleReject() == RejectAndGiveUp) |
||
502 | return false; |
||
503 | break; |
||
504 | } |
||
505 | |||
506 | MachineMemOperand *MMO |
||
507 | = *(State.MIs[InsnID]->memoperands_begin() + MMOIdx); |
||
508 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
509 | dbgs() << CurrentIdx << ": GIM_CheckMemoryAlignment" |
||
510 | << "(MIs[" << InsnID << "]->memoperands() + " << MMOIdx |
||
511 | << ")->getAlignment() >= " << MinAlign << ")\n"); |
||
512 | if (MMO->getAlign() < MinAlign && handleReject() == RejectAndGiveUp) |
||
513 | return false; |
||
514 | |||
515 | break; |
||
516 | } |
||
517 | case GIM_CheckMemorySizeEqualTo: { |
||
518 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
519 | int64_t MMOIdx = MatchTable[CurrentIdx++]; |
||
520 | uint64_t Size = MatchTable[CurrentIdx++]; |
||
521 | |||
522 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
523 | dbgs() << CurrentIdx |
||
524 | << ": GIM_CheckMemorySizeEqual(MIs[" << InsnID |
||
525 | << "]->memoperands() + " << MMOIdx |
||
526 | << ", Size=" << Size << ")\n"); |
||
527 | assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); |
||
528 | |||
529 | if (State.MIs[InsnID]->getNumMemOperands() <= MMOIdx) { |
||
530 | if (handleReject() == RejectAndGiveUp) |
||
531 | return false; |
||
532 | break; |
||
533 | } |
||
534 | |||
535 | MachineMemOperand *MMO = *(State.MIs[InsnID]->memoperands_begin() + MMOIdx); |
||
536 | |||
537 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
538 | dbgs() << MMO->getSize() << " bytes vs " << Size |
||
539 | << " bytes\n"); |
||
540 | if (MMO->getSize() != Size) |
||
541 | if (handleReject() == RejectAndGiveUp) |
||
542 | return false; |
||
543 | |||
544 | break; |
||
545 | } |
||
546 | case GIM_CheckMemorySizeEqualToLLT: |
||
547 | case GIM_CheckMemorySizeLessThanLLT: |
||
548 | case GIM_CheckMemorySizeGreaterThanLLT: { |
||
549 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
550 | int64_t MMOIdx = MatchTable[CurrentIdx++]; |
||
551 | int64_t OpIdx = MatchTable[CurrentIdx++]; |
||
552 | |||
553 | DEBUG_WITH_TYPE( |
||
554 | TgtInstructionSelector::getName(), |
||
555 | dbgs() << CurrentIdx << ": GIM_CheckMemorySize" |
||
556 | << (MatcherOpcode == GIM_CheckMemorySizeEqualToLLT |
||
557 | ? "EqualTo" |
||
558 | : MatcherOpcode == GIM_CheckMemorySizeGreaterThanLLT |
||
559 | ? "GreaterThan" |
||
560 | : "LessThan") |
||
561 | << "LLT(MIs[" << InsnID << "]->memoperands() + " << MMOIdx |
||
562 | << ", OpIdx=" << OpIdx << ")\n"); |
||
563 | assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); |
||
564 | |||
565 | MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx); |
||
566 | if (!MO.isReg()) { |
||
567 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
568 | dbgs() << CurrentIdx << ": Not a register\n"); |
||
569 | if (handleReject() == RejectAndGiveUp) |
||
570 | return false; |
||
571 | break; |
||
572 | } |
||
573 | |||
574 | if (State.MIs[InsnID]->getNumMemOperands() <= MMOIdx) { |
||
575 | if (handleReject() == RejectAndGiveUp) |
||
576 | return false; |
||
577 | break; |
||
578 | } |
||
579 | |||
580 | MachineMemOperand *MMO = *(State.MIs[InsnID]->memoperands_begin() + MMOIdx); |
||
581 | |||
582 | unsigned Size = MRI.getType(MO.getReg()).getSizeInBits(); |
||
583 | if (MatcherOpcode == GIM_CheckMemorySizeEqualToLLT && |
||
584 | MMO->getSizeInBits() != Size) { |
||
585 | if (handleReject() == RejectAndGiveUp) |
||
586 | return false; |
||
587 | } else if (MatcherOpcode == GIM_CheckMemorySizeLessThanLLT && |
||
588 | MMO->getSizeInBits() >= Size) { |
||
589 | if (handleReject() == RejectAndGiveUp) |
||
590 | return false; |
||
591 | } else if (MatcherOpcode == GIM_CheckMemorySizeGreaterThanLLT && |
||
592 | MMO->getSizeInBits() <= Size) |
||
593 | if (handleReject() == RejectAndGiveUp) |
||
594 | return false; |
||
595 | |||
596 | break; |
||
597 | } |
||
598 | case GIM_CheckType: { |
||
599 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
600 | int64_t OpIdx = MatchTable[CurrentIdx++]; |
||
601 | int64_t TypeID = MatchTable[CurrentIdx++]; |
||
602 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
603 | dbgs() << CurrentIdx << ": GIM_CheckType(MIs[" << InsnID |
||
604 | << "]->getOperand(" << OpIdx |
||
605 | << "), TypeID=" << TypeID << ")\n"); |
||
606 | assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); |
||
607 | MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx); |
||
608 | if (!MO.isReg() || |
||
609 | MRI.getType(MO.getReg()) != ISelInfo.TypeObjects[TypeID]) { |
||
610 | if (handleReject() == RejectAndGiveUp) |
||
611 | return false; |
||
612 | } |
||
613 | break; |
||
614 | } |
||
615 | case GIM_CheckPointerToAny: { |
||
616 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
617 | int64_t OpIdx = MatchTable[CurrentIdx++]; |
||
618 | uint64_t SizeInBits = MatchTable[CurrentIdx++]; |
||
619 | |||
620 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
621 | dbgs() << CurrentIdx << ": GIM_CheckPointerToAny(MIs[" |
||
622 | << InsnID << "]->getOperand(" << OpIdx |
||
623 | << "), SizeInBits=" << SizeInBits << ")\n"); |
||
624 | assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); |
||
625 | MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx); |
||
626 | const LLT Ty = MRI.getType(MO.getReg()); |
||
627 | |||
628 | // iPTR must be looked up in the target. |
||
629 | if (SizeInBits == 0) { |
||
630 | MachineFunction *MF = State.MIs[InsnID]->getParent()->getParent(); |
||
631 | const unsigned AddrSpace = Ty.getAddressSpace(); |
||
632 | SizeInBits = MF->getDataLayout().getPointerSizeInBits(AddrSpace); |
||
633 | } |
||
634 | |||
635 | assert(SizeInBits != 0 && "Pointer size must be known"); |
||
636 | |||
637 | if (MO.isReg()) { |
||
638 | if (!Ty.isPointer() || Ty.getSizeInBits() != SizeInBits) |
||
639 | if (handleReject() == RejectAndGiveUp) |
||
640 | return false; |
||
641 | } else if (handleReject() == RejectAndGiveUp) |
||
642 | return false; |
||
643 | |||
644 | break; |
||
645 | } |
||
646 | case GIM_RecordNamedOperand: { |
||
647 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
648 | int64_t OpIdx = MatchTable[CurrentIdx++]; |
||
649 | uint64_t StoreIdx = MatchTable[CurrentIdx++]; |
||
650 | |||
651 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
652 | dbgs() << CurrentIdx << ": GIM_RecordNamedOperand(MIs[" |
||
653 | << InsnID << "]->getOperand(" << OpIdx |
||
654 | << "), StoreIdx=" << StoreIdx << ")\n"); |
||
655 | assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); |
||
656 | assert(StoreIdx < State.RecordedOperands.size() && "Index out of range"); |
||
657 | State.RecordedOperands[StoreIdx] = &State.MIs[InsnID]->getOperand(OpIdx); |
||
658 | break; |
||
659 | } |
||
660 | case GIM_CheckRegBankForClass: { |
||
661 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
662 | int64_t OpIdx = MatchTable[CurrentIdx++]; |
||
663 | int64_t RCEnum = MatchTable[CurrentIdx++]; |
||
664 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
665 | dbgs() << CurrentIdx << ": GIM_CheckRegBankForClass(MIs[" |
||
666 | << InsnID << "]->getOperand(" << OpIdx |
||
667 | << "), RCEnum=" << RCEnum << ")\n"); |
||
668 | assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); |
||
669 | MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx); |
||
670 | if (!MO.isReg() || |
||
671 | &RBI.getRegBankFromRegClass(*TRI.getRegClass(RCEnum), |
||
672 | MRI.getType(MO.getReg())) != |
||
673 | RBI.getRegBank(MO.getReg(), MRI, TRI)) { |
||
674 | if (handleReject() == RejectAndGiveUp) |
||
675 | return false; |
||
676 | } |
||
677 | break; |
||
678 | } |
||
679 | |||
680 | case GIM_CheckComplexPattern: { |
||
681 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
682 | int64_t OpIdx = MatchTable[CurrentIdx++]; |
||
683 | int64_t RendererID = MatchTable[CurrentIdx++]; |
||
684 | int64_t ComplexPredicateID = MatchTable[CurrentIdx++]; |
||
685 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
686 | dbgs() << CurrentIdx << ": State.Renderers[" << RendererID |
||
687 | << "] = GIM_CheckComplexPattern(MIs[" << InsnID |
||
688 | << "]->getOperand(" << OpIdx |
||
689 | << "), ComplexPredicateID=" << ComplexPredicateID |
||
690 | << ")\n"); |
||
691 | assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); |
||
692 | // FIXME: Use std::invoke() when it's available. |
||
693 | ComplexRendererFns Renderer = |
||
694 | (ISel.*ISelInfo.ComplexPredicates[ComplexPredicateID])( |
||
695 | State.MIs[InsnID]->getOperand(OpIdx)); |
||
696 | if (Renderer) |
||
697 | State.Renderers[RendererID] = *Renderer; |
||
698 | else |
||
699 | if (handleReject() == RejectAndGiveUp) |
||
700 | return false; |
||
701 | break; |
||
702 | } |
||
703 | |||
704 | case GIM_CheckConstantInt: { |
||
705 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
706 | int64_t OpIdx = MatchTable[CurrentIdx++]; |
||
707 | int64_t Value = MatchTable[CurrentIdx++]; |
||
708 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
709 | dbgs() << CurrentIdx << ": GIM_CheckConstantInt(MIs[" |
||
710 | << InsnID << "]->getOperand(" << OpIdx |
||
711 | << "), Value=" << Value << ")\n"); |
||
712 | assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); |
||
713 | MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx); |
||
714 | if (MO.isReg()) { |
||
715 | // isOperandImmEqual() will sign-extend to 64-bits, so should we. |
||
716 | LLT Ty = MRI.getType(MO.getReg()); |
||
717 | Value = SignExtend64(Value, Ty.getSizeInBits()); |
||
718 | |||
719 | if (!isOperandImmEqual(MO, Value, MRI)) { |
||
720 | if (handleReject() == RejectAndGiveUp) |
||
721 | return false; |
||
722 | } |
||
723 | } else if (handleReject() == RejectAndGiveUp) |
||
724 | return false; |
||
725 | |||
726 | break; |
||
727 | } |
||
728 | |||
729 | case GIM_CheckLiteralInt: { |
||
730 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
731 | int64_t OpIdx = MatchTable[CurrentIdx++]; |
||
732 | int64_t Value = MatchTable[CurrentIdx++]; |
||
733 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
734 | dbgs() << CurrentIdx << ": GIM_CheckLiteralInt(MIs[" |
||
735 | << InsnID << "]->getOperand(" << OpIdx |
||
736 | << "), Value=" << Value << ")\n"); |
||
737 | assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); |
||
738 | MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx); |
||
739 | if (MO.isImm() && MO.getImm() == Value) |
||
740 | break; |
||
741 | |||
742 | if (MO.isCImm() && MO.getCImm()->equalsInt(Value)) |
||
743 | break; |
||
744 | |||
745 | if (handleReject() == RejectAndGiveUp) |
||
746 | return false; |
||
747 | |||
748 | break; |
||
749 | } |
||
750 | |||
751 | case GIM_CheckIntrinsicID: { |
||
752 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
753 | int64_t OpIdx = MatchTable[CurrentIdx++]; |
||
754 | int64_t Value = MatchTable[CurrentIdx++]; |
||
755 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
756 | dbgs() << CurrentIdx << ": GIM_CheckIntrinsicID(MIs[" |
||
757 | << InsnID << "]->getOperand(" << OpIdx |
||
758 | << "), Value=" << Value << ")\n"); |
||
759 | assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); |
||
760 | MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx); |
||
761 | if (!MO.isIntrinsicID() || MO.getIntrinsicID() != Value) |
||
762 | if (handleReject() == RejectAndGiveUp) |
||
763 | return false; |
||
764 | break; |
||
765 | } |
||
766 | case GIM_CheckCmpPredicate: { |
||
767 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
768 | int64_t OpIdx = MatchTable[CurrentIdx++]; |
||
769 | int64_t Value = MatchTable[CurrentIdx++]; |
||
770 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
771 | dbgs() << CurrentIdx << ": GIM_CheckCmpPredicate(MIs[" |
||
772 | << InsnID << "]->getOperand(" << OpIdx |
||
773 | << "), Value=" << Value << ")\n"); |
||
774 | assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); |
||
775 | MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx); |
||
776 | if (!MO.isPredicate() || MO.getPredicate() != Value) |
||
777 | if (handleReject() == RejectAndGiveUp) |
||
778 | return false; |
||
779 | break; |
||
780 | } |
||
781 | case GIM_CheckIsMBB: { |
||
782 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
783 | int64_t OpIdx = MatchTable[CurrentIdx++]; |
||
784 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
785 | dbgs() << CurrentIdx << ": GIM_CheckIsMBB(MIs[" << InsnID |
||
786 | << "]->getOperand(" << OpIdx << "))\n"); |
||
787 | assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); |
||
788 | if (!State.MIs[InsnID]->getOperand(OpIdx).isMBB()) { |
||
789 | if (handleReject() == RejectAndGiveUp) |
||
790 | return false; |
||
791 | } |
||
792 | break; |
||
793 | } |
||
794 | case GIM_CheckIsImm: { |
||
795 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
796 | int64_t OpIdx = MatchTable[CurrentIdx++]; |
||
797 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
798 | dbgs() << CurrentIdx << ": GIM_CheckIsImm(MIs[" << InsnID |
||
799 | << "]->getOperand(" << OpIdx << "))\n"); |
||
800 | assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); |
||
801 | if (!State.MIs[InsnID]->getOperand(OpIdx).isImm()) { |
||
802 | if (handleReject() == RejectAndGiveUp) |
||
803 | return false; |
||
804 | } |
||
805 | break; |
||
806 | } |
||
807 | case GIM_CheckIsSafeToFold: { |
||
808 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
809 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
810 | dbgs() << CurrentIdx << ": GIM_CheckIsSafeToFold(MIs[" |
||
811 | << InsnID << "])\n"); |
||
812 | assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); |
||
813 | if (!isObviouslySafeToFold(*State.MIs[InsnID], *State.MIs[0])) { |
||
814 | if (handleReject() == RejectAndGiveUp) |
||
815 | return false; |
||
816 | } |
||
817 | break; |
||
818 | } |
||
819 | case GIM_CheckIsSameOperand: { |
||
820 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
821 | int64_t OpIdx = MatchTable[CurrentIdx++]; |
||
822 | int64_t OtherInsnID = MatchTable[CurrentIdx++]; |
||
823 | int64_t OtherOpIdx = MatchTable[CurrentIdx++]; |
||
824 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
825 | dbgs() << CurrentIdx << ": GIM_CheckIsSameOperand(MIs[" |
||
826 | << InsnID << "][" << OpIdx << "], MIs[" |
||
827 | << OtherInsnID << "][" << OtherOpIdx << "])\n"); |
||
828 | assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); |
||
829 | assert(State.MIs[OtherInsnID] != nullptr && "Used insn before defined"); |
||
830 | if (!State.MIs[InsnID]->getOperand(OpIdx).isIdenticalTo( |
||
831 | State.MIs[OtherInsnID]->getOperand(OtherOpIdx))) { |
||
832 | if (handleReject() == RejectAndGiveUp) |
||
833 | return false; |
||
834 | } |
||
835 | break; |
||
836 | } |
||
837 | case GIM_Reject: |
||
838 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
839 | dbgs() << CurrentIdx << ": GIM_Reject\n"); |
||
840 | if (handleReject() == RejectAndGiveUp) |
||
841 | return false; |
||
842 | break; |
||
843 | |||
844 | case GIR_MutateOpcode: { |
||
845 | int64_t OldInsnID = MatchTable[CurrentIdx++]; |
||
846 | uint64_t NewInsnID = MatchTable[CurrentIdx++]; |
||
847 | int64_t NewOpcode = MatchTable[CurrentIdx++]; |
||
848 | if (NewInsnID >= OutMIs.size()) |
||
849 | OutMIs.resize(NewInsnID + 1); |
||
850 | |||
851 | OutMIs[NewInsnID] = MachineInstrBuilder(*State.MIs[OldInsnID]->getMF(), |
||
852 | State.MIs[OldInsnID]); |
||
853 | OutMIs[NewInsnID]->setDesc(TII.get(NewOpcode)); |
||
854 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
855 | dbgs() << CurrentIdx << ": GIR_MutateOpcode(OutMIs[" |
||
856 | << NewInsnID << "], MIs[" << OldInsnID << "], " |
||
857 | << NewOpcode << ")\n"); |
||
858 | break; |
||
859 | } |
||
860 | |||
861 | case GIR_BuildMI: { |
||
862 | uint64_t NewInsnID = MatchTable[CurrentIdx++]; |
||
863 | int64_t Opcode = MatchTable[CurrentIdx++]; |
||
864 | if (NewInsnID >= OutMIs.size()) |
||
865 | OutMIs.resize(NewInsnID + 1); |
||
866 | |||
867 | OutMIs[NewInsnID] = BuildMI(*State.MIs[0]->getParent(), State.MIs[0], |
||
868 | MIMetadata(*State.MIs[0]), TII.get(Opcode)); |
||
869 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
870 | dbgs() << CurrentIdx << ": GIR_BuildMI(OutMIs[" |
||
871 | << NewInsnID << "], " << Opcode << ")\n"); |
||
872 | break; |
||
873 | } |
||
874 | |||
875 | case GIR_Copy: { |
||
876 | int64_t NewInsnID = MatchTable[CurrentIdx++]; |
||
877 | int64_t OldInsnID = MatchTable[CurrentIdx++]; |
||
878 | int64_t OpIdx = MatchTable[CurrentIdx++]; |
||
879 | assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction"); |
||
880 | OutMIs[NewInsnID].add(State.MIs[OldInsnID]->getOperand(OpIdx)); |
||
881 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
882 | dbgs() |
||
883 | << CurrentIdx << ": GIR_Copy(OutMIs[" << NewInsnID |
||
884 | << "], MIs[" << OldInsnID << "], " << OpIdx << ")\n"); |
||
885 | break; |
||
886 | } |
||
887 | |||
888 | case GIR_CopyOrAddZeroReg: { |
||
889 | int64_t NewInsnID = MatchTable[CurrentIdx++]; |
||
890 | int64_t OldInsnID = MatchTable[CurrentIdx++]; |
||
891 | int64_t OpIdx = MatchTable[CurrentIdx++]; |
||
892 | int64_t ZeroReg = MatchTable[CurrentIdx++]; |
||
893 | assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction"); |
||
894 | MachineOperand &MO = State.MIs[OldInsnID]->getOperand(OpIdx); |
||
895 | if (isOperandImmEqual(MO, 0, MRI)) |
||
896 | OutMIs[NewInsnID].addReg(ZeroReg); |
||
897 | else |
||
898 | OutMIs[NewInsnID].add(MO); |
||
899 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
900 | dbgs() << CurrentIdx << ": GIR_CopyOrAddZeroReg(OutMIs[" |
||
901 | << NewInsnID << "], MIs[" << OldInsnID << "], " |
||
902 | << OpIdx << ", " << ZeroReg << ")\n"); |
||
903 | break; |
||
904 | } |
||
905 | |||
906 | case GIR_CopySubReg: { |
||
907 | int64_t NewInsnID = MatchTable[CurrentIdx++]; |
||
908 | int64_t OldInsnID = MatchTable[CurrentIdx++]; |
||
909 | int64_t OpIdx = MatchTable[CurrentIdx++]; |
||
910 | int64_t SubRegIdx = MatchTable[CurrentIdx++]; |
||
911 | assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction"); |
||
912 | OutMIs[NewInsnID].addReg(State.MIs[OldInsnID]->getOperand(OpIdx).getReg(), |
||
913 | 0, SubRegIdx); |
||
914 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
915 | dbgs() << CurrentIdx << ": GIR_CopySubReg(OutMIs[" |
||
916 | << NewInsnID << "], MIs[" << OldInsnID << "], " |
||
917 | << OpIdx << ", " << SubRegIdx << ")\n"); |
||
918 | break; |
||
919 | } |
||
920 | |||
921 | case GIR_AddImplicitDef: { |
||
922 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
923 | int64_t RegNum = MatchTable[CurrentIdx++]; |
||
924 | assert(OutMIs[InsnID] && "Attempted to add to undefined instruction"); |
||
925 | OutMIs[InsnID].addDef(RegNum, RegState::Implicit); |
||
926 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
927 | dbgs() << CurrentIdx << ": GIR_AddImplicitDef(OutMIs[" |
||
928 | << InsnID << "], " << RegNum << ")\n"); |
||
929 | break; |
||
930 | } |
||
931 | |||
932 | case GIR_AddImplicitUse: { |
||
933 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
934 | int64_t RegNum = MatchTable[CurrentIdx++]; |
||
935 | assert(OutMIs[InsnID] && "Attempted to add to undefined instruction"); |
||
936 | OutMIs[InsnID].addUse(RegNum, RegState::Implicit); |
||
937 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
938 | dbgs() << CurrentIdx << ": GIR_AddImplicitUse(OutMIs[" |
||
939 | << InsnID << "], " << RegNum << ")\n"); |
||
940 | break; |
||
941 | } |
||
942 | |||
943 | case GIR_AddRegister: { |
||
944 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
945 | int64_t RegNum = MatchTable[CurrentIdx++]; |
||
946 | uint64_t RegFlags = MatchTable[CurrentIdx++]; |
||
947 | assert(OutMIs[InsnID] && "Attempted to add to undefined instruction"); |
||
948 | OutMIs[InsnID].addReg(RegNum, RegFlags); |
||
949 | DEBUG_WITH_TYPE( |
||
950 | TgtInstructionSelector::getName(), |
||
951 | dbgs() << CurrentIdx << ": GIR_AddRegister(OutMIs[" |
||
952 | << InsnID << "], " << RegNum << ", " << RegFlags << ")\n"); |
||
953 | break; |
||
954 | } |
||
955 | |||
956 | case GIR_AddTempRegister: |
||
957 | case GIR_AddTempSubRegister: { |
||
958 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
959 | int64_t TempRegID = MatchTable[CurrentIdx++]; |
||
960 | uint64_t TempRegFlags = MatchTable[CurrentIdx++]; |
||
961 | unsigned SubReg = 0; |
||
962 | if (MatcherOpcode == GIR_AddTempSubRegister) |
||
963 | SubReg = MatchTable[CurrentIdx++]; |
||
964 | |||
965 | assert(OutMIs[InsnID] && "Attempted to add to undefined instruction"); |
||
966 | |||
967 | OutMIs[InsnID].addReg(State.TempRegisters[TempRegID], TempRegFlags, SubReg); |
||
968 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
969 | dbgs() << CurrentIdx << ": GIR_AddTempRegister(OutMIs[" |
||
970 | << InsnID << "], TempRegisters[" << TempRegID |
||
971 | << "]"; |
||
972 | if (SubReg) |
||
973 | dbgs() << '.' << TRI.getSubRegIndexName(SubReg); |
||
974 | dbgs() << ", " << TempRegFlags << ")\n"); |
||
975 | break; |
||
976 | } |
||
977 | |||
978 | case GIR_AddImm: { |
||
979 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
980 | int64_t Imm = MatchTable[CurrentIdx++]; |
||
981 | assert(OutMIs[InsnID] && "Attempted to add to undefined instruction"); |
||
982 | OutMIs[InsnID].addImm(Imm); |
||
983 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
984 | dbgs() << CurrentIdx << ": GIR_AddImm(OutMIs[" << InsnID |
||
985 | << "], " << Imm << ")\n"); |
||
986 | break; |
||
987 | } |
||
988 | |||
989 | case GIR_ComplexRenderer: { |
||
990 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
991 | int64_t RendererID = MatchTable[CurrentIdx++]; |
||
992 | assert(OutMIs[InsnID] && "Attempted to add to undefined instruction"); |
||
993 | for (const auto &RenderOpFn : State.Renderers[RendererID]) |
||
994 | RenderOpFn(OutMIs[InsnID]); |
||
995 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
996 | dbgs() << CurrentIdx << ": GIR_ComplexRenderer(OutMIs[" |
||
997 | << InsnID << "], " << RendererID << ")\n"); |
||
998 | break; |
||
999 | } |
||
1000 | case GIR_ComplexSubOperandRenderer: { |
||
1001 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
1002 | int64_t RendererID = MatchTable[CurrentIdx++]; |
||
1003 | int64_t RenderOpID = MatchTable[CurrentIdx++]; |
||
1004 | assert(OutMIs[InsnID] && "Attempted to add to undefined instruction"); |
||
1005 | State.Renderers[RendererID][RenderOpID](OutMIs[InsnID]); |
||
1006 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
1007 | dbgs() << CurrentIdx |
||
1008 | << ": GIR_ComplexSubOperandRenderer(OutMIs[" |
||
1009 | << InsnID << "], " << RendererID << ", " |
||
1010 | << RenderOpID << ")\n"); |
||
1011 | break; |
||
1012 | } |
||
1013 | |||
1014 | case GIR_CopyConstantAsSImm: { |
||
1015 | int64_t NewInsnID = MatchTable[CurrentIdx++]; |
||
1016 | int64_t OldInsnID = MatchTable[CurrentIdx++]; |
||
1017 | assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction"); |
||
1018 | assert(State.MIs[OldInsnID]->getOpcode() == TargetOpcode::G_CONSTANT && "Expected G_CONSTANT"); |
||
1019 | if (State.MIs[OldInsnID]->getOperand(1).isCImm()) { |
||
1020 | OutMIs[NewInsnID].addImm( |
||
1021 | State.MIs[OldInsnID]->getOperand(1).getCImm()->getSExtValue()); |
||
1022 | } else if (State.MIs[OldInsnID]->getOperand(1).isImm()) |
||
1023 | OutMIs[NewInsnID].add(State.MIs[OldInsnID]->getOperand(1)); |
||
1024 | else |
||
1025 | llvm_unreachable("Expected Imm or CImm operand"); |
||
1026 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
1027 | dbgs() << CurrentIdx << ": GIR_CopyConstantAsSImm(OutMIs[" |
||
1028 | << NewInsnID << "], MIs[" << OldInsnID << "])\n"); |
||
1029 | break; |
||
1030 | } |
||
1031 | |||
1032 | // TODO: Needs a test case once we have a pattern that uses this. |
||
1033 | case GIR_CopyFConstantAsFPImm: { |
||
1034 | int64_t NewInsnID = MatchTable[CurrentIdx++]; |
||
1035 | int64_t OldInsnID = MatchTable[CurrentIdx++]; |
||
1036 | assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction"); |
||
1037 | assert(State.MIs[OldInsnID]->getOpcode() == TargetOpcode::G_FCONSTANT && "Expected G_FCONSTANT"); |
||
1038 | if (State.MIs[OldInsnID]->getOperand(1).isFPImm()) |
||
1039 | OutMIs[NewInsnID].addFPImm( |
||
1040 | State.MIs[OldInsnID]->getOperand(1).getFPImm()); |
||
1041 | else |
||
1042 | llvm_unreachable("Expected FPImm operand"); |
||
1043 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
1044 | dbgs() << CurrentIdx << ": GIR_CopyFPConstantAsFPImm(OutMIs[" |
||
1045 | << NewInsnID << "], MIs[" << OldInsnID << "])\n"); |
||
1046 | break; |
||
1047 | } |
||
1048 | |||
1049 | case GIR_CustomRenderer: { |
||
1050 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
1051 | int64_t OldInsnID = MatchTable[CurrentIdx++]; |
||
1052 | int64_t RendererFnID = MatchTable[CurrentIdx++]; |
||
1053 | assert(OutMIs[InsnID] && "Attempted to add to undefined instruction"); |
||
1054 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
1055 | dbgs() << CurrentIdx << ": GIR_CustomRenderer(OutMIs[" |
||
1056 | << InsnID << "], MIs[" << OldInsnID << "], " |
||
1057 | << RendererFnID << ")\n"); |
||
1058 | (ISel.*ISelInfo.CustomRenderers[RendererFnID])( |
||
1059 | OutMIs[InsnID], *State.MIs[OldInsnID], |
||
1060 | -1); // Not a source operand of the old instruction. |
||
1061 | break; |
||
1062 | } |
||
1063 | case GIR_CustomOperandRenderer: { |
||
1064 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
1065 | int64_t OldInsnID = MatchTable[CurrentIdx++]; |
||
1066 | int64_t OpIdx = MatchTable[CurrentIdx++]; |
||
1067 | int64_t RendererFnID = MatchTable[CurrentIdx++]; |
||
1068 | assert(OutMIs[InsnID] && "Attempted to add to undefined instruction"); |
||
1069 | |||
1070 | DEBUG_WITH_TYPE( |
||
1071 | TgtInstructionSelector::getName(), |
||
1072 | dbgs() << CurrentIdx << ": GIR_CustomOperandRenderer(OutMIs[" |
||
1073 | << InsnID << "], MIs[" << OldInsnID << "]->getOperand(" |
||
1074 | << OpIdx << "), " |
||
1075 | << RendererFnID << ")\n"); |
||
1076 | (ISel.*ISelInfo.CustomRenderers[RendererFnID])(OutMIs[InsnID], |
||
1077 | *State.MIs[OldInsnID], |
||
1078 | OpIdx); |
||
1079 | break; |
||
1080 | } |
||
1081 | case GIR_ConstrainOperandRC: { |
||
1082 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
1083 | int64_t OpIdx = MatchTable[CurrentIdx++]; |
||
1084 | int64_t RCEnum = MatchTable[CurrentIdx++]; |
||
1085 | assert(OutMIs[InsnID] && "Attempted to add to undefined instruction"); |
||
1086 | MachineInstr &I = *OutMIs[InsnID].getInstr(); |
||
1087 | MachineFunction &MF = *I.getParent()->getParent(); |
||
1088 | MachineRegisterInfo &MRI = MF.getRegInfo(); |
||
1089 | const TargetRegisterClass &RC = *TRI.getRegClass(RCEnum); |
||
1090 | MachineOperand &MO = I.getOperand(OpIdx); |
||
1091 | constrainOperandRegClass(MF, TRI, MRI, TII, RBI, I, RC, MO); |
||
1092 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
1093 | dbgs() << CurrentIdx << ": GIR_ConstrainOperandRC(OutMIs[" |
||
1094 | << InsnID << "], " << OpIdx << ", " << RCEnum |
||
1095 | << ")\n"); |
||
1096 | break; |
||
1097 | } |
||
1098 | |||
1099 | case GIR_ConstrainSelectedInstOperands: { |
||
1100 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
1101 | assert(OutMIs[InsnID] && "Attempted to add to undefined instruction"); |
||
1102 | constrainSelectedInstRegOperands(*OutMIs[InsnID].getInstr(), TII, TRI, |
||
1103 | RBI); |
||
1104 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
1105 | dbgs() << CurrentIdx |
||
1106 | << ": GIR_ConstrainSelectedInstOperands(OutMIs[" |
||
1107 | << InsnID << "])\n"); |
||
1108 | break; |
||
1109 | } |
||
1110 | |||
1111 | case GIR_MergeMemOperands: { |
||
1112 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
1113 | assert(OutMIs[InsnID] && "Attempted to add to undefined instruction"); |
||
1114 | |||
1115 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
1116 | dbgs() << CurrentIdx << ": GIR_MergeMemOperands(OutMIs[" |
||
1117 | << InsnID << "]"); |
||
1118 | int64_t MergeInsnID = GIU_MergeMemOperands_EndOfList; |
||
1119 | while ((MergeInsnID = MatchTable[CurrentIdx++]) != |
||
1120 | GIU_MergeMemOperands_EndOfList) { |
||
1121 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
1122 | dbgs() << ", MIs[" << MergeInsnID << "]"); |
||
1123 | for (const auto &MMO : State.MIs[MergeInsnID]->memoperands()) |
||
1124 | OutMIs[InsnID].addMemOperand(MMO); |
||
1125 | } |
||
1126 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), dbgs() << ")\n"); |
||
1127 | break; |
||
1128 | } |
||
1129 | |||
1130 | case GIR_EraseFromParent: { |
||
1131 | int64_t InsnID = MatchTable[CurrentIdx++]; |
||
1132 | assert(State.MIs[InsnID] && |
||
1133 | "Attempted to erase an undefined instruction"); |
||
1134 | State.MIs[InsnID]->eraseFromParent(); |
||
1135 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
1136 | dbgs() << CurrentIdx << ": GIR_EraseFromParent(MIs[" |
||
1137 | << InsnID << "])\n"); |
||
1138 | break; |
||
1139 | } |
||
1140 | |||
1141 | case GIR_MakeTempReg: { |
||
1142 | int64_t TempRegID = MatchTable[CurrentIdx++]; |
||
1143 | int64_t TypeID = MatchTable[CurrentIdx++]; |
||
1144 | |||
1145 | State.TempRegisters[TempRegID] = |
||
1146 | MRI.createGenericVirtualRegister(ISelInfo.TypeObjects[TypeID]); |
||
1147 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
1148 | dbgs() << CurrentIdx << ": TempRegs[" << TempRegID |
||
1149 | << "] = GIR_MakeTempReg(" << TypeID << ")\n"); |
||
1150 | break; |
||
1151 | } |
||
1152 | |||
1153 | case GIR_Coverage: { |
||
1154 | int64_t RuleID = MatchTable[CurrentIdx++]; |
||
1155 | CoverageInfo.setCovered(RuleID); |
||
1156 | |||
1157 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
1158 | dbgs() |
||
1159 | << CurrentIdx << ": GIR_Coverage(" << RuleID << ")"); |
||
1160 | break; |
||
1161 | } |
||
1162 | |||
1163 | case GIR_Done: |
||
1164 | DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), |
||
1165 | dbgs() << CurrentIdx << ": GIR_Done\n"); |
||
1166 | propagateFlags(OutMIs); |
||
1167 | return true; |
||
1168 | |||
1169 | default: |
||
1170 | llvm_unreachable("Unexpected command"); |
||
1171 | } |
||
1172 | } |
||
1173 | } |
||
1174 | |||
1175 | } // end namespace llvm |
||
1176 | |||
1177 | #endif // LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTORIMPL_H |