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