15#ifndef LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTORIMPL_H
16#define LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTORIMPL_H
48template <
class TgtInstructionSelector,
class PredicateBitset,
49 class ComplexMatcherMemFn,
class CustomRendererFn>
63 bool NoFPException = !State.
MIs[0]->getDesc().mayRaiseFPException();
67 enum RejectAction { RejectAndGiveUp, RejectAndResume };
68 auto handleReject = [&]() -> RejectAction {
70 dbgs() << CurrentIdx <<
": Rejected\n");
71 if (OnFailResumeAt.
empty())
72 return RejectAndGiveUp;
75 dbgs() << CurrentIdx <<
": Resume at " << CurrentIdx <<
" ("
76 << OnFailResumeAt.
size() <<
" try-blocks remain)\n");
77 return RejectAndResume;
81 for (
auto MIB : OutMIs) {
85 if (NoFPException && MIB->mayRaiseFPException())
87 MIB.setMIFlags(MIBFlags);
94 assert(CurrentIdx != ~0u &&
"Invalid MatchTable index");
95 int64_t MatcherOpcode = MatchTable[CurrentIdx++];
96 switch (MatcherOpcode) {
99 dbgs() << CurrentIdx <<
": Begin try-block\n");
100 OnFailResumeAt.
push_back(MatchTable[CurrentIdx++]);
106 int64_t NewInsnID = MatchTable[CurrentIdx++];
107 int64_t InsnID = MatchTable[CurrentIdx++];
108 int64_t OpIdx = MatchTable[CurrentIdx++];
112 assert(NewInsnID != 0 &&
"Refusing to modify MIs[0]");
117 dbgs() << CurrentIdx <<
": Not a register\n");
118 if (handleReject() == RejectAndGiveUp)
124 dbgs() << CurrentIdx <<
": Is a physical register\n");
125 if (handleReject() == RejectAndGiveUp)
136 if ((
size_t)NewInsnID < State.
MIs.
size())
137 State.
MIs[NewInsnID] = NewMI;
140 "Expected to store MIs in order");
144 dbgs() << CurrentIdx <<
": MIs[" << NewInsnID
145 <<
"] = GIM_RecordInsn(" << InsnID <<
", " << OpIdx
151 int64_t ExpectedBitsetID = MatchTable[CurrentIdx++];
154 <<
": GIM_CheckFeatures(ExpectedBitsetID="
155 << ExpectedBitsetID <<
")\n");
156 if ((AvailableFeatures & ISelInfo.
FeatureBitsets[ExpectedBitsetID]) !=
158 if (handleReject() == RejectAndGiveUp)
166 int64_t InsnID = MatchTable[CurrentIdx++];
167 int64_t Expected0 = MatchTable[CurrentIdx++];
168 int64_t Expected1 = -1;
170 Expected1 = MatchTable[CurrentIdx++];
172 assert(State.
MIs[InsnID] !=
nullptr &&
"Used insn before defined");
173 unsigned Opcode = State.
MIs[InsnID]->getOpcode();
176 dbgs() << CurrentIdx <<
": GIM_CheckOpcode(MIs[" << InsnID
177 <<
"], ExpectedOpcode=" << Expected0;
179 dbgs() <<
" || " << Expected1;
180 dbgs() <<
") // Got=" << Opcode <<
"\n";
183 if (Opcode != Expected0 && Opcode != Expected1) {
184 if (handleReject() == RejectAndGiveUp)
190 int64_t InsnID = MatchTable[CurrentIdx++];
191 int64_t LowerBound = MatchTable[CurrentIdx++];
192 int64_t UpperBound = MatchTable[CurrentIdx++];
193 int64_t
Default = MatchTable[CurrentIdx++];
195 assert(State.
MIs[InsnID] !=
nullptr &&
"Used insn before defined");
196 const int64_t Opcode = State.
MIs[InsnID]->getOpcode();
199 dbgs() << CurrentIdx <<
": GIM_SwitchOpcode(MIs[" << InsnID <<
"], ["
200 << LowerBound <<
", " << UpperBound <<
"), Default=" <<
Default
201 <<
", JumpTable...) // Got=" << Opcode <<
"\n";
203 if (Opcode < LowerBound || UpperBound <= Opcode) {
207 CurrentIdx = MatchTable[CurrentIdx + (Opcode - LowerBound)];
217 int64_t InsnID = MatchTable[CurrentIdx++];
218 int64_t OpIdx = MatchTable[CurrentIdx++];
219 int64_t LowerBound = MatchTable[CurrentIdx++];
220 int64_t UpperBound = MatchTable[CurrentIdx++];
221 int64_t
Default = MatchTable[CurrentIdx++];
223 assert(State.
MIs[InsnID] !=
nullptr &&
"Used insn before defined");
227 dbgs() << CurrentIdx <<
": GIM_SwitchType(MIs[" << InsnID
228 <<
"]->getOperand(" << OpIdx <<
"), [" << LowerBound <<
", "
229 << UpperBound <<
"), Default=" <<
Default
230 <<
", JumpTable...) // Got=";
232 dbgs() <<
"Not a VReg\n";
241 const auto TyI = ISelInfo.
TypeIDMap.find(Ty);
246 const int64_t
TypeID = TyI->second;
251 CurrentIdx = MatchTable[CurrentIdx + (
TypeID - LowerBound)];
261 int64_t InsnID = MatchTable[CurrentIdx++];
262 int64_t
Expected = MatchTable[CurrentIdx++];
264 dbgs() << CurrentIdx <<
": GIM_CheckNumOperands(MIs["
265 << InsnID <<
"], Expected=" <<
Expected <<
")\n");
266 assert(State.
MIs[InsnID] !=
nullptr &&
"Used insn before defined");
267 if (State.
MIs[InsnID]->getNumOperands() !=
Expected) {
268 if (handleReject() == RejectAndGiveUp)
275 int64_t InsnID = MatchTable[CurrentIdx++];
277 ? MatchTable[CurrentIdx++]
279 int64_t Predicate = MatchTable[CurrentIdx++];
281 dbgs() << CurrentIdx <<
": GIM_CheckImmPredicate(MIs["
282 << InsnID <<
"]->getOperand(" << OpIdx
283 <<
"), Predicate=" << Predicate <<
")\n");
284 assert(State.
MIs[InsnID] !=
nullptr &&
"Used insn before defined");
285 assert((State.
MIs[InsnID]->getOperand(OpIdx).isImm() ||
286 State.
MIs[InsnID]->getOperand(OpIdx).isCImm()) &&
287 "Expected immediate operand");
290 if (State.
MIs[InsnID]->getOperand(OpIdx).isCImm())
291 Value = State.
MIs[InsnID]->getOperand(OpIdx).getCImm()->getSExtValue();
292 else if (State.
MIs[InsnID]->getOperand(OpIdx).isImm())
293 Value = State.
MIs[InsnID]->getOperand(OpIdx).getImm();
298 if (handleReject() == RejectAndGiveUp)
303 int64_t InsnID = MatchTable[CurrentIdx++];
304 int64_t Predicate = MatchTable[CurrentIdx++];
307 << CurrentIdx <<
": GIM_CheckAPIntImmPredicate(MIs["
308 << InsnID <<
"], Predicate=" << Predicate <<
")\n");
309 assert(State.
MIs[InsnID] !=
nullptr &&
"Used insn before defined");
310 assert(State.
MIs[InsnID]->getOpcode() == TargetOpcode::G_CONSTANT &&
311 "Expected G_CONSTANT");
314 if (State.
MIs[InsnID]->getOperand(1).isCImm())
315 Value = State.
MIs[InsnID]->getOperand(1).getCImm()->getValue();
320 if (handleReject() == RejectAndGiveUp)
325 int64_t InsnID = MatchTable[CurrentIdx++];
326 int64_t Predicate = MatchTable[CurrentIdx++];
329 << CurrentIdx <<
": GIM_CheckAPFloatImmPredicate(MIs["
330 << InsnID <<
"], Predicate=" << Predicate <<
")\n");
331 assert(State.
MIs[InsnID] !=
nullptr &&
"Used insn before defined");
332 assert(State.
MIs[InsnID]->getOpcode() == TargetOpcode::G_FCONSTANT &&
333 "Expected G_FCONSTANT");
334 assert(State.
MIs[InsnID]->getOperand(1).isFPImm() &&
"Expected FPImm operand");
336 APFloat Value = State.
MIs[InsnID]->getOperand(1).getFPImm()->getValueAPF();
339 if (handleReject() == RejectAndGiveUp)
345 int64_t InsnID = MatchTable[CurrentIdx++];
349 <<
": GIM_CheckBuildVectorAll{Zeros|Ones}(MIs["
350 << InsnID <<
"])\n");
351 assert(State.
MIs[InsnID] !=
nullptr &&
"Used insn before defined");
354 assert((
MI->getOpcode() == TargetOpcode::G_BUILD_VECTOR ||
355 MI->getOpcode() == TargetOpcode::G_BUILD_VECTOR_TRUNC) &&
356 "Expected G_BUILD_VECTOR or G_BUILD_VECTOR_TRUNC");
360 if (handleReject() == RejectAndGiveUp)
365 if (handleReject() == RejectAndGiveUp)
373 int64_t InsnID = MatchTable[CurrentIdx++];
374 int64_t Predicate = MatchTable[CurrentIdx++];
377 << CurrentIdx <<
": GIM_CheckCxxPredicate(MIs["
378 << InsnID <<
"], Predicate=" << Predicate <<
")\n");
379 assert(State.
MIs[InsnID] !=
nullptr &&
"Used insn before defined");
384 if (handleReject() == RejectAndGiveUp)
389 int64_t InsnID = MatchTable[CurrentIdx++];
392 dbgs() << CurrentIdx <<
": GIM_CheckHasNoUse(MIs["
396 assert(
MI &&
"Used insn before defined");
397 assert(
MI->getNumDefs() > 0 &&
"No defs");
398 const Register Res =
MI->getOperand(0).getReg();
400 if (!
MRI.use_nodbg_empty(Res)) {
401 if (handleReject() == RejectAndGiveUp)
408 int64_t InsnID = MatchTable[CurrentIdx++];
411 dbgs() << CurrentIdx <<
": GIM_CheckAtomicOrdering(MIs["
412 << InsnID <<
"], " << (
uint64_t)Ordering <<
")\n");
413 assert(State.
MIs[InsnID] !=
nullptr &&
"Used insn before defined");
414 if (!State.
MIs[InsnID]->hasOneMemOperand())
415 if (handleReject() == RejectAndGiveUp)
418 for (
const auto &MMO : State.
MIs[InsnID]->memoperands())
419 if (MMO->getMergedOrdering() != Ordering)
420 if (handleReject() == RejectAndGiveUp)
425 int64_t InsnID = MatchTable[CurrentIdx++];
429 <<
": GIM_CheckAtomicOrderingOrStrongerThan(MIs["
430 << InsnID <<
"], " << (
uint64_t)Ordering <<
")\n");
431 assert(State.
MIs[InsnID] !=
nullptr &&
"Used insn before defined");
432 if (!State.
MIs[InsnID]->hasOneMemOperand())
433 if (handleReject() == RejectAndGiveUp)
436 for (
const auto &MMO : State.
MIs[InsnID]->memoperands())
438 if (handleReject() == RejectAndGiveUp)
443 int64_t InsnID = MatchTable[CurrentIdx++];
447 <<
": GIM_CheckAtomicOrderingWeakerThan(MIs["
448 << InsnID <<
"], " << (
uint64_t)Ordering <<
")\n");
449 assert(State.
MIs[InsnID] !=
nullptr &&
"Used insn before defined");
450 if (!State.
MIs[InsnID]->hasOneMemOperand())
451 if (handleReject() == RejectAndGiveUp)
454 for (
const auto &MMO : State.
MIs[InsnID]->memoperands())
456 if (handleReject() == RejectAndGiveUp)
461 int64_t InsnID = MatchTable[CurrentIdx++];
462 int64_t MMOIdx = MatchTable[CurrentIdx++];
464 const int NumAddrSpace = MatchTable[CurrentIdx++];
466 if (State.
MIs[InsnID]->getNumMemOperands() <= MMOIdx) {
467 if (handleReject() == RejectAndGiveUp)
474 const uint64_t LastIdx = CurrentIdx + NumAddrSpace;
477 = *(State.
MIs[InsnID]->memoperands_begin() + MMOIdx);
481 for (
int I = 0;
I != NumAddrSpace; ++
I) {
482 unsigned AddrSpace = MatchTable[CurrentIdx++];
484 TgtInstructionSelector::getName(),
485 dbgs() <<
"addrspace(" << MMOAddrSpace <<
") vs "
486 << AddrSpace <<
'\n');
488 if (AddrSpace == MMOAddrSpace) {
494 CurrentIdx = LastIdx;
495 if (!
Success && handleReject() == RejectAndGiveUp)
500 int64_t InsnID = MatchTable[CurrentIdx++];
501 int64_t MMOIdx = MatchTable[CurrentIdx++];
502 unsigned MinAlign = MatchTable[CurrentIdx++];
504 assert(State.
MIs[InsnID] !=
nullptr &&
"Used insn before defined");
506 if (State.
MIs[InsnID]->getNumMemOperands() <= MMOIdx) {
507 if (handleReject() == RejectAndGiveUp)
513 = *(State.
MIs[InsnID]->memoperands_begin() + MMOIdx);
515 dbgs() << CurrentIdx <<
": GIM_CheckMemoryAlignment"
516 <<
"(MIs[" << InsnID <<
"]->memoperands() + " << MMOIdx
517 <<
")->getAlignment() >= " <<
MinAlign <<
")\n");
524 int64_t InsnID = MatchTable[CurrentIdx++];
525 int64_t MMOIdx = MatchTable[CurrentIdx++];
530 <<
": GIM_CheckMemorySizeEqual(MIs[" << InsnID
531 <<
"]->memoperands() + " << MMOIdx
532 <<
", Size=" <<
Size <<
")\n");
533 assert(State.
MIs[InsnID] !=
nullptr &&
"Used insn before defined");
535 if (State.
MIs[InsnID]->getNumMemOperands() <= MMOIdx) {
536 if (handleReject() == RejectAndGiveUp)
547 if (handleReject() == RejectAndGiveUp)
555 int64_t InsnID = MatchTable[CurrentIdx++];
556 int64_t MMOIdx = MatchTable[CurrentIdx++];
557 int64_t OpIdx = MatchTable[CurrentIdx++];
560 TgtInstructionSelector::getName(),
561 dbgs() << CurrentIdx <<
": GIM_CheckMemorySize"
567 <<
"LLT(MIs[" << InsnID <<
"]->memoperands() + " << MMOIdx
568 <<
", OpIdx=" << OpIdx <<
")\n");
569 assert(State.
MIs[InsnID] !=
nullptr &&
"Used insn before defined");
574 dbgs() << CurrentIdx <<
": Not a register\n");
575 if (handleReject() == RejectAndGiveUp)
580 if (State.
MIs[InsnID]->getNumMemOperands() <= MMOIdx) {
581 if (handleReject() == RejectAndGiveUp)
591 if (handleReject() == RejectAndGiveUp)
595 if (handleReject() == RejectAndGiveUp)
599 if (handleReject() == RejectAndGiveUp)
605 int64_t InsnID = MatchTable[CurrentIdx++];
606 int64_t OpIdx = MatchTable[CurrentIdx++];
607 int64_t
TypeID = MatchTable[CurrentIdx++];
609 dbgs() << CurrentIdx <<
": GIM_CheckType(MIs[" << InsnID
610 <<
"]->getOperand(" << OpIdx
611 <<
"), TypeID=" <<
TypeID <<
")\n");
612 assert(State.
MIs[InsnID] !=
nullptr &&
"Used insn before defined");
616 if (handleReject() == RejectAndGiveUp)
622 int64_t InsnID = MatchTable[CurrentIdx++];
623 int64_t OpIdx = MatchTable[CurrentIdx++];
624 uint64_t SizeInBits = MatchTable[CurrentIdx++];
627 dbgs() << CurrentIdx <<
": GIM_CheckPointerToAny(MIs["
628 << InsnID <<
"]->getOperand(" << OpIdx
629 <<
"), SizeInBits=" << SizeInBits <<
")\n");
630 assert(State.
MIs[InsnID] !=
nullptr &&
"Used insn before defined");
635 if (SizeInBits == 0) {
641 assert(SizeInBits != 0 &&
"Pointer size must be known");
645 if (handleReject() == RejectAndGiveUp)
647 }
else if (handleReject() == RejectAndGiveUp)
653 int64_t InsnID = MatchTable[CurrentIdx++];
654 int64_t OpIdx = MatchTable[CurrentIdx++];
655 uint64_t StoreIdx = MatchTable[CurrentIdx++];
658 dbgs() << CurrentIdx <<
": GIM_RecordNamedOperand(MIs["
659 << InsnID <<
"]->getOperand(" << OpIdx
660 <<
"), StoreIdx=" << StoreIdx <<
")\n");
661 assert(State.
MIs[InsnID] !=
nullptr &&
"Used insn before defined");
667 int64_t InsnID = MatchTable[CurrentIdx++];
668 int64_t OpIdx = MatchTable[CurrentIdx++];
669 int64_t RCEnum = MatchTable[CurrentIdx++];
671 dbgs() << CurrentIdx <<
": GIM_CheckRegBankForClass(MIs["
672 << InsnID <<
"]->getOperand(" << OpIdx
673 <<
"), RCEnum=" << RCEnum <<
")\n");
674 assert(State.
MIs[InsnID] !=
nullptr &&
"Used insn before defined");
680 if (handleReject() == RejectAndGiveUp)
687 int64_t InsnID = MatchTable[CurrentIdx++];
688 int64_t OpIdx = MatchTable[CurrentIdx++];
689 int64_t RendererID = MatchTable[CurrentIdx++];
690 int64_t ComplexPredicateID = MatchTable[CurrentIdx++];
692 dbgs() << CurrentIdx <<
": State.Renderers[" << RendererID
693 <<
"] = GIM_CheckComplexPattern(MIs[" << InsnID
694 <<
"]->getOperand(" << OpIdx
695 <<
"), ComplexPredicateID=" << ComplexPredicateID
697 assert(State.
MIs[InsnID] !=
nullptr &&
"Used insn before defined");
701 State.
MIs[InsnID]->getOperand(OpIdx));
705 if (handleReject() == RejectAndGiveUp)
711 int64_t InsnID = MatchTable[CurrentIdx++];
712 int64_t OpIdx = MatchTable[CurrentIdx++];
713 int64_t
Value = MatchTable[CurrentIdx++];
715 dbgs() << CurrentIdx <<
": GIM_CheckConstantInt(MIs["
716 << InsnID <<
"]->getOperand(" << OpIdx
717 <<
"), Value=" <<
Value <<
")\n");
718 assert(State.
MIs[InsnID] !=
nullptr &&
"Used insn before defined");
726 if (handleReject() == RejectAndGiveUp)
729 }
else if (handleReject() == RejectAndGiveUp)
736 int64_t InsnID = MatchTable[CurrentIdx++];
737 int64_t OpIdx = MatchTable[CurrentIdx++];
738 int64_t
Value = MatchTable[CurrentIdx++];
740 dbgs() << CurrentIdx <<
": GIM_CheckLiteralInt(MIs["
741 << InsnID <<
"]->getOperand(" << OpIdx
742 <<
"), Value=" <<
Value <<
")\n");
743 assert(State.
MIs[InsnID] !=
nullptr &&
"Used insn before defined");
751 if (handleReject() == RejectAndGiveUp)
758 int64_t InsnID = MatchTable[CurrentIdx++];
759 int64_t OpIdx = MatchTable[CurrentIdx++];
760 int64_t
Value = MatchTable[CurrentIdx++];
762 dbgs() << CurrentIdx <<
": GIM_CheckIntrinsicID(MIs["
763 << InsnID <<
"]->getOperand(" << OpIdx
764 <<
"), Value=" <<
Value <<
")\n");
765 assert(State.
MIs[InsnID] !=
nullptr &&
"Used insn before defined");
768 if (handleReject() == RejectAndGiveUp)
773 int64_t InsnID = MatchTable[CurrentIdx++];
774 int64_t OpIdx = MatchTable[CurrentIdx++];
775 int64_t
Value = MatchTable[CurrentIdx++];
777 dbgs() << CurrentIdx <<
": GIM_CheckCmpPredicate(MIs["
778 << InsnID <<
"]->getOperand(" << OpIdx
779 <<
"), Value=" <<
Value <<
")\n");
780 assert(State.
MIs[InsnID] !=
nullptr &&
"Used insn before defined");
783 if (handleReject() == RejectAndGiveUp)
788 int64_t InsnID = MatchTable[CurrentIdx++];
789 int64_t OpIdx = MatchTable[CurrentIdx++];
791 dbgs() << CurrentIdx <<
": GIM_CheckIsMBB(MIs[" << InsnID
792 <<
"]->getOperand(" << OpIdx <<
"))\n");
793 assert(State.
MIs[InsnID] !=
nullptr &&
"Used insn before defined");
794 if (!State.
MIs[InsnID]->getOperand(OpIdx).isMBB()) {
795 if (handleReject() == RejectAndGiveUp)
801 int64_t InsnID = MatchTable[CurrentIdx++];
802 int64_t OpIdx = MatchTable[CurrentIdx++];
804 dbgs() << CurrentIdx <<
": GIM_CheckIsImm(MIs[" << InsnID
805 <<
"]->getOperand(" << OpIdx <<
"))\n");
806 assert(State.
MIs[InsnID] !=
nullptr &&
"Used insn before defined");
807 if (!State.
MIs[InsnID]->getOperand(OpIdx).isImm()) {
808 if (handleReject() == RejectAndGiveUp)
814 int64_t InsnID = MatchTable[CurrentIdx++];
816 dbgs() << CurrentIdx <<
": GIM_CheckIsSafeToFold(MIs["
817 << InsnID <<
"])\n");
818 assert(State.
MIs[InsnID] !=
nullptr &&
"Used insn before defined");
820 if (handleReject() == RejectAndGiveUp)
827 int64_t InsnID = MatchTable[CurrentIdx++];
828 int64_t OpIdx = MatchTable[CurrentIdx++];
829 int64_t OtherInsnID = MatchTable[CurrentIdx++];
830 int64_t OtherOpIdx = MatchTable[CurrentIdx++];
832 dbgs() << CurrentIdx <<
": GIM_CheckIsSameOperand(MIs["
833 << InsnID <<
"][" << OpIdx <<
"], MIs["
834 << OtherInsnID <<
"][" << OtherOpIdx <<
"])\n");
835 assert(State.
MIs[InsnID] !=
nullptr &&
"Used insn before defined");
836 assert(State.
MIs[OtherInsnID] !=
nullptr &&
"Used insn before defined");
842 if (Op.isReg() && OtherOp.
isReg()) {
845 if (
MI &&
MI == OtherMI)
850 if (!Op.isIdenticalTo(OtherOp)) {
851 if (handleReject() == RejectAndGiveUp)
858 dbgs() << CurrentIdx <<
": GIM_Reject\n");
859 if (handleReject() == RejectAndGiveUp)
864 int64_t OldInsnID = MatchTable[CurrentIdx++];
865 uint64_t NewInsnID = MatchTable[CurrentIdx++];
866 int64_t NewOpcode = MatchTable[CurrentIdx++];
867 if (NewInsnID >= OutMIs.
size())
868 OutMIs.
resize(NewInsnID + 1);
871 State.
MIs[OldInsnID]);
872 OutMIs[NewInsnID]->setDesc(
TII.get(NewOpcode));
874 dbgs() << CurrentIdx <<
": GIR_MutateOpcode(OutMIs["
875 << NewInsnID <<
"], MIs[" << OldInsnID <<
"], "
876 << NewOpcode <<
")\n");
881 uint64_t NewInsnID = MatchTable[CurrentIdx++];
882 int64_t Opcode = MatchTable[CurrentIdx++];
883 if (NewInsnID >= OutMIs.
size())
884 OutMIs.
resize(NewInsnID + 1);
886 OutMIs[NewInsnID] =
BuildMI(*State.
MIs[0]->getParent(), State.
MIs[0],
889 dbgs() << CurrentIdx <<
": GIR_BuildMI(OutMIs["
890 << NewInsnID <<
"], " << Opcode <<
")\n");
895 int64_t NewInsnID = MatchTable[CurrentIdx++];
896 int64_t OldInsnID = MatchTable[CurrentIdx++];
897 int64_t OpIdx = MatchTable[CurrentIdx++];
898 assert(OutMIs[NewInsnID] &&
"Attempted to add to undefined instruction");
899 OutMIs[NewInsnID].add(State.
MIs[OldInsnID]->getOperand(OpIdx));
902 << CurrentIdx <<
": GIR_Copy(OutMIs[" << NewInsnID
903 <<
"], MIs[" << OldInsnID <<
"], " << OpIdx <<
")\n");
908 int64_t NewInsnID = MatchTable[CurrentIdx++];
909 int64_t OldInsnID = MatchTable[CurrentIdx++];
910 int64_t OpIdx = MatchTable[CurrentIdx++];
911 int64_t ZeroReg = MatchTable[CurrentIdx++];
912 assert(OutMIs[NewInsnID] &&
"Attempted to add to undefined instruction");
915 OutMIs[NewInsnID].addReg(ZeroReg);
917 OutMIs[NewInsnID].add(MO);
919 dbgs() << CurrentIdx <<
": GIR_CopyOrAddZeroReg(OutMIs["
920 << NewInsnID <<
"], MIs[" << OldInsnID <<
"], "
921 << OpIdx <<
", " << ZeroReg <<
")\n");
926 int64_t NewInsnID = MatchTable[CurrentIdx++];
927 int64_t OldInsnID = MatchTable[CurrentIdx++];
928 int64_t OpIdx = MatchTable[CurrentIdx++];
929 int64_t SubRegIdx = MatchTable[CurrentIdx++];
930 assert(OutMIs[NewInsnID] &&
"Attempted to add to undefined instruction");
931 OutMIs[NewInsnID].addReg(State.
MIs[OldInsnID]->getOperand(OpIdx).getReg(),
934 dbgs() << CurrentIdx <<
": GIR_CopySubReg(OutMIs["
935 << NewInsnID <<
"], MIs[" << OldInsnID <<
"], "
936 << OpIdx <<
", " << SubRegIdx <<
")\n");
941 int64_t InsnID = MatchTable[CurrentIdx++];
942 int64_t RegNum = MatchTable[CurrentIdx++];
943 assert(OutMIs[InsnID] &&
"Attempted to add to undefined instruction");
946 dbgs() << CurrentIdx <<
": GIR_AddImplicitDef(OutMIs["
947 << InsnID <<
"], " << RegNum <<
")\n");
952 int64_t InsnID = MatchTable[CurrentIdx++];
953 int64_t RegNum = MatchTable[CurrentIdx++];
954 assert(OutMIs[InsnID] &&
"Attempted to add to undefined instruction");
957 dbgs() << CurrentIdx <<
": GIR_AddImplicitUse(OutMIs["
958 << InsnID <<
"], " << RegNum <<
")\n");
963 int64_t InsnID = MatchTable[CurrentIdx++];
964 int64_t RegNum = MatchTable[CurrentIdx++];
965 uint64_t RegFlags = MatchTable[CurrentIdx++];
966 assert(OutMIs[InsnID] &&
"Attempted to add to undefined instruction");
967 OutMIs[InsnID].addReg(RegNum, RegFlags);
969 TgtInstructionSelector::getName(),
970 dbgs() << CurrentIdx <<
": GIR_AddRegister(OutMIs["
971 << InsnID <<
"], " << RegNum <<
", " << RegFlags <<
")\n");
977 int64_t InsnID = MatchTable[CurrentIdx++];
978 int64_t TempRegID = MatchTable[CurrentIdx++];
979 uint64_t TempRegFlags = MatchTable[CurrentIdx++];
982 SubReg = MatchTable[CurrentIdx++];
984 assert(OutMIs[InsnID] &&
"Attempted to add to undefined instruction");
988 dbgs() << CurrentIdx <<
": GIR_AddTempRegister(OutMIs["
989 << InsnID <<
"], TempRegisters[" << TempRegID
993 dbgs() <<
", " << TempRegFlags <<
")\n");
998 int64_t InsnID = MatchTable[CurrentIdx++];
999 int64_t Imm = MatchTable[CurrentIdx++];
1000 assert(OutMIs[InsnID] &&
"Attempted to add to undefined instruction");
1001 OutMIs[InsnID].addImm(Imm);
1003 dbgs() << CurrentIdx <<
": GIR_AddImm(OutMIs[" << InsnID
1004 <<
"], " << Imm <<
")\n");
1009 int64_t InsnID = MatchTable[CurrentIdx++];
1010 int64_t RendererID = MatchTable[CurrentIdx++];
1011 assert(OutMIs[InsnID] &&
"Attempted to add to undefined instruction");
1012 for (
const auto &RenderOpFn : State.
Renderers[RendererID])
1013 RenderOpFn(OutMIs[InsnID]);
1015 dbgs() << CurrentIdx <<
": GIR_ComplexRenderer(OutMIs["
1016 << InsnID <<
"], " << RendererID <<
")\n");
1020 int64_t InsnID = MatchTable[CurrentIdx++];
1021 int64_t RendererID = MatchTable[CurrentIdx++];
1022 int64_t RenderOpID = MatchTable[CurrentIdx++];
1023 assert(OutMIs[InsnID] &&
"Attempted to add to undefined instruction");
1024 State.
Renderers[RendererID][RenderOpID](OutMIs[InsnID]);
1026 dbgs() << CurrentIdx
1027 <<
": GIR_ComplexSubOperandRenderer(OutMIs["
1028 << InsnID <<
"], " << RendererID <<
", "
1029 << RenderOpID <<
")\n");
1033 int64_t InsnID = MatchTable[CurrentIdx++];
1034 int64_t RendererID = MatchTable[CurrentIdx++];
1035 int64_t RenderOpID = MatchTable[CurrentIdx++];
1036 int64_t SubRegIdx = MatchTable[CurrentIdx++];
1038 assert(
MI &&
"Attempted to add to undefined instruction");
1040 MI->getOperand(
MI->getNumOperands() - 1).setSubReg(SubRegIdx);
1042 dbgs() << CurrentIdx
1043 <<
": GIR_ComplexSubOperandSubRegRenderer(OutMIs["
1044 << InsnID <<
"], " << RendererID <<
", "
1045 << RenderOpID <<
", " << SubRegIdx <<
")\n");
1050 int64_t NewInsnID = MatchTable[CurrentIdx++];
1051 int64_t OldInsnID = MatchTable[CurrentIdx++];
1052 assert(OutMIs[NewInsnID] &&
"Attempted to add to undefined instruction");
1053 assert(State.
MIs[OldInsnID]->getOpcode() == TargetOpcode::G_CONSTANT &&
"Expected G_CONSTANT");
1054 if (State.
MIs[OldInsnID]->getOperand(1).isCImm()) {
1055 OutMIs[NewInsnID].addImm(
1056 State.
MIs[OldInsnID]->getOperand(1).getCImm()->getSExtValue());
1057 }
else if (State.
MIs[OldInsnID]->getOperand(1).isImm())
1058 OutMIs[NewInsnID].add(State.
MIs[OldInsnID]->getOperand(1));
1062 dbgs() << CurrentIdx <<
": GIR_CopyConstantAsSImm(OutMIs["
1063 << NewInsnID <<
"], MIs[" << OldInsnID <<
"])\n");
1069 int64_t NewInsnID = MatchTable[CurrentIdx++];
1070 int64_t OldInsnID = MatchTable[CurrentIdx++];
1071 assert(OutMIs[NewInsnID] &&
"Attempted to add to undefined instruction");
1072 assert(State.
MIs[OldInsnID]->getOpcode() == TargetOpcode::G_FCONSTANT &&
"Expected G_FCONSTANT");
1073 if (State.
MIs[OldInsnID]->getOperand(1).isFPImm())
1074 OutMIs[NewInsnID].addFPImm(
1075 State.
MIs[OldInsnID]->getOperand(1).getFPImm());
1079 dbgs() << CurrentIdx <<
": GIR_CopyFPConstantAsFPImm(OutMIs["
1080 << NewInsnID <<
"], MIs[" << OldInsnID <<
"])\n");
1085 int64_t InsnID = MatchTable[CurrentIdx++];
1086 int64_t OldInsnID = MatchTable[CurrentIdx++];
1087 int64_t RendererFnID = MatchTable[CurrentIdx++];
1088 assert(OutMIs[InsnID] &&
"Attempted to add to undefined instruction");
1090 dbgs() << CurrentIdx <<
": GIR_CustomRenderer(OutMIs["
1091 << InsnID <<
"], MIs[" << OldInsnID <<
"], "
1092 << RendererFnID <<
")\n");
1094 OutMIs[InsnID], *State.
MIs[OldInsnID],
1099 int64_t InsnID = MatchTable[CurrentIdx++];
1100 int64_t OldInsnID = MatchTable[CurrentIdx++];
1101 int64_t OpIdx = MatchTable[CurrentIdx++];
1102 int64_t RendererFnID = MatchTable[CurrentIdx++];
1103 assert(OutMIs[InsnID] &&
"Attempted to add to undefined instruction");
1106 TgtInstructionSelector::getName(),
1107 dbgs() << CurrentIdx <<
": GIR_CustomOperandRenderer(OutMIs["
1108 << InsnID <<
"], MIs[" << OldInsnID <<
"]->getOperand("
1110 << RendererFnID <<
")\n");
1112 *State.
MIs[OldInsnID],
1117 int64_t InsnID = MatchTable[CurrentIdx++];
1118 int64_t OpIdx = MatchTable[CurrentIdx++];
1119 int64_t RCEnum = MatchTable[CurrentIdx++];
1120 assert(OutMIs[InsnID] &&
"Attempted to add to undefined instruction");
1128 dbgs() << CurrentIdx <<
": GIR_ConstrainOperandRC(OutMIs["
1129 << InsnID <<
"], " << OpIdx <<
", " << RCEnum
1135 int64_t InsnID = MatchTable[CurrentIdx++];
1136 assert(OutMIs[InsnID] &&
"Attempted to add to undefined instruction");
1140 dbgs() << CurrentIdx
1141 <<
": GIR_ConstrainSelectedInstOperands(OutMIs["
1142 << InsnID <<
"])\n");
1147 int64_t InsnID = MatchTable[CurrentIdx++];
1148 assert(OutMIs[InsnID] &&
"Attempted to add to undefined instruction");
1151 dbgs() << CurrentIdx <<
": GIR_MergeMemOperands(OutMIs["
1154 while ((MergeInsnID = MatchTable[CurrentIdx++]) !=
1157 dbgs() <<
", MIs[" << MergeInsnID <<
"]");
1158 for (
const auto &MMO : State.
MIs[MergeInsnID]->memoperands())
1159 OutMIs[InsnID].addMemOperand(MMO);
1166 int64_t InsnID = MatchTable[CurrentIdx++];
1168 "Attempted to erase an undefined instruction");
1169 State.
MIs[InsnID]->eraseFromParent();
1171 dbgs() << CurrentIdx <<
": GIR_EraseFromParent(MIs["
1172 << InsnID <<
"])\n");
1177 int64_t TempRegID = MatchTable[CurrentIdx++];
1178 int64_t
TypeID = MatchTable[CurrentIdx++];
1183 dbgs() << CurrentIdx <<
": TempRegs[" << TempRegID
1184 <<
"] = GIR_MakeTempReg(" <<
TypeID <<
")\n");
1189 int64_t RuleID = MatchTable[CurrentIdx++];
1194 << CurrentIdx <<
": GIR_Coverage(" << RuleID <<
")");
1200 dbgs() << CurrentIdx <<
": GIR_Done\n");
1201 propagateFlags(OutMIs);
unsigned const MachineRegisterInfo * MRI
This file contains the declarations for the subclasses of Constant, which represent the different fla...
#define DEBUG_WITH_TYPE(TYPE, X)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
const HexagonInstrInfo * TII
unsigned const TargetRegisterInfo * TRI
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallVector class.
Class for arbitrary precision integers.
void setCovered(uint64_t RuleID)
bool equalsInt(uint64_t V) const
A helper method that can be used to determine if the constant contained within is equal to a constant...
unsigned getPointerSizeInBits(unsigned AS=0) const
Layout pointer size, in bits FIXME: The defaults need to be removed once all of the backends/clients ...
Tagged union holding either a T or a Error.
virtual bool testImmPredicate_APInt(unsigned, const APInt &) const
virtual bool testImmPredicate_I64(unsigned, int64_t) const
bool isOperandImmEqual(const MachineOperand &MO, int64_t Value, const MachineRegisterInfo &MRI) const
bool isObviouslySafeToFold(MachineInstr &MI, MachineInstr &IntoMI) const
Return true if MI can obviously be folded into IntoMI.
virtual bool testMIPredicate_MI(unsigned, const MachineInstr &, const std::array< const MachineOperand *, 3 > &Operands) const
CodeGenCoverage * CoverageInfo
bool executeMatchTable(TgtInstructionSelector &ISel, NewMIVector &OutMIs, MatcherState &State, const ISelInfoTy< PredicateBitset, ComplexMatcherMemFn, CustomRendererFn > &ISelInfo, const int64_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
std::optional< SmallVector< std::function< void(MachineInstrBuilder &)>, 4 > > ComplexRendererFns
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
constexpr unsigned getAddressSpace() const
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Representation of each machine instruction.
A description of a memory reference used in the backend.
unsigned getAddrSpace() const
uint64_t getSize() const
Return the size in bytes of the memory reference.
uint64_t getSizeInBits() const
Return the size in bits of the memory reference.
Align getAlign() const
Return the minimum known alignment in bytes of the actual 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.
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.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
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.
#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.
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...
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...
@ GIU_MergeMemOperands_EndOfList
Indicates the end of the variable-length MergeInsnID list in a GIR_MergeMemOperands opcode.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
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...
@ GIR_ComplexRenderer
Render complex operands to the specified instruction.
@ 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.
@ 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.
@ 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_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
Check if the specified operand is safe to fold into the current instruction.
@ GIM_CheckOpcode
Check the opcode on the specified instruction.
@ 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_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_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.
@ GIM_CheckIsSameOperandIgnoreCopies
@ GIM_CheckIsMBB
Check the specified operand is an MBB.
@ GIM_CheckMemorySizeGreaterThanLLT
@ GIM_CheckRegBankForClass
Check the register bank for the specified operand.
@ GIM_CheckLiteralInt
Check the operand is a specific literal integer (i.e.
@ GIM_CheckMemorySizeLessThanLLT
@ GIR_BuildMI
Build a new instruction.
@ GIM_RecordInsn
Record the specified instruction.
@ GIM_CheckIsImm
Check the specified operand is an Imm.
@ GIM_CheckFeatures
Check the feature bits.
@ 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_CheckCmpPredicate
Check the operand is a specific predicate.
@ GIM_CheckOpcodeIsEither
Check the opcode on the specified instruction, checking 2 acceptable alternatives.
@ 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
@ GIM_CheckIntrinsicID
Check the operand is a specific intrinsic ID.
@ GIM_CheckConstantInt
Check the operand is a specific integer.
@ 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.
MachineInstr * getDefIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the def instruction for Reg, folding away any trivial copies.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool isAtLeastOrStrongerThan(AtomicOrdering AO, AtomicOrdering Other)
bool isBuildVectorAllOnes(const MachineInstr &MI, const MachineRegisterInfo &MRI, bool AllowUndef=false)
Return true if the specified instruction is a G_BUILD_VECTOR or G_BUILD_VECTOR_TRUNC where all of the...
AtomicOrdering
Atomic ordering for LLVM's memory model.
constexpr uint64_t MinAlign(uint64_t A, uint64_t B)
A and B are either alignments or offsets.
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
@ Default
The result values are uniform if and only if all operands are uniform.
bool isStrongerThan(AtomicOrdering AO, AtomicOrdering Other)
Returns true if ao is stronger than other as defined by the AtomicOrdering lattice,...
const ComplexMatcherMemFn * ComplexPredicates
const CustomRendererFn * CustomRenderers
SmallDenseMap< LLT, unsigned, 64 > TypeIDMap
const PredicateBitset * FeatureBitsets
std::array< const MachineOperand *, 3 > RecordedOperands
Named operands that predicate with 'let PredicateCodeUsesOperands = 1' referenced in its argument lis...
std::vector< ComplexRendererFns::value_type > Renderers
DenseMap< unsigned, unsigned > TempRegisters