48 #define DEBUG_TYPE "X86-isel" 54 #define GET_GLOBALISEL_PREDICATE_BITSET 55 #include "X86GenGlobalISel.inc" 56 #undef GET_GLOBALISEL_PREDICATE_BITSET 72 unsigned getLoadStoreOp(
const LLT &Ty,
const RegisterBank &RB,
unsigned Opc,
73 uint64_t Alignment)
const;
107 const unsigned DstReg,
109 const unsigned SrcReg,
122 bool emitInsertSubreg(
unsigned DstReg,
unsigned SrcReg,
MachineInstr &I,
125 bool emitExtractSubreg(
unsigned DstReg,
unsigned SrcReg,
MachineInstr &I,
138 #define GET_GLOBALISEL_PREDICATES_DECL 139 #include "X86GenGlobalISel.inc" 140 #undef GET_GLOBALISEL_PREDICATES_DECL 142 #define GET_GLOBALISEL_TEMPORARIES_DECL 143 #include "X86GenGlobalISel.inc" 144 #undef GET_GLOBALISEL_TEMPORARIES_DECL 149 #define GET_GLOBALISEL_IMPL 150 #include "X86GenGlobalISel.inc" 151 #undef GET_GLOBALISEL_IMPL 157 TRI(*STI.getRegisterInfo()), RBI(RBI),
159 #include
"X86GenGlobalISel.inc" 162 #include
"X86GenGlobalISel.inc" 171 if (RB.
getID() == X86::GPRRegBankID) {
173 return &X86::GR8RegClass;
175 return &X86::GR16RegClass;
177 return &X86::GR32RegClass;
179 return &X86::GR64RegClass;
181 if (RB.
getID() == X86::VECRRegBankID) {
183 return STI.hasAVX512() ? &X86::FR32XRegClass : &X86::FR32RegClass;
185 return STI.hasAVX512() ? &X86::FR64XRegClass : &X86::FR64RegClass;
187 return STI.hasAVX512() ? &X86::VR128XRegClass : &X86::VR128RegClass;
189 return STI.hasAVX512() ? &X86::VR256XRegClass : &X86::VR256RegClass;
191 return &X86::VR512RegClass;
205 unsigned SubIdx = X86::NoSubRegister;
206 if (RC == &X86::GR32RegClass) {
207 SubIdx = X86::sub_32bit;
208 }
else if (RC == &X86::GR16RegClass) {
209 SubIdx = X86::sub_16bit;
210 }
else if (RC == &X86::GR8RegClass) {
211 SubIdx = X86::sub_8bit;
218 assert(Register::isPhysicalRegister(Reg));
219 if (X86::GR64RegClass.
contains(Reg))
220 return &X86::GR64RegClass;
221 if (X86::GR32RegClass.
contains(Reg))
222 return &X86::GR32RegClass;
223 if (X86::GR16RegClass.
contains(Reg))
224 return &X86::GR16RegClass;
226 return &X86::GR8RegClass;
235 const unsigned DstSize = RBI.getSizeInBits(DstReg, MRI,
TRI);
239 const unsigned SrcSize = RBI.getSizeInBits(SrcReg, MRI,
TRI);
242 if (Register::isPhysicalRegister(DstReg)) {
243 assert(I.
isCopy() &&
"Generic operators do not allow physical registers");
245 if (DstSize > SrcSize && SrcRegBank.
getID() == X86::GPRRegBankID &&
246 DstRegBank.
getID() == X86::GPRRegBankID) {
252 if (SrcRC != DstRC) {
256 TII.get(TargetOpcode::SUBREG_TO_REG))
260 .
addImm(getSubRegIndex(SrcRC));
269 assert((!Register::isPhysicalRegister(SrcReg) || I.
isCopy()) &&
270 "No phys reg on generic operators");
271 assert((DstSize == SrcSize ||
274 (Register::isPhysicalRegister(SrcReg) &&
275 DstSize <= RBI.getSizeInBits(SrcReg, MRI,
TRI))) &&
276 "Copy with different width?!");
281 if (SrcRegBank.
getID() == X86::GPRRegBankID &&
282 DstRegBank.
getID() == X86::GPRRegBankID && SrcSize > DstSize &&
283 Register::isPhysicalRegister(SrcReg)) {
288 if (DstRC != SrcRC) {
299 if (!RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
321 if (Opcode == TargetOpcode::LOAD_STACK_GUARD)
331 "Generic instruction has unexpected implicit operands\n");
342 case TargetOpcode::G_STORE:
343 case TargetOpcode::G_LOAD:
344 return selectLoadStoreOp(I, MRI, MF);
345 case TargetOpcode::G_GEP:
346 case TargetOpcode::G_FRAME_INDEX:
347 return selectFrameIndexOrGep(I, MRI, MF);
348 case TargetOpcode::G_GLOBAL_VALUE:
349 return selectGlobalValue(I, MRI, MF);
350 case TargetOpcode::G_CONSTANT:
351 return selectConstant(I, MRI, MF);
352 case TargetOpcode::G_FCONSTANT:
353 return materializeFP(I, MRI, MF);
354 case TargetOpcode::G_PTRTOINT:
355 case TargetOpcode::G_TRUNC:
356 return selectTruncOrPtrToInt(I, MRI, MF);
357 case TargetOpcode::G_INTTOPTR:
359 case TargetOpcode::G_ZEXT:
360 return selectZext(I, MRI, MF);
361 case TargetOpcode::G_ANYEXT:
362 return selectAnyext(I, MRI, MF);
363 case TargetOpcode::G_ICMP:
364 return selectCmp(I, MRI, MF);
365 case TargetOpcode::G_FCMP:
366 return selectFCmp(I, MRI, MF);
367 case TargetOpcode::G_UADDE:
368 return selectUadde(I, MRI, MF);
369 case TargetOpcode::G_UNMERGE_VALUES:
371 case TargetOpcode::G_MERGE_VALUES:
372 case TargetOpcode::G_CONCAT_VECTORS:
374 case TargetOpcode::G_EXTRACT:
375 return selectExtract(I, MRI, MF);
376 case TargetOpcode::G_INSERT:
377 return selectInsert(I, MRI, MF);
378 case TargetOpcode::G_BRCOND:
379 return selectCondBranch(I, MRI, MF);
380 case TargetOpcode::G_IMPLICIT_DEF:
381 case TargetOpcode::G_PHI:
382 return selectImplicitDefOrPHI(I, MRI);
383 case TargetOpcode::G_SHL:
384 case TargetOpcode::G_ASHR:
385 case TargetOpcode::G_LSHR:
386 return selectShift(I, MRI, MF);
387 case TargetOpcode::G_SDIV:
388 case TargetOpcode::G_UDIV:
389 case TargetOpcode::G_SREM:
390 case TargetOpcode::G_UREM:
391 return selectDivRem(I, MRI, MF);
392 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
393 return selectIntrinsicWSideEffects(I, MRI, MF);
399 unsigned X86InstructionSelector::getLoadStoreOp(
const LLT &Ty,
402 uint64_t Alignment)
const {
403 bool Isload = (Opc == TargetOpcode::G_LOAD);
404 bool HasAVX = STI.hasAVX();
405 bool HasAVX512 = STI.hasAVX512();
406 bool HasVLX = STI.hasVLX();
408 if (Ty == LLT::scalar(8)) {
409 if (X86::GPRRegBankID == RB.
getID())
410 return Isload ? X86::MOV8rm : X86::MOV8mr;
411 }
else if (Ty == LLT::scalar(16)) {
412 if (X86::GPRRegBankID == RB.
getID())
413 return Isload ? X86::MOV16rm : X86::MOV16mr;
414 }
else if (Ty == LLT::scalar(32) || Ty == LLT::pointer(0, 32)) {
415 if (X86::GPRRegBankID == RB.
getID())
416 return Isload ? X86::MOV32rm : X86::MOV32mr;
417 if (X86::VECRRegBankID == RB.
getID())
418 return Isload ? (HasAVX512 ? X86::VMOVSSZrm_alt :
419 HasAVX ? X86::VMOVSSrm_alt :
421 : (HasAVX512 ? X86::VMOVSSZmr :
422 HasAVX ? X86::VMOVSSmr :
424 }
else if (Ty == LLT::scalar(64) || Ty == LLT::pointer(0, 64)) {
425 if (X86::GPRRegBankID == RB.
getID())
426 return Isload ? X86::MOV64rm : X86::MOV64mr;
427 if (X86::VECRRegBankID == RB.
getID())
428 return Isload ? (HasAVX512 ? X86::VMOVSDZrm_alt :
429 HasAVX ? X86::VMOVSDrm_alt :
431 : (HasAVX512 ? X86::VMOVSDZmr :
432 HasAVX ? X86::VMOVSDmr :
436 return Isload ? (HasVLX ? X86::VMOVAPSZ128rm
438 ? X86::VMOVAPSZ128rm_NOVLX
439 : HasAVX ? X86::VMOVAPSrm : X86::MOVAPSrm)
440 : (HasVLX ? X86::VMOVAPSZ128mr
442 ? X86::VMOVAPSZ128mr_NOVLX
443 : HasAVX ? X86::VMOVAPSmr : X86::MOVAPSmr);
445 return Isload ? (HasVLX ? X86::VMOVUPSZ128rm
447 ? X86::VMOVUPSZ128rm_NOVLX
448 : HasAVX ? X86::VMOVUPSrm : X86::MOVUPSrm)
449 : (HasVLX ? X86::VMOVUPSZ128mr
451 ? X86::VMOVUPSZ128mr_NOVLX
452 : HasAVX ? X86::VMOVUPSmr : X86::MOVUPSmr);
455 return Isload ? (HasVLX ? X86::VMOVAPSZ256rm
456 : HasAVX512 ? X86::VMOVAPSZ256rm_NOVLX
458 : (HasVLX ? X86::VMOVAPSZ256mr
459 : HasAVX512 ? X86::VMOVAPSZ256mr_NOVLX
462 return Isload ? (HasVLX ? X86::VMOVUPSZ256rm
463 : HasAVX512 ? X86::VMOVUPSZ256rm_NOVLX
465 : (HasVLX ? X86::VMOVUPSZ256mr
466 : HasAVX512 ? X86::VMOVUPSZ256mr_NOVLX
470 return Isload ? X86::VMOVAPSZrm : X86::VMOVAPSZmr;
472 return Isload ? X86::VMOVUPSZrm : X86::VMOVUPSZmr;
483 "unsupported type.");
485 if (I.
getOpcode() == TargetOpcode::G_GEP) {
489 AM.
Disp =
static_cast<int32_t
>(Imm);
494 }
else if (I.
getOpcode() == TargetOpcode::G_FRAME_INDEX) {
496 AM.
BaseType = X86AddressMode::FrameIndexBase;
504 bool X86InstructionSelector::selectLoadStoreOp(
MachineInstr &I,
509 assert((Opc == TargetOpcode::G_STORE || Opc == TargetOpcode::G_LOAD) &&
510 "unexpected instruction");
518 if (MemOp.isAtomic()) {
524 if (!MemOp.isUnordered()) {
534 unsigned NewOpc = getLoadStoreOp(Ty, RB, Opc, MemOp.getAlignment());
543 if (Opc == TargetOpcode::G_LOAD) {
556 if (Ty == LLT::pointer(0, 64))
558 else if (Ty == LLT::pointer(0, 32))
564 bool X86InstructionSelector::selectFrameIndexOrGep(
MachineInstr &I,
569 assert((Opc == TargetOpcode::G_FRAME_INDEX || Opc == TargetOpcode::G_GEP) &&
570 "unexpected instruction");
576 unsigned NewOpc =
getLeaOP(Ty, STI);
580 if (Opc == TargetOpcode::G_FRAME_INDEX) {
592 bool X86InstructionSelector::selectGlobalValue(
MachineInstr &I,
596 "unexpected instruction");
599 if (GV->isThreadLocal()) {
609 AM.
GVOpFlags = STI.classifyGlobalReference(GV);
619 if (STI.isPICStyleRIPRel()) {
627 unsigned NewOpc =
getLeaOP(Ty, STI);
638 bool X86InstructionSelector::selectConstant(
MachineInstr &I,
642 "unexpected instruction");
647 if (RBI.getRegBank(DefReg, MRI,
TRI)->getID() != X86::GPRRegBankID)
662 NewOpc = X86::MOV8ri;
665 NewOpc = X86::MOV16ri;
668 NewOpc = X86::MOV32ri;
673 NewOpc = X86::MOV64ri32;
675 NewOpc = X86::MOV64ri;
690 return (DstRC == &X86::FR32RegClass || DstRC == &X86::FR32XRegClass ||
691 DstRC == &X86::FR64RegClass || DstRC == &X86::FR64XRegClass) &&
692 (SrcRC == &X86::VR128RegClass || SrcRC == &X86::VR128XRegClass);
695 bool X86InstructionSelector::selectTurnIntoCOPY(
700 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
701 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
710 bool X86InstructionSelector::selectTruncOrPtrToInt(
MachineInstr &I,
714 I.
getOpcode() == TargetOpcode::G_PTRTOINT) &&
715 "unexpected instruction");
728 <<
" input/output on different banks\n");
735 if (!DstRC || !SrcRC)
742 return selectTurnIntoCOPY(I, MRI, DstReg, DstRC, SrcReg, SrcRC);
744 if (DstRB.
getID() != X86::GPRRegBankID)
748 if (DstRC == SrcRC) {
750 SubIdx = X86::NoSubRegister;
751 }
else if (DstRC == &X86::GR32RegClass) {
752 SubIdx = X86::sub_32bit;
753 }
else if (DstRC == &X86::GR16RegClass) {
754 SubIdx = X86::sub_16bit;
755 }
else if (DstRC == &X86::GR8RegClass) {
756 SubIdx = X86::sub_8bit;
761 SrcRC =
TRI.getSubClassWithSubReg(SrcRC, SubIdx);
763 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
764 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
776 bool X86InstructionSelector::selectZext(
MachineInstr &I,
779 assert((I.
getOpcode() == TargetOpcode::G_ZEXT) &&
"unexpected instruction");
787 assert(!(SrcTy == LLT::scalar(8) && DstTy == LLT::scalar(32)) &&
788 "8=>32 Zext is handled by tablegen");
789 assert(!(SrcTy == LLT::scalar(16) && DstTy == LLT::scalar(32)) &&
790 "16=>32 Zext is handled by tablegen");
792 const static struct ZextEntry {
796 bool NeedSubregToReg;
798 {LLT::scalar(8), LLT::scalar(16), X86::MOVZX16rr8,
false},
799 {LLT::scalar(8), LLT::scalar(64), X86::MOVZX32rr8,
true},
800 {LLT::scalar(16), LLT::scalar(64), X86::MOVZX32rr16,
true},
801 {LLT::scalar(32), LLT::scalar(64), 0,
true}
806 [SrcTy, DstTy](
const ZextEntry &El) {
807 return El.DstTy == DstTy && El.SrcTy == SrcTy;
811 if (ZextEntryIt !=
std::end(OpTable)) {
817 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
818 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
824 unsigned TransitRegTo = DstReg;
825 unsigned TransitRegFrom = SrcReg;
826 if (ZextEntryIt->MovOp) {
829 if (ZextEntryIt->NeedSubregToReg) {
832 TransitRegTo = TransitRegFrom;
836 .addDef(TransitRegTo)
839 if (ZextEntryIt->NeedSubregToReg) {
841 TII.get(TargetOpcode::SUBREG_TO_REG))
851 if (SrcTy != LLT::scalar(1))
855 if (DstTy == LLT::scalar(8))
856 AndOpc = X86::AND8ri;
857 else if (DstTy == LLT::scalar(16))
858 AndOpc = X86::AND16ri8;
859 else if (DstTy == LLT::scalar(32))
860 AndOpc = X86::AND32ri8;
861 else if (DstTy == LLT::scalar(64))
862 AndOpc = X86::AND64ri8;
866 unsigned DefReg = SrcReg;
867 if (DstTy != LLT::scalar(8)) {
870 TII.get(TargetOpcode::SUBREG_TO_REG), DefReg)
887 bool X86InstructionSelector::selectAnyext(
MachineInstr &I,
890 assert((I.
getOpcode() == TargetOpcode::G_ANYEXT) &&
"unexpected instruction");
902 "G_ANYEXT input/output on different banks\n");
905 "G_ANYEXT incorrect operand size");
914 return selectTurnIntoCOPY(I, MRI, SrcReg, SrcRC, DstReg, DstRC);
916 if (DstRB.
getID() != X86::GPRRegBankID)
919 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
920 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
926 if (SrcRC == DstRC) {
932 TII.get(TargetOpcode::SUBREG_TO_REG))
936 .
addImm(getSubRegIndex(SrcRC));
945 assert((I.
getOpcode() == TargetOpcode::G_ICMP) &&
"unexpected instruction");
968 OpCmp = X86::CMP16rr;
971 OpCmp = X86::CMP32rr;
974 OpCmp = X86::CMP64rr;
993 bool X86InstructionSelector::selectFCmp(
MachineInstr &I,
996 assert((I.
getOpcode() == TargetOpcode::G_FCMP) &&
"unexpected instruction");
1004 static const uint16_t SETFOpcTable[2][3] = {
1007 const uint16_t *SETFOpc =
nullptr;
1008 switch (Predicate) {
1011 case CmpInst::FCMP_OEQ:
1012 SETFOpc = &SETFOpcTable[0][0];
1014 case CmpInst::FCMP_UNE:
1015 SETFOpc = &SETFOpcTable[1][0];
1026 OpCmp = X86::UCOMISSrr;
1029 OpCmp = X86::UCOMISDrr;
1034 RBI.constrainGenericRegister(
1036 *
getRegClass(LLT::scalar(8), *RBI.getRegBank(ResultReg, MRI,
TRI)), MRI);
1046 TII.get(X86::SETCCr), FlagReg1).addImm(SETFOpc[0]);
1048 TII.get(X86::SETCCr), FlagReg2).addImm(SETFOpc[1]);
1050 TII.get(SETFOpc[2]), ResultReg)
1084 bool X86InstructionSelector::selectUadde(
MachineInstr &I,
1087 assert((I.
getOpcode() == TargetOpcode::G_UADDE) &&
"unexpected instruction");
1097 if (DstTy != LLT::scalar(32))
1102 while (Def->
getOpcode() == TargetOpcode::G_TRUNC) {
1108 if (Def->
getOpcode() == TargetOpcode::G_UADDE) {
1112 .addReg(CarryInReg);
1114 if (!RBI.constrainGenericRegister(CarryInReg, X86::GR32RegClass, MRI))
1117 Opcode = X86::ADC32rr;
1123 Opcode = X86::ADD32rr;
1133 .addReg(X86::EFLAGS);
1136 !RBI.constrainGenericRegister(CarryOutReg, X86::GR32RegClass, MRI))
1143 bool X86InstructionSelector::selectExtract(
MachineInstr &I,
1147 "unexpected instruction");
1165 if (!emitExtractSubreg(DstReg, SrcReg, I, MRI, MF))
1172 bool HasAVX = STI.hasAVX();
1173 bool HasAVX512 = STI.hasAVX512();
1174 bool HasVLX = STI.hasVLX();
1178 I.
setDesc(
TII.get(X86::VEXTRACTF32x4Z256rr));
1200 bool X86InstructionSelector::emitExtractSubreg(
unsigned DstReg,
unsigned SrcReg,
1206 unsigned SubIdx = X86::NoSubRegister;
1212 "Incorrect Src/Dst register size");
1215 SubIdx = X86::sub_xmm;
1217 SubIdx = X86::sub_ymm;
1224 SrcRC =
TRI.getSubClassWithSubReg(SrcRC, SubIdx);
1226 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
1227 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
1233 .addReg(SrcReg, 0, SubIdx);
1238 bool X86InstructionSelector::emitInsertSubreg(
unsigned DstReg,
unsigned SrcReg,
1244 unsigned SubIdx = X86::NoSubRegister;
1251 "Incorrect Src/Dst register size");
1254 SubIdx = X86::sub_xmm;
1256 SubIdx = X86::sub_ymm;
1263 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
1264 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
1276 bool X86InstructionSelector::selectInsert(
MachineInstr &I,
1279 assert((I.
getOpcode() == TargetOpcode::G_INSERT) &&
"unexpected instruction");
1287 const LLT InsertRegTy = MRI.
getType(InsertReg);
1298 if (!emitInsertSubreg(DstReg, InsertReg, I, MRI, MF))
1305 bool HasAVX = STI.hasAVX();
1306 bool HasAVX512 = STI.hasAVX512();
1307 bool HasVLX = STI.hasVLX();
1337 "unexpected instruction");
1344 for (
unsigned Idx = 0; Idx < NumDefs; ++Idx) {
1351 if (!select(ExtrInst))
1362 I.
getOpcode() == TargetOpcode::G_CONCAT_VECTORS) &&
1363 "unexpected instruction");
1382 Register Tmp = MRI.createGenericVirtualRegister(DstTy);
1383 MRI.setRegBank(Tmp, RegBank);
1386 TII.get(TargetOpcode::G_INSERT), Tmp)
1389 .addImm((Idx - 1) * SrcSize);
1393 if (!select(InsertInst))
1398 TII.get(TargetOpcode::COPY), DstReg)
1401 if (!select(CopyInst))
1408 bool X86InstructionSelector::selectCondBranch(
MachineInstr &I,
1411 assert((I.
getOpcode() == TargetOpcode::G_BRCOND) &&
"unexpected instruction");
1429 bool X86InstructionSelector::materializeFP(
MachineInstr &I,
1433 "unexpected instruction");
1446 unsigned Opc = getLoadStoreOp(DstTy, RegBank, TargetOpcode::G_LOAD, Align);
1452 unsigned char OpFlag = STI.classifyLocalReference(
nullptr);
1460 .addConstantPoolIndex(CPI, 0, OpFlag);
1463 MachinePointerInfo::getConstantPool(MF), MachineMemOperand::MOLoad,
1476 unsigned PICBase = 0;
1495 bool X86InstructionSelector::selectImplicitDefOrPHI(
1498 I.
getOpcode() == TargetOpcode::G_PHI) &&
1499 "unexpected instruction");
1507 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
1514 if (I.
getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
1526 bool X86InstructionSelector::selectShift(
MachineInstr &I,
1531 I.
getOpcode() == TargetOpcode::G_ASHR ||
1532 I.
getOpcode() == TargetOpcode::G_LSHR) &&
1533 "unexpected instruction");
1539 const static struct ShiftEntry {
1540 unsigned SizeInBits;
1545 {8, X86::SHR8rCL, X86::SAR8rCL, X86::SHL8rCL},
1546 {16, X86::SHR16rCL, X86::SAR16rCL, X86::SHL16rCL},
1547 {32, X86::SHR32rCL, X86::SAR32rCL, X86::SHL32rCL},
1548 {64, X86::SHR64rCL, X86::SAR64rCL, X86::SHL64rCL}
1551 if (DstRB.
getID() != X86::GPRRegBankID)
1558 if (ShiftEntryIt ==
std::end(OpTable))
1561 unsigned Opcode = 0;
1563 case TargetOpcode::G_SHL:
1564 Opcode = ShiftEntryIt->OpSHL;
1566 case TargetOpcode::G_ASHR:
1567 Opcode = ShiftEntryIt->OpASHR;
1569 case TargetOpcode::G_LSHR:
1570 Opcode = ShiftEntryIt->OpLSHR;
1594 bool X86InstructionSelector::selectDivRem(
MachineInstr &I,
1599 I.
getOpcode() == TargetOpcode::G_SREM ||
1600 I.
getOpcode() == TargetOpcode::G_UDIV ||
1601 I.
getOpcode() == TargetOpcode::G_UREM) &&
1602 "unexpected instruction");
1610 "Arguments and return value types must match");
1613 if (!RegRB || RegRB->getID() != X86::GPRRegBankID)
1616 const static unsigned NumTypes = 4;
1617 const static unsigned NumOps = 4;
1618 const static bool S =
true;
1619 const static bool U =
false;
1620 const static unsigned Copy = TargetOpcode::COPY;
1629 const static struct DivRemEntry {
1631 unsigned SizeInBits;
1635 struct DivRemResult {
1637 unsigned OpSignExtend;
1641 unsigned DivRemResultReg;
1643 } ResultTable[NumOps];
1644 } OpTable[NumTypes] = {
1649 {X86::IDIV8r, 0, X86::MOVSX16rr8,
X86::AL, S},
1650 {X86::IDIV8r, 0, X86::MOVSX16rr8, X86::AH, S},
1651 {X86::DIV8r, 0, X86::MOVZX16rr8,
X86::AL, U},
1652 {X86::DIV8r, 0, X86::MOVZX16rr8, X86::AH, U},
1658 {X86::IDIV16r, X86::CWD, Copy, X86::AX, S},
1659 {X86::IDIV16r, X86::CWD, Copy, X86::DX, S},
1660 {X86::DIV16r, X86::MOV32r0, Copy, X86::AX, U},
1661 {X86::DIV16r, X86::MOV32r0, Copy, X86::DX, U},
1667 {X86::IDIV32r, X86::CDQ, Copy,
X86::EAX, S},
1668 {X86::IDIV32r, X86::CDQ, Copy,
X86::EDX, S},
1669 {X86::DIV32r, X86::MOV32r0, Copy,
X86::EAX, U},
1670 {X86::DIV32r, X86::MOV32r0, Copy,
X86::EDX, U},
1676 {X86::IDIV64r, X86::CQO, Copy, X86::RAX, S},
1677 {X86::IDIV64r, X86::CQO, Copy, X86::RDX, S},
1678 {X86::DIV64r, X86::MOV32r0, Copy, X86::RAX, U},
1679 {X86::DIV64r, X86::MOV32r0, Copy, X86::RDX, U},
1684 [RegTy](
const DivRemEntry &El) {
1687 if (OpEntryIt ==
std::end(OpTable))
1694 case TargetOpcode::G_SDIV:
1697 case TargetOpcode::G_SREM:
1700 case TargetOpcode::G_UDIV:
1703 case TargetOpcode::G_UREM:
1708 const DivRemEntry &TypeEntry = *OpEntryIt;
1709 const DivRemEntry::DivRemResult &OpEntry = TypeEntry.ResultTable[OpIndex];
1712 if (!RBI.constrainGenericRegister(Op1Reg, *RegRC, MRI) ||
1713 !RBI.constrainGenericRegister(Op2Reg, *RegRC, MRI) ||
1714 !RBI.constrainGenericRegister(DstReg, *RegRC, MRI)) {
1725 if (OpEntry.OpSignExtend) {
1726 if (OpEntry.IsOpSigned)
1728 TII.get(OpEntry.OpSignExtend));
1739 TypeEntry.HighInReg)
1740 .addReg(Zero32, 0, X86::sub_16bit);
1743 TypeEntry.HighInReg)
1747 TII.get(TargetOpcode::SUBREG_TO_REG), TypeEntry.HighInReg)
1765 if ((I.
getOpcode() == Instruction::SRem ||
1767 OpEntry.DivRemResultReg == X86::AH && STI.is64Bit()) {
1776 .addReg(SourceSuperReg)
1781 TII.get(TargetOpcode::SUBREG_TO_REG))
1789 .addReg(OpEntry.DivRemResultReg);
1795 bool X86InstructionSelector::selectIntrinsicWSideEffects(
1799 "unexpected instruction");
1814 return new X86InstructionSelector(TM, Subtarget, RBI);
const_iterator end(StringRef path)
Get end iterator over path.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
This class is the base class for the comparison instructions.
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
MachineBasicBlock * getMBB() const
Atomic ordering constants.
static bool selectMergeValues(MachineInstrBuilder &MIB, const ARMBaseInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
This class represents lattice values for constants.
static const MachineInstrBuilder & addConstantPoolReference(const MachineInstrBuilder &MIB, unsigned CPI, unsigned GlobalBaseReg, unsigned char OpFlags)
addConstantPoolReference - This function is used to add a reference to the base of a constant value s...
Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
unsigned getSizeInBits(Register Reg, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI) const
Get the size in bits of Reg.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
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...
unsigned const TargetRegisterInfo * TRI
An instruction for reading from memory.
void setRegBank(unsigned Reg, const RegisterBank &RegBank)
Set the register bank to RegBank for Reg.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
LegalityPredicate isPointer(unsigned TypeIdx)
True iff the specified type index is a pointer (with any address space).
static const TargetRegisterClass * getRegClassFromGRPhysReg(unsigned Reg)
return AArch64::GPR64RegClass contains(Reg)
union llvm::X86AddressMode::@524 Base
void substPhysReg(MCRegister Reg, const TargetRegisterInfo &)
substPhysReg - Substitute the current register with the physical register Reg, taking any existing Su...
A description of a memory reference used in the backend.
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
const HexagonInstrInfo * TII
const ConstantFP * getFPImm() const
unsigned getNumOperands() const
Retuns the total number of operands.
This class provides the information for the target register banks.
static bool isGlobalStubReference(unsigned char TargetFlag)
isGlobalStubReference - Return true if the specified TargetFlag operand is a reference to a stub for ...
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
static StringRef getName(Value *V)
static int getRegClass(RegisterKind Is, unsigned RegWidth)
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, uint64_t s, unsigned base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineInstr * getVRegDef(unsigned Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
static bool isGlobalRelativeToPICBase(unsigned char TargetFlag)
isGlobalRelativeToPICBase - Return true if the specified global value reference is relative to a 32-b...
static bool canTurnIntoCOPY(const TargetRegisterClass *DstRC, const TargetRegisterClass *SrcRC)
void setReg(Register Reg)
Change the register this operand corresponds to.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
void ChangeToImmediate(int64_t ImmVal)
ChangeToImmediate - Replace this operand with a new immediate operand of the specified value...
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
std::pair< CondCode, bool > getX86ConditionCode(CmpInst::Predicate Predicate)
Return a pair of condition code for the given predicate and whether the instruction operands should b...
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
unsigned const MachineRegisterInfo * MRI
#define GET_GLOBALISEL_PREDICATES_INIT
unsigned getPointerSize(unsigned AS=0) const
Layout pointer size FIXME: The defaults need to be removed once all of the backends/clients are updat...
const GlobalValue * getGlobal() const
ConstantFP - Floating Point Values [float, double].
bool isCImm() const
isCImm - Test if this is a MO_CImmediate operand.
bool hasOneMemOperand() const
Return true if this instruction has exactly one MachineMemOperand.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
int64_t addOffset(int64_t LHS, int64_t RHS)
void setImm(int64_t immVal)
TRAP - Trapping instruction.
static bool selectUnmergeValues(MachineInstrBuilder &MIB, const ARMBaseInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
void print(raw_ostream &OS, bool IsStandalone=true, bool SkipOpers=false, bool SkipDebugLoc=false, bool AddNewLine=true, const TargetInstrInfo *TII=nullptr) const
Print this MI to OS.
auto find_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range))
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly...
static void X86SelectAddress(const MachineInstr &I, const MachineRegisterInfo &MRI, X86AddressMode &AM)
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
bool isImplicitDef() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
This struct is a compact representation of a valid (non-zero power of two) alignment.
bool hasSubClassEq(const TargetRegisterClass *RC) const
Returns true if RC is a sub-class of or equal to this class.
This file declares the targeting of the RegisterBankInfo class for X86.
void setDesc(const MCInstrDesc &tid)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one...
constexpr bool isInt< 32 >(int64_t x)
void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
MachineOperand class - Representation of each machine instruction operand.
Intrinsic::ID getIntrinsicID() const
Predicate
Predicate - These are "(BI << 5) | BO" for various predicates.
unsigned getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
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...
InstructionSelector * createX86InstructionSelector(const X86TargetMachine &TM, X86Subtarget &, X86RegisterBankInfo &)
This class implements the register bank concept.
bool isTarget64BitILP32() const
Is this x86_64 with the ILP32 programming model (x32 ABI)?
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Optional< int64_t > getConstantVRegVal(unsigned VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT fits in int64_t returns it.
const MachineBasicBlock * getParent() 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.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MO_GOTOFF - On a symbol operand this indicates that the immediate is the offset to the location of th...
static const MachineInstrBuilder & addDirectMem(const MachineInstrBuilder &MIB, unsigned Reg)
addDirectMem - This function is used to add a direct memory reference to the current instruction – t...
static unsigned getLeaOP(LLT Ty, const X86Subtarget &STI)
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
void setSubReg(unsigned subReg)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
#define GET_GLOBALISEL_TEMPORARIES_INIT
const TargetRegisterClass * getRegClassOrNull(unsigned Reg) const
Return the register class of Reg, or null if Reg has not been assigned a register class yet...
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...
enum llvm::X86AddressMode::@523 BaseType
MO_PIC_BASE_OFFSET - On a symbol operand this indicates that the immediate should get the value of th...
void RemoveOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with...
Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
Register getReg() const
getReg - Returns the register number.
X86AddressMode - This struct holds a generalized full x86 address mode.
static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
const MachineOperand & getOperand(unsigned i) const
const ConstantInt * getCImm() const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
static const MachineInstrBuilder & addFullAddress(const MachineInstrBuilder &MIB, const X86AddressMode &AM)
unsigned getConstantPoolIndex(const Constant *C, unsigned Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one...
Wrapper class representing virtual and physical registers.
unsigned getID() const
Get the identifier of this register bank.
unsigned getPredicate() const