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;
108 unsigned selectSimpleExtOpc(
unsigned Opc,
unsigned Size)
const;
112 unsigned selectLoadStoreOpCode(
unsigned Opc,
unsigned RegBank,
113 unsigned Size)
const;
115 #define GET_GLOBALISEL_PREDICATES_DECL 116 #include "ARMGenGlobalISel.inc" 117 #undef GET_GLOBALISEL_PREDICATES_DECL 121 #define GET_GLOBALISEL_TEMPORARIES_DECL 122 #include "ARMGenGlobalISel.inc" 123 #undef GET_GLOBALISEL_TEMPORARIES_DECL 132 return new ARMInstructionSelector(TM, STI, RBI);
138 #define GET_GLOBALISEL_IMPL 139 #include "ARMGenGlobalISel.inc" 140 #undef GET_GLOBALISEL_IMPL 146 TRI(*STI.getRegisterInfo()), TM(TM), RBI(RBI), STI(STI), Opcodes(STI),
148 #include
"ARMGenGlobalISel.inc" 151 #include
"ARMGenGlobalISel.inc" 161 assert(RegBank &&
"Can't get reg bank for virtual register");
165 RegBank->
getID() == ARM::FPRRegBankID) &&
166 "Unsupported reg bank");
168 if (RegBank->
getID() == ARM::FPRRegBankID) {
170 return &ARM::SPRRegClass;
172 return &ARM::DPRRegClass;
173 else if (Size == 128)
174 return &ARM::QPRRegClass;
179 return &ARM::GPRRegClass;
186 if (TargetRegisterInfo::isPhysicalRegister(DstReg))
215 "Unsupported operand for G_MERGE_VALUES");
220 "Unsupported operand for G_MERGE_VALUES");
225 "Unsupported operand for G_MERGE_VALUES");
246 "Unsupported operand for G_UNMERGE_VALUES");
251 "Unsupported operand for G_UNMERGE_VALUES");
256 "Unsupported operand for G_UNMERGE_VALUES");
264 ARMInstructionSelector::OpcodeCache::OpcodeCache(
const ARMSubtarget &STI) {
267 using namespace TargetOpcode;
269 #define STORE_OPCODE(VAR, OPC) VAR = isThumb ? ARM::t2##OPC : ARM::OPC 283 STORE16 = isThumb ? ARM::t2STRHi12 : ARM::STRH;
284 LOAD16 = isThumb ? ARM::t2LDRHi12 : ARM::LDRH;
291 unsigned ARMInstructionSelector::selectSimpleExtOpc(
unsigned Opc,
292 unsigned Size)
const {
293 using namespace TargetOpcode;
295 if (Size != 8 && Size != 16)
299 return Size == 8 ? Opcodes.SEXT8 : Opcodes.SEXT16;
302 return Size == 8 ? Opcodes.ZEXT8 : Opcodes.ZEXT16;
307 unsigned ARMInstructionSelector::selectLoadStoreOpCode(
unsigned Opc,
309 unsigned Size)
const {
310 bool isStore = Opc == TargetOpcode::G_STORE;
312 if (RegBank == ARM::GPRRegBankID) {
316 return isStore ? Opcodes.STORE8 : Opcodes.LOAD8;
318 return isStore ? Opcodes.STORE16 : Opcodes.LOAD16;
320 return isStore ? Opcodes.STORE32 : Opcodes.LOAD32;
326 if (RegBank == ARM::FPRRegBankID) {
329 return isStore ? ARM::VSTRS : ARM::VLDRS;
331 return isStore ? ARM::VSTRD : ARM::VLDRD;
343 static std::pair<ARMCC::CondCodes, ARMCC::CondCodes>
347 case CmpInst::FCMP_ONE:
350 case CmpInst::FCMP_UEQ:
353 case CmpInst::ICMP_EQ:
354 case CmpInst::FCMP_OEQ:
357 case CmpInst::ICMP_SGT:
358 case CmpInst::FCMP_OGT:
361 case CmpInst::ICMP_SGE:
362 case CmpInst::FCMP_OGE:
365 case CmpInst::ICMP_UGT:
366 case CmpInst::FCMP_UGT:
369 case CmpInst::FCMP_OLT:
372 case CmpInst::ICMP_ULE:
373 case CmpInst::FCMP_OLE:
376 case CmpInst::FCMP_ORD:
379 case CmpInst::FCMP_UNO:
382 case CmpInst::FCMP_UGE:
385 case CmpInst::ICMP_SLT:
386 case CmpInst::FCMP_ULT:
389 case CmpInst::ICMP_SLE:
390 case CmpInst::FCMP_ULE:
393 case CmpInst::FCMP_UNE:
394 case CmpInst::ICMP_NE:
397 case CmpInst::ICMP_UGE:
400 case CmpInst::ICMP_ULT:
406 assert(Preds.first != ARMCC::AL &&
"No comparisons needed?");
411 CmpConstants(
unsigned CmpOpcode,
unsigned FlagsOpcode,
unsigned OpRegBank,
413 : ComparisonOpcode(CmpOpcode), ReadFlagsOpcode(FlagsOpcode),
414 OperandRegBankID(OpRegBank), OperandSize(OpSize) {}
432 : MBB(*MIB->
getParent()), InsertBefore(
std::next(MIB->getIterator())),
440 void ARMInstructionSelector::putConstant(
InsertInfo I,
unsigned DestReg,
450 unsigned LHSReg,
unsigned RHSReg,
451 unsigned ExpectedSize,
452 unsigned ExpectedRegBankID)
const {
454 validReg(MRI, LHSReg, ExpectedSize, ExpectedRegBankID) &&
455 validReg(MRI, RHSReg, ExpectedSize, ExpectedRegBankID);
459 unsigned ExpectedSize,
460 unsigned ExpectedRegBankID)
const {
474 bool ARMInstructionSelector::selectCmp(
CmpConstants Helper,
480 if (!validReg(MRI, ResReg, 1, ARM::GPRRegBankID))
485 if (Cond == CmpInst::FCMP_TRUE || Cond == CmpInst::FCMP_FALSE) {
486 putConstant(I, ResReg, Cond == CmpInst::FCMP_TRUE ? 1 : 0);
493 if (!validOpRegPair(MRI, LHSReg, RHSReg, Helper.
OperandSize,
499 putConstant(I, ZeroReg, 0);
503 if (!insertComparison(Helper, I, ResReg, ARMConds.first, LHSReg, RHSReg,
509 if (!insertComparison(Helper, I, IntermediateRes, ARMConds.first, LHSReg,
512 if (!insertComparison(Helper, I, ResReg, ARMConds.second, LHSReg, RHSReg,
524 unsigned LHSReg,
unsigned RHSReg,
525 unsigned PrevRes)
const {
564 if (GV->isThreadLocal()) {
572 bool UseMovt = STI.
useMovt(MF);
574 unsigned Size =
TM.getPointerSize(0);
575 unsigned Alignment = 4;
577 auto addOpsForConstantPoolLoad = [&MF, Alignment,
580 assert(MIB->getOpcode() == ARM::LDRi12 &&
"Unsupported instruction");
581 auto ConstPool = MF.getConstantPool();
586 ? ConstPool->getConstantPoolIndex(
587 ARMConstantPoolConstant::Create(GV,
ARMCP::SBREL), Alignment)
588 : ConstPool->getConstantPoolIndex(GV, Alignment);
589 MIB.addConstantPoolIndex(CPIndex, 0, 0)
591 MF.getMachineMemOperand(MachinePointerInfo::getConstantPool(MF),
592 MachineMemOperand::MOLoad, Size, Alignment))
597 if (
TM.isPositionIndependent()) {
603 ? (Indirect ? ARM::MOV_ga_pcrel_ldr : ARM::MOV_ga_pcrel)
604 : (Indirect ? ARM::LDRLIT_ga_pcrel_ldr : ARM::LDRLIT_ga_pcrel);
605 MIB->setDesc(
TII.get(Opc));
612 MIB->getOperand(1).setTargetFlags(TargetFlags);
615 MIB.addMemOperand(MF.getMachineMemOperand(
616 MachinePointerInfo::getGOT(MF), MachineMemOperand::MOLoad,
617 TM.getProgramPointerSize(), Alignment));
623 if (STI.
isROPI() && isReadOnly) {
624 unsigned Opc = UseMovt ? ARM::MOV_ga_pcrel : ARM::LDRLIT_ga_pcrel;
625 MIB->setDesc(
TII.get(Opc));
628 if (STI.
isRWPI() && !isReadOnly) {
632 OffsetMIB =
BuildMI(MBB, *MIB, MIB->getDebugLoc(),
639 addOpsForConstantPoolLoad(OffsetMIB, GV,
true);
645 MIB->setDesc(
TII.get(ARM::ADDrr));
646 MIB->RemoveOperand(1);
657 MIB->setDesc(
TII.get(ARM::MOVi32imm));
660 MIB->setDesc(
TII.get(ARM::LDRi12));
661 MIB->RemoveOperand(1);
662 addOpsForConstantPoolLoad(MIB, GV,
false);
666 MIB->setDesc(
TII.get(ARM::MOVi32imm));
668 MIB->setDesc(
TII.get(ARM::LDRLIT_ga_abs));
685 assert(validReg(MRI, CondReg, 1, ARM::GPRRegBankID) &&
686 "Unsupported types for select operation");
687 auto CmpI =
BuildMI(MBB, InsertBefore, DbgLoc,
TII.get(ARM::CMPri))
699 assert(validOpRegPair(MRI, ResReg, TrueReg, 32, ARM::GPRRegBankID) &&
700 validOpRegPair(MRI, TrueReg, FalseReg, 32, ARM::GPRRegBankID) &&
701 "Unsupported types for select operation");
702 auto Mov1I =
BuildMI(MBB, InsertBefore, DbgLoc,
TII.get(ARM::MOVCCr))
714 bool ARMInstructionSelector::selectShift(
unsigned ShiftOpc,
729 auto &MRI = MF.getRegInfo();
738 using namespace TargetOpcode;
746 switch (I.getOpcode()) {
751 LLT DstTy = MRI.
getType(I.getOperand(0).getReg());
754 LLVM_DEBUG(
dbgs() <<
"Unsupported destination size for extension");
758 LLT SrcTy = MRI.
getType(I.getOperand(1).getReg());
763 I.setDesc(
TII.get(Opcodes.AND));
767 unsigned SExtResult = I.getOperand(0).getReg();
771 I.getOperand(0).setReg(AndResult);
773 auto InsertBefore = std::next(I.getIterator());
775 BuildMI(MBB, InsertBefore, I.getDebugLoc(),
TII.get(Opcodes.RSB))
788 unsigned NewOpc = selectSimpleExtOpc(I.getOpcode(), SrcSize);
789 if (NewOpc == I.getOpcode())
791 I.setDesc(
TII.get(NewOpc));
805 auto SrcReg = I.getOperand(1).getReg();
806 auto DstReg = I.getOperand(0).getReg();
808 const auto &SrcRegBank = *RBI.
getRegBank(SrcReg, MRI, TRI);
809 const auto &DstRegBank = *RBI.
getRegBank(DstReg, MRI, TRI);
811 if (SrcRegBank.getID() == ARM::FPRRegBankID) {
815 assert(I.getOpcode() == G_TRUNC &&
"Unsupported operand for G_ANYEXT");
816 assert(DstRegBank.getID() == ARM::GPRRegBankID &&
817 "Unsupported combination of register banks");
822 auto InsertBefore = std::next(I.getIterator());
836 if (SrcRegBank.getID() != DstRegBank.getID()) {
838 dbgs() <<
"G_TRUNC/G_ANYEXT operands on different register banks\n");
842 if (SrcRegBank.getID() != ARM::GPRRegBankID) {
843 LLVM_DEBUG(
dbgs() <<
"G_TRUNC/G_ANYEXT on non-GPR not supported yet\n");
847 I.setDesc(
TII.get(COPY));
851 if (!MRI.
getType(I.getOperand(0).getReg()).isPointer()) {
857 auto &Val = I.getOperand(1);
859 if (!Val.getCImm()->isZero()) {
863 Val.ChangeToImmediate(0);
865 assert(Val.isImm() &&
"Unexpected operand for G_CONSTANT");
866 if (Val.getImm() != 0) {
872 I.setDesc(
TII.get(ARM::MOVi));
878 auto SrcReg = I.getOperand(1).getReg();
879 auto DstReg = I.getOperand(0).getReg();
881 const auto &SrcRegBank = *RBI.
getRegBank(SrcReg, MRI, TRI);
882 const auto &DstRegBank = *RBI.
getRegBank(DstReg, MRI, TRI);
884 if (SrcRegBank.getID() != DstRegBank.getID()) {
887 <<
"G_INTTOPTR/G_PTRTOINT operands on different register banks\n");
891 if (SrcRegBank.getID() != ARM::GPRRegBankID) {
893 dbgs() <<
"G_INTTOPTR/G_PTRTOINT on non-GPR not supported yet\n");
897 I.setDesc(
TII.get(COPY));
901 return selectSelect(MIB, MRI);
903 CmpConstants Helper(ARM::CMPrr, ARM::INSTRUCTION_LIST_END,
904 ARM::GPRRegBankID, 32);
905 return selectCmp(Helper, MIB, MRI);
910 unsigned OpReg = I.getOperand(2).getReg();
917 if (Size != 32 && Size != 64) {
923 ARM::FPRRegBankID, Size);
924 return selectCmp(Helper, MIB, MRI);
934 I.setDesc(
TII.get(ARM::ADDrr));
940 I.setDesc(
TII.get(ARM::ADDri));
944 return selectGlobal(MIB, MRI);
947 const auto &MemOp = **I.memoperands_begin();
948 if (MemOp.getOrdering() != AtomicOrdering::NotAtomic) {
953 unsigned Reg = I.getOperand(0).getReg();
960 "Don't know how to load/store 64-bit value without VFP");
962 const auto NewOpc = selectLoadStoreOpCode(I.getOpcode(), RegBank, ValSize);
963 if (NewOpc == G_LOAD || NewOpc == G_STORE)
966 I.setDesc(
TII.get(NewOpc));
968 if (NewOpc == ARM::LDRH || NewOpc == ARM::STRH)
974 case G_MERGE_VALUES: {
979 case G_UNMERGE_VALUES: {
985 if (!validReg(MRI, I.getOperand(0).getReg(), 1, ARM::GPRRegBankID)) {
986 LLVM_DEBUG(
dbgs() <<
"Unsupported condition register for G_BRCOND");
991 auto Test =
BuildMI(*I.getParent(),
I, I.getDebugLoc(),
TII.get(ARM::TSTri))
992 .addReg(I.getOperand(0).getReg())
1000 .
add(I.getOperand(1))
1004 I.eraseFromParent();
1008 I.setDesc(
TII.get(PHI));
1010 unsigned DstReg = I.getOperand(0).getReg();
const MachineInstrBuilder & add(const MachineOperand &MO) const
InsertInfo(MachineInstrBuilder &MIB)
static bool selectMergeValues(MachineInstrBuilder &MIB, const ARMBaseInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
This class represents lattice values for constants.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
unsigned getReg() const
getReg - Returns the register number.
const ARMTargetLowering * getTargetLowering() const override
static uint64_t selectImpl(uint64_t CandidateMask, uint64_t &NextInSequenceMask)
LLT getType(unsigned Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register...
#define GET_GLOBALISEL_PREDICATES_INIT
unsigned const TargetRegisterInfo * TRI
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned char TargetFlags=0) const
InstructionSelector * createARMInstructionSelector(const ARMBaseTargetMachine &TM, const ARMSubtarget &STI, const ARMRegisterBankInfo &RBI)
static bool isThumb(const MCSubtargetInfo &STI)
const unsigned ReadFlagsOpcode
Holds all the information related to register banks.
MO_SBREL - On a symbol operand, this represents a static base relative relocation.
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
const HexagonInstrInfo * TII
CmpConstants(unsigned CmpOpcode, unsigned FlagsOpcode, unsigned OpRegBank, unsigned OpSize)
const MachineInstrBuilder & addUse(unsigned RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
static StringRef getName(Value *V)
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool isGVIndirectSymbol(const GlobalValue *GV) const
True if the GV will be accessed via an indirect symbol.
static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)
Get the operands corresponding to the given Pred value.
MO_GOT - This flag indicates that a symbol operand represents the address of the GOT entry for the sy...
bool useMovt(const MachineFunction &MF) const
static bool isStore(int Opcode)
This class provides the information for the target register banks.
bool isTargetDarwin() const
const ARMSubtarget & getSubtarget() const
bool isReadOnly(const GlobalValue *GV) const
static std::pair< ARMCC::CondCodes, ARMCC::CondCodes > getComparePreds(CmpInst::Predicate Pred)
TargetInstrInfo - Interface to description of machine instruction set.
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
unsigned const MachineRegisterInfo * MRI
This file declares the targeting of the RegisterBankInfo class for ARM.
This is an important base class in LLVM.
#define STORE_OPCODE(VAR, OPC)
const GlobalValue * getGlobal() const
bool isGVInGOT(const GlobalValue *GV) const
Returns the constant pool modifier needed to access the GV.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
static bool selectUnmergeValues(MachineInstrBuilder &MIB, const ARMBaseInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
self_iterator getIterator()
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
StringRef getName(unsigned Opcode) const
Returns the name for the instructions with the given opcode.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
void setDesc(const MCInstrDesc &tid)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one...
RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
unsigned getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
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...
This class implements the register bank concept.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
const unsigned OperandRegBankID
const MachineBasicBlock * getParent() const
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
Section Relative (Windows TLS)
Provides the logic to select generic machine instructions.
Representation of each machine instruction.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
Bitwise operators - logical and, logical or, logical xor.
static MachineOperand condCodeOp(unsigned CCReg=0)
Get the operand corresponding to the conditional code result.
static DebugLoc getDebugLoc(MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
Return the first found DebugLoc that has a DILocation, given a range of instructions.
static const TargetRegisterClass * constrainGenericRegister(unsigned Reg, const TargetRegisterClass &RC, MachineRegisterInfo &MRI)
Constrain the (possibly generic) virtual register Reg to RC.
#define GET_GLOBALISEL_TEMPORARIES_INIT
const unsigned ComparisonOpcode
const unsigned OperandSize
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Instructions::iterator instr_iterator
bool isTargetMachO() const
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool isPreISelGenericOpcode(unsigned Opcode)
Check whether the given Opcode is a generic opcode that is not supposed to appear after ISel...
static const Function * getParent(const Value *V)
MO_NONLAZY - This is an independent flag, on a symbol operand "FOO" it represents a symbol which...
const MachineBasicBlock::instr_iterator InsertBefore
const MachineInstrBuilder & addDef(unsigned RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineOperand & getOperand(unsigned i) const
unsigned createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
unsigned getID() const
Get the identifier of this register bank.
unsigned getPredicate() const