LLVM: lib/Target/ARM/ARMInstructionSelector.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
22
23#define DEBUG_TYPE "arm-isel"
24
25using namespace llvm;
26
27namespace {
28
29#define GET_GLOBALISEL_PREDICATE_BITSET
30#include "ARMGenGlobalISel.inc"
31#undef GET_GLOBALISEL_PREDICATE_BITSET
32
34public:
37
40
41private:
43
44 struct CmpConstants;
45 struct InsertInfo;
46
49
50
51
52
53 bool insertComparison(CmpConstants Helper, InsertInfo I, unsigned ResReg,
55 unsigned PrevRes) const;
56
57
58 void putConstant(InsertInfo I, unsigned DestReg, unsigned Constant) const;
59
63
64
65
67 unsigned ExpectedSize, unsigned ExpectedRegBankID) const;
68
69
71 unsigned ExpectedRegBankID) const;
72
78
79
80
81
83
84
85
86 struct OpcodeCache {
87 unsigned ZEXT16;
88 unsigned SEXT16;
89
90 unsigned ZEXT8;
91 unsigned SEXT8;
92
93
94 unsigned AND;
95 unsigned RSB;
96
97 unsigned STORE32;
98 unsigned LOAD32;
99
100 unsigned STORE16;
101 unsigned LOAD16;
102
103 unsigned STORE8;
104 unsigned LOAD8;
105
106 unsigned ADDrr;
107 unsigned ADDri;
108
109
110 unsigned CMPrr;
111 unsigned MOVi;
112 unsigned MOVCCi;
113
114
115 unsigned MOVCCr;
116
117 unsigned TSTri;
118 unsigned Bcc;
119
120
121 unsigned MOVi32imm;
122 unsigned ConstPoolLoad;
123 unsigned MOV_ga_pcrel;
124 unsigned LDRLIT_ga_pcrel;
125 unsigned LDRLIT_ga_abs;
126
128 } const Opcodes;
129
130
131
132
133
134 unsigned selectSimpleExtOpc(unsigned Opc, unsigned Size) const;
135
136
137
138 unsigned selectLoadStoreOpCode(unsigned Opc, unsigned RegBank,
139 unsigned Size) const;
140
142 int OpIdx = -1) const;
144 int OpIdx = -1) const;
146 int OpIdx = -1) const;
147
148#define GET_GLOBALISEL_PREDICATES_DECL
149#include "ARMGenGlobalISel.inc"
150#undef GET_GLOBALISEL_PREDICATES_DECL
151
152
153
154#define GET_GLOBALISEL_TEMPORARIES_DECL
155#include "ARMGenGlobalISel.inc"
156#undef GET_GLOBALISEL_TEMPORARIES_DECL
157};
158}
159
160namespace llvm {
165 return new ARMInstructionSelector(TM, STI, RBI);
166}
167}
168
169#define GET_GLOBALISEL_IMPL
170#include "ARMGenGlobalISel.inc"
171#undef GET_GLOBALISEL_IMPL
172
173ARMInstructionSelector::ARMInstructionSelector(const ARMBaseTargetMachine &TM,
176 : TII(*STI.getInstrInfo()), TRI(*STI.getRegisterInfo()), TM(TM), RBI(RBI),
177 STI(STI), Opcodes(STI),
179#include "ARMGenGlobalISel.inc"
182#include "ARMGenGlobalISel.inc"
184{
185}
186
192 assert(RegBank && "Can't get reg bank for virtual register");
193
194 const unsigned Size = MRI.getType(Reg).getSizeInBits();
195 assert((RegBank->getID() == ARM::GPRRegBankID ||
196 RegBank->getID() == ARM::FPRRegBankID) &&
197 "Unsupported reg bank");
198
199 if (RegBank->getID() == ARM::FPRRegBankID) {
200 if (Size == 32)
201 return &ARM::SPRRegClass;
202 else if (Size == 64)
203 return &ARM::DPRRegClass;
204 else if (Size == 128)
205 return &ARM::QPRRegClass;
206 else
208 }
209
210 return &ARM::GPRRegClass;
211}
212
216 Register DstReg = I.getOperand(0).getReg();
218 return true;
219
221
222
223
224
226 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
227 << " operand\n");
228 return false;
229 }
230 return true;
231}
232
238 assert(TII.getSubtarget().hasVFP2Base() && "Can't select merge without VFP");
239
240
241
243 (void)VReg0;
244 assert(MRI.getType(VReg0).getSizeInBits() == 64 &&
246 "Unsupported operand for G_MERGE_VALUES");
248 (void)VReg1;
249 assert(MRI.getType(VReg1).getSizeInBits() == 32 &&
251 "Unsupported operand for G_MERGE_VALUES");
253 (void)VReg2;
254 assert(MRI.getType(VReg2).getSizeInBits() == 32 &&
256 "Unsupported operand for G_MERGE_VALUES");
257
260
261 return true;
262}
263
269 assert(TII.getSubtarget().hasVFP2Base() &&
270 "Can't select unmerge without VFP");
271
272
273
275 (void)VReg0;
276 assert(MRI.getType(VReg0).getSizeInBits() == 32 &&
278 "Unsupported operand for G_UNMERGE_VALUES");
280 (void)VReg1;
281 assert(MRI.getType(VReg1).getSizeInBits() == 32 &&
283 "Unsupported operand for G_UNMERGE_VALUES");
285 (void)VReg2;
286 assert(MRI.getType(VReg2).getSizeInBits() == 64 &&
288 "Unsupported operand for G_UNMERGE_VALUES");
289
292
293 return true;
294}
295
296ARMInstructionSelector::OpcodeCache::OpcodeCache(const ARMSubtarget &STI) {
297 bool isThumb = STI.isThumb();
298
299 using namespace TargetOpcode;
300
301#define STORE_OPCODE(VAR, OPC) VAR = isThumb ? ARM::t2##OPC : ARM::OPC
304
307
310
313
314
315 STORE16 = isThumb ? ARM::t2STRHi12 : ARM::STRH;
316 LOAD16 = isThumb ? ARM::t2LDRHi12 : ARM::LDRH;
317
320
323
327
329
332
334 ConstPoolLoad = isThumb ? ARM::t2LDRpci : ARM::LDRi12;
336 LDRLIT_ga_pcrel = isThumb ? ARM::tLDRLIT_ga_pcrel : ARM::LDRLIT_ga_pcrel;
337 LDRLIT_ga_abs = isThumb ? ARM::tLDRLIT_ga_abs : ARM::LDRLIT_ga_abs;
338#undef MAP_OPCODE
339}
340
341unsigned ARMInstructionSelector::selectSimpleExtOpc(unsigned Opc,
342 unsigned Size) const {
343 using namespace TargetOpcode;
344
346 return Opc;
347
348 if (Opc == G_SEXT)
349 return Size == 8 ? Opcodes.SEXT8 : Opcodes.SEXT16;
350
351 if (Opc == G_ZEXT)
352 return Size == 8 ? Opcodes.ZEXT8 : Opcodes.ZEXT16;
353
354 return Opc;
355}
356
357unsigned ARMInstructionSelector::selectLoadStoreOpCode(unsigned Opc,
358 unsigned RegBank,
359 unsigned Size) const {
360 bool isStore = Opc == TargetOpcode::G_STORE;
361
362 if (RegBank == ARM::GPRRegBankID) {
363 switch (Size) {
364 case 1:
365 case 8:
366 return isStore ? Opcodes.STORE8 : Opcodes.LOAD8;
367 case 16:
368 return isStore ? Opcodes.STORE16 : Opcodes.LOAD16;
369 case 32:
370 return isStore ? Opcodes.STORE32 : Opcodes.LOAD32;
371 default:
372 return Opc;
373 }
374 }
375
376 if (RegBank == ARM::FPRRegBankID) {
377 switch (Size) {
378 case 32:
379 return isStore ? ARM::VSTRS : ARM::VLDRS;
380 case 64:
381 return isStore ? ARM::VSTRD : ARM::VLDRD;
382 default:
383 return Opc;
384 }
385 }
386
387 return Opc;
388}
389
390
391
392
393static std::pair<ARMCC::CondCodes, ARMCC::CondCodes>
395 std::pair<ARMCC::CondCodes, ARMCC::CondCodes> Preds = {ARMCC::AL, ARMCC::AL};
396 switch (Pred) {
399 break;
402 break;
406 break;
410 break;
414 break;
418 break;
421 break;
425 break;
428 break;
431 break;
434 break;
438 break;
442 break;
446 break;
449 break;
452 break;
453 default:
454 break;
455 }
456 assert(Preds.first != ARMCC::AL && "No comparisons needed?");
457 return Preds;
458}
459
461 CmpConstants(unsigned CmpOpcode, unsigned FlagsOpcode, unsigned SelectOpcode,
462 unsigned OpRegBank, unsigned OpSize)
466
467
469
470
471
473
474
476
477
479
480
482};
483
493
494void ARMInstructionSelector::putConstant(InsertInfo I, unsigned DestReg,
496 (void)BuildMI(I.MBB, I.InsertBefore, I.DbgLoc, TII.get(Opcodes.MOVi))
501}
502
504 unsigned LHSReg, unsigned RHSReg,
505 unsigned ExpectedSize,
506 unsigned ExpectedRegBankID) const {
507 return MRI.getType(LHSReg) == MRI.getType(RHSReg) &&
508 validReg(MRI, LHSReg, ExpectedSize, ExpectedRegBankID) &&
509 validReg(MRI, RHSReg, ExpectedSize, ExpectedRegBankID);
510}
511
512bool ARMInstructionSelector::validReg(MachineRegisterInfo &MRI, unsigned Reg,
513 unsigned ExpectedSize,
514 unsigned ExpectedRegBankID) const {
515 if (MRI.getType(Reg).getSizeInBits() != ExpectedSize) {
516 LLVM_DEBUG(dbgs() << "Unexpected size for register");
517 return false;
518 }
519
521 LLVM_DEBUG(dbgs() << "Unexpected register bank for register");
522 return false;
523 }
524
525 return true;
526}
527
528bool ARMInstructionSelector::selectCmp(CmpConstants Helper,
529 MachineInstrBuilder &MIB,
530 MachineRegisterInfo &MRI) const {
531 const InsertInfo I(MIB);
532
533 auto ResReg = MIB.getReg(0);
534 if (!validReg(MRI, ResReg, 1, ARM::GPRRegBankID))
535 return false;
536
542 return true;
543 }
544
545 auto LHSReg = MIB.getReg(2);
546 auto RHSReg = MIB.getReg(3);
547 if (!validOpRegPair(MRI, LHSReg, RHSReg, Helper.OperandSize,
548 Helper.OperandRegBankID))
549 return false;
550
552 auto ZeroReg = MRI.createVirtualRegister(&ARM::GPRRegClass);
553 putConstant(I, ZeroReg, 0);
554
555 if (ARMConds.second == ARMCC::AL) {
556
557 if (!insertComparison(Helper, I, ResReg, ARMConds.first, LHSReg, RHSReg,
558 ZeroReg))
559 return false;
560 } else {
561
562 auto IntermediateRes = MRI.createVirtualRegister(&ARM::GPRRegClass);
563 if (!insertComparison(Helper, I, IntermediateRes, ARMConds.first, LHSReg,
564 RHSReg, ZeroReg))
565 return false;
566 if (!insertComparison(Helper, I, ResReg, ARMConds.second, LHSReg, RHSReg,
567 IntermediateRes))
568 return false;
569 }
570
572 return true;
573}
574
575bool ARMInstructionSelector::insertComparison(CmpConstants Helper, InsertInfo I,
576 unsigned ResReg,
578 unsigned LHSReg, unsigned RHSReg,
579 unsigned PrevRes) const {
580
581 auto CmpI =
582 BuildMI(I.MBB, I.InsertBefore, I.DbgLoc, TII.get(Helper.ComparisonOpcode))
587 return false;
588
589
590 if (Helper.ReadFlagsOpcode != ARM::INSTRUCTION_LIST_END) {
591 auto ReadI = BuildMI(I.MBB, I.InsertBefore, I.DbgLoc,
592 TII.get(Helper.ReadFlagsOpcode))
595 return false;
596 }
597
598
599 auto Mov1I = BuildMI(I.MBB, I.InsertBefore, I.DbgLoc,
600 TII.get(Helper.SelectResultOpcode))
606 return false;
607
608 return true;
609}
610
611bool ARMInstructionSelector::selectGlobal(MachineInstrBuilder &MIB,
612 MachineRegisterInfo &MRI) const {
614 LLVM_DEBUG(dbgs() << "ROPI and RWPI only supported for ELF\n");
615 return false;
616 }
617
619 if (GV->isThreadLocal()) {
620 LLVM_DEBUG(dbgs() << "TLS variables not supported yet\n");
621 return false;
622 }
623
626
627 bool UseMovt = STI.useMovt();
628
630 const Align Alignment(4);
631
632 auto addOpsForConstantPoolLoad = [&MF, Alignment, PtrTy](
633 MachineInstrBuilder &MIB,
634 const GlobalValue *GV, bool IsSBREL) {
635 assert((MIB->getOpcode() == ARM::LDRi12 ||
636 MIB->getOpcode() == ARM::t2LDRpci) &&
637 "Unsupported instruction");
638 auto ConstPool = MF.getConstantPool();
639 auto CPIndex =
640
641
642 IsSBREL
643 ? ConstPool->getConstantPoolIndex(
645 : ConstPool->getConstantPoolIndex(GV, Alignment);
646 MIB.addConstantPoolIndex(CPIndex, 0, 0)
647 .addMemOperand(MF.getMachineMemOperand(
649 PtrTy, Alignment));
650 if (MIB->getOpcode() == ARM::LDRi12)
651 MIB.addImm(0);
653 };
654
655 auto addGOTMemOperand = [this, &MF, Alignment](MachineInstrBuilder &MIB) {
656 MIB.addMemOperand(MF.getMachineMemOperand(
659 };
660
663
664
665
666
667
668
669 bool UseOpcodeThatLoads = Indirect && !STI.isThumb();
670
671
672
673 unsigned Opc =
675 ? (UseOpcodeThatLoads ? (unsigned)ARM::MOV_ga_pcrel_ldr
676 : Opcodes.MOV_ga_pcrel)
677 : (UseOpcodeThatLoads ? (unsigned)ARM::LDRLIT_ga_pcrel_ldr
678 : Opcodes.LDRLIT_ga_pcrel);
680
686 MIB->getOperand(1).setTargetFlags(TargetFlags);
687
688 if (Indirect) {
689 if (!UseOpcodeThatLoads) {
690 auto ResultReg = MIB.getReg(0);
691 auto AddressReg = MRI.createVirtualRegister(&ARM::GPRRegClass);
692
693 MIB->getOperand(0).setReg(AddressReg);
694
695 auto InsertBefore = std::next(MIB->getIterator());
696 auto MIBLoad = BuildMI(MBB, InsertBefore, MIB->getDebugLoc(),
702 addGOTMemOperand(MIBLoad);
703
705 return false;
706 } else {
707 addGOTMemOperand(MIB);
708 }
709 }
710
712 }
713
715 if (STI.isROPI() && isReadOnly) {
716 unsigned Opc = UseMovt ? Opcodes.MOV_ga_pcrel : Opcodes.LDRLIT_ga_pcrel;
719 }
720 if (STI.isRWPI() && !isReadOnly) {
721 auto Offset = MRI.createVirtualRegister(&ARM::GPRRegClass);
722 MachineInstrBuilder OffsetMIB;
723 if (UseMovt) {
724 OffsetMIB = BuildMI(MBB, *MIB, MIB->getDebugLoc(),
727 } else {
728
729 OffsetMIB = BuildMI(MBB, *MIB, MIB->getDebugLoc(),
731 addOpsForConstantPoolLoad(OffsetMIB, GV, true);
732 }
734 return false;
735
736
737 MIB->setDesc(TII.get(Opcodes.ADDrr));
738 MIB->removeOperand(1);
739 MIB.addReg(ARM::R9)
743
745 }
746
748 if (UseMovt) {
749 MIB->setDesc(TII.get(Opcodes.MOVi32imm));
750 } else {
751
752 MIB->setDesc(TII.get(Opcodes.ConstPoolLoad));
753 MIB->removeOperand(1);
754 addOpsForConstantPoolLoad(MIB, GV, false);
755 }
757 if (UseMovt)
758 MIB->setDesc(TII.get(Opcodes.MOVi32imm));
759 else
760 MIB->setDesc(TII.get(Opcodes.LDRLIT_ga_abs));
761 } else {
762 LLVM_DEBUG(dbgs() << "Object format not supported yet\n");
763 return false;
764 }
765
767}
768
769bool ARMInstructionSelector::selectSelect(MachineInstrBuilder &MIB,
770 MachineRegisterInfo &MRI) const {
772 auto InsertBefore = std::next(MIB->getIterator());
774
775
776 auto CondReg = MIB.getReg(1);
777 assert(validReg(MRI, CondReg, 1, ARM::GPRRegBankID) &&
778 "Unsupported types for select operation");
779 auto CmpI = BuildMI(MBB, InsertBefore, DbgLoc, TII.get(Opcodes.TSTri))
784 return false;
785
786
787
788 auto ResReg = MIB.getReg(0);
789 auto TrueReg = MIB.getReg(2);
790 auto FalseReg = MIB.getReg(3);
791 assert(validOpRegPair(MRI, ResReg, TrueReg, 32, ARM::GPRRegBankID) &&
792 validOpRegPair(MRI, TrueReg, FalseReg, 32, ARM::GPRRegBankID) &&
793 "Unsupported types for select operation");
794 auto Mov1I = BuildMI(MBB, InsertBefore, DbgLoc, TII.get(Opcodes.MOVCCr))
800 return false;
801
803 return true;
804}
805
806bool ARMInstructionSelector::selectShift(unsigned ShiftOpc,
807 MachineInstrBuilder &MIB) const {
808 assert(!STI.isThumb() && "Unsupported subtarget");
810 MIB.addImm(ShiftOpc);
813}
814
815void ARMInstructionSelector::renderVFPF32Imm(
816 MachineInstrBuilder &NewInstBuilder, const MachineInstr &OldInst,
817 int OpIdx) const {
818 assert(OldInst.getOpcode() == TargetOpcode::G_FCONSTANT &&
819 OpIdx == -1 && "Expected G_FCONSTANT");
820
823 assert(FPImmEncoding != -1 && "Invalid immediate value");
824
825 NewInstBuilder.addImm(FPImmEncoding);
826}
827
828void ARMInstructionSelector::renderVFPF64Imm(
829 MachineInstrBuilder &NewInstBuilder, const MachineInstr &OldInst, int OpIdx) const {
830 assert(OldInst.getOpcode() == TargetOpcode::G_FCONSTANT &&
831 OpIdx == -1 && "Expected G_FCONSTANT");
832
835 assert(FPImmEncoding != -1 && "Invalid immediate value");
836
837 NewInstBuilder.addImm(FPImmEncoding);
838}
839
840void ARMInstructionSelector::renderInvertedImm(MachineInstrBuilder &MIB,
841 const MachineInstr &MI,
842 int OpIdx) const {
843 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
844 "Expected G_CONSTANT");
845 int64_t CVal = MI.getOperand(1).getCImm()->getSExtValue();
847}
848
849bool ARMInstructionSelector::select(MachineInstr &I) {
850 assert(I.getParent() && "Instruction should be in a basic block!");
851 assert(I.getParent()->getParent() && "Instruction should be in a function!");
852
855 auto &MRI = MF.getRegInfo();
856
858 if (I.isCopy())
860
861 return true;
862 }
863
864 using namespace TargetOpcode;
865
866 if (selectImpl(I, *CoverageInfo))
867 return true;
868
869 MachineInstrBuilder MIB{MF, I};
870 bool isSExt = false;
871
872 switch (I.getOpcode()) {
873 case G_SEXT:
874 isSExt = true;
875 [[fallthrough]];
876 case G_ZEXT: {
877 assert(MRI.getType(I.getOperand(0).getReg()).getSizeInBits() <= 32 &&
878 "Unsupported destination size for extension");
879
880 LLT SrcTy = MRI.getType(I.getOperand(1).getReg());
882 switch (SrcSize) {
883 case 1: {
884
885 I.setDesc(TII.get(Opcodes.AND));
887
888 if (isSExt) {
889 Register SExtResult = I.getOperand(0).getReg();
890
891
892 Register AndResult = MRI.createVirtualRegister(&ARM::GPRRegClass);
893 I.getOperand(0).setReg(AndResult);
894
895 auto InsertBefore = std::next(I.getIterator());
896 auto SubI =
897 BuildMI(MBB, InsertBefore, I.getDebugLoc(), TII.get(Opcodes.RSB))
904 return false;
905 }
906 break;
907 }
908 case 8:
909 case 16: {
910 unsigned NewOpc = selectSimpleExtOpc(I.getOpcode(), SrcSize);
911 if (NewOpc == I.getOpcode())
912 return false;
913 I.setDesc(TII.get(NewOpc));
915 break;
916 }
917 default:
918 LLVM_DEBUG(dbgs() << "Unsupported source size for extension");
919 return false;
920 }
921 break;
922 }
923 case G_ANYEXT:
924 case G_TRUNC: {
925
926
927 auto SrcReg = I.getOperand(1).getReg();
928 auto DstReg = I.getOperand(0).getReg();
929
932
933 if (SrcRegBank.getID() == ARM::FPRRegBankID) {
934
935
936
937 assert(I.getOpcode() == G_TRUNC && "Unsupported operand for G_ANYEXT");
938 assert(DstRegBank.getID() == ARM::GPRRegBankID &&
939 "Unsupported combination of register banks");
940 assert(MRI.getType(SrcReg).getSizeInBits() == 64 && "Unsupported size");
941 assert(MRI.getType(DstReg).getSizeInBits() <= 32 && "Unsupported size");
942
943 Register IgnoredBits = MRI.createVirtualRegister(&ARM::GPRRegClass);
944 auto InsertBefore = std::next(I.getIterator());
945 auto MovI =
946 BuildMI(MBB, InsertBefore, I.getDebugLoc(), TII.get(ARM::VMOVRRD))
952 return false;
953
955 return true;
956 }
957
958 if (SrcRegBank.getID() != DstRegBank.getID()) {
960 dbgs() << "G_TRUNC/G_ANYEXT operands on different register banks\n");
961 return false;
962 }
963
964 if (SrcRegBank.getID() != ARM::GPRRegBankID) {
965 LLVM_DEBUG(dbgs() << "G_TRUNC/G_ANYEXT on non-GPR not supported yet\n");
966 return false;
967 }
968
971 }
972 case G_CONSTANT: {
973 if (.getType(I.getOperand(0).getReg()).isPointer()) {
974
976 return false;
977 }
978
979 auto &Val = I.getOperand(1);
980 if (Val.isCImm()) {
981 if (!Val.getCImm()->isZero()) {
982 LLVM_DEBUG(dbgs() << "Unsupported pointer constant value\n");
983 return false;
984 }
985 Val.ChangeToImmediate(0);
986 } else {
987 assert(Val.isImm() && "Unexpected operand for G_CONSTANT");
988 if (Val.getImm() != 0) {
989 LLVM_DEBUG(dbgs() << "Unsupported pointer constant value\n");
990 return false;
991 }
992 }
993
994 assert(!STI.isThumb() && "Unsupported subtarget");
995 I.setDesc(TII.get(ARM::MOVi));
997 break;
998 }
999 case G_FCONSTANT: {
1000
1001 unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits() / 8;
1003
1004 assert((Size == 4 || Size == 8) && "Unsupported FP constant type");
1005 auto LoadOpcode = Size == 4 ? ARM::VLDRS : ARM::VLDRD;
1006
1007 auto ConstPool = MF.getConstantPool();
1008 auto CPIndex =
1009 ConstPool->getConstantPoolIndex(I.getOperand(1).getFPImm(), Alignment);
1018 break;
1019 }
1020 case G_INTTOPTR:
1021 case G_PTRTOINT: {
1022 auto SrcReg = I.getOperand(1).getReg();
1023 auto DstReg = I.getOperand(0).getReg();
1024
1027
1028 if (SrcRegBank.getID() != DstRegBank.getID()) {
1031 << "G_INTTOPTR/G_PTRTOINT operands on different register banks\n");
1032 return false;
1033 }
1034
1035 if (SrcRegBank.getID() != ARM::GPRRegBankID) {
1037 dbgs() << "G_INTTOPTR/G_PTRTOINT on non-GPR not supported yet\n");
1038 return false;
1039 }
1040
1041 I.setDesc(TII.get(COPY));
1043 }
1044 case G_SELECT:
1045 return selectSelect(MIB, MRI);
1046 case G_ICMP: {
1047 CmpConstants Helper(Opcodes.CMPrr, ARM::INSTRUCTION_LIST_END,
1048 Opcodes.MOVCCi, ARM::GPRRegBankID, 32);
1049 return selectCmp(Helper, MIB, MRI);
1050 }
1051 case G_FCMP: {
1053
1054 Register OpReg = I.getOperand(2).getReg();
1055 unsigned Size = MRI.getType(OpReg).getSizeInBits();
1056
1057 if (Size == 64 && !STI.hasFP64()) {
1058 LLVM_DEBUG(dbgs() << "Subtarget only supports single precision");
1059 return false;
1060 }
1061 if (Size != 32 && Size != 64) {
1062 LLVM_DEBUG(dbgs() << "Unsupported size for G_FCMP operand");
1063 return false;
1064 }
1065
1066 CmpConstants Helper(Size == 32 ? ARM::VCMPS : ARM::VCMPD, ARM::FMSTAT,
1067 Opcodes.MOVCCi, ARM::FPRRegBankID, Size);
1068 return selectCmp(Helper, MIB, MRI);
1069 }
1070 case G_LSHR:
1071 return selectShift(ARM_AM::ShiftOpc::lsr, MIB);
1072 case G_ASHR:
1073 return selectShift(ARM_AM::ShiftOpc::asr, MIB);
1074 case G_SHL: {
1075 return selectShift(ARM_AM::ShiftOpc::lsl, MIB);
1076 }
1077 case G_PTR_ADD:
1078 I.setDesc(TII.get(Opcodes.ADDrr));
1080 break;
1081 case G_FRAME_INDEX:
1082
1083
1084 I.setDesc(TII.get(Opcodes.ADDri));
1086 break;
1087 case G_GLOBAL_VALUE:
1088 return selectGlobal(MIB, MRI);
1089 case G_STORE:
1090 case G_LOAD: {
1091 auto &MemOp = **I.memoperands_begin();
1092 if (MemOp.isAtomic()) {
1093 LLVM_DEBUG(dbgs() << "Atomic load/store not supported yet\n");
1094 return false;
1095 }
1096
1099
1100 LLT ValTy = MRI.getType(Reg);
1102
1104 "Don't know how to load/store 64-bit value without VFP");
1105
1107 Register PtrReg = LoadMI->getPointerReg();
1108 MachineInstr *Ptr = MRI.getVRegDef(PtrReg);
1109 if (Ptr->getOpcode() == TargetOpcode::G_CONSTANT_POOL) {
1111 unsigned Opcode = Subtarget->isThumb() ? ARM::tLDRpci : ARM::LDRcp;
1112
1115 .add(Index)
1120 return false;
1121 I.eraseFromParent();
1122 return true;
1123 }
1124 }
1125
1126 const auto NewOpc = selectLoadStoreOpCode(I.getOpcode(), RegBank, ValSize);
1127 if (NewOpc == G_LOAD || NewOpc == G_STORE)
1128 return false;
1129
1130 I.setDesc(TII.get(NewOpc));
1131
1132 if (NewOpc == ARM::LDRH || NewOpc == ARM::STRH)
1133
1136 break;
1137 }
1138 case G_MERGE_VALUES: {
1140 return false;
1141 break;
1142 }
1143 case G_UNMERGE_VALUES: {
1145 return false;
1146 break;
1147 }
1148 case G_BRCOND: {
1149 if (!validReg(MRI, I.getOperand(0).getReg(), 1, ARM::GPRRegBankID)) {
1150 LLVM_DEBUG(dbgs() << "Unsupported condition register for G_BRCOND");
1151 return false;
1152 }
1153
1154
1156 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcodes.TSTri))
1157 .addReg(I.getOperand(0).getReg())
1161 return false;
1162
1163
1165 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcodes.Bcc))
1169 return false;
1170 I.eraseFromParent();
1171 return true;
1172 }
1173 case G_PHI: {
1175
1176 Register DstReg = I.getOperand(0).getReg();
1177 const TargetRegisterClass *RC = guessRegClass(DstReg, MRI, TRI, RBI);
1179 break;
1180 }
1181
1182 return true;
1183 }
1184 default:
1185 return false;
1186 }
1187
1189}
unsigned const MachineRegisterInfo * MRI
#define GET_GLOBALISEL_PREDICATES_INIT
#define GET_GLOBALISEL_TEMPORARIES_INIT
static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
const TargetInstrInfo & TII
static bool isStore(int Opcode)
static bool isThumb(const MCSubtargetInfo &STI)
static std::pair< ARMCC::CondCodes, ARMCC::CondCodes > getComparePreds(CmpInst::Predicate Pred)
Definition ARMInstructionSelector.cpp:394
static bool selectMergeValues(MachineInstrBuilder &MIB, const ARMBaseInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
Definition ARMInstructionSelector.cpp:233
static bool selectUnmergeValues(MachineInstrBuilder &MIB, const ARMBaseInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
Definition ARMInstructionSelector.cpp:264
static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
Definition ARMInstructionSelector.cpp:213
#define STORE_OPCODE(VAR, OPC)
This file declares the targeting of the RegisterBankInfo class for ARM.
static const Function * getParent(const Value *V)
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
static DebugLoc getDebugLoc(MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
Return the first DebugLoc that has line number information, given a range of instructions.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
MachineInstr unsigned OpIdx
static StringRef getName(Value *V)
const SmallVectorImpl< MachineOperand > & Cond
static ARMConstantPoolConstant * Create(const Constant *C, unsigned ID)
This class provides the information for the target register banks.
bool isTargetMachO() const
bool isGVIndirectSymbol(const GlobalValue *GV) const
True if the GV will be accessed via an indirect symbol.
const ARMTargetLowering * getTargetLowering() const override
bool isTargetDarwin() const
bool isGVInGOT(const GlobalValue *GV) const
Returns the constant pool modifier needed to access the GV.
bool isReadOnly(const GlobalValue *GV) const
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ FCMP_TRUE
1 1 1 1 Always true (always folded)
@ ICMP_SLT
signed less than
@ ICMP_SLE
signed less or equal
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
@ ICMP_UGE
unsigned greater or equal
@ ICMP_UGT
unsigned greater than
@ ICMP_SGT
signed greater than
@ FCMP_ULT
1 1 0 0 True if unordered or less than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
@ ICMP_ULT
unsigned less than
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ ICMP_SGE
signed greater or equal
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
@ ICMP_ULE
unsigned less or equal
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
@ FCMP_FALSE
0 0 0 0 Always false (always folded)
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
const APFloat & getValueAPF() const
This is an important base class in LLVM.
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Instructions::iterator instr_iterator
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
Register getReg(unsigned Idx) const
Get the register for the operand index.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
LLVM_ABI void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
LLVM_ABI void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
LLVM_ABI void removeOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with.
const MachineOperand & getOperand(unsigned i) const
@ MOLoad
The memory access reads data.
const GlobalValue * getGlobal() const
Register getReg() const
getReg - Returns the register number.
const ConstantFP * getFPImm() const
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Holds all the information related to register banks.
static const TargetRegisterClass * constrainGenericRegister(Register Reg, const TargetRegisterClass &RC, MachineRegisterInfo &MRI)
Constrain the (possibly generic) virtual register Reg to RC.
const RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
This class implements the register bank concept.
unsigned getID() const
Get the identifier of this register bank.
Wrapper class representing virtual and physical registers.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
TargetInstrInfo - Interface to description of machine instruction set.
bool isPositionIndependent() const
unsigned getProgramPointerSize() const
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
@ SBREL
Section Relative (Windows TLS)
@ MO_NONLAZY
MO_NONLAZY - This is an independent flag, on a symbol operand "FOO" it represents a symbol which,...
@ MO_SBREL
MO_SBREL - On a symbol operand, this represents a static base relative relocation.
@ MO_GOT
MO_GOT - On a symbol operand, this represents a GOT relative relocation.
int getFP32Imm(const APInt &Imm)
getFP32Imm - Return an 8-bit floating-point version of the 32-bit floating-point value.
int getFP64Imm(const APInt &Imm)
getFP64Imm - Return an 8-bit floating-point version of the 64-bit floating-point value.
Predicate getPredicate(unsigned Condition, unsigned Hint)
Return predicate consisting of specified condition and hint bits.
NodeAddr< InstrNode * > Instr
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
InstructionSelector * createARMInstructionSelector(const ARMBaseTargetMachine &TM, const ARMSubtarget &STI, const ARMRegisterBankInfo &RBI)
Definition ARMInstructionSelector.cpp:162
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
LLVM_ABI bool constrainSelectedInstRegOperands(MachineInstr &I, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
Mutate the newly-selected instruction I to constrain its (possibly generic) virtual register operands...
bool isPreISelGenericOpcode(unsigned Opcode)
Check whether the given Opcode is a generic opcode that is not supposed to appear after ISel.
static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)
Get the operands corresponding to the given Pred value.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
static MachineOperand condCodeOp(unsigned CCReg=0)
Get the operand corresponding to the conditional code result.
Implement std::hash so that hash_code can be used in STL containers.
CmpConstants(unsigned CmpOpcode, unsigned FlagsOpcode, unsigned SelectOpcode, unsigned OpRegBank, unsigned OpSize)
Definition ARMInstructionSelector.cpp:461
const unsigned OperandRegBankID
Definition ARMInstructionSelector.cpp:478
const unsigned ReadFlagsOpcode
Definition ARMInstructionSelector.cpp:472
const unsigned SelectResultOpcode
Definition ARMInstructionSelector.cpp:475
const unsigned ComparisonOpcode
Definition ARMInstructionSelector.cpp:468
const unsigned OperandSize
Definition ARMInstructionSelector.cpp:481
MachineBasicBlock & MBB
Definition ARMInstructionSelector.cpp:489
const MachineBasicBlock::instr_iterator InsertBefore
Definition ARMInstructionSelector.cpp:490
InsertInfo(MachineInstrBuilder &MIB)
Definition ARMInstructionSelector.cpp:485
const DebugLoc & DbgLoc
Definition ARMInstructionSelector.cpp:491
static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)
Return a MachinePointerInfo record that refers to a GOT entry.