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