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