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