31 #define DEBUG_TYPE "aarch64-isel"
35 #ifndef LLVM_BUILD_GLOBAL_ISEL
36 #error "You shouldn't build this"
39 #include "AArch64GenGlobalISel.inc"
45 TRI(*STI.getRegisterInfo()), RBI(RBI) {}
54 return &AArch64::GPR32RegClass;
56 return &AArch64::GPR64RegClass;
62 return &AArch64::FPR32RegClass;
64 return &AArch64::FPR64RegClass;
66 return &AArch64::FPR128RegClass;
85 DEBUG(
dbgs() <<
"Generic binop register should be typed\n");
93 DEBUG(
dbgs() <<
"Generic inst non-reg operands are unsupported\n");
102 DEBUG(
dbgs() <<
"Generic inst has physical register operand\n");
108 DEBUG(
dbgs() <<
"Generic register has no bank or class\n");
112 if (PrevOpBank && OpBank != PrevOpBank) {
113 DEBUG(
dbgs() <<
"Generic inst operands have different banks\n");
130 assert((OpSize == 32 || (GenericOpc != TargetOpcode::G_SDIV &&
131 GenericOpc != TargetOpcode::G_UDIV &&
132 GenericOpc != TargetOpcode::G_LSHR &&
133 GenericOpc != TargetOpcode::G_ASHR)) &&
134 "operation should have been legalized before now");
136 switch (GenericOpc) {
137 case TargetOpcode::G_OR:
138 return AArch64::ORRWrr;
139 case TargetOpcode::G_XOR:
140 return AArch64::EORWrr;
141 case TargetOpcode::G_AND:
142 return AArch64::ANDWrr;
143 case TargetOpcode::G_ADD:
144 assert(OpSize != 32 &&
"s32 G_ADD should have been selected");
145 return AArch64::ADDWrr;
146 case TargetOpcode::G_SUB:
147 return AArch64::SUBWrr;
148 case TargetOpcode::G_SHL:
149 return AArch64::LSLVWr;
150 case TargetOpcode::G_LSHR:
151 return AArch64::LSRVWr;
152 case TargetOpcode::G_ASHR:
153 return AArch64::ASRVWr;
154 case TargetOpcode::G_SDIV:
155 return AArch64::SDIVWr;
156 case TargetOpcode::G_UDIV:
157 return AArch64::UDIVWr;
161 }
else if (OpSize == 64) {
162 switch (GenericOpc) {
163 case TargetOpcode::G_OR:
164 return AArch64::ORRXrr;
165 case TargetOpcode::G_XOR:
166 return AArch64::EORXrr;
167 case TargetOpcode::G_AND:
168 return AArch64::ANDXrr;
169 case TargetOpcode::G_GEP:
170 return AArch64::ADDXrr;
171 case TargetOpcode::G_SUB:
172 return AArch64::SUBXrr;
173 case TargetOpcode::G_SHL:
174 return AArch64::LSLVXr;
175 case TargetOpcode::G_LSHR:
176 return AArch64::LSRVXr;
177 case TargetOpcode::G_ASHR:
178 return AArch64::ASRVXr;
179 case TargetOpcode::G_SDIV:
180 return AArch64::SDIVXr;
181 case TargetOpcode::G_UDIV:
182 return AArch64::UDIVXr;
190 switch (GenericOpc) {
191 case TargetOpcode::G_FADD:
192 return AArch64::FADDSrr;
193 case TargetOpcode::G_FSUB:
194 return AArch64::FSUBSrr;
195 case TargetOpcode::G_FMUL:
196 return AArch64::FMULSrr;
197 case TargetOpcode::G_FDIV:
198 return AArch64::FDIVSrr;
203 switch (GenericOpc) {
204 case TargetOpcode::G_FADD:
205 return AArch64::FADDDrr;
206 case TargetOpcode::G_FSUB:
207 return AArch64::FSUBDrr;
208 case TargetOpcode::G_FMUL:
209 return AArch64::FMULDrr;
210 case TargetOpcode::G_FDIV:
211 return AArch64::FDIVDrr;
212 case TargetOpcode::G_OR:
213 return AArch64::ORRv8i8;
229 const bool isStore = GenericOpc == TargetOpcode::G_STORE;
234 return isStore ? AArch64::STRBBui : AArch64::LDRBBui;
236 return isStore ? AArch64::STRHHui : AArch64::LDRHHui;
238 return isStore ? AArch64::STRWui : AArch64::LDRWui;
240 return isStore ? AArch64::STRXui : AArch64::LDRXui;
245 return isStore ? AArch64::STRBui : AArch64::LDRBui;
247 return isStore ? AArch64::STRHui : AArch64::LDRHui;
249 return isStore ? AArch64::STRSui : AArch64::LDRSui;
251 return isStore ? AArch64::STRDui : AArch64::LDRDui;
263 assert(I.
isCopy() &&
"Generic operators do not allow physical registers");
270 const unsigned SrcSize = RBI.getSizeInBits(SrcReg, MRI, TRI);
273 "No phys reg on generic operators");
275 (DstSize == SrcSize ||
279 DstSize <= RBI.getSizeInBits(SrcReg, MRI, TRI)) ||
283 (((DstSize + 31) / 32 == (SrcSize + 31) / 32) && DstSize > SrcSize)) &&
284 "Copy with different width?!");
286 "GPRs cannot get more than 64-bit width values");
291 RC = &AArch64::FPR32RegClass;
292 else if (DstSize <= 64)
293 RC = &AArch64::FPR64RegClass;
294 else if (DstSize <= 128)
295 RC = &AArch64::FPR128RegClass;
297 DEBUG(
dbgs() <<
"Unexpected bitcast size " << DstSize <<
'\n');
302 "Bitcast for the flags?");
304 DstSize <= 32 ? &AArch64::GPR32allRegClass : &AArch64::GPR64allRegClass;
330 switch (GenericOpc) {
331 case TargetOpcode::G_SITOFP:
332 return AArch64::SCVTFUWSri;
333 case TargetOpcode::G_UITOFP:
334 return AArch64::UCVTFUWSri;
335 case TargetOpcode::G_FPTOSI:
336 return AArch64::FCVTZSUWSr;
337 case TargetOpcode::G_FPTOUI:
338 return AArch64::FCVTZUUWSr;
343 switch (GenericOpc) {
344 case TargetOpcode::G_SITOFP:
345 return AArch64::SCVTFUXSri;
346 case TargetOpcode::G_UITOFP:
347 return AArch64::UCVTFUXSri;
348 case TargetOpcode::G_FPTOSI:
349 return AArch64::FCVTZSUWDr;
350 case TargetOpcode::G_FPTOUI:
351 return AArch64::FCVTZUUWDr;
361 switch (GenericOpc) {
362 case TargetOpcode::G_SITOFP:
363 return AArch64::SCVTFUWDri;
364 case TargetOpcode::G_UITOFP:
365 return AArch64::UCVTFUWDri;
366 case TargetOpcode::G_FPTOSI:
367 return AArch64::FCVTZSUXSr;
368 case TargetOpcode::G_FPTOUI:
369 return AArch64::FCVTZUUXSr;
374 switch (GenericOpc) {
375 case TargetOpcode::G_SITOFP:
376 return AArch64::SCVTFUXDri;
377 case TargetOpcode::G_UITOFP:
378 return AArch64::UCVTFUXDri;
379 case TargetOpcode::G_FPTOSI:
380 return AArch64::FCVTZSUXDr;
381 case TargetOpcode::G_FPTOUI:
382 return AArch64::FCVTZUUXDr;
488 if (Opcode == TargetOpcode::LOAD_STACK_GUARD)
491 if (Opcode == TargetOpcode::PHI) {
497 DefRC = TRI.getRegClass(DefReg);
505 DEBUG(
dbgs() <<
"PHI operand has no type, not a gvreg?\n");
511 DEBUG(
dbgs() <<
"PHI operand has unexpected size/bank\n");
528 DEBUG(
dbgs() <<
"Generic instruction has unexpected implicit operands\n");
539 case TargetOpcode::G_BRCOND: {
544 DEBUG(
dbgs() <<
"G_BRCOND has type: " << Ty
545 <<
", expected at most 32-bits");
561 case TargetOpcode::G_FCONSTANT:
562 case TargetOpcode::G_CONSTANT: {
563 const bool isFP = Opcode == TargetOpcode::G_FCONSTANT;
576 if (Ty != s32 && Ty != s64) {
577 DEBUG(
dbgs() <<
"Unable to materialize FP " << Ty
578 <<
" constant, expected: " << s32 <<
" or " << s64
584 DEBUG(
dbgs() <<
"Unable to materialize FP " << Ty
585 <<
" constant on bank: " << RB <<
", expected: FPR\n");
589 if (Ty != s32 && Ty != s64 && Ty != p0) {
590 DEBUG(
dbgs() <<
"Unable to materialize integer " << Ty
591 <<
" constant, expected: " << s32 <<
", " << s64 <<
", or "
597 DEBUG(
dbgs() <<
"Unable to materialize integer " << Ty
598 <<
" constant on bank: " << RB <<
", expected: GPR\n");
603 const unsigned MovOpc =
604 DefSize == 32 ? AArch64::MOVi32imm : AArch64::MOVi64imm;
610 DefSize == 32 ? AArch64::GPR32RegClass : AArch64::GPR64RegClass;
612 DefSize == 32 ? AArch64::FPR32RegClass : AArch64::FPR64RegClass;
619 TII.get(AArch64::COPY))
624 DEBUG(
dbgs() <<
"Failed to constrain G_FCONSTANT def operand\n");
641 case TargetOpcode::G_FRAME_INDEX: {
644 DEBUG(
dbgs() <<
"G_FRAME_INDEX pointer has type: " << Ty
649 I.
setDesc(TII.get(AArch64::ADDXri));
658 case TargetOpcode::G_GLOBAL_VALUE: {
660 if (GV->isThreadLocal()) {
669 I.
setDesc(TII.get(AArch64::MOVaddr));
678 case TargetOpcode::G_LOAD:
679 case TargetOpcode::G_STORE: {
684 DEBUG(
dbgs() <<
"Load/Store pointer has type: " << PtrTy
694 "Load/Store pointer operand isn't a GPR");
696 "Load/Store pointer operand isn't a pointer");
702 const unsigned NewOpc =
713 case TargetOpcode::G_MUL: {
722 DEBUG(
dbgs() <<
"G_MUL on bank: " << RB <<
", expected: GPR\n");
729 NewOpc = AArch64::MADDWrrr;
730 ZeroReg = AArch64::WZR;
732 NewOpc = AArch64::MADDXrrr;
733 ZeroReg = AArch64::XZR;
735 DEBUG(
dbgs() <<
"G_MUL has type: " << Ty <<
", expected: "
749 case TargetOpcode::G_FADD:
750 case TargetOpcode::G_FSUB:
751 case TargetOpcode::G_FMUL:
752 case TargetOpcode::G_FDIV:
754 case TargetOpcode::G_OR:
755 case TargetOpcode::G_XOR:
756 case TargetOpcode::G_AND:
757 case TargetOpcode::G_SHL:
758 case TargetOpcode::G_LSHR:
759 case TargetOpcode::G_ASHR:
760 case TargetOpcode::G_SDIV:
761 case TargetOpcode::G_UDIV:
762 case TargetOpcode::G_ADD:
763 case TargetOpcode::G_SUB:
764 case TargetOpcode::G_GEP: {
786 case TargetOpcode::G_PTRTOINT:
787 case TargetOpcode::G_TRUNC: {
798 DEBUG(
dbgs() <<
"G_TRUNC input/output on different banks\n");
815 DEBUG(
dbgs() <<
"Failed to constrain G_TRUNC\n");
819 if (DstRC == SrcRC) {
821 }
else if (DstRC == &AArch64::GPR32RegClass &&
822 SrcRC == &AArch64::GPR64RegClass) {
828 I.
setDesc(TII.get(TargetOpcode::COPY));
832 I.
setDesc(TII.get(AArch64::XTNv4i16));
841 case TargetOpcode::G_ANYEXT: {
847 DEBUG(
dbgs() <<
"G_ANYEXT on bank: " << RBDst <<
", expected: GPR\n");
853 DEBUG(
dbgs() <<
"G_ANYEXT on bank: " << RBSrc <<
", expected: GPR\n");
860 DEBUG(
dbgs() <<
"G_ANYEXT operand has no size, not a gvreg?\n");
864 if (DstSize != 64 && DstSize > 32) {
865 DEBUG(
dbgs() <<
"G_ANYEXT to size: " << DstSize
866 <<
", expected: 32 or 64\n");
883 case TargetOpcode::G_ZEXT:
884 case TargetOpcode::G_SEXT: {
888 const bool isSigned = Opcode == TargetOpcode::G_SEXT;
895 <<
", expected: GPR\n");
903 DEBUG(
dbgs() <<
"Failed to constrain " << TII.getName(Opcode)
908 const unsigned SrcXReg =
916 const unsigned NewOpc = isSigned ? AArch64::SBFMXri : AArch64::UBFMXri;
921 .
addImm(SrcTy.getSizeInBits() - 1);
923 const unsigned NewOpc = isSigned ? AArch64::SBFMWri : AArch64::UBFMWri;
928 .
addImm(SrcTy.getSizeInBits() - 1);
939 case TargetOpcode::G_SITOFP:
940 case TargetOpcode::G_UITOFP:
941 case TargetOpcode::G_FPTOSI:
942 case TargetOpcode::G_FPTOUI: {
946 if (NewOpc == Opcode)
956 case TargetOpcode::G_INTTOPTR:
957 case TargetOpcode::G_BITCAST:
960 case TargetOpcode::G_FPEXT: {
968 DEBUG(
dbgs() <<
"G_FPEXT from type " << Ty
977 DEBUG(
dbgs() <<
"G_FPEXT on bank: " << RB <<
", expected: FPR\n");
981 I.
setDesc(TII.get(AArch64::FCVTDSr));
987 case TargetOpcode::G_FPTRUNC: {
989 DEBUG(
dbgs() <<
"G_FPTRUNC to type " << Ty
995 DEBUG(
dbgs() <<
"G_FPTRUNC from type " << Ty
1004 DEBUG(
dbgs() <<
"G_FPTRUNC on bank: " << RB <<
", expected: FPR\n");
1008 I.
setDesc(TII.get(AArch64::FCVTSDr));
1014 case TargetOpcode::G_SELECT: {
1016 DEBUG(
dbgs() <<
"G_SELECT cond has type: " << Ty
1025 unsigned CSelOpc = 0;
1028 CSelOpc = AArch64::CSELWr;
1030 CSelOpc = AArch64::CSELXr;
1037 .addDef(AArch64::WZR)
1053 case TargetOpcode::G_ICMP: {
1055 DEBUG(
dbgs() <<
"G_ICMP result has type: " << Ty
1060 unsigned CmpOpc = 0;
1065 CmpOpc = AArch64::SUBSWrr;
1066 ZReg = AArch64::WZR;
1068 CmpOpc = AArch64::SUBSXrr;
1069 ZReg = AArch64::XZR;
1089 .addUse(AArch64::WZR)
1100 case TargetOpcode::G_FCMP: {
1102 DEBUG(
dbgs() <<
"G_FCMP result has type: " << Ty
1107 unsigned CmpOpc = 0;
1110 CmpOpc = AArch64::FCMPSrr;
1112 CmpOpc = AArch64::FCMPDrr;
1128 unsigned Def1Reg = DefReg;
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
const GlobalValue * getGlobal() const
uint64_t getZExtValue() const
Get zero extended value.
LLT getType(unsigned VReg) const
Get the low-level type of VReg or LLT{} if VReg is not a generic (target independent) virtual registe...
MO_PAGE - A symbol operand with this flag represents the pc-relative offset of the 4K page containing...
void setTargetFlags(unsigned F)
const ConstantFP * getFPImm() const
MachineBasicBlock * getMBB() const
unsigned createVirtualRegister(const TargetRegisterClass *RegClass)
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
static const TargetRegisterClass * getRegClassForTypeOnBank(LLT Ty, const RegisterBank &RB, const RegisterBankInfo &RBI)
T dyn_cast() const
Returns the current pointer if it is of the specified pointer type, otherwises returns null...
static bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
Predicate getInversePredicate() const
For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE, etc.
bool constrainSelectedInstRegOperands(MachineInstr &I, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI) const
Mutate the newly-selected instruction I to constrain its (possibly generic) virtual register operands...
0 1 0 0 True if ordered and less than
1 1 1 0 True if unordered or not equal
iterator_range< mop_iterator > operands()
This file declares the targeting of the RegisterBankInfo class for AArch64.
1 0 0 1 True if unordered or equal
Holds all the information related to register banks.
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
const HexagonInstrInfo * TII
static MachineOperand CreateReg(unsigned Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
StringRef getName(unsigned Opcode) const
Returns the name for the instructions with the given opcode.
0 1 0 1 True if ordered and less than or equal
APInt bitcastToAPInt() const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
unsigned getNumOperands() const
Access to explicit operands of the instruction.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
MO_GOT - This flag indicates that a symbol operand represents the address of the GOT entry for the sy...
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out...
static LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
void ChangeToImmediate(int64_t ImmVal)
ChangeToImmediate - Replace this operand with a new immediate operand of the specified value...
const MachineBasicBlock * getParent() const
TargetInstrInfo - Interface to description of machine instruction set.
static unsigned selectBinaryOp(unsigned GenericOpc, unsigned RegBankID, unsigned OpSize)
Select the AArch64 opcode for the basic binary operation GenericOpc (such as G_OR or G_ADD)...
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
unsigned const MachineRegisterInfo * MRI
static unsigned selectLoadStoreUIOp(unsigned GenericOpc, unsigned RegBankID, unsigned OpSize)
Select the AArch64 opcode for the G_LOAD or G_STORE operation GenericOpc, appropriate for the (value)...
static unsigned selectFPConvOpc(unsigned GenericOpc, LLT DstTy, LLT SrcTy)
const MachineOperand & getOperand(unsigned i) const
unsigned getID() const
Get the identifier of this register bank.
unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
int64_t getOffset() const
Return the offset from the symbol in this operand.
0 1 1 1 True if ordered (no nans)
self_iterator getIterator()
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
This file declares the targeting of the InstructionSelector class for AArch64.
1 1 0 1 True if unordered, less than, or equal
unsigned char ClassifyGlobalReference(const GlobalValue *GV, const TargetMachine &TM) const
ClassifyGlobalReference - Find the target operand flags that describe how a global value should be re...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode...
bool select(MachineInstr &I) const override
Select the (possibly generic) instruction I to only use target-specific opcodes.
0 0 1 0 True if ordered and greater than
static uint64_t encodeLogicalImmediate(uint64_t imm, unsigned regSize)
encodeLogicalImmediate - Return the encoded immediate value for a logical immediate instruction of th...
void setDesc(const MCInstrDesc &tid)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one...
void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
T get() const
Returns the value of the specified pointer type.
RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
MachineOperand class - Representation of each machine instruction operand.
1 1 0 0 True if unordered or less than
unsigned getPredicate() const
This class implements the register bank concept.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
const ConstantInt * getCImm() const
static bool isPreISelGenericOpcode(unsigned Opcode)
Check whether the given Opcode is a generic opcode that is not supposed to appear after ISel...
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned char TargetFlags=0) const
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
Provides the logic to select generic machine instructions.
Representation of each machine instruction.
static bool isPhysicalRegister(unsigned Reg)
Return true if the specified register number is in the physical register namespace.
This class provides the information for the target register banks.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
unsigned greater or equal
static AArch64CC::CondCode changeICMPPredToAArch64CC(CmpInst::Predicate P)
const RegClassOrRegBank & getRegClassOrRegBank(unsigned Reg) const
Return the register bank or register class of Reg.
void setReg(unsigned Reg)
Change the register this operand corresponds to.
static MachineOperand CreateImm(int64_t Val)
MO_PAGEOFF - A symbol operand with this flag represents the offset of that symbol within a 4K page...
void setSubReg(unsigned subReg)
static const TargetRegisterClass * constrainGenericRegister(unsigned Reg, const TargetRegisterClass &RC, MachineRegisterInfo &MRI)
Constrain the (possibly generic) virtual register Reg to RC.
0 1 1 0 True if ordered and operands are unequal
1 0 1 0 True if unordered or greater than
const APFloat & getValueAPF() const
unsigned getReg() const
getReg - Returns the register number.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static void changeFCMPPredToAArch64CC(CmpInst::Predicate P, AArch64CC::CondCode &CondCode, AArch64CC::CondCode &CondCode2)
const MachineInstrBuilder & addUse(unsigned RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
0 0 0 1 True if ordered and equal
static LLT pointer(uint16_t AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space (defaulting to 0).
1 0 1 1 True if unordered, greater than, or equal
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned char TargetFlags=0) const
General Purpose Registers: W, X.
static bool unsupportedBinOp(const MachineInstr &I, const AArch64RegisterBankInfo &RBI, const MachineRegisterInfo &MRI, const AArch64RegisterInfo &TRI)
Check whether I is a currently unsupported binary operation:
MO_NC - Indicates whether the linker is expected to check the symbol reference for overflow...
unsigned getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
static LLT vector(uint16_t NumElements, unsigned ScalarSizeInBits)
Get a low-level vector of some number of elements and element width.
static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
AArch64InstructionSelector(const AArch64TargetMachine &TM, const AArch64Subtarget &STI, const AArch64RegisterBankInfo &RBI)
0 0 1 1 True if ordered and greater than or equal
A discriminated union of two pointer types, with the discriminator in the low bit of the pointer...