LLVM 23.0.0git
GIMatchTableExecutorImpl.h
Go to the documentation of this file.
1//===- llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.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 implements GIMatchTableExecutor's `executeMatchTable`
10/// function. This is implemented in a separate file because the function is
11/// quite large.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_CODEGEN_GLOBALISEL_GIMATCHTABLEEXECUTORIMPL_H
16#define LLVM_CODEGEN_GLOBALISEL_GIMATCHTABLEEXECUTORIMPL_H
17
29#include "llvm/IR/Constants.h"
30#include "llvm/IR/DataLayout.h"
31#include "llvm/IR/Type.h"
33#include "llvm/Support/Debug.h"
35#include <cassert>
36#include <cstddef>
37#include <cstdint>
38
39namespace llvm {
40
41template <class TgtExecutor, class PredicateBitset, class ComplexMatcherMemFn,
42 class CustomRendererFn>
44 TgtExecutor &Exec, MatcherState &State,
46 &ExecInfo,
47 MachineIRBuilder &Builder, const uint8_t *MatchTable,
49 const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI,
50 const PredicateBitset &AvailableFeatures,
52
53 uint64_t CurrentIdx = 0;
54 SmallVector<uint64_t, 4> OnFailResumeAt;
55 NewMIVector OutMIs;
56
57 GISelChangeObserver *Observer = Builder.getObserver();
58 // Bypass the flag check on the instruction, and only look at the MCInstrDesc.
59 bool NoFPException = !State.MIs[0]->getDesc().mayRaiseFPException();
60
61 const uint32_t Flags = State.MIs[0]->getFlags();
62 bool BuilderInitialized = false;
63 const auto initializeBuilder = [&]() {
64 if (BuilderInitialized)
65 return;
66 // Delay setting the insertion point and debug location until a successful
67 // action needs the builder.
68 Builder.setInstrAndDebugLoc(*State.MIs[0]);
69 BuilderInitialized = true;
70 };
71
72 enum RejectAction { RejectAndGiveUp, RejectAndResume };
73 auto handleReject = [&]() -> RejectAction {
74 DEBUG_WITH_TYPE(TgtExecutor::getName(),
75 dbgs() << CurrentIdx << ": Rejected\n");
76 if (OnFailResumeAt.empty())
77 return RejectAndGiveUp;
78 CurrentIdx = OnFailResumeAt.pop_back_val();
79 DEBUG_WITH_TYPE(TgtExecutor::getName(),
80 dbgs() << CurrentIdx << ": Resume at " << CurrentIdx << " ("
81 << OnFailResumeAt.size() << " try-blocks remain)\n");
82 return RejectAndResume;
83 };
84
85 const auto propagateFlags = [&]() {
86 for (auto MIB : OutMIs) {
87 // Set the NoFPExcept flag when no original matched instruction could
88 // raise an FP exception, but the new instruction potentially might.
89 uint32_t MIBFlags = Flags | MIB.getInstr()->getFlags();
90 if (NoFPException && MIB->mayRaiseFPException())
91 MIBFlags |= MachineInstr::NoFPExcept;
92 if (Observer)
93 Observer->changingInstr(*MIB);
94 MIB.setMIFlags(MIBFlags);
95 if (Observer)
96 Observer->changedInstr(*MIB);
97 }
98 };
99
100 // If the index is >= 0, it's an index in the type objects generated by
101 // TableGen. If the index is <0, it's an index in the recorded types object.
102 const auto getTypeFromIdx = [&](int64_t Idx) -> LLT {
103 if (Idx >= 0)
104 return ExecInfo.TypeObjects[Idx];
105 return State.RecordedTypes[1 - Idx];
106 };
107
108 const auto readULEB = [&]() {
109 return fastDecodeULEB128(MatchTable, CurrentIdx);
110 };
111
112 // Convenience function to return a signed value. This avoids
113 // us forgetting to first cast to int8_t before casting to a
114 // wider signed int type.
115 // if we casted uint8 directly to a wider type we'd lose
116 // negative values.
117 const auto readS8 = [&]() { return (int8_t)MatchTable[CurrentIdx++]; };
118
119 const auto readU16 = [&]() {
120 auto V = readBytesAs<uint16_t>(MatchTable + CurrentIdx);
121 CurrentIdx += 2;
122 return V;
123 };
124
125 const auto readU32 = [&]() {
126 auto V = readBytesAs<uint32_t>(MatchTable + CurrentIdx);
127 CurrentIdx += 4;
128 return V;
129 };
130
131 const auto readU64 = [&]() {
132 auto V = readBytesAs<uint64_t>(MatchTable + CurrentIdx);
133 CurrentIdx += 8;
134 return V;
135 };
136
137 const auto eraseImpl = [&](MachineInstr *MI) {
138 initializeBuilder();
139 // If we're erasing the insertion point, ensure we don't leave a dangling
140 // pointer in the builder.
141 if (Builder.getInsertPt() == MI)
142 Builder.setInsertPt(*MI->getParent(), ++MI->getIterator());
143 if (Observer)
144 Observer->erasingInstr(*MI);
145 MI->eraseFromParent();
146 };
147
148 while (true) {
149 assert(CurrentIdx != ~0u && "Invalid MatchTable index");
150 uint8_t MatcherOpcode = MatchTable[CurrentIdx++];
151 switch (MatcherOpcode) {
152 case GIM_Try: {
153 DEBUG_WITH_TYPE(TgtExecutor::getName(),
154 dbgs() << CurrentIdx << ": Begin try-block\n");
155 OnFailResumeAt.push_back(readU32());
156 break;
157 }
158
159 case GIM_RecordInsn:
161 uint64_t NewInsnID = readULEB();
162 uint64_t InsnID = readULEB();
163 uint64_t OpIdx = readULEB();
164
165 // As an optimisation we require that MIs[0] is always the root. Refuse
166 // any attempt to modify it.
167 assert(NewInsnID != 0 && "Refusing to modify MIs[0]");
168
169 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
170 if (!MO.isReg()) {
171 DEBUG_WITH_TYPE(TgtExecutor::getName(),
172 dbgs() << CurrentIdx << ": Not a register\n");
173 if (handleReject() == RejectAndGiveUp)
174 return false;
175 break;
176 }
177 if (MO.getReg().isPhysical()) {
178 DEBUG_WITH_TYPE(TgtExecutor::getName(),
179 dbgs() << CurrentIdx << ": Is a physical register\n");
180 if (handleReject() == RejectAndGiveUp)
181 return false;
182 break;
183 }
184
185 MachineInstr *NewMI;
186 if (MatcherOpcode == GIM_RecordInsnIgnoreCopies)
187 NewMI = getDefIgnoringCopies(MO.getReg(), MRI);
188 else
189 NewMI = MRI.getVRegDef(MO.getReg());
190
191 if ((size_t)NewInsnID < State.MIs.size())
192 State.MIs[NewInsnID] = NewMI;
193 else {
194 assert((size_t)NewInsnID == State.MIs.size() &&
195 "Expected to store MIs in order");
196 State.MIs.push_back(NewMI);
197 }
198 DEBUG_WITH_TYPE(TgtExecutor::getName(),
199 dbgs() << CurrentIdx << ": MIs[" << NewInsnID
200 << "] = GIM_RecordInsn(" << InsnID << ", " << OpIdx
201 << ")\n");
202 break;
203 }
204
205 case GIM_CheckFeatures: {
206 uint16_t ExpectedBitsetID = readU16();
207 DEBUG_WITH_TYPE(TgtExecutor::getName(),
208 dbgs() << CurrentIdx
209 << ": GIM_CheckFeatures(ExpectedBitsetID="
210 << ExpectedBitsetID << ")\n");
211 if ((AvailableFeatures & ExecInfo.FeatureBitsets[ExpectedBitsetID]) !=
212 ExecInfo.FeatureBitsets[ExpectedBitsetID]) {
213 if (handleReject() == RejectAndGiveUp)
214 return false;
215 }
216 break;
217 }
218 case GIM_CheckOpcode:
220 uint64_t InsnID = readULEB();
221 uint16_t Expected0 = readU16();
222 uint16_t Expected1 = -1;
223 if (MatcherOpcode == GIM_CheckOpcodeIsEither)
224 Expected1 = readU16();
225
226 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
227 unsigned Opcode = State.MIs[InsnID]->getOpcode();
228
229 DEBUG_WITH_TYPE(TgtExecutor::getName(), {
230 dbgs() << CurrentIdx << ": GIM_CheckOpcode(MIs[" << InsnID
231 << "], ExpectedOpcode=" << Expected0;
232 if (MatcherOpcode == GIM_CheckOpcodeIsEither)
233 dbgs() << " || " << Expected1;
234 dbgs() << ") // Got=" << Opcode << "\n";
235 });
236
237 if (Opcode != Expected0 && Opcode != Expected1) {
238 if (handleReject() == RejectAndGiveUp)
239 return false;
240 }
241 break;
242 }
243 case GIM_SwitchOpcode: {
244 uint64_t InsnID = readULEB();
245 uint16_t LowerBound = readU16();
246 uint16_t UpperBound = readU16();
247 uint32_t Default = readU32();
248
249 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
250 const int64_t Opcode = State.MIs[InsnID]->getOpcode();
251
252 DEBUG_WITH_TYPE(TgtExecutor::getName(), {
253 dbgs() << CurrentIdx << ": GIM_SwitchOpcode(MIs[" << InsnID << "], ["
254 << LowerBound << ", " << UpperBound << "), Default=" << Default
255 << ", JumpTable...) // Got=" << Opcode << "\n";
256 });
257 if (Opcode < LowerBound || UpperBound <= Opcode) {
258 CurrentIdx = Default;
259 break;
260 }
261 const auto EntryIdx = (Opcode - LowerBound);
262 // Each entry is 4 bytes
263 CurrentIdx =
264 readBytesAs<uint32_t>(MatchTable + CurrentIdx + (EntryIdx * 4));
265 if (!CurrentIdx) {
266 CurrentIdx = Default;
267 break;
268 }
269 OnFailResumeAt.push_back(Default);
270 break;
271 }
272
273 case GIM_SwitchType:
274 case GIM_SwitchTypeShape: {
275 uint64_t InsnID = readULEB();
276 uint64_t OpIdx = readULEB();
277 uint16_t LowerBound = readU16();
278 uint16_t UpperBound = readU16();
279 int64_t Default = readU32();
280 bool IsShape = MatcherOpcode == GIM_SwitchTypeShape;
281
282 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
283 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
284
285 DEBUG_WITH_TYPE(TgtExecutor::getName(), {
286 dbgs() << CurrentIdx << ": GIM_SwitchType" << (IsShape ? "Shape" : "")
287 << "(MIs[" << InsnID << "]->getOperand(" << OpIdx << "), ["
288 << LowerBound << ", " << UpperBound << "), Default=" << Default
289 << ", JumpTable...) // Got=";
290 if (!MO.isReg())
291 dbgs() << "Not a VReg\n";
292 else
293 dbgs() << MRI.getType(MO.getReg()) << "\n";
294 });
295 if (!MO.isReg()) {
296 CurrentIdx = Default;
297 break;
298 }
299
300 LLT Ty = MRI.getType(MO.getReg());
301 if (IsShape)
302 Ty = Ty.changeElementType(LLT::scalar(Ty.getScalarSizeInBits()));
303
304 const auto TyI = ExecInfo.TypeIDMap.find(Ty.getUniqueRAWLLTData());
305 if (TyI == ExecInfo.TypeIDMap.end()) {
306 CurrentIdx = Default;
307 break;
308 }
309 const int64_t TypeID = TyI->second;
310 if (TypeID < LowerBound || UpperBound <= TypeID) {
311 CurrentIdx = Default;
312 break;
313 }
314 const auto NumEntry = (TypeID - LowerBound);
315 // Each entry is 4 bytes
316 CurrentIdx =
317 readBytesAs<uint32_t>(MatchTable + CurrentIdx + (NumEntry * 4));
318 if (!CurrentIdx) {
319 CurrentIdx = Default;
320 break;
321 }
322 OnFailResumeAt.push_back(Default);
323 break;
324 }
325
328 uint64_t InsnID = readULEB();
329 uint64_t Expected = readULEB();
330 const bool IsLE = (MatcherOpcode == GIM_CheckNumOperandsLE);
331 DEBUG_WITH_TYPE(TgtExecutor::getName(),
332 dbgs() << CurrentIdx << ": GIM_CheckNumOperands"
333 << (IsLE ? "LE" : "GE") << "(MIs[" << InsnID
334 << "], Expected=" << Expected << ")\n");
335 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
336 const unsigned NumOps = State.MIs[InsnID]->getNumOperands();
337 if (IsLE ? (NumOps > Expected) : (NumOps < Expected)) {
338 if (handleReject() == RejectAndGiveUp)
339 return false;
340 }
341 break;
342 }
344 uint64_t InsnID = readULEB();
345 uint64_t Expected = readULEB();
346 DEBUG_WITH_TYPE(TgtExecutor::getName(),
347 dbgs() << CurrentIdx << ": GIM_CheckNumOperands(MIs["
348 << InsnID << "], Expected=" << Expected << ")\n");
349 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
350 if (State.MIs[InsnID]->getNumOperands() != Expected) {
351 if (handleReject() == RejectAndGiveUp)
352 return false;
353 }
354 break;
355 }
358 uint64_t InsnID = readULEB();
359 unsigned OpIdx =
360 MatcherOpcode == GIM_CheckImmOperandPredicate ? readULEB() : 1;
361 uint16_t Predicate = readU16();
362 DEBUG_WITH_TYPE(TgtExecutor::getName(),
363 dbgs() << CurrentIdx << ": GIM_CheckImmPredicate(MIs["
364 << InsnID << "]->getOperand(" << OpIdx
365 << "), Predicate=" << Predicate << ")\n");
366 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
367 assert((State.MIs[InsnID]->getOperand(OpIdx).isImm() ||
368 State.MIs[InsnID]->getOperand(OpIdx).isCImm()) &&
369 "Expected immediate operand");
370 assert(Predicate > GICXXPred_Invalid && "Expected a valid predicate");
371 int64_t Value = 0;
372 if (State.MIs[InsnID]->getOperand(OpIdx).isCImm())
373 Value = State.MIs[InsnID]->getOperand(OpIdx).getCImm()->getSExtValue();
374 else if (State.MIs[InsnID]->getOperand(OpIdx).isImm())
375 Value = State.MIs[InsnID]->getOperand(OpIdx).getImm();
376 else
377 llvm_unreachable("Expected Imm or CImm operand");
378
380 if (handleReject() == RejectAndGiveUp)
381 return false;
382 break;
383 }
385 uint64_t InsnID = readULEB();
386 uint16_t Predicate = readU16();
387 DEBUG_WITH_TYPE(TgtExecutor::getName(),
388 dbgs()
389 << CurrentIdx << ": GIM_CheckAPIntImmPredicate(MIs["
390 << InsnID << "], Predicate=" << Predicate << ")\n");
391 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
392 assert(State.MIs[InsnID]->getOpcode() == TargetOpcode::G_CONSTANT &&
393 "Expected G_CONSTANT");
394 assert(Predicate > GICXXPred_Invalid && "Expected a valid predicate");
395 if (!State.MIs[InsnID]->getOperand(1).isCImm())
396 llvm_unreachable("Expected Imm or CImm operand");
397
398 const APInt &Value =
399 State.MIs[InsnID]->getOperand(1).getCImm()->getValue();
401 if (handleReject() == RejectAndGiveUp)
402 return false;
403 break;
404 }
406 uint64_t InsnID = readULEB();
407 uint16_t Predicate = readU16();
408 DEBUG_WITH_TYPE(TgtExecutor::getName(),
409 dbgs()
410 << CurrentIdx << ": GIM_CheckAPFloatImmPredicate(MIs["
411 << InsnID << "], Predicate=" << Predicate << ")\n");
412 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
413 assert(State.MIs[InsnID]->getOpcode() == TargetOpcode::G_FCONSTANT &&
414 "Expected G_FCONSTANT");
415 assert(State.MIs[InsnID]->getOperand(1).isFPImm() &&
416 "Expected FPImm operand");
417 assert(Predicate > GICXXPred_Invalid && "Expected a valid predicate");
418 const APFloat &Value =
419 State.MIs[InsnID]->getOperand(1).getFPImm()->getValueAPF();
420
422 if (handleReject() == RejectAndGiveUp)
423 return false;
424 break;
425 }
427 uint64_t InsnID = readULEB();
428 uint64_t OpIdx = readULEB();
429 uint16_t Predicate = readU16();
430 DEBUG_WITH_TYPE(TgtExecutor::getName(),
431 dbgs() << CurrentIdx
432 << ": GIM_CheckLeafOperandPredicate(MIs[" << InsnID
433 << "]->getOperand(" << OpIdx
434 << "), Predicate=" << Predicate << ")\n");
435 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
436 assert(State.MIs[InsnID]->getOperand(OpIdx).isReg() &&
437 "Expected register operand");
438 assert(Predicate > GICXXPred_Invalid && "Expected a valid predicate");
439 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
440
441 if (!testMOPredicate_MO(Predicate, MO, State))
442 if (handleReject() == RejectAndGiveUp)
443 return false;
444 break;
445 }
448 uint64_t InsnID = readULEB();
449
450 DEBUG_WITH_TYPE(TgtExecutor::getName(),
451 dbgs() << CurrentIdx
452 << ": GIM_CheckBuildVectorAll{Zeros|Ones}(MIs["
453 << InsnID << "])\n");
454 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
455
456 const MachineInstr *MI = State.MIs[InsnID];
457 assert((MI->getOpcode() == TargetOpcode::G_BUILD_VECTOR ||
458 MI->getOpcode() == TargetOpcode::G_BUILD_VECTOR_TRUNC) &&
459 "Expected G_BUILD_VECTOR or G_BUILD_VECTOR_TRUNC");
460
461 if (MatcherOpcode == GIM_CheckIsBuildVectorAllOnes) {
462 if (!isBuildVectorAllOnes(*MI, MRI)) {
463 if (handleReject() == RejectAndGiveUp)
464 return false;
465 }
466 } else {
467 if (!isBuildVectorAllZeros(*MI, MRI)) {
468 if (handleReject() == RejectAndGiveUp)
469 return false;
470 }
471 }
472
473 break;
474 }
476 // Note: we don't check for invalid here because this is purely a hook to
477 // allow some executors (such as the combiner) to check arbitrary,
478 // contextless predicates, such as whether a rule is enabled or not.
479 uint16_t Predicate = readU16();
480 DEBUG_WITH_TYPE(TgtExecutor::getName(),
481 dbgs() << CurrentIdx
482 << ": GIM_CheckSimplePredicate(Predicate="
483 << Predicate << ")\n");
484 assert(Predicate > GICXXPred_Invalid && "Expected a valid predicate");
486 if (handleReject() == RejectAndGiveUp)
487 return false;
488 }
489 break;
490 }
492 uint64_t InsnID = readULEB();
493 uint16_t Predicate = readU16();
494 DEBUG_WITH_TYPE(TgtExecutor::getName(),
495 dbgs()
496 << CurrentIdx << ": GIM_CheckCxxPredicate(MIs["
497 << InsnID << "], Predicate=" << Predicate << ")\n");
498 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
499 assert(Predicate > GICXXPred_Invalid && "Expected a valid predicate");
500
501 if (!testMIPredicate_MI(Predicate, *State.MIs[InsnID], State))
502 if (handleReject() == RejectAndGiveUp)
503 return false;
504 break;
505 }
506 case GIM_CheckHasNoUse: {
507 uint64_t InsnID = readULEB();
508
509 DEBUG_WITH_TYPE(TgtExecutor::getName(),
510 dbgs() << CurrentIdx << ": GIM_CheckHasNoUse(MIs["
511 << InsnID << "]\n");
512
513 const MachineInstr *MI = State.MIs[InsnID];
514 assert(MI && "Used insn before defined");
515 assert(MI->getNumDefs() > 0 && "No defs");
516 const Register Res = MI->getOperand(0).getReg();
517
518 if (!MRI.use_nodbg_empty(Res)) {
519 if (handleReject() == RejectAndGiveUp)
520 return false;
521 }
522 break;
523 }
524 case GIM_CheckHasOneUse: {
525 uint64_t InsnID = readULEB();
526
527 DEBUG_WITH_TYPE(TgtExecutor::getName(),
528 dbgs() << CurrentIdx << ": GIM_CheckHasOneUse(MIs["
529 << InsnID << "]\n");
530
531 const MachineInstr *MI = State.MIs[InsnID];
532 assert(MI && "Used insn before defined");
533 assert(MI->getNumDefs() > 0 && "No defs");
534 const Register Res = MI->getOperand(0).getReg();
535
536 if (!MRI.hasOneNonDBGUse(Res)) {
537 if (handleReject() == RejectAndGiveUp)
538 return false;
539 }
540 break;
541 }
543 uint64_t InsnID = readULEB();
544 auto Ordering = (AtomicOrdering)MatchTable[CurrentIdx++];
545 DEBUG_WITH_TYPE(TgtExecutor::getName(),
546 dbgs() << CurrentIdx << ": GIM_CheckAtomicOrdering(MIs["
547 << InsnID << "], " << (uint64_t)Ordering << ")\n");
548 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
549 if (!State.MIs[InsnID]->hasOneMemOperand())
550 if (handleReject() == RejectAndGiveUp)
551 return false;
552
553 for (const auto &MMO : State.MIs[InsnID]->memoperands())
554 if (MMO->getMergedOrdering() != Ordering)
555 if (handleReject() == RejectAndGiveUp)
556 return false;
557 break;
558 }
560 uint64_t InsnID = readULEB();
561 auto Ordering = (AtomicOrdering)MatchTable[CurrentIdx++];
562 DEBUG_WITH_TYPE(TgtExecutor::getName(),
563 dbgs() << CurrentIdx
564 << ": GIM_CheckAtomicOrderingOrStrongerThan(MIs["
565 << InsnID << "], " << (uint64_t)Ordering << ")\n");
566 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
567 if (!State.MIs[InsnID]->hasOneMemOperand())
568 if (handleReject() == RejectAndGiveUp)
569 return false;
570
571 for (const auto &MMO : State.MIs[InsnID]->memoperands())
572 if (!isAtLeastOrStrongerThan(MMO->getMergedOrdering(), Ordering))
573 if (handleReject() == RejectAndGiveUp)
574 return false;
575 break;
576 }
578 uint64_t InsnID = readULEB();
579 auto Ordering = (AtomicOrdering)MatchTable[CurrentIdx++];
580 DEBUG_WITH_TYPE(TgtExecutor::getName(),
581 dbgs() << CurrentIdx
582 << ": GIM_CheckAtomicOrderingWeakerThan(MIs["
583 << InsnID << "], " << (uint64_t)Ordering << ")\n");
584 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
585 if (!State.MIs[InsnID]->hasOneMemOperand())
586 if (handleReject() == RejectAndGiveUp)
587 return false;
588
589 for (const auto &MMO : State.MIs[InsnID]->memoperands())
590 if (!isStrongerThan(Ordering, MMO->getMergedOrdering()))
591 if (handleReject() == RejectAndGiveUp)
592 return false;
593 break;
594 }
596 uint64_t InsnID = readULEB();
597 uint64_t MMOIdx = readULEB();
598 // This accepts a list of possible address spaces.
599 const uint64_t NumAddrSpace = MatchTable[CurrentIdx++];
600
601 if (State.MIs[InsnID]->getNumMemOperands() <= MMOIdx) {
602 if (handleReject() == RejectAndGiveUp)
603 return false;
604 break;
605 }
606
607 // Need to still jump to the end of the list of address spaces if we find
608 // a match earlier.
609 const uint64_t LastIdx = CurrentIdx + NumAddrSpace;
610
611 const MachineMemOperand *MMO =
612 *(State.MIs[InsnID]->memoperands_begin() + MMOIdx);
613 const unsigned MMOAddrSpace = MMO->getAddrSpace();
614
615 bool Success = false;
616 for (unsigned I = 0; I != NumAddrSpace; ++I) {
617 uint64_t AddrSpace = readULEB();
618 DEBUG_WITH_TYPE(TgtExecutor::getName(),
619 dbgs() << "addrspace(" << MMOAddrSpace << ") vs "
620 << AddrSpace << '\n');
621
622 if (AddrSpace == MMOAddrSpace) {
623 Success = true;
624 break;
625 }
626 }
627
628 CurrentIdx = LastIdx;
629 if (!Success && handleReject() == RejectAndGiveUp)
630 return false;
631 break;
632 }
634 uint64_t InsnID = readULEB();
635 uint64_t MMOIdx = readULEB();
636 uint64_t MinAlign = MatchTable[CurrentIdx++];
637
638 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
639
640 if (State.MIs[InsnID]->getNumMemOperands() <= MMOIdx) {
641 if (handleReject() == RejectAndGiveUp)
642 return false;
643 break;
644 }
645
646 MachineMemOperand *MMO =
647 *(State.MIs[InsnID]->memoperands_begin() + MMOIdx);
648 DEBUG_WITH_TYPE(TgtExecutor::getName(),
649 dbgs() << CurrentIdx << ": GIM_CheckMemoryAlignment"
650 << "(MIs[" << InsnID << "]->memoperands() + "
651 << MMOIdx << ")->getAlignment() >= " << MinAlign
652 << ")\n");
653 if (MMO->getAlign() < MinAlign && handleReject() == RejectAndGiveUp)
654 return false;
655
656 break;
657 }
659 uint64_t InsnID = readULEB();
660 uint64_t MMOIdx = readULEB();
661 uint32_t Size = readU32();
662
663 DEBUG_WITH_TYPE(TgtExecutor::getName(),
664 dbgs() << CurrentIdx << ": GIM_CheckMemorySizeEqual(MIs["
665 << InsnID << "]->memoperands() + " << MMOIdx
666 << ", Size=" << Size << ")\n");
667 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
668
669 if (State.MIs[InsnID]->getNumMemOperands() <= MMOIdx) {
670 if (handleReject() == RejectAndGiveUp)
671 return false;
672 break;
673 }
674
675 MachineMemOperand *MMO =
676 *(State.MIs[InsnID]->memoperands_begin() + MMOIdx);
677
678 DEBUG_WITH_TYPE(TgtExecutor::getName(), dbgs() << MMO->getSize()
679 << " bytes vs " << Size
680 << " bytes\n");
681 if (MMO->getSize() != Size)
682 if (handleReject() == RejectAndGiveUp)
683 return false;
684
685 break;
686 }
690 uint64_t InsnID = readULEB();
691 uint64_t MMOIdx = readULEB();
692 uint64_t OpIdx = readULEB();
693
695 TgtExecutor::getName(),
696 dbgs() << CurrentIdx << ": GIM_CheckMemorySize"
697 << (MatcherOpcode == GIM_CheckMemorySizeEqualToLLT ? "EqualTo"
698 : MatcherOpcode == GIM_CheckMemorySizeGreaterThanLLT
699 ? "GreaterThan"
700 : "LessThan")
701 << "LLT(MIs[" << InsnID << "]->memoperands() + " << MMOIdx
702 << ", OpIdx=" << OpIdx << ")\n");
703 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
704
705 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
706 if (!MO.isReg()) {
707 DEBUG_WITH_TYPE(TgtExecutor::getName(),
708 dbgs() << CurrentIdx << ": Not a register\n");
709 if (handleReject() == RejectAndGiveUp)
710 return false;
711 break;
712 }
713
714 if (State.MIs[InsnID]->getNumMemOperands() <= MMOIdx) {
715 if (handleReject() == RejectAndGiveUp)
716 return false;
717 break;
718 }
719
720 MachineMemOperand *MMO =
721 *(State.MIs[InsnID]->memoperands_begin() + MMOIdx);
722
723 const TypeSize Size = MRI.getType(MO.getReg()).getSizeInBits();
724 if (MatcherOpcode == GIM_CheckMemorySizeEqualToLLT &&
725 MMO->getSizeInBits() != Size) {
726 if (handleReject() == RejectAndGiveUp)
727 return false;
728 } else if (MatcherOpcode == GIM_CheckMemorySizeLessThanLLT &&
730 if (handleReject() == RejectAndGiveUp)
731 return false;
732 } else if (MatcherOpcode == GIM_CheckMemorySizeGreaterThanLLT &&
734 if (handleReject() == RejectAndGiveUp)
735 return false;
736
737 break;
738 }
740 case GIM_CheckType: {
741 uint64_t InsnID = (MatcherOpcode == GIM_RootCheckType) ? 0 : readULEB();
742 uint64_t OpIdx = readULEB();
743 int TypeID = readS8();
744 DEBUG_WITH_TYPE(TgtExecutor::getName(),
745 dbgs() << CurrentIdx << ": GIM_CheckType(MIs[" << InsnID
746 << "]->getOperand(" << OpIdx
747 << "), TypeID=" << TypeID << ")\n");
748 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
749 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
750 if (!MO.isReg() || MRI.getType(MO.getReg()) != getTypeFromIdx(TypeID)) {
751 if (handleReject() == RejectAndGiveUp)
752 return false;
753 }
754 break;
755 }
757 uint64_t InsnID = readULEB();
758 uint64_t OpIdx = readULEB();
759 uint64_t SizeInBits = readULEB();
760
761 DEBUG_WITH_TYPE(TgtExecutor::getName(),
762 dbgs() << CurrentIdx << ": GIM_CheckPointerToAny(MIs["
763 << InsnID << "]->getOperand(" << OpIdx
764 << "), SizeInBits=" << SizeInBits << ")\n");
765 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
766 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
767 const LLT Ty = MRI.getType(MO.getReg());
768
769 // iPTR must be looked up in the target.
770 if (SizeInBits == 0) {
771 MachineFunction *MF = State.MIs[InsnID]->getParent()->getParent();
772 const unsigned AddrSpace = Ty.getAddressSpace();
773 SizeInBits = MF->getDataLayout().getPointerSizeInBits(AddrSpace);
774 }
775
776 assert(SizeInBits != 0 && "Pointer size must be known");
777
778 if (MO.isReg()) {
779 if (!Ty.isPointer() || Ty.getSizeInBits() != SizeInBits)
780 if (handleReject() == RejectAndGiveUp)
781 return false;
782 } else if (handleReject() == RejectAndGiveUp)
783 return false;
784
785 break;
786 }
788 uint64_t InsnID = readULEB();
789 uint64_t OpIdx = readULEB();
790 uint64_t StoreIdx = readULEB();
791
792 DEBUG_WITH_TYPE(TgtExecutor::getName(),
793 dbgs() << CurrentIdx << ": GIM_RecordNamedOperand(MIs["
794 << InsnID << "]->getOperand(" << OpIdx
795 << "), StoreIdx=" << StoreIdx << ")\n");
796 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
797 assert(StoreIdx < State.RecordedOperands.size() && "Index out of range");
798 State.RecordedOperands[StoreIdx] = &State.MIs[InsnID]->getOperand(OpIdx);
799 break;
800 }
801 case GIM_RecordRegType: {
802 uint64_t InsnID = readULEB();
803 uint64_t OpIdx = readULEB();
804 int TypeIdx = readS8();
805
806 DEBUG_WITH_TYPE(TgtExecutor::getName(),
807 dbgs() << CurrentIdx << ": GIM_RecordRegType(MIs["
808 << InsnID << "]->getOperand(" << OpIdx
809 << "), TypeIdx=" << TypeIdx << ")\n");
810 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
811 assert(TypeIdx < 0 && "Temp types always have negative indexes!");
812 // Indexes start at -1.
813 TypeIdx = 1 - TypeIdx;
814 const auto &Op = State.MIs[InsnID]->getOperand(OpIdx);
815 if (State.RecordedTypes.size() <= (uint64_t)TypeIdx)
816 State.RecordedTypes.resize(TypeIdx + 1, LLT());
817 State.RecordedTypes[TypeIdx] = MRI.getType(Op.getReg());
818 break;
819 }
820
823 uint64_t InsnID =
824 (MatcherOpcode == GIM_RootCheckRegBankForClass) ? 0 : readULEB();
825 uint64_t OpIdx = readULEB();
826 uint16_t RCEnum = readU16();
827 DEBUG_WITH_TYPE(TgtExecutor::getName(),
828 dbgs() << CurrentIdx << ": GIM_CheckRegBankForClass(MIs["
829 << InsnID << "]->getOperand(" << OpIdx
830 << "), RCEnum=" << RCEnum << ")\n");
831 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
832 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
833 if (!MO.isReg() ||
834 &RBI.getRegBankFromRegClass(*TRI.getRegClass(RCEnum),
835 MRI.getType(MO.getReg())) !=
836 RBI.getRegBank(MO.getReg(), MRI, TRI)) {
837 if (handleReject() == RejectAndGiveUp)
838 return false;
839 }
840 break;
841 }
842
844 uint64_t InsnID = readULEB();
845 uint64_t OpIdx = readULEB();
846 uint16_t RendererID = readU16();
847 uint16_t ComplexPredicateID = readU16();
848 DEBUG_WITH_TYPE(TgtExecutor::getName(),
849 dbgs() << CurrentIdx << ": State.Renderers[" << RendererID
850 << "] = GIM_CheckComplexPattern(MIs[" << InsnID
851 << "]->getOperand(" << OpIdx
852 << "), ComplexPredicateID=" << ComplexPredicateID
853 << ")\n");
854 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
855 // FIXME: Use std::invoke() when it's available.
856 ComplexRendererFns Renderer =
857 (Exec.*ExecInfo.ComplexPredicates[ComplexPredicateID])(
858 State.MIs[InsnID]->getOperand(OpIdx));
859 if (Renderer)
860 State.Renderers[RendererID] = *Renderer;
861 else if (handleReject() == RejectAndGiveUp)
862 return false;
863 break;
864 }
865
868 const bool IsInt8 = (MatcherOpcode == GIM_CheckConstantInt8);
869
870 uint64_t InsnID = readULEB();
871 uint64_t OpIdx = readULEB();
872 uint64_t Value = IsInt8 ? (int64_t)readS8() : readU64();
873 DEBUG_WITH_TYPE(TgtExecutor::getName(),
874 dbgs() << CurrentIdx << ": GIM_CheckConstantInt(MIs["
875 << InsnID << "]->getOperand(" << OpIdx
876 << "), Value=" << Value << ")\n");
877 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
878 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
879 if (MO.isReg()) {
880 // isOperandImmEqual() will sign-extend to 64-bits, so should we.
881 LLT Ty = MRI.getType(MO.getReg());
882 // If the type is > 64 bits, it can't be a constant int, so we bail
883 // early because SignExtend64 will assert otherwise.
884 if (Ty.getScalarSizeInBits() > 64) {
885 if (handleReject() == RejectAndGiveUp)
886 return false;
887 break;
888 }
889
890 Value = SignExtend64(Value, Ty.getScalarSizeInBits());
891 if (!isOperandImmEqual(MO, Value, MRI, /*Splat=*/true)) {
892 if (handleReject() == RejectAndGiveUp)
893 return false;
894 }
895 } else if (handleReject() == RejectAndGiveUp)
896 return false;
897
898 break;
899 }
900
901 case GIM_CheckLiteralInt: {
902 uint64_t InsnID = readULEB();
903 uint64_t OpIdx = readULEB();
904 int64_t Value = readU64();
905 DEBUG_WITH_TYPE(TgtExecutor::getName(),
906 dbgs() << CurrentIdx << ": GIM_CheckLiteralInt(MIs["
907 << InsnID << "]->getOperand(" << OpIdx
908 << "), Value=" << Value << ")\n");
909 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
910 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
911 if (MO.isImm() && MO.getImm() == Value)
912 break;
913
914 if (MO.isCImm() && MO.getCImm()->equalsInt(Value))
915 break;
916
917 if (handleReject() == RejectAndGiveUp)
918 return false;
919
920 break;
921 }
922
924 uint64_t InsnID = readULEB();
925 uint64_t OpIdx = readULEB();
926 uint16_t Value = readU16();
927 DEBUG_WITH_TYPE(TgtExecutor::getName(),
928 dbgs() << CurrentIdx << ": GIM_CheckIntrinsicID(MIs["
929 << InsnID << "]->getOperand(" << OpIdx
930 << "), Value=" << Value << ")\n");
931 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
932 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
933 if (!MO.isIntrinsicID() || MO.getIntrinsicID() != Value)
934 if (handleReject() == RejectAndGiveUp)
935 return false;
936 break;
937 }
939 uint64_t InsnID = readULEB();
940 uint64_t OpIdx = readULEB();
941 uint16_t Value = readU16();
942 DEBUG_WITH_TYPE(TgtExecutor::getName(),
943 dbgs() << CurrentIdx << ": GIM_CheckCmpPredicate(MIs["
944 << InsnID << "]->getOperand(" << OpIdx
945 << "), Value=" << Value << ")\n");
946 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
947 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
948 if (!MO.isPredicate() || MO.getPredicate() != Value)
949 if (handleReject() == RejectAndGiveUp)
950 return false;
951 break;
952 }
953 case GIM_CheckIsMBB: {
954 uint64_t InsnID = readULEB();
955 uint64_t OpIdx = readULEB();
956 DEBUG_WITH_TYPE(TgtExecutor::getName(),
957 dbgs() << CurrentIdx << ": GIM_CheckIsMBB(MIs[" << InsnID
958 << "]->getOperand(" << OpIdx << "))\n");
959 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
960 if (!State.MIs[InsnID]->getOperand(OpIdx).isMBB()) {
961 if (handleReject() == RejectAndGiveUp)
962 return false;
963 }
964 break;
965 }
966 case GIM_CheckIsImm: {
967 uint64_t InsnID = readULEB();
968 uint64_t OpIdx = readULEB();
969 DEBUG_WITH_TYPE(TgtExecutor::getName(),
970 dbgs() << CurrentIdx << ": GIM_CheckIsImm(MIs[" << InsnID
971 << "]->getOperand(" << OpIdx << "))\n");
972 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
973 if (!State.MIs[InsnID]->getOperand(OpIdx).isImm()) {
974 if (handleReject() == RejectAndGiveUp)
975 return false;
976 }
977 break;
978 }
980 uint64_t NumInsn = MatchTable[CurrentIdx++];
981 DEBUG_WITH_TYPE(TgtExecutor::getName(),
982 dbgs() << CurrentIdx << ": GIM_CheckIsSafeToFold(N = "
983 << NumInsn << ")\n");
984 MachineInstr &Root = *State.MIs[0];
985 for (unsigned K = 1, E = NumInsn + 1; K < E; ++K) {
986 if (!isObviouslySafeToFold(*State.MIs[K], Root)) {
987 if (handleReject() == RejectAndGiveUp)
988 return false;
989 }
990 }
991 break;
992 }
995 uint64_t InsnID = readULEB();
996 uint64_t OpIdx = readULEB();
997 uint64_t OtherInsnID = readULEB();
998 uint64_t OtherOpIdx = readULEB();
999 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1000 dbgs() << CurrentIdx << ": GIM_CheckIsSameOperand(MIs["
1001 << InsnID << "][" << OpIdx << "], MIs["
1002 << OtherInsnID << "][" << OtherOpIdx << "])\n");
1003 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
1004 assert(State.MIs[OtherInsnID] != nullptr && "Used insn before defined");
1005
1006 MachineOperand &Op = State.MIs[InsnID]->getOperand(OpIdx);
1007 MachineOperand &OtherOp = State.MIs[OtherInsnID]->getOperand(OtherOpIdx);
1008
1009 if (MatcherOpcode == GIM_CheckIsSameOperandIgnoreCopies) {
1010 if (Op.isReg() && OtherOp.isReg()) {
1011 if (getSrcRegIgnoringCopies(Op.getReg(), MRI) ==
1012 getSrcRegIgnoringCopies(OtherOp.getReg(), MRI))
1013 break;
1014 }
1015 }
1016
1017 if (!Op.isIdenticalTo(OtherOp)) {
1018 if (handleReject() == RejectAndGiveUp)
1019 return false;
1020 }
1021 break;
1022 }
1024 uint64_t OldInsnID = readULEB();
1025 uint64_t OldOpIdx = readULEB();
1026 uint64_t NewInsnID = readULEB();
1027 uint64_t NewOpIdx = readULEB();
1028
1029 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1030 dbgs() << CurrentIdx << ": GIM_CheckCanReplaceReg(MIs["
1031 << OldInsnID << "][" << OldOpIdx << "] = MIs["
1032 << NewInsnID << "][" << NewOpIdx << "])\n");
1033
1034 Register Old = State.MIs[OldInsnID]->getOperand(OldOpIdx).getReg();
1035 Register New = State.MIs[NewInsnID]->getOperand(NewOpIdx).getReg();
1036 if (!canReplaceReg(Old, New, MRI)) {
1037 if (handleReject() == RejectAndGiveUp)
1038 return false;
1039 }
1040 break;
1041 }
1042 case GIM_MIFlags: {
1043 uint64_t InsnID = readULEB();
1044 uint32_t Flags = readU32();
1045
1046 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1047 dbgs() << CurrentIdx << ": GIM_MIFlags(MIs[" << InsnID
1048 << "], " << Flags << ")\n");
1049 if ((State.MIs[InsnID]->getFlags() & Flags) != Flags) {
1050 if (handleReject() == RejectAndGiveUp)
1051 return false;
1052 }
1053 break;
1054 }
1055 case GIM_MIFlagsNot: {
1056 uint64_t InsnID = readULEB();
1057 uint32_t Flags = readU32();
1058
1059 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1060 dbgs() << CurrentIdx << ": GIM_MIFlagsNot(MIs[" << InsnID
1061 << "], " << Flags << ")\n");
1062 if ((State.MIs[InsnID]->getFlags() & Flags)) {
1063 if (handleReject() == RejectAndGiveUp)
1064 return false;
1065 }
1066 break;
1067 }
1068 case GIM_Reject:
1069 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1070 dbgs() << CurrentIdx << ": GIM_Reject\n");
1071 if (handleReject() == RejectAndGiveUp)
1072 return false;
1073 break;
1074 case GIR_MutateOpcode: {
1075 uint64_t OldInsnID = readULEB();
1076 uint64_t NewInsnID = readULEB();
1077 uint32_t NewOpcode = readU16();
1078 if (NewInsnID >= OutMIs.size())
1079 OutMIs.resize(NewInsnID + 1);
1080
1081 MachineInstr *OldMI = State.MIs[OldInsnID];
1082 if (Observer)
1083 Observer->changingInstr(*OldMI);
1084 OutMIs[NewInsnID] = MachineInstrBuilder(*OldMI->getMF(), OldMI);
1085 OutMIs[NewInsnID]->setDesc(TII.get(NewOpcode));
1086 if (Observer)
1087 Observer->changedInstr(*OldMI);
1088 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1089 dbgs() << CurrentIdx << ": GIR_MutateOpcode(OutMIs["
1090 << NewInsnID << "], MIs[" << OldInsnID << "], "
1091 << NewOpcode << ")\n");
1092 break;
1093 }
1094
1095 case GIR_BuildRootMI:
1096 case GIR_BuildMI: {
1097 uint64_t NewInsnID = (MatcherOpcode == GIR_BuildRootMI) ? 0 : readULEB();
1098 uint32_t Opcode = readU16();
1099 if (NewInsnID >= OutMIs.size())
1100 OutMIs.resize(NewInsnID + 1);
1101
1102 initializeBuilder();
1103 OutMIs[NewInsnID] = Builder.buildInstr(Opcode);
1104 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1105 dbgs() << CurrentIdx << ": GIR_BuildMI(OutMIs["
1106 << NewInsnID << "], " << Opcode << ")\n");
1107 break;
1108 }
1109
1110 case GIR_BuildConstant: {
1111 uint64_t TempRegID = readULEB();
1112 uint64_t Imm = readU64();
1113 initializeBuilder();
1114 Builder.buildConstant(State.TempRegisters[TempRegID], Imm);
1115 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1116 dbgs() << CurrentIdx << ": GIR_BuildConstant(TempReg["
1117 << TempRegID << "], Imm=" << Imm << ")\n");
1118 break;
1119 }
1120
1121 case GIR_RootToRootCopy:
1122 case GIR_Copy: {
1123 uint64_t NewInsnID =
1124 (MatcherOpcode == GIR_RootToRootCopy) ? 0 : readULEB();
1125 uint64_t OldInsnID =
1126 (MatcherOpcode == GIR_RootToRootCopy) ? 0 : readULEB();
1127 uint64_t OpIdx = readULEB();
1128 assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
1129 OutMIs[NewInsnID].add(State.MIs[OldInsnID]->getOperand(OpIdx));
1130 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1131 dbgs()
1132 << CurrentIdx << ": GIR_Copy(OutMIs[" << NewInsnID
1133 << "], MIs[" << OldInsnID << "], " << OpIdx << ")\n");
1134 break;
1135 }
1136
1137 case GIR_CopyRemaining: {
1138 uint64_t NewInsnID = readULEB();
1139 uint64_t OldInsnID = readULEB();
1140 uint64_t OpIdx = readULEB();
1141 assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
1142 MachineInstr &OldMI = *State.MIs[OldInsnID];
1143 MachineInstrBuilder &NewMI = OutMIs[NewInsnID];
1144 for (const auto &Op : drop_begin(OldMI.operands(), OpIdx))
1145 NewMI.add(Op);
1146 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1147 dbgs() << CurrentIdx << ": GIR_CopyRemaining(OutMIs["
1148 << NewInsnID << "], MIs[" << OldInsnID
1149 << "], /*start=*/" << OpIdx << ")\n");
1150 break;
1151 }
1152
1153 case GIR_CopyOrAddZeroReg: {
1154 uint64_t NewInsnID = readULEB();
1155 uint64_t OldInsnID = readULEB();
1156 uint64_t OpIdx = readULEB();
1157 uint16_t ZeroReg = readU16();
1158 assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
1159 MachineOperand &MO = State.MIs[OldInsnID]->getOperand(OpIdx);
1160 if (isOperandImmEqual(MO, 0, MRI))
1161 OutMIs[NewInsnID].addReg(ZeroReg);
1162 else
1163 OutMIs[NewInsnID].add(MO);
1164 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1165 dbgs() << CurrentIdx << ": GIR_CopyOrAddZeroReg(OutMIs["
1166 << NewInsnID << "], MIs[" << OldInsnID << "], "
1167 << OpIdx << ", " << ZeroReg << ")\n");
1168 break;
1169 }
1170
1171 case GIR_CopySubReg: {
1172 uint64_t NewInsnID = readULEB();
1173 uint64_t OldInsnID = readULEB();
1174 uint64_t OpIdx = readULEB();
1175 uint16_t SubRegIdx = readU16();
1176 assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
1177 OutMIs[NewInsnID].addReg(State.MIs[OldInsnID]->getOperand(OpIdx).getReg(),
1178 {}, SubRegIdx);
1179 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1180 dbgs() << CurrentIdx << ": GIR_CopySubReg(OutMIs["
1181 << NewInsnID << "], MIs[" << OldInsnID << "], "
1182 << OpIdx << ", " << SubRegIdx << ")\n");
1183 break;
1184 }
1185
1186 case GIR_AddImplicitDef: {
1187 uint64_t InsnID = readULEB();
1188 uint16_t RegNum = readU16();
1189 RegState Flags = static_cast<RegState>(readU16());
1190 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1191 Flags |= RegState::Implicit;
1192 OutMIs[InsnID].addDef(RegNum, Flags);
1193 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1194 dbgs() << CurrentIdx << ": GIR_AddImplicitDef(OutMIs["
1195 << InsnID << "], " << RegNum << ", "
1196 << static_cast<uint16_t>(Flags) << ")\n");
1197 break;
1198 }
1199
1200 case GIR_AddImplicitUse: {
1201 uint64_t InsnID = readULEB();
1202 uint16_t RegNum = readU16();
1203 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1204 OutMIs[InsnID].addUse(RegNum, RegState::Implicit);
1205 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1206 dbgs() << CurrentIdx << ": GIR_AddImplicitUse(OutMIs["
1207 << InsnID << "], " << RegNum << ")\n");
1208 break;
1209 }
1210
1211 case GIR_AddRegister: {
1212 uint64_t InsnID = readULEB();
1213 uint16_t RegNum = readU16();
1214 RegState RegFlags = static_cast<RegState>(readU16());
1215 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1216 OutMIs[InsnID].addReg(RegNum, RegFlags);
1217 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1218 dbgs() << CurrentIdx << ": GIR_AddRegister(OutMIs["
1219 << InsnID << "], " << RegNum << ", "
1220 << static_cast<uint16_t>(RegFlags) << ")\n");
1221 break;
1222 }
1223 case GIR_AddIntrinsicID: {
1224 uint64_t InsnID = readULEB();
1225 uint16_t Value = readU16();
1226 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1227 OutMIs[InsnID].addIntrinsicID((Intrinsic::ID)Value);
1228 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1229 dbgs() << CurrentIdx << ": GIR_AddIntrinsicID(OutMIs["
1230 << InsnID << "], " << Value << ")\n");
1231 break;
1232 }
1234 uint64_t InsnID = readULEB();
1235 uint64_t OpIdx = readULEB();
1236 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1237 dbgs() << CurrentIdx << ": GIR_SetImplicitDefDead(OutMIs["
1238 << InsnID << "], OpIdx=" << OpIdx << ")\n");
1239 MachineInstr *MI = OutMIs[InsnID];
1240 assert(MI && "Modifying undefined instruction");
1241 MI->getOperand(MI->getNumExplicitOperands() + OpIdx).setIsDead();
1242 break;
1243 }
1244 case GIR_SetMIFlags: {
1245 uint64_t InsnID = readULEB();
1246 uint32_t Flags = readU32();
1247
1248 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1249 dbgs() << CurrentIdx << ": GIR_SetMIFlags(OutMIs["
1250 << InsnID << "], " << Flags << ")\n");
1251 MachineInstr *MI = OutMIs[InsnID];
1252 MI->setFlags(MI->getFlags() | Flags);
1253 break;
1254 }
1255 case GIR_UnsetMIFlags: {
1256 uint64_t InsnID = readULEB();
1257 uint32_t Flags = readU32();
1258
1259 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1260 dbgs() << CurrentIdx << ": GIR_UnsetMIFlags(OutMIs["
1261 << InsnID << "], " << Flags << ")\n");
1262 MachineInstr *MI = OutMIs[InsnID];
1263 MI->setFlags(MI->getFlags() & ~Flags);
1264 break;
1265 }
1266 case GIR_CopyMIFlags: {
1267 uint64_t InsnID = readULEB();
1268 uint64_t OldInsnID = readULEB();
1269
1270 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1271 dbgs() << CurrentIdx << ": GIR_CopyMIFlags(OutMIs["
1272 << InsnID << "], MIs[" << OldInsnID << "])\n");
1273 MachineInstr *MI = OutMIs[InsnID];
1274 MI->setFlags(MI->getFlags() | State.MIs[OldInsnID]->getFlags());
1275 break;
1276 }
1280 uint64_t InsnID = readULEB();
1281 uint64_t TempRegID = readULEB();
1282 RegState TempRegFlags = {};
1283 if (MatcherOpcode != GIR_AddSimpleTempRegister)
1284 TempRegFlags = static_cast<RegState>(readU16());
1285 uint16_t SubReg = 0;
1286 if (MatcherOpcode == GIR_AddTempSubRegister)
1287 SubReg = readU16();
1288
1289 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1290
1291 OutMIs[InsnID].addReg(State.TempRegisters[TempRegID], TempRegFlags,
1292 SubReg);
1294 TgtExecutor::getName(),
1295 dbgs() << CurrentIdx << ": GIR_AddTempRegister(OutMIs[" << InsnID
1296 << "], TempRegisters[" << TempRegID << "]";
1297 if (SubReg) dbgs() << '.' << TRI.getSubRegIndexName(SubReg);
1298 dbgs() << ", " << static_cast<uint16_t>(TempRegFlags) << ")\n");
1299 break;
1300 }
1301
1302 case GIR_AddImm8:
1303 case GIR_AddImm: {
1304 const bool IsAdd8 = (MatcherOpcode == GIR_AddImm8);
1305 uint64_t InsnID = readULEB();
1306 uint64_t Imm = IsAdd8 ? (int64_t)readS8() : readU64();
1307 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1308 OutMIs[InsnID].addImm(Imm);
1309 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1310 dbgs() << CurrentIdx << ": GIR_AddImm(OutMIs[" << InsnID
1311 << "], " << Imm << ")\n");
1312 break;
1313 }
1314
1315 case GIR_AddCImm: {
1316 uint64_t InsnID = readULEB();
1317 int TypeID = readS8();
1318 uint64_t Imm = readU64();
1319 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1320
1321 unsigned Width = ExecInfo.TypeObjects[TypeID].getScalarSizeInBits();
1322 LLVMContext &Ctx = MF->getFunction().getContext();
1323 OutMIs[InsnID].addCImm(
1324 ConstantInt::get(IntegerType::get(Ctx, Width), Imm, /*signed*/ true));
1325 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1326 dbgs() << CurrentIdx << ": GIR_AddCImm(OutMIs[" << InsnID
1327 << "], TypeID=" << TypeID << ", Imm=" << Imm
1328 << ")\n");
1329 break;
1330 }
1331
1332 case GIR_ComplexRenderer: {
1333 uint64_t InsnID = readULEB();
1334 uint16_t RendererID = readU16();
1335 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1336 for (const auto &RenderOpFn : State.Renderers[RendererID])
1337 RenderOpFn(OutMIs[InsnID]);
1338 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1339 dbgs() << CurrentIdx << ": GIR_ComplexRenderer(OutMIs["
1340 << InsnID << "], " << RendererID << ")\n");
1341 break;
1342 }
1344 uint64_t InsnID = readULEB();
1345 uint16_t RendererID = readU16();
1346 uint64_t RenderOpID = readULEB();
1347 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1348 State.Renderers[RendererID][RenderOpID](OutMIs[InsnID]);
1349 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1350 dbgs() << CurrentIdx
1351 << ": GIR_ComplexSubOperandRenderer(OutMIs["
1352 << InsnID << "], " << RendererID << ", "
1353 << RenderOpID << ")\n");
1354 break;
1355 }
1357 uint64_t InsnID = readULEB();
1358 uint16_t RendererID = readU16();
1359 uint64_t RenderOpID = readULEB();
1360 uint16_t SubRegIdx = readU16();
1361 MachineInstrBuilder &MI = OutMIs[InsnID];
1362 assert(MI && "Attempted to add to undefined instruction");
1363 State.Renderers[RendererID][RenderOpID](MI);
1364 MI->getOperand(MI->getNumOperands() - 1).setSubReg(SubRegIdx);
1365 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1366 dbgs() << CurrentIdx
1367 << ": GIR_ComplexSubOperandSubRegRenderer(OutMIs["
1368 << InsnID << "], " << RendererID << ", "
1369 << RenderOpID << ", " << SubRegIdx << ")\n");
1370 break;
1371 }
1372
1374 uint64_t NewInsnID = readULEB();
1375 uint64_t OldInsnID = readULEB();
1376 assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
1377 assert(State.MIs[OldInsnID]->getOpcode() == TargetOpcode::G_CONSTANT &&
1378 "Expected G_CONSTANT");
1379 if (State.MIs[OldInsnID]->getOperand(1).isCImm()) {
1380 OutMIs[NewInsnID].addImm(
1381 State.MIs[OldInsnID]->getOperand(1).getCImm()->getSExtValue());
1382 } else if (State.MIs[OldInsnID]->getOperand(1).isImm())
1383 OutMIs[NewInsnID].add(State.MIs[OldInsnID]->getOperand(1));
1384 else
1385 llvm_unreachable("Expected Imm or CImm operand");
1386 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1387 dbgs() << CurrentIdx << ": GIR_CopyConstantAsSImm(OutMIs["
1388 << NewInsnID << "], MIs[" << OldInsnID << "])\n");
1389 break;
1390 }
1391
1392 // TODO: Needs a test case once we have a pattern that uses this.
1394 uint64_t NewInsnID = readULEB();
1395 uint64_t OldInsnID = readULEB();
1396 assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
1397 assert(State.MIs[OldInsnID]->getOpcode() == TargetOpcode::G_FCONSTANT &&
1398 "Expected G_FCONSTANT");
1399 if (State.MIs[OldInsnID]->getOperand(1).isFPImm())
1400 OutMIs[NewInsnID].addFPImm(
1401 State.MIs[OldInsnID]->getOperand(1).getFPImm());
1402 else
1403 llvm_unreachable("Expected FPImm operand");
1404 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1405 dbgs()
1406 << CurrentIdx << ": GIR_CopyFPConstantAsFPImm(OutMIs["
1407 << NewInsnID << "], MIs[" << OldInsnID << "])\n");
1408 break;
1409 }
1410
1411 case GIR_CustomRenderer: {
1412 uint64_t InsnID = readULEB();
1413 uint64_t OldInsnID = readULEB();
1414 uint16_t RendererFnID = readU16();
1415 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1416 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1417 dbgs() << CurrentIdx << ": GIR_CustomRenderer(OutMIs["
1418 << InsnID << "], MIs[" << OldInsnID << "], "
1419 << RendererFnID << ")\n");
1420 (Exec.*ExecInfo.CustomRenderers[RendererFnID])(
1421 OutMIs[InsnID], *State.MIs[OldInsnID],
1422 -1); // Not a source operand of the old instruction.
1423 break;
1424 }
1426 uint16_t FnID = readU16();
1427 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1428 dbgs() << CurrentIdx << ": GIR_DoneWithCustomAction(FnID="
1429 << FnID << ")\n");
1430 assert(FnID > GICXXCustomAction_Invalid && "Expected a valid FnID");
1431 if (runCustomAction(FnID, State, OutMIs)) {
1432 propagateFlags();
1433 return true;
1434 }
1435
1436 if (handleReject() == RejectAndGiveUp)
1437 return false;
1438 break;
1439 }
1441 uint64_t InsnID = readULEB();
1442 uint64_t OldInsnID = readULEB();
1443 uint64_t OpIdx = readULEB();
1444 uint16_t RendererFnID = readU16();
1445 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1446
1447 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1448 dbgs() << CurrentIdx
1449 << ": GIR_CustomOperandRenderer(OutMIs[" << InsnID
1450 << "], MIs[" << OldInsnID << "]->getOperand("
1451 << OpIdx << "), " << RendererFnID << ")\n");
1452 (Exec.*ExecInfo.CustomRenderers[RendererFnID])(
1453 OutMIs[InsnID], *State.MIs[OldInsnID], OpIdx);
1454 break;
1455 }
1457 uint64_t InsnID = readULEB();
1458 uint64_t OpIdx = readULEB();
1459 uint16_t RCEnum = readU16();
1460 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1461 MachineInstr &I = *OutMIs[InsnID].getInstr();
1462 MachineFunction &MF = *I.getParent()->getParent();
1463 MachineRegisterInfo &MRI = MF.getRegInfo();
1464 const TargetRegisterClass &RC = *TRI.getRegClass(RCEnum);
1465 MachineOperand &MO = I.getOperand(OpIdx);
1466 constrainOperandRegClass(MF, TRI, MRI, TII, RBI, I, RC, MO);
1467 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1468 dbgs() << CurrentIdx << ": GIR_ConstrainOperandRC(OutMIs["
1469 << InsnID << "], " << OpIdx << ", " << RCEnum
1470 << ")\n");
1471 break;
1472 }
1473
1476 uint64_t InsnID = (MatcherOpcode == GIR_RootConstrainSelectedInstOperands)
1477 ? 0
1478 : readULEB();
1479 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1480 constrainSelectedInstRegOperands(*OutMIs[InsnID].getInstr(), TII, TRI,
1481 RBI);
1482 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1483 dbgs() << CurrentIdx
1484 << ": GIR_ConstrainSelectedInstOperands(OutMIs["
1485 << InsnID << "])\n");
1486 break;
1487 }
1488 case GIR_MergeMemOperands: {
1489 uint64_t InsnID = readULEB();
1490 uint64_t NumInsn = MatchTable[CurrentIdx++];
1491 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1492
1493 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1494 dbgs() << CurrentIdx << ": GIR_MergeMemOperands(OutMIs["
1495 << InsnID << "]");
1496 for (unsigned K = 0; K < NumInsn; ++K) {
1497 uint64_t NextID = readULEB();
1498 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1499 dbgs() << ", MIs[" << NextID << "]");
1500 for (const auto &MMO : State.MIs[NextID]->memoperands())
1501 OutMIs[InsnID].addMemOperand(MMO);
1502 }
1503 DEBUG_WITH_TYPE(TgtExecutor::getName(), dbgs() << ")\n");
1504 break;
1505 }
1506 case GIR_EraseFromParent: {
1507 uint64_t InsnID = readULEB();
1508 MachineInstr *MI = State.MIs[InsnID];
1509 assert(MI && "Attempted to erase an undefined instruction");
1510 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1511 dbgs() << CurrentIdx << ": GIR_EraseFromParent(MIs["
1512 << InsnID << "])\n");
1513 eraseImpl(MI);
1514 break;
1515 }
1517 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1518 dbgs()
1519 << CurrentIdx << ": GIR_EraseRootFromParent_Done\n");
1520 eraseImpl(State.MIs[0]);
1521 propagateFlags();
1522 return true;
1523 }
1524 case GIR_MakeTempReg: {
1525 uint64_t TempRegID = readULEB();
1526 int TypeID = readS8();
1527
1528 State.TempRegisters[TempRegID] =
1529 MRI.createGenericVirtualRegister(getTypeFromIdx(TypeID));
1530 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1531 dbgs() << CurrentIdx << ": TempRegs[" << TempRegID
1532 << "] = GIR_MakeTempReg(" << TypeID << ")\n");
1533 break;
1534 }
1535 case GIR_ReplaceReg: {
1536 uint64_t OldInsnID = readULEB();
1537 uint64_t OldOpIdx = readULEB();
1538 uint64_t NewInsnID = readULEB();
1539 uint64_t NewOpIdx = readULEB();
1540
1541 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1542 dbgs() << CurrentIdx << ": GIR_ReplaceReg(MIs["
1543 << OldInsnID << "][" << OldOpIdx << "] = MIs["
1544 << NewInsnID << "][" << NewOpIdx << "])\n");
1545
1546 Register Old = State.MIs[OldInsnID]->getOperand(OldOpIdx).getReg();
1547 Register New = State.MIs[NewInsnID]->getOperand(NewOpIdx).getReg();
1548 if (Observer)
1549 Observer->changingAllUsesOfReg(MRI, Old);
1550 MRI.replaceRegWith(Old, New);
1551 if (Observer)
1552 Observer->finishedChangingAllUsesOfReg();
1553 break;
1554 }
1556 uint64_t OldInsnID = readULEB();
1557 uint64_t OldOpIdx = readULEB();
1558 uint64_t TempRegID = readULEB();
1559
1560 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1561 dbgs() << CurrentIdx << ": GIR_ReplaceRegWithTempReg(MIs["
1562 << OldInsnID << "][" << OldOpIdx << "] = TempRegs["
1563 << TempRegID << "])\n");
1564
1565 Register Old = State.MIs[OldInsnID]->getOperand(OldOpIdx).getReg();
1566 Register New = State.TempRegisters[TempRegID];
1567 if (Observer)
1568 Observer->changingAllUsesOfReg(MRI, Old);
1569 MRI.replaceRegWith(Old, New);
1570 if (Observer)
1571 Observer->finishedChangingAllUsesOfReg();
1572 break;
1573 }
1574 case GIR_Coverage: {
1575 uint32_t RuleID = readU32();
1577 CoverageInfo->setCovered(RuleID);
1578
1579 DEBUG_WITH_TYPE(TgtExecutor::getName(), dbgs() << CurrentIdx
1580 << ": GIR_Coverage("
1581 << RuleID << ")");
1582 break;
1583 }
1584
1585 case GIR_Done:
1586 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1587 dbgs() << CurrentIdx << ": GIR_Done\n");
1588 propagateFlags();
1589 return true;
1590 default:
1591 llvm_unreachable("Unexpected command");
1592 }
1593 }
1594}
1595
1596} // end namespace llvm
1597
1598#endif // LLVM_CODEGEN_GLOBALISEL_GIMATCHTABLEEXECUTORIMPL_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This contains common code to allow clients to notify changes to machine instr.
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
#define I(x, y, z)
Definition MD5.cpp:57
This file declares the MachineIRBuilder class.
Register const TargetRegisterInfo * TRI
Type::TypeID TypeID
MachineInstr unsigned OpIdx
This file defines the SmallVector class.
#define DEBUG_WITH_TYPE(TYPE,...)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
Definition Debug.h:72
Class for arbitrary precision integers.
Definition APInt.h:78
bool equalsInt(uint64_t V) const
A helper method that can be used to determine if the constant contained within is equal to a constant...
Definition Constants.h:194
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:178
iterator end()
Definition DenseMap.h:81
Tagged union holding either a T or a Error.
Definition Error.h:485
virtual bool testSimplePredicate(unsigned) const
bool executeMatchTable(TgtExecutor &Exec, MatcherState &State, const ExecInfoTy< PredicateBitset, ComplexMatcherMemFn, CustomRendererFn > &ExecInfo, MachineIRBuilder &Builder, const uint8_t *MatchTable, const TargetInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI, const PredicateBitset &AvailableFeatures, CodeGenCoverage *CoverageInfo) const
Execute a given matcher table and return true if the match was successful and false otherwise.
virtual bool testImmPredicate_APFloat(unsigned, const APFloat &) const
virtual bool testMOPredicate_MO(unsigned, const MachineOperand &, const MatcherState &State) const
virtual bool testImmPredicate_APInt(unsigned, const APInt &) const
virtual bool testMIPredicate_MI(unsigned, const MachineInstr &, const MatcherState &State) const
virtual bool testImmPredicate_I64(unsigned, int64_t) const
SmallVector< MachineInstrBuilder, 4 > NewMIVector
static Ty readBytesAs(const uint8_t *MatchTable)
std::optional< SmallVector< std::function< void(MachineInstrBuilder &)>, 4 > > ComplexRendererFns
static LLVM_ATTRIBUTE_ALWAYS_INLINE uint64_t fastDecodeULEB128(const uint8_t *LLVM_ATTRIBUTE_RESTRICT MatchTable, uint64_t &CurrentIdx)
LLVM_ABI bool isOperandImmEqual(const MachineOperand &MO, int64_t Value, const MachineRegisterInfo &MRI, bool Splat=false) const
LLVM_ABI bool isObviouslySafeToFold(MachineInstr &MI, MachineInstr &IntoMI) const
Return true if MI can obviously be folded into IntoMI.
virtual bool runCustomAction(unsigned, const MatcherState &State, NewMIVector &OutMIs) const
Abstract class that contains various methods for clients to notify about changes.
virtual void changingInstr(MachineInstr &MI)=0
This instruction is about to be mutated in some way.
LLVM_ABI void finishedChangingAllUsesOfReg()
All instructions reported as changing by changingAllUsesOfReg() have finished being changed.
virtual void changedInstr(MachineInstr &MI)=0
This instruction was mutated in some way.
virtual void erasingInstr(MachineInstr &MI)=0
An instruction is about to be erased.
LLVM_ABI void changingAllUsesOfReg(const MachineRegisterInfo &MRI, Register Reg)
All the instructions using the given register are being changed.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
Definition Type.cpp:354
constexpr unsigned getScalarSizeInBits() const
constexpr LLT changeElementType(LLT NewEltTy) const
If this type is a vector, return a vector with the same number of elements but the new element type.
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
TypeSize getValue() const
Helper class to build MachineInstr.
const MachineInstrBuilder & add(const MachineOperand &MO) const
Representation of each machine instruction.
mop_range operands()
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
A description of a memory reference used in the backend.
LocationSize getSize() const
Return the size in bytes of the memory reference.
unsigned getAddrSpace() const
LLVM_ABI Align getAlign() const
Return the minimum known alignment in bytes of the actual memory reference.
LocationSize getSizeInBits() const
Return the size in bits of the memory reference.
MachineOperand class - Representation of each machine instruction operand.
const ConstantInt * getCImm() const
bool isCImm() const
isCImm - Test if this is a MO_CImmediate operand.
int64_t getImm() const
bool isIntrinsicID() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
Register getReg() const
getReg - Returns the register number.
Intrinsic::ID getIntrinsicID() const
unsigned getPredicate() const
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
bool use_nodbg_empty(Register RegNo) const
use_nodbg_empty - Return true if there are no non-Debug instructions using the specified register.
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
LLVM_ABI Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
Holds all the information related to register banks.
const RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
virtual const RegisterBank & getRegBankFromRegClass(const TargetRegisterClass &RC, LLT Ty) const
Get a register bank that covers RC.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:83
void resize(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
LLVM Value Representation.
Definition Value.h:75
static constexpr bool isKnownLE(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
Definition TypeSize.h:230
static constexpr bool isKnownGE(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
Definition TypeSize.h:237
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:315
LLVM_ABI bool isBuildVectorAllZeros(const MachineInstr &MI, const MachineRegisterInfo &MRI, bool AllowUndef=false)
Return true if the specified instruction is a G_BUILD_VECTOR or G_BUILD_VECTOR_TRUNC where all of the...
Definition Utils.cpp:1440
LLVM_ABI Register constrainOperandRegClass(const MachineFunction &MF, const TargetRegisterInfo &TRI, MachineRegisterInfo &MRI, const TargetInstrInfo &TII, const RegisterBankInfo &RBI, MachineInstr &InsertPt, const TargetRegisterClass &RegClass, MachineOperand &RegMO)
Constrain the Register operand OpIdx, so that it is now constrained to the TargetRegisterClass passed...
Definition Utils.cpp:57
RegState
Flags to represent properties of register accesses.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
LLVM_ABI void constrainSelectedInstRegOperands(MachineInstr &I, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
Mutate the newly-selected instruction I to constrain its (possibly generic) virtual register operands...
Definition Utils.cpp:156
LLVM_ABI MachineInstr * getDefIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the def instruction for Reg, folding away any trivial copies.
Definition Utils.cpp:494
constexpr T MinAlign(U A, V B)
A and B are either alignments or offsets.
Definition MathExtras.h:357
LLVM_ABI bool canReplaceReg(Register DstReg, Register SrcReg, MachineRegisterInfo &MRI)
Check if DstReg can be replaced with SrcReg depending on the register constraints.
Definition Utils.cpp:200
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
bool isAtLeastOrStrongerThan(AtomicOrdering AO, AtomicOrdering Other)
LLVM_ABI bool isBuildVectorAllOnes(const MachineInstr &MI, const MachineRegisterInfo &MRI, bool AllowUndef=false)
Return true if the specified instruction is a G_BUILD_VECTOR or G_BUILD_VECTOR_TRUNC where all of the...
Definition Utils.cpp:1446
@ Success
The lock was released successfully.
AtomicOrdering
Atomic ordering for LLVM's memory model.
DWARFExpression::Operation Op
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
Definition MathExtras.h:572
LLVM_ABI Register getSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the source register for Reg, folding away any trivial copies.
Definition Utils.cpp:501
@ GICXXCustomAction_Invalid
@ GIR_AddIntrinsicID
Adds an intrinsic ID to the specified instruction.
@ GIR_ComplexRenderer
Render complex operands to the specified instruction.
@ GIR_ReplaceRegWithTempReg
Replaces all references to a register with a temporary register.
@ GIR_ComplexSubOperandRenderer
Render sub-operands of complex operands to the specified instruction.
@ GIR_MakeTempReg
Create a new temporary register that's not constrained.
@ GIM_CheckMemorySizeEqualTo
Check the size of the memory access for the given machine memory operand.
@ GIM_RootCheckType
GIM_CheckType but InsnID is omitted and defaults to zero.
@ GIM_RootCheckRegBankForClass
GIM_CheckRegBankForClass but InsnID is omitted and defaults to zero.
@ GIR_Done
A successful emission.
@ GIM_RecordNamedOperand
Predicates with 'let PredicateCodeUsesOperands = 1' need to examine some named operands that will be ...
@ GIM_Try
Begin a try-block to attempt a match and jump to OnFail if it is unsuccessful.
@ GIR_RootConstrainSelectedInstOperands
GIR_ConstrainSelectedInstOperands but InsnID is omitted and defaults to zero.
@ GIM_CheckIsBuildVectorAllOnes
Check if this is a vector that can be treated as a vector splat constant.
@ GIM_CheckNumOperands
Check the instruction has the right number of operands.
@ GIR_AddCImm
Add an CImm to the specified instruction.
@ GIR_ConstrainOperandRC
Constrain an instruction operand to a register class.
@ GIM_CheckI64ImmPredicate
Check an immediate predicate on the specified instruction.
@ GIR_AddImplicitDef
Add an implicit register def to the specified instruction.
@ GIM_CheckAPIntImmPredicate
Check an immediate predicate on the specified instruction via an APInt.
@ GIM_CheckHasNoUse
Check if there's no use of the first result.
@ GIM_CheckPointerToAny
Check the type of a pointer to any address space.
@ GIM_CheckMemorySizeEqualToLLT
Check the size of the memory access for the given machine memory operand against the size of an opera...
@ GIM_CheckComplexPattern
Check the operand matches a complex predicate.
@ GIR_CopyConstantAsSImm
Render a G_CONSTANT operator as a sign-extended immediate.
@ GIR_EraseFromParent
Erase from parent.
@ GIM_SwitchType
Switch over the LLT on the specified instruction operand.
@ GIR_CopySubReg
Copy an operand to the specified instruction.
@ GIR_MutateOpcode
Mutate an instruction.
@ GIM_CheckIsBuildVectorAllZeros
@ GIM_CheckAtomicOrderingOrStrongerThan
@ GIR_AddRegister
Add an register to the specified instruction.
@ GIR_AddTempSubRegister
Add a temporary register to the specified instruction.
@ GIM_CheckIsSafeToFold
Checks if the matched instructions numbered [1, 1+N) can be folded into the root (inst 0).
@ GIM_CheckOpcode
Check the opcode on the specified instruction.
@ GIR_ReplaceReg
Replaces all references to a register from an instruction with another register from another instruct...
@ GIM_SwitchOpcode
Switch over the opcode on the specified instruction.
@ GIM_CheckAPFloatImmPredicate
Check a floating point immediate predicate on the specified instruction.
@ GIM_Reject
Fail the current try-block, or completely fail to match if there is no current try-block.
@ GIR_AddSimpleTempRegister
Add a temporary register to the specified instruction without setting any flags.
@ GIR_AddTempRegister
Add a temporary register to the specified instruction.
@ GIR_Copy
Copy an operand to the specified instruction.
@ GIR_AddImm
Add an immediate to the specified instruction.
@ GIR_CopyFConstantAsFPImm
Render a G_FCONSTANT operator as a sign-extended immediate.
@ GIR_CopyRemaining
Copies all operand starting from OpIdx in OldInsnID into the new instruction NewInsnID.
@ GIM_MIFlags
Check that a matched instruction has, or doesn't have a MIFlag.
@ GIR_CopyOrAddZeroReg
Copy an operand to the specified instruction or add a zero register if the operand is a zero immediat...
@ GIM_CheckMemoryAlignment
Check the minimum alignment of the memory access for the given machine memory operand.
@ GIM_CheckIsSameOperand
Check the specified operands are identical.
@ GIR_AddImm8
Add signed 8 bit immediate to the specified instruction.
@ GIM_CheckIsSameOperandIgnoreCopies
@ GIM_CheckIsMBB
Check the specified operand is an MBB.
@ GIM_CheckNumOperandsLE
Check the instruction has a number of operands <= or >= than given number.
@ GIM_CheckMemorySizeGreaterThanLLT
@ GIM_CheckRegBankForClass
Check the register bank for the specified operand.
@ GIM_CheckLiteralInt
Check the operand is a specific literal integer (i.e.
@ GIM_CheckMemorySizeLessThanLLT
@ GIM_RecordRegType
Records an operand's register type into the set of temporary types.
@ GIM_CheckLeafOperandPredicate
Check a leaf predicate on the specified instruction.
@ GIM_CheckHasOneUse
Check if there's one use of the first result.
@ GIR_EraseRootFromParent_Done
Combines both a GIR_EraseFromParent 0 + GIR_Done.
@ GIR_CopyMIFlags
Copy the MIFlags of a matched instruction into an output instruction.
@ GIR_DoneWithCustomAction
Calls a C++ function that concludes the current match.
@ GIR_BuildMI
Build a new instruction.
@ GIM_RecordInsn
Record the specified instruction.
@ GIM_CheckIsImm
Check the specified operand is an Imm.
@ GIR_BuildRootMI
GIR_BuildMI but InsnID is omitted and defaults to zero.
@ GIM_CheckFeatures
Check the feature bits Feature(2) - Expected features.
@ GIM_CheckCanReplaceReg
Check we can replace all uses of a register with another.
@ GIM_CheckMemoryAddressSpace
Check the address space of the memory access for the given machine memory operand.
@ GIR_CustomRenderer
Render operands to the specified instruction using a custom function.
@ GIM_CheckAtomicOrdering
Check a memory operation has the specified atomic ordering.
@ GIM_CheckType
Check the type for the specified operand.
@ GIM_CheckConstantInt8
Check the operand is a specific 8-bit signed integer.
@ GIM_CheckCmpPredicate
Check the operand is a specific predicate.
@ GIM_CheckOpcodeIsEither
Check the opcode on the specified instruction, checking 2 acceptable alternatives.
@ GIR_SetImplicitDefDead
Marks the implicit def of a register as dead.
@ GIR_BuildConstant
Builds a constant and stores its result in a TempReg.
@ GIR_AddImplicitUse
Add an implicit register use to the specified instruction.
@ GIR_Coverage
Increment the rule coverage counter.
@ GIR_MergeMemOperands
Merge all memory operands into instruction.
@ GIM_CheckImmOperandPredicate
Check an immediate predicate on the specified instruction.
@ GIM_CheckAtomicOrderingWeakerThan
@ GIR_SetMIFlags
Set or unset a MIFlag on an instruction.
@ GIM_CheckIntrinsicID
Check the operand is a specific intrinsic ID.
@ GIM_CheckConstantInt
Check the operand is a specific integer.
@ GIM_SwitchTypeShape
Switch over the shape of an LLT on the specified instruction operand.
@ GIR_RootToRootCopy
GIR_Copy but with both New/OldInsnIDs omitted and defaulting to zero.
@ GIR_ComplexSubOperandSubRegRenderer
Render subregisters of suboperands of complex operands to the specified instruction.
@ GIM_RecordInsnIgnoreCopies
@ GIR_CustomOperandRenderer
Render operands to the specified instruction using a custom function, reading from a specific operand...
@ GIR_ConstrainSelectedInstOperands
Constrain an instructions operands according to the instruction description.
@ GIM_CheckCxxInsnPredicate
Check a generic C++ instruction predicate.
@ GIM_CheckSimplePredicate
Check a trivial predicate which takes no arguments.
@ Default
The result value is uniform if and only if all operands are uniform.
Definition Uniformity.h:20
bool isStrongerThan(AtomicOrdering AO, AtomicOrdering Other)
Returns true if ao is stronger than other as defined by the AtomicOrdering lattice,...
SmallDenseMap< uint64_t, unsigned, 64 > TypeIDMap
const ComplexMatcherMemFn * ComplexPredicates