20 #include "llvm/IR/IntrinsicsARM.h"
23 #define DEBUG_TYPE "arm-isel"
29 #define GET_GLOBALISEL_PREDICATE_BITSET
30 #include "ARMGenGlobalISel.inc"
31 #undef GET_GLOBALISEL_PREDICATE_BITSET
53 bool insertComparison(CmpConstants Helper, InsertInfo
I,
unsigned ResReg,
55 unsigned PrevRes)
const;
58 void putConstant(InsertInfo
I,
unsigned DestReg,
unsigned Constant)
const;
67 unsigned ExpectedSize,
unsigned ExpectedRegBankID)
const;
71 unsigned ExpectedRegBankID)
const;
122 unsigned ConstPoolLoad;
123 unsigned MOV_ga_pcrel;
124 unsigned LDRLIT_ga_pcrel;
125 unsigned LDRLIT_ga_abs;
134 unsigned selectSimpleExtOpc(
unsigned Opc,
unsigned Size)
const;
138 unsigned selectLoadStoreOpCode(
unsigned Opc,
unsigned RegBank,
139 unsigned Size)
const;
142 int OpIdx = -1)
const;
144 int OpIdx = -1)
const;
146 #define GET_GLOBALISEL_PREDICATES_DECL
147 #include "ARMGenGlobalISel.inc"
148 #undef GET_GLOBALISEL_PREDICATES_DECL
152 #define GET_GLOBALISEL_TEMPORARIES_DECL
153 #include "ARMGenGlobalISel.inc"
154 #undef GET_GLOBALISEL_TEMPORARIES_DECL
163 return new ARMInstructionSelector(
TM, STI, RBI);
167 #define GET_GLOBALISEL_IMPL
168 #include "ARMGenGlobalISel.inc"
169 #undef GET_GLOBALISEL_IMPL
174 :
TII(*STI.getInstrInfo()),
TRI(*STI.getRegisterInfo()),
TM(
TM), RBI(RBI),
175 STI(STI), Opcodes(STI),
177 #
include "ARMGenGlobalISel.inc"
180 #
include "ARMGenGlobalISel.inc"
190 assert(RegBank &&
"Can't get reg bank for virtual register");
194 RegBank->
getID() == ARM::FPRRegBankID) &&
195 "Unsupported reg bank");
197 if (RegBank->
getID() == ARM::FPRRegBankID) {
199 return &ARM::SPRRegClass;
201 return &ARM::DPRRegClass;
202 else if (
Size == 128)
203 return &ARM::QPRRegClass;
208 return &ARM::GPRRegClass;
214 Register DstReg =
I.getOperand(0).getReg();
236 assert(
TII.getSubtarget().hasVFP2Base() &&
"Can't select merge without VFP");
244 "Unsupported operand for G_MERGE_VALUES");
249 "Unsupported operand for G_MERGE_VALUES");
254 "Unsupported operand for G_MERGE_VALUES");
267 assert(
TII.getSubtarget().hasVFP2Base() &&
268 "Can't select unmerge without VFP");
276 "Unsupported operand for G_UNMERGE_VALUES");
281 "Unsupported operand for G_UNMERGE_VALUES");
286 "Unsupported operand for G_UNMERGE_VALUES");
294 ARMInstructionSelector::OpcodeCache::OpcodeCache(
const ARMSubtarget &STI) {
297 using namespace TargetOpcode;
299 #define STORE_OPCODE(VAR, OPC) VAR = isThumb ? ARM::t2##OPC : ARM::OPC
313 STORE16 =
isThumb ? ARM::t2STRHi12 : ARM::STRH;
314 LOAD16 =
isThumb ? ARM::t2LDRHi12 : ARM::LDRH;
332 ConstPoolLoad =
isThumb ? ARM::t2LDRpci : ARM::LDRi12;
334 LDRLIT_ga_pcrel =
isThumb ? ARM::tLDRLIT_ga_pcrel : ARM::LDRLIT_ga_pcrel;
335 LDRLIT_ga_abs =
isThumb ? ARM::tLDRLIT_ga_abs : ARM::LDRLIT_ga_abs;
339 unsigned ARMInstructionSelector::selectSimpleExtOpc(
unsigned Opc,
340 unsigned Size)
const {
341 using namespace TargetOpcode;
347 return Size == 8 ? Opcodes.SEXT8 : Opcodes.SEXT16;
350 return Size == 8 ? Opcodes.ZEXT8 : Opcodes.ZEXT16;
355 unsigned ARMInstructionSelector::selectLoadStoreOpCode(
unsigned Opc,
357 unsigned Size)
const {
358 bool isStore = Opc == TargetOpcode::G_STORE;
360 if (RegBank == ARM::GPRRegBankID) {
364 return isStore ? Opcodes.STORE8 : Opcodes.LOAD8;
366 return isStore ? Opcodes.STORE16 : Opcodes.LOAD16;
368 return isStore ? Opcodes.STORE32 : Opcodes.LOAD32;
374 if (RegBank == ARM::FPRRegBankID) {
377 return isStore ? ARM::VSTRS : ARM::VLDRS;
379 return isStore ? ARM::VSTRD : ARM::VLDRD;
391 static std::pair<ARMCC::CondCodes, ARMCC::CondCodes>
395 case CmpInst::FCMP_ONE:
398 case CmpInst::FCMP_UEQ:
401 case CmpInst::ICMP_EQ:
402 case CmpInst::FCMP_OEQ:
405 case CmpInst::ICMP_SGT:
406 case CmpInst::FCMP_OGT:
409 case CmpInst::ICMP_SGE:
410 case CmpInst::FCMP_OGE:
413 case CmpInst::ICMP_UGT:
414 case CmpInst::FCMP_UGT:
417 case CmpInst::FCMP_OLT:
420 case CmpInst::ICMP_ULE:
421 case CmpInst::FCMP_OLE:
424 case CmpInst::FCMP_ORD:
427 case CmpInst::FCMP_UNO:
430 case CmpInst::FCMP_UGE:
433 case CmpInst::ICMP_SLT:
434 case CmpInst::FCMP_ULT:
437 case CmpInst::ICMP_SLE:
438 case CmpInst::FCMP_ULE:
441 case CmpInst::FCMP_UNE:
442 case CmpInst::ICMP_NE:
445 case CmpInst::ICMP_UGE:
448 case CmpInst::ICMP_ULT:
459 CmpConstants(
unsigned CmpOpcode,
unsigned FlagsOpcode,
unsigned SelectOpcode,
460 unsigned OpRegBank,
unsigned OpSize)
492 void ARMInstructionSelector::putConstant(
InsertInfo I,
unsigned DestReg,
494 (void)
BuildMI(
I.MBB,
I.InsertBefore,
I.DbgLoc,
TII.get(Opcodes.MOVi))
502 unsigned LHSReg,
unsigned RHSReg,
503 unsigned ExpectedSize,
504 unsigned ExpectedRegBankID)
const {
506 validReg(
MRI, LHSReg, ExpectedSize, ExpectedRegBankID) &&
507 validReg(
MRI, RHSReg, ExpectedSize, ExpectedRegBankID);
511 unsigned ExpectedSize,
512 unsigned ExpectedRegBankID)
const {
526 bool ARMInstructionSelector::selectCmp(CmpConstants Helper,
529 const InsertInfo
I(MIB);
531 auto ResReg = MIB.
getReg(0);
532 if (!validReg(
MRI, ResReg, 1, ARM::GPRRegBankID))
537 if (
Cond == CmpInst::FCMP_TRUE ||
Cond == CmpInst::FCMP_FALSE) {
538 putConstant(
I, ResReg,
Cond == CmpInst::FCMP_TRUE ? 1 : 0);
543 auto LHSReg = MIB.
getReg(2);
544 auto RHSReg = MIB.
getReg(3);
545 if (!validOpRegPair(
MRI, LHSReg, RHSReg, Helper.OperandSize,
546 Helper.OperandRegBankID))
551 putConstant(
I, ZeroReg, 0);
555 if (!insertComparison(Helper,
I, ResReg, ARMConds.first, LHSReg, RHSReg,
561 if (!insertComparison(Helper,
I, IntermediateRes, ARMConds.first, LHSReg,
564 if (!insertComparison(Helper,
I, ResReg, ARMConds.second, LHSReg, RHSReg,
573 bool ARMInstructionSelector::insertComparison(CmpConstants Helper, InsertInfo
I,
576 unsigned LHSReg,
unsigned RHSReg,
577 unsigned PrevRes)
const {
580 BuildMI(
I.MBB,
I.InsertBefore,
I.DbgLoc,
TII.get(Helper.ComparisonOpcode))
588 if (Helper.ReadFlagsOpcode != ARM::INSTRUCTION_LIST_END) {
589 auto ReadI =
BuildMI(
I.MBB,
I.InsertBefore,
I.DbgLoc,
590 TII.get(Helper.ReadFlagsOpcode))
597 auto Mov1I =
BuildMI(
I.MBB,
I.InsertBefore,
I.DbgLoc,
598 TII.get(Helper.SelectResultOpcode))
617 if (GV->isThreadLocal()) {
628 const Align Alignment(4);
630 auto addOpsForConstantPoolLoad = [&MF, Alignment, PtrTy](
633 assert((MIB->getOpcode() == ARM::LDRi12 ||
634 MIB->getOpcode() == ARM::t2LDRpci) &&
635 "Unsupported instruction");
636 auto ConstPool = MF.getConstantPool();
641 ? ConstPool->getConstantPoolIndex(
642 ARMConstantPoolConstant::Create(GV,
ARMCP::SBREL), Alignment)
643 : ConstPool->getConstantPoolIndex(GV, Alignment);
644 MIB.addConstantPoolIndex(CPIndex, 0, 0)
645 .addMemOperand(MF.getMachineMemOperand(
646 MachinePointerInfo::getConstantPool(MF), MachineMemOperand::MOLoad,
648 if (MIB->getOpcode() == ARM::LDRi12)
654 MIB.addMemOperand(MF.getMachineMemOperand(
655 MachinePointerInfo::getGOT(MF), MachineMemOperand::MOLoad,
656 TM.getProgramPointerSize(), Alignment));
659 if (
TM.isPositionIndependent()) {
667 bool UseOpcodeThatLoads =
Indirect && !STI.isThumb();
673 ? (UseOpcodeThatLoads ? (unsigned)ARM::MOV_ga_pcrel_ldr
674 : Opcodes.MOV_ga_pcrel)
675 : (UseOpcodeThatLoads ? (unsigned)ARM::LDRLIT_ga_pcrel_ldr
676 : Opcodes.LDRLIT_ga_pcrel);
677 MIB->setDesc(
TII.get(Opc));
684 MIB->getOperand(1).setTargetFlags(TargetFlags);
687 if (!UseOpcodeThatLoads) {
688 auto ResultReg = MIB.getReg(0);
691 MIB->getOperand(0).setReg(AddressReg);
693 auto InsertBefore = std::next(MIB->getIterator());
694 auto MIBLoad =
BuildMI(
MBB, InsertBefore, MIB->getDebugLoc(),
695 TII.get(Opcodes.LOAD32))
700 addGOTMemOperand(MIBLoad);
705 addGOTMemOperand(MIB);
713 if (STI.
isROPI() && isReadOnly) {
714 unsigned Opc = UseMovt ? Opcodes.MOV_ga_pcrel : Opcodes.LDRLIT_ga_pcrel;
715 MIB->setDesc(
TII.get(Opc));
718 if (STI.
isRWPI() && !isReadOnly) {
722 OffsetMIB =
BuildMI(
MBB, *MIB, MIB->getDebugLoc(),
727 OffsetMIB =
BuildMI(
MBB, *MIB, MIB->getDebugLoc(),
729 addOpsForConstantPoolLoad(OffsetMIB, GV,
true);
735 MIB->setDesc(
TII.get(Opcodes.ADDrr));
736 MIB->removeOperand(1);
747 MIB->setDesc(
TII.get(Opcodes.MOVi32imm));
750 MIB->setDesc(
TII.get(Opcodes.ConstPoolLoad));
751 MIB->removeOperand(1);
752 addOpsForConstantPoolLoad(MIB, GV,
false);
756 MIB->setDesc(
TII.get(Opcodes.MOVi32imm));
758 MIB->setDesc(
TII.get(Opcodes.LDRLIT_ga_abs));
774 auto CondReg = MIB.
getReg(1);
775 assert(validReg(
MRI, CondReg, 1, ARM::GPRRegBankID) &&
776 "Unsupported types for select operation");
777 auto CmpI =
BuildMI(
MBB, InsertBefore, DbgLoc,
TII.get(Opcodes.TSTri))
786 auto ResReg = MIB.
getReg(0);
787 auto TrueReg = MIB.
getReg(2);
788 auto FalseReg = MIB.
getReg(3);
789 assert(validOpRegPair(
MRI, ResReg, TrueReg, 32, ARM::GPRRegBankID) &&
790 validOpRegPair(
MRI, TrueReg, FalseReg, 32, ARM::GPRRegBankID) &&
791 "Unsupported types for select operation");
792 auto Mov1I =
BuildMI(
MBB, InsertBefore, DbgLoc,
TII.get(Opcodes.MOVCCr))
804 bool ARMInstructionSelector::selectShift(
unsigned ShiftOpc,
806 assert(!STI.isThumb() &&
"Unsupported subtarget");
813 void ARMInstructionSelector::renderVFPF32Imm(
817 OpIdx == -1 &&
"Expected G_FCONSTANT");
821 assert(FPImmEncoding != -1 &&
"Invalid immediate value");
823 NewInstBuilder.
addImm(FPImmEncoding);
826 void ARMInstructionSelector::renderVFPF64Imm(
829 OpIdx == -1 &&
"Expected G_FCONSTANT");
833 assert(FPImmEncoding != -1 &&
"Invalid immediate value");
835 NewInstBuilder.
addImm(FPImmEncoding);
839 assert(
I.getParent() &&
"Instruction should be in a basic block!");
840 assert(
I.getParent()->getParent() &&
"Instruction should be in a function!");
842 auto &
MBB = *
I.getParent();
844 auto &
MRI = MF.getRegInfo();
853 using namespace TargetOpcode;
861 switch (
I.getOpcode()) {
867 "Unsupported destination size for extension");
874 I.setDesc(
TII.get(Opcodes.AND));
878 Register SExtResult =
I.getOperand(0).getReg();
882 I.getOperand(0).setReg(AndResult);
884 auto InsertBefore = std::next(
I.getIterator());
899 unsigned NewOpc = selectSimpleExtOpc(
I.getOpcode(), SrcSize);
900 if (NewOpc ==
I.getOpcode())
902 I.setDesc(
TII.get(NewOpc));
916 auto SrcReg =
I.getOperand(1).getReg();
917 auto DstReg =
I.getOperand(0).getReg();
922 if (SrcRegBank.getID() == ARM::FPRRegBankID) {
926 assert(
I.getOpcode() == G_TRUNC &&
"Unsupported operand for G_ANYEXT");
927 assert(DstRegBank.getID() == ARM::GPRRegBankID &&
928 "Unsupported combination of register banks");
933 auto InsertBefore = std::next(
I.getIterator());
947 if (SrcRegBank.getID() != DstRegBank.getID()) {
949 dbgs() <<
"G_TRUNC/G_ANYEXT operands on different register banks\n");
953 if (SrcRegBank.getID() != ARM::GPRRegBankID) {
954 LLVM_DEBUG(
dbgs() <<
"G_TRUNC/G_ANYEXT on non-GPR not supported yet\n");
958 I.setDesc(
TII.get(COPY));
968 auto &Val =
I.getOperand(1);
970 if (!Val.getCImm()->isZero()) {
974 Val.ChangeToImmediate(0);
976 assert(Val.isImm() &&
"Unexpected operand for G_CONSTANT");
977 if (Val.getImm() != 0) {
983 assert(!STI.isThumb() &&
"Unsupported subtarget");
984 I.setDesc(
TII.get(ARM::MOVi));
993 assert((
Size == 4 ||
Size == 8) &&
"Unsupported FP constant type");
994 auto LoadOpcode =
Size == 4 ? ARM::VLDRS : ARM::VLDRD;
996 auto ConstPool = MF.getConstantPool();
998 ConstPool->getConstantPoolIndex(
I.getOperand(1).getFPImm(), Alignment);
1003 MF.getMachineMemOperand(MachinePointerInfo::getConstantPool(MF),
1004 MachineMemOperand::MOLoad,
Size, Alignment))
1011 auto SrcReg =
I.getOperand(1).getReg();
1012 auto DstReg =
I.getOperand(0).getReg();
1017 if (SrcRegBank.getID() != DstRegBank.getID()) {
1020 <<
"G_INTTOPTR/G_PTRTOINT operands on different register banks\n");
1024 if (SrcRegBank.getID() != ARM::GPRRegBankID) {
1026 dbgs() <<
"G_INTTOPTR/G_PTRTOINT on non-GPR not supported yet\n");
1030 I.setDesc(
TII.get(COPY));
1034 return selectSelect(MIB,
MRI);
1036 CmpConstants Helper(Opcodes.CMPrr, ARM::INSTRUCTION_LIST_END,
1037 Opcodes.MOVCCi, ARM::GPRRegBankID, 32);
1038 return selectCmp(Helper, MIB,
MRI);
1043 Register OpReg =
I.getOperand(2).getReg();
1046 if (
Size == 64 && !STI.hasFP64()) {
1047 LLVM_DEBUG(
dbgs() <<
"Subtarget only supports single precision");
1055 CmpConstants Helper(
Size == 32 ? ARM::VCMPS : ARM::VCMPD,
ARM::FMSTAT,
1056 Opcodes.MOVCCi, ARM::FPRRegBankID,
Size);
1057 return selectCmp(Helper, MIB,
MRI);
1067 I.setDesc(
TII.get(Opcodes.ADDrr));
1073 I.setDesc(
TII.get(Opcodes.ADDri));
1076 case G_GLOBAL_VALUE:
1077 return selectGlobal(MIB,
MRI);
1080 const auto &
MemOp = **
I.memoperands_begin();
1081 if (
MemOp.isAtomic()) {
1093 "Don't know how to load/store 64-bit value without VFP");
1095 const auto NewOpc = selectLoadStoreOpCode(
I.getOpcode(), RegBank, ValSize);
1096 if (NewOpc == G_LOAD || NewOpc == G_STORE)
1099 I.setDesc(
TII.get(NewOpc));
1101 if (NewOpc == ARM::LDRH || NewOpc == ARM::STRH)
1107 case G_MERGE_VALUES: {
1112 case G_UNMERGE_VALUES: {
1118 if (!validReg(
MRI,
I.getOperand(0).getReg(), 1, ARM::GPRRegBankID)) {
1119 LLVM_DEBUG(
dbgs() <<
"Unsupported condition register for G_BRCOND");
1125 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(Opcodes.TSTri))
1126 .
addReg(
I.getOperand(0).getReg())
1134 BuildMI(*
I.getParent(),
I,
I.getDebugLoc(),
TII.get(Opcodes.Bcc))
1135 .
add(
I.getOperand(1))
1139 I.eraseFromParent();
1145 Register DstReg =
I.getOperand(0).getReg();