67#define GET_INSTRINFO_CTOR_DTOR
68#include "AArch64GenInstrInfo.inc"
70#define DEBUG_TYPE "AArch64InstrInfo"
72STATISTIC(NumCopyInstrs,
"Number of COPY instructions expanded");
73STATISTIC(NumZCRegMoveInstrsGPR,
"Number of zero-cycle GPR register move "
74 "instructions expanded from canonical COPY");
75STATISTIC(NumZCRegMoveInstrsFPR,
"Number of zero-cycle FPR register move "
76 "instructions expanded from canonical COPY");
77STATISTIC(NumZCZeroingInstrsGPR,
"Number of zero-cycle GPR zeroing "
78 "instructions expanded from canonical COPY");
83 cl::desc(
"Restrict range of CB instructions (DEBUG)"));
87 cl::desc(
"Restrict range of TB[N]Z instructions (DEBUG)"));
91 cl::desc(
"Restrict range of CB[N]Z instructions (DEBUG)"));
95 cl::desc(
"Restrict range of Bcc instructions (DEBUG)"));
99 cl::desc(
"Restrict range of B instructions (DEBUG)"));
103 cl::desc(
"Restrict range of instructions to search for the "
104 "machine-combiner gather pattern optimization"));
108 cl::desc(
"Use a frame record for Mach-O non-leaf outlined functions"));
113 RI(STI.getTargetTriple(), STI.getHwMode()), Subtarget(STI) {}
123 switch (
MI.getOpcode()) {
146 case AArch64::BLRAAZ:
148 case AArch64::BLRABZ:
152 case AArch64::AUTIASP:
153 case AArch64::AUTIBSP:
154 case AArch64::AUTIAZ:
155 case AArch64::AUTIBZ:
156 case AArch64::XPACLRI:
161 if (
MI.getOperand(0).getImm() == 3 &&
MI.getOperand(1).getImm() == 7 &&
162 MI.getOperand(3).getImm() == 1)
170 bool ModifiesLR =
false;
171 bool ModifiesSP =
false;
175 if (MO.getReg() == AArch64::LR)
177 else if (MO.getReg() == AArch64::SP)
186 if (
MI.mayLoadOrStore()) {
194 if (ModifiesSP || ModifiesLR)
207 if (!
Desc.isPseudo() && !Subtarget.isLFI()) {
208 assert(
Desc.getSize() == 4 &&
"Unexpected instruction size");
218 auto Op =
MI.getOpcode();
219 if (
Op == AArch64::INLINEASM ||
Op == AArch64::INLINEASM_BR)
220 return getInlineAsmLength(
MI.getOperand(0).getSymbolName(), MAI);
224 if (
MI.isMetaInstruction())
229 unsigned NumBytes = 0;
238 NumBytes =
Desc.getSize() ?
Desc.getSize() : 4;
241 if (!MFI->shouldSignReturnAddress(*MF))
244 auto Method = STI.getAuthenticatedLRCheckMethod(*MF);
252 switch (
Desc.getOpcode()) {
255 return Desc.getSize();
262 case TargetOpcode::STACKMAP:
265 assert(NumBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
267 case TargetOpcode::PATCHPOINT:
270 assert(NumBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
272 case TargetOpcode::STATEPOINT:
274 assert(NumBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
279 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
284 F.getFnAttributeAsParsedInteger(
"patchable-function-entry", 9) * 4;
286 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
287 case TargetOpcode::PATCHABLE_TAIL_CALL:
288 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
292 case TargetOpcode::PATCHABLE_EVENT_CALL:
298 NumBytes =
MI.getOperand(1).getImm();
300 case AArch64::MOVaddr:
301 case AArch64::MOVaddrJT:
302 case AArch64::MOVaddrCP:
303 case AArch64::MOVaddrBA:
304 case AArch64::MOVaddrTLS:
305 case AArch64::MOVaddrEXT: {
309 MI.getOperand(1).getTargetFlags(),
310 Subtarget.isTargetMachO(), Insn);
311 NumBytes = Insn.
size() * 4;
315 case AArch64::MOVi32imm:
316 case AArch64::MOVi64imm: {
318 unsigned BitSize =
Desc.getOpcode() == AArch64::MOVi32imm ? 32 : 64;
321 NumBytes = Insn.
size() * 4;
325 case TargetOpcode::BUNDLE:
326 NumBytes = getInstBundleSize(
MI);
362 case AArch64::CBWPri:
363 case AArch64::CBXPri:
364 case AArch64::CBWPrr:
365 case AArch64::CBXPrr:
373 case AArch64::CBBAssertExt:
374 case AArch64::CBHAssertExt:
405 case AArch64::CBWPri:
406 case AArch64::CBXPri:
407 case AArch64::CBBAssertExt:
408 case AArch64::CBHAssertExt:
409 case AArch64::CBWPrr:
410 case AArch64::CBXPrr:
416 int64_t BrOffset)
const {
418 assert(Bits >= 3 &&
"max branch displacement must be enough to jump"
419 "over conditional branch expansion");
420 return isIntN(Bits, BrOffset / 4);
425 switch (
MI.getOpcode()) {
429 return MI.getOperand(0).getMBB();
434 return MI.getOperand(2).getMBB();
440 return MI.getOperand(1).getMBB();
441 case AArch64::CBWPri:
442 case AArch64::CBXPri:
443 case AArch64::CBBAssertExt:
444 case AArch64::CBHAssertExt:
445 case AArch64::CBWPrr:
446 case AArch64::CBXPrr:
447 return MI.getOperand(3).getMBB();
457 assert(RS &&
"RegScavenger required for long branching");
459 "new block should be inserted for expanding unconditional branch");
462 "restore block should be inserted for restoring clobbered registers");
469 "Branch offsets outside of the signed 33-bit range not supported");
480 RS->enterBasicBlockEnd(
MBB);
483 constexpr Register Reg = AArch64::X16;
484 if (!RS->isRegUsed(Reg)) {
485 insertUnconditionalBranch(
MBB, &NewDestBB,
DL);
496 Register Scavenged = RS->FindUnusedReg(&AArch64::GPR64RegClass);
498 buildIndirectBranch(Scavenged, NewDestBB);
499 RS->setRegUsed(Scavenged);
508 "Unable to insert indirect branch inside function that has red zone");
531 bool AllowModify)
const {
538 if (
I->getOpcode() == AArch64::SpeculationBarrierISBDSBEndBB ||
539 I->getOpcode() == AArch64::SpeculationBarrierSBEndBB) {
543 if (!isUnpredicatedTerminator(*
I))
550 unsigned LastOpc = LastInst->
getOpcode();
551 if (
I ==
MBB.begin() || !isUnpredicatedTerminator(*--
I)) {
566 unsigned SecondLastOpc = SecondLastInst->
getOpcode();
573 LastInst = SecondLastInst;
575 if (
I ==
MBB.begin() || !isUnpredicatedTerminator(*--
I)) {
580 SecondLastInst = &*
I;
581 SecondLastOpc = SecondLastInst->
getOpcode();
592 LastInst = SecondLastInst;
594 if (
I ==
MBB.begin() || !isUnpredicatedTerminator(*--
I)) {
596 "unreachable unconditional branches removed above");
605 SecondLastInst = &*
I;
606 SecondLastOpc = SecondLastInst->
getOpcode();
610 if (SecondLastInst &&
I !=
MBB.begin() && isUnpredicatedTerminator(*--
I))
626 I->eraseFromParent();
635 I->eraseFromParent();
644 MachineBranchPredicate &MBP,
645 bool AllowModify)
const {
657 assert(MBP.TrueDest &&
"expected!");
658 MBP.FalseDest = FBB ? FBB :
MBB.getNextNode();
660 MBP.ConditionDef =
nullptr;
661 MBP.SingleUseCondition =
false;
671 if (
I ==
MBB.begin())
687 if (
MI.modifiesRegister(AArch64::NZCV,
nullptr)) {
688 MBP.ConditionDef = &
MI;
697 case AArch64::CBNZX: {
701 MBP.Predicate = (
Opc == AArch64::CBNZX ||
Opc == AArch64::CBNZW)
702 ? MachineBranchPredicate::PRED_NE
703 : MachineBranchPredicate::PRED_EQ;
704 Register CondReg = MBP.LHS.getReg();
713 case AArch64::TBNZX: {
734 Cond[1].setImm(AArch64::CBNZW);
737 Cond[1].setImm(AArch64::CBZW);
740 Cond[1].setImm(AArch64::CBNZX);
743 Cond[1].setImm(AArch64::CBZX);
746 Cond[1].setImm(AArch64::TBNZW);
749 Cond[1].setImm(AArch64::TBZW);
752 Cond[1].setImm(AArch64::TBNZX);
755 Cond[1].setImm(AArch64::TBZX);
759 case AArch64::CBWPri:
760 case AArch64::CBXPri:
761 case AArch64::CBBAssertExt:
762 case AArch64::CBHAssertExt:
763 case AArch64::CBWPrr:
764 case AArch64::CBXPrr: {
777 int *BytesRemoved)
const {
787 I->eraseFromParent();
791 if (
I ==
MBB.begin()) {
804 I->eraseFromParent();
811void AArch64InstrInfo::instantiateCondBranch(
836 if (
Cond.size() > 5) {
847 assert(
TBB &&
"insertBranch must not be told to insert a fallthrough");
878 return Opc == AArch64::CBBAssertExt;
881 return Opc == AArch64::CBHAssertExt;
893 switch (
Cond.size()) {
968 unsigned SubsOpc, SubsDestReg;
974 case AArch64::CBWPri:
975 SubsOpc = AArch64::SUBSWri;
976 SubsDestReg = AArch64::WZR;
979 case AArch64::CBXPri:
980 SubsOpc = AArch64::SUBSXri;
981 SubsDestReg = AArch64::XZR;
984 case AArch64::CBWPrr:
985 SubsOpc = AArch64::SUBSWrr;
986 SubsDestReg = AArch64::WZR;
989 case AArch64::CBXPrr:
990 SubsOpc = AArch64::SUBSXrr;
991 SubsDestReg = AArch64::XZR;
1025 "Unexpected compare-and-branch instruction for extend type");
1026 switch (ExtendType) {
1030 ExtOpc = AArch64::SBFMWri;
1034 ExtOpc = AArch64::SBFMWri;
1038 ExtOpc = AArch64::ANDWri;
1042 ExtOpc = AArch64::ANDWri;
1051 if (ExtOpc != AArch64::ANDWri)
1053 MBBI.addImm(ExtBits);
1062 "Unexpected compare-and-branch instruction for extend type");
1083 unsigned Opc =
MI.getOpcode();
1090 if (
MI.getOperand(0).getReg() == AArch64::WZR ||
1091 MI.getOperand(0).getReg() == AArch64::XZR) {
1093 dbgs() <<
"Removing always taken branch: " <<
MI);
1096 for (
auto *S : Succs)
1098 MBB->removeSuccessor(S);
1100 while (
MBB->rbegin() != &
MI)
1101 MBB->rbegin()->eraseFromParent();
1102 MI.eraseFromParent();
1107 case AArch64::CBNZW:
1108 case AArch64::CBNZX:
1109 case AArch64::TBNZW:
1110 case AArch64::TBNZX:
1112 if (
MI.getOperand(0).getReg() == AArch64::WZR ||
1113 MI.getOperand(0).getReg() == AArch64::XZR) {
1115 dbgs() <<
"Removing never taken branch: " <<
MI);
1117 MI.getParent()->removeSuccessor(
Target);
1118 MI.eraseFromParent();
1133 VReg =
DefMI->getOperand(1).getReg();
1142 unsigned *NewReg =
nullptr) {
1147 bool Is64Bit = AArch64::GPR64allRegClass.hasSubClassEq(MRI.
getRegClass(VReg));
1152 unsigned SrcReg = 0;
1153 switch (
DefMI->getOpcode()) {
1154 case AArch64::SUBREG_TO_REG:
1158 if (!
DefMI->getOperand(1).isReg())
1160 if (!
DefMI->getOperand(2).isImm() ||
1161 DefMI->getOperand(2).getImm() != AArch64::sub_32)
1164 if (
DefMI->getOpcode() != AArch64::MOVi32imm)
1166 if (!
DefMI->getOperand(1).isImm() ||
DefMI->getOperand(1).getImm() != 1)
1169 SrcReg = AArch64::XZR;
1170 Opc = AArch64::CSINCXr;
1173 case AArch64::MOVi32imm:
1174 case AArch64::MOVi64imm:
1175 if (!
DefMI->getOperand(1).isImm() ||
DefMI->getOperand(1).getImm() != 1)
1177 SrcReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1178 Opc = Is64Bit ? AArch64::CSINCXr : AArch64::CSINCWr;
1181 case AArch64::ADDSXri:
1182 case AArch64::ADDSWri:
1184 if (
DefMI->findRegisterDefOperandIdx(AArch64::NZCV,
nullptr,
1189 case AArch64::ADDXri:
1190 case AArch64::ADDWri:
1192 if (!
DefMI->getOperand(2).isImm() ||
DefMI->getOperand(2).getImm() != 1 ||
1193 DefMI->getOperand(3).getImm() != 0)
1195 SrcReg =
DefMI->getOperand(1).getReg();
1196 Opc = Is64Bit ? AArch64::CSINCXr : AArch64::CSINCWr;
1199 case AArch64::ORNXrr:
1200 case AArch64::ORNWrr: {
1203 if (ZReg != AArch64::XZR && ZReg != AArch64::WZR)
1205 SrcReg =
DefMI->getOperand(2).getReg();
1206 Opc = Is64Bit ? AArch64::CSINVXr : AArch64::CSINVWr;
1210 case AArch64::SUBSXrr:
1211 case AArch64::SUBSWrr:
1213 if (
DefMI->findRegisterDefOperandIdx(AArch64::NZCV,
nullptr,
1218 case AArch64::SUBXrr:
1219 case AArch64::SUBWrr: {
1222 if (ZReg != AArch64::XZR && ZReg != AArch64::WZR)
1224 SrcReg =
DefMI->getOperand(2).getReg();
1225 Opc = Is64Bit ? AArch64::CSNEGXr : AArch64::CSNEGWr;
1231 assert(
Opc && SrcReg &&
"Missing parameters");
1241 Register FalseReg,
int &CondCycles,
1243 int &FalseCycles)
const {
1254 if (!RI.getCommonSubClass(RC, MRI.
getRegClass(DstReg)))
1258 unsigned ExtraCondLat =
Cond.size() != 1;
1262 if (AArch64::GPR64allRegClass.hasSubClassEq(RC) ||
1263 AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
1265 CondCycles = 1 + ExtraCondLat;
1266 TrueCycles = FalseCycles = 1;
1276 if (AArch64::FPR64RegClass.hasSubClassEq(RC) ||
1277 AArch64::FPR32RegClass.hasSubClassEq(RC)) {
1278 CondCycles = 5 + ExtraCondLat;
1279 TrueCycles = FalseCycles = 2;
1285 if (AArch64::FPR128RegClass.hasSubClassEq(RC) &&
1286 Subtarget.isNeonAvailable() &&
1287 !
MBB.getParent()->getFunction().hasMinSize()) {
1288 CondCycles = 8 + ExtraCondLat;
1289 TrueCycles = FalseCycles = 2;
1308 assert(Subtarget.isNeonAvailable() &&
"Expected NEON for a vector select");
1327 bool TryFold =
false;
1329 RC = &AArch64::GPR64RegClass;
1330 Opc = AArch64::CSELXr;
1333 RC = &AArch64::GPR32RegClass;
1334 Opc = AArch64::CSELWr;
1337 RC = &AArch64::FPR64RegClass;
1338 Opc = AArch64::FCSELDrrr;
1340 RC = &AArch64::FPR32RegClass;
1341 Opc = AArch64::FCSELSrrr;
1343 assert(RC &&
"Unsupported regclass");
1347 unsigned NewReg = 0;
1370 (FalseReg.
isVirtual() || FalseReg == AArch64::WZR ||
1371 FalseReg == AArch64::XZR) &&
1372 "FalseReg was folded into a non-virtual register other than WZR or XZR");
1389 assert(BitSize == 64 &&
"Only bit sizes of 32 or 64 allowed");
1394 return Is.
size() <= 2;
1399 assert(
MI.isCopy() &&
"Expected COPY instruction");
1405 if (
Reg.isVirtual())
1407 if (
Reg.isPhysical())
1408 return RI.getMinimalPhysRegClass(
Reg);
1413 if (DstRC && SrcRC && !RI.getCommonSubClass(DstRC, SrcRC))
1416 return MI.isAsCheapAsAMove();
1422 if (Subtarget.hasExynosCheapAsMoveHandling()) {
1423 if (isExynosCheapAsMove(
MI))
1425 return MI.isAsCheapAsAMove();
1428 switch (
MI.getOpcode()) {
1430 return MI.isAsCheapAsAMove();
1432 case TargetOpcode::COPY:
1435 case AArch64::ADDWrs:
1436 case AArch64::ADDXrs:
1437 case AArch64::SUBWrs:
1438 case AArch64::SUBXrs:
1439 return Subtarget.hasALULSLFast() &&
MI.getOperand(3).getImm() <= 4;
1444 case AArch64::MOVi32imm:
1446 case AArch64::MOVi64imm:
1451bool AArch64InstrInfo::isFalkorShiftExtFast(
const MachineInstr &
MI) {
1452 switch (
MI.getOpcode()) {
1456 case AArch64::ADDWrs:
1457 case AArch64::ADDXrs:
1458 case AArch64::ADDSWrs:
1459 case AArch64::ADDSXrs: {
1460 unsigned Imm =
MI.getOperand(3).getImm();
1467 case AArch64::ADDWrx:
1468 case AArch64::ADDXrx:
1469 case AArch64::ADDXrx64:
1470 case AArch64::ADDSWrx:
1471 case AArch64::ADDSXrx:
1472 case AArch64::ADDSXrx64: {
1473 unsigned Imm =
MI.getOperand(3).getImm();
1485 case AArch64::SUBWrs:
1486 case AArch64::SUBSWrs: {
1487 unsigned Imm =
MI.getOperand(3).getImm();
1489 return ShiftVal == 0 ||
1493 case AArch64::SUBXrs:
1494 case AArch64::SUBSXrs: {
1495 unsigned Imm =
MI.getOperand(3).getImm();
1497 return ShiftVal == 0 ||
1501 case AArch64::SUBWrx:
1502 case AArch64::SUBXrx:
1503 case AArch64::SUBXrx64:
1504 case AArch64::SUBSWrx:
1505 case AArch64::SUBSXrx:
1506 case AArch64::SUBSXrx64: {
1507 unsigned Imm =
MI.getOperand(3).getImm();
1519 case AArch64::LDRBBroW:
1520 case AArch64::LDRBBroX:
1521 case AArch64::LDRBroW:
1522 case AArch64::LDRBroX:
1523 case AArch64::LDRDroW:
1524 case AArch64::LDRDroX:
1525 case AArch64::LDRHHroW:
1526 case AArch64::LDRHHroX:
1527 case AArch64::LDRHroW:
1528 case AArch64::LDRHroX:
1529 case AArch64::LDRQroW:
1530 case AArch64::LDRQroX:
1531 case AArch64::LDRSBWroW:
1532 case AArch64::LDRSBWroX:
1533 case AArch64::LDRSBXroW:
1534 case AArch64::LDRSBXroX:
1535 case AArch64::LDRSHWroW:
1536 case AArch64::LDRSHWroX:
1537 case AArch64::LDRSHXroW:
1538 case AArch64::LDRSHXroX:
1539 case AArch64::LDRSWroW:
1540 case AArch64::LDRSWroX:
1541 case AArch64::LDRSroW:
1542 case AArch64::LDRSroX:
1543 case AArch64::LDRWroW:
1544 case AArch64::LDRWroX:
1545 case AArch64::LDRXroW:
1546 case AArch64::LDRXroX:
1547 case AArch64::PRFMroW:
1548 case AArch64::PRFMroX:
1549 case AArch64::STRBBroW:
1550 case AArch64::STRBBroX:
1551 case AArch64::STRBroW:
1552 case AArch64::STRBroX:
1553 case AArch64::STRDroW:
1554 case AArch64::STRDroX:
1555 case AArch64::STRHHroW:
1556 case AArch64::STRHHroX:
1557 case AArch64::STRHroW:
1558 case AArch64::STRHroX:
1559 case AArch64::STRQroW:
1560 case AArch64::STRQroX:
1561 case AArch64::STRSroW:
1562 case AArch64::STRSroX:
1563 case AArch64::STRWroW:
1564 case AArch64::STRWroX:
1565 case AArch64::STRXroW:
1566 case AArch64::STRXroX: {
1567 unsigned IsSigned =
MI.getOperand(3).getImm();
1574 unsigned Opc =
MI.getOpcode();
1578 case AArch64::SEH_StackAlloc:
1579 case AArch64::SEH_SaveFPLR:
1580 case AArch64::SEH_SaveFPLR_X:
1581 case AArch64::SEH_SaveReg:
1582 case AArch64::SEH_SaveReg_X:
1583 case AArch64::SEH_SaveRegP:
1584 case AArch64::SEH_SaveRegP_X:
1585 case AArch64::SEH_SaveFReg:
1586 case AArch64::SEH_SaveFReg_X:
1587 case AArch64::SEH_SaveFRegP:
1588 case AArch64::SEH_SaveFRegP_X:
1589 case AArch64::SEH_SetFP:
1590 case AArch64::SEH_AddFP:
1591 case AArch64::SEH_Nop:
1592 case AArch64::SEH_PrologEnd:
1593 case AArch64::SEH_EpilogStart:
1594 case AArch64::SEH_EpilogEnd:
1595 case AArch64::SEH_PACSignLR:
1596 case AArch64::SEH_SaveAnyRegI:
1597 case AArch64::SEH_SaveAnyRegIP:
1598 case AArch64::SEH_SaveAnyRegQP:
1599 case AArch64::SEH_SaveAnyRegQPX:
1600 case AArch64::SEH_AllocZ:
1601 case AArch64::SEH_SaveZReg:
1602 case AArch64::SEH_SavePReg:
1609 unsigned &SubIdx)
const {
1610 switch (
MI.getOpcode()) {
1613 case AArch64::SBFMXri:
1614 case AArch64::UBFMXri:
1617 if (
MI.getOperand(2).getImm() != 0 ||
MI.getOperand(3).getImm() != 31)
1620 SrcReg =
MI.getOperand(1).getReg();
1621 DstReg =
MI.getOperand(0).getReg();
1622 SubIdx = AArch64::sub_32;
1631 int64_t OffsetA = 0, OffsetB = 0;
1632 TypeSize WidthA(0,
false), WidthB(0,
false);
1633 bool OffsetAIsScalable =
false, OffsetBIsScalable =
false;
1654 OffsetAIsScalable == OffsetBIsScalable) {
1655 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
1656 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
1657 TypeSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
1658 if (LowWidth.
isScalable() == OffsetAIsScalable &&
1676 switch (
MI.getOpcode()) {
1679 if (
MI.getOperand(0).getImm() == 0x14)
1686 case AArch64::MSRpstatesvcrImm1:
1693 auto Next = std::next(
MI.getIterator());
1694 return Next !=
MBB->end() &&
Next->isCFIInstruction();
1701 Register &SrcReg2, int64_t &CmpMask,
1702 int64_t &CmpValue)
const {
1706 assert(
MI.getNumOperands() >= 2 &&
"All AArch64 cmps should have 2 operands");
1707 if (!
MI.getOperand(1).isReg() ||
MI.getOperand(1).getSubReg())
1710 switch (
MI.getOpcode()) {
1713 case AArch64::PTEST_PP:
1714 case AArch64::PTEST_PP_ANY:
1715 case AArch64::PTEST_PP_FIRST:
1716 SrcReg =
MI.getOperand(0).getReg();
1717 SrcReg2 =
MI.getOperand(1).getReg();
1718 if (
MI.getOperand(2).getSubReg())
1725 case AArch64::SUBSWrr:
1726 case AArch64::SUBSWrs:
1727 case AArch64::SUBSWrx:
1728 case AArch64::SUBSXrr:
1729 case AArch64::SUBSXrs:
1730 case AArch64::SUBSXrx:
1731 case AArch64::ADDSWrr:
1732 case AArch64::ADDSWrs:
1733 case AArch64::ADDSWrx:
1734 case AArch64::ADDSXrr:
1735 case AArch64::ADDSXrs:
1736 case AArch64::ADDSXrx:
1738 SrcReg =
MI.getOperand(1).getReg();
1739 SrcReg2 =
MI.getOperand(2).getReg();
1742 if (
MI.getOperand(2).getSubReg())
1748 case AArch64::SUBSWri:
1749 case AArch64::ADDSWri:
1750 case AArch64::SUBSXri:
1751 case AArch64::ADDSXri:
1752 SrcReg =
MI.getOperand(1).getReg();
1755 CmpValue =
MI.getOperand(2).getImm();
1757 case AArch64::ANDSWri:
1758 case AArch64::ANDSXri:
1761 SrcReg =
MI.getOperand(1).getReg();
1765 MI.getOperand(2).getImm(),
1766 MI.getOpcode() == AArch64::ANDSWri ? 32 : 64);
1775 assert(
MBB &&
"Can't get MachineBasicBlock here");
1777 assert(MF &&
"Can't get MachineFunction here");
1782 for (
unsigned OpIdx = 0, EndIdx = Instr.getNumOperands(); OpIdx < EndIdx;
1786 Instr.getRegClassConstraint(OpIdx,
TII,
TRI);
1789 if (!OpRegCstraints)
1797 "Operand has register constraints without being a register!");
1800 if (
Reg.isPhysical()) {
1817 bool MIDefinesZeroReg =
false;
1818 if (
MI.definesRegister(AArch64::WZR,
nullptr) ||
1819 MI.definesRegister(AArch64::XZR,
nullptr))
1820 MIDefinesZeroReg =
true;
1822 switch (
MI.getOpcode()) {
1824 return MI.getOpcode();
1825 case AArch64::ADDSWrr:
1826 return AArch64::ADDWrr;
1827 case AArch64::ADDSWri:
1828 return MIDefinesZeroReg ? AArch64::ADDSWri : AArch64::ADDWri;
1829 case AArch64::ADDSWrs:
1830 return MIDefinesZeroReg ? AArch64::ADDSWrs : AArch64::ADDWrs;
1831 case AArch64::ADDSWrx:
1832 return AArch64::ADDWrx;
1833 case AArch64::ADDSXrr:
1834 return AArch64::ADDXrr;
1835 case AArch64::ADDSXri:
1836 return MIDefinesZeroReg ? AArch64::ADDSXri : AArch64::ADDXri;
1837 case AArch64::ADDSXrs:
1838 return MIDefinesZeroReg ? AArch64::ADDSXrs : AArch64::ADDXrs;
1839 case AArch64::ADDSXrx:
1840 return AArch64::ADDXrx;
1841 case AArch64::SUBSWrr:
1842 return AArch64::SUBWrr;
1843 case AArch64::SUBSWri:
1844 return MIDefinesZeroReg ? AArch64::SUBSWri : AArch64::SUBWri;
1845 case AArch64::SUBSWrs:
1846 return MIDefinesZeroReg ? AArch64::SUBSWrs : AArch64::SUBWrs;
1847 case AArch64::SUBSWrx:
1848 return AArch64::SUBWrx;
1849 case AArch64::SUBSXrr:
1850 return AArch64::SUBXrr;
1851 case AArch64::SUBSXri:
1852 return MIDefinesZeroReg ? AArch64::SUBSXri : AArch64::SUBXri;
1853 case AArch64::SUBSXrs:
1854 return MIDefinesZeroReg ? AArch64::SUBSXrs : AArch64::SUBXrs;
1855 case AArch64::SUBSXrx:
1856 return AArch64::SUBXrx;
1871 if (To == To->getParent()->begin())
1876 if (To->getParent() != From->getParent())
1888 Instr.modifiesRegister(AArch64::NZCV,
TRI)) ||
1889 ((AccessToCheck &
AK_Read) && Instr.readsRegister(AArch64::NZCV,
TRI)))
1895std::optional<unsigned>
1899 unsigned MaskOpcode =
Mask->getOpcode();
1900 unsigned PredOpcode = Pred->
getOpcode();
1901 bool PredIsPTestLike = isPTestLikeOpcode(PredOpcode);
1902 bool PredIsWhileLike = isWhileOpcode(PredOpcode);
1904 if (PredIsWhileLike) {
1908 if ((Mask == Pred) && PTest->
getOpcode() == AArch64::PTEST_PP_ANY)
1915 getElementSizeForOpcode(MaskOpcode) ==
1916 getElementSizeForOpcode(PredOpcode))
1922 if (PTest->
getOpcode() == AArch64::PTEST_PP_FIRST &&
1929 if (PredIsPTestLike) {
1934 if ((Mask == Pred) && PTest->
getOpcode() == AArch64::PTEST_PP_ANY)
1942 if (Mask != PTestLikeMask && PTestLikeMask->isFullCopy() &&
1943 PTestLikeMask->getOperand(1).getReg().isVirtual())
1951 getElementSizeForOpcode(MaskOpcode) ==
1952 getElementSizeForOpcode(PredOpcode)) {
1953 if (Mask == PTestLikeMask || PTest->
getOpcode() == AArch64::PTEST_PP_ANY)
1979 uint64_t PredElementSize = getElementSizeForOpcode(PredOpcode);
1981 PTest->
getOpcode() == AArch64::PTEST_PP_ANY))
1989 switch (PredOpcode) {
1990 case AArch64::AND_PPzPP:
1991 case AArch64::BIC_PPzPP:
1992 case AArch64::EOR_PPzPP:
1993 case AArch64::NAND_PPzPP:
1994 case AArch64::NOR_PPzPP:
1995 case AArch64::ORN_PPzPP:
1996 case AArch64::ORR_PPzPP:
1997 case AArch64::BRKA_PPzP:
1998 case AArch64::BRKPA_PPzPP:
1999 case AArch64::BRKB_PPzP:
2000 case AArch64::BRKPB_PPzPP:
2001 case AArch64::RDFFR_PPz: {
2005 if (Mask != PredMask)
2009 case AArch64::BRKN_PPzP: {
2013 if ((MaskOpcode != AArch64::PTRUE_B) ||
2014 (
Mask->getOperand(1).getImm() != 31))
2018 case AArch64::PTRUE_B:
2031bool AArch64InstrInfo::optimizePTestInstr(
2032 MachineInstr *PTest,
unsigned MaskReg,
unsigned PredReg,
2037 if (Pred->
isCopy() && PTest->
getOpcode() == AArch64::PTEST_PP_FIRST) {
2041 if (
Op.isReg() &&
Op.getReg().isVirtual() &&
2042 Op.getSubReg() == AArch64::psub0)
2046 unsigned PredOpcode = Pred->
getOpcode();
2047 auto NewOp = canRemovePTestInstr(PTest, Mask, Pred, MRI);
2063 if (*NewOp != PredOpcode) {
2074 for (; i !=
e; ++i) {
2105 if (DeadNZCVIdx != -1) {
2124 if (CmpInstr.
getOpcode() == AArch64::PTEST_PP ||
2125 CmpInstr.
getOpcode() == AArch64::PTEST_PP_ANY ||
2126 CmpInstr.
getOpcode() == AArch64::PTEST_PP_FIRST)
2127 return optimizePTestInstr(&CmpInstr, SrcReg, SrcReg2, MRI);
2136 if (CmpValue == 0 && substituteCmpToZero(CmpInstr, SrcReg, *MRI))
2138 return (CmpValue == 0 || CmpValue == 1) &&
2139 removeCmpToZeroOrOne(CmpInstr, SrcReg, CmpValue, *MRI);
2147 switch (Instr.getOpcode()) {
2149 return AArch64::INSTRUCTION_LIST_END;
2151 case AArch64::ADDSWrr:
2152 case AArch64::ADDSWri:
2153 case AArch64::ADDSXrr:
2154 case AArch64::ADDSXri:
2155 case AArch64::ADDSWrx:
2156 case AArch64::ADDSXrx:
2157 case AArch64::ADDSWrs:
2158 case AArch64::ADDSXrs:
2159 case AArch64::SUBSWrr:
2160 case AArch64::SUBSWri:
2161 case AArch64::SUBSWrx:
2162 case AArch64::SUBSWrs:
2163 case AArch64::SUBSXrr:
2164 case AArch64::SUBSXri:
2165 case AArch64::SUBSXrx:
2166 case AArch64::SUBSXrs:
2167 case AArch64::ANDSWri:
2168 case AArch64::ANDSWrr:
2169 case AArch64::ANDSWrs:
2170 case AArch64::ANDSXri:
2171 case AArch64::ANDSXrr:
2172 case AArch64::ANDSXrs:
2173 case AArch64::BICSWrr:
2174 case AArch64::BICSXrr:
2175 case AArch64::BICSWrs:
2176 case AArch64::BICSXrs:
2177 case AArch64::ADCSWr:
2178 case AArch64::ADCSXr:
2179 case AArch64::SBCSWr:
2180 case AArch64::SBCSXr:
2181 return Instr.getOpcode();
2183 case AArch64::ADDWrr:
2184 return AArch64::ADDSWrr;
2185 case AArch64::ADDWri:
2186 return AArch64::ADDSWri;
2187 case AArch64::ADDXrr:
2188 return AArch64::ADDSXrr;
2189 case AArch64::ADDXri:
2190 return AArch64::ADDSXri;
2191 case AArch64::ADDWrx:
2192 return AArch64::ADDSWrx;
2193 case AArch64::ADDXrx:
2194 return AArch64::ADDSXrx;
2195 case AArch64::ADDWrs:
2196 return AArch64::ADDSWrs;
2197 case AArch64::ADDXrs:
2198 return AArch64::ADDSXrs;
2199 case AArch64::ADCWr:
2200 return AArch64::ADCSWr;
2201 case AArch64::ADCXr:
2202 return AArch64::ADCSXr;
2203 case AArch64::SUBWrr:
2204 return AArch64::SUBSWrr;
2205 case AArch64::SUBWri:
2206 return AArch64::SUBSWri;
2207 case AArch64::SUBXrr:
2208 return AArch64::SUBSXrr;
2209 case AArch64::SUBXri:
2210 return AArch64::SUBSXri;
2211 case AArch64::SUBWrx:
2212 return AArch64::SUBSWrx;
2213 case AArch64::SUBXrx:
2214 return AArch64::SUBSXrx;
2215 case AArch64::SUBWrs:
2216 return AArch64::SUBSWrs;
2217 case AArch64::SUBXrs:
2218 return AArch64::SUBSXrs;
2219 case AArch64::SBCWr:
2220 return AArch64::SBCSWr;
2221 case AArch64::SBCXr:
2222 return AArch64::SBCSXr;
2223 case AArch64::ANDWri:
2224 return AArch64::ANDSWri;
2225 case AArch64::ANDXri:
2226 return AArch64::ANDSXri;
2227 case AArch64::ANDWrr:
2228 return AArch64::ANDSWrr;
2229 case AArch64::ANDWrs:
2230 return AArch64::ANDSWrs;
2231 case AArch64::ANDXrr:
2232 return AArch64::ANDSXrr;
2233 case AArch64::ANDXrs:
2234 return AArch64::ANDSXrs;
2235 case AArch64::BICWrr:
2236 return AArch64::BICSWrr;
2237 case AArch64::BICXrr:
2238 return AArch64::BICSXrr;
2239 case AArch64::BICWrs:
2240 return AArch64::BICSWrs;
2241 case AArch64::BICXrs:
2242 return AArch64::BICSXrs;
2248 for (
auto *BB :
MBB->successors())
2249 if (BB->isLiveIn(AArch64::NZCV))
2256int AArch64InstrInfo::findCondCodeUseOperandIdxForBranchOrSelect(
2258 switch (
Instr.getOpcode()) {
2262 case AArch64::Bcc: {
2263 int Idx =
Instr.findRegisterUseOperandIdx(AArch64::NZCV,
nullptr);
2268 case AArch64::CSINVWr:
2269 case AArch64::CSINVXr:
2270 case AArch64::CSINCWr:
2271 case AArch64::CSINCXr:
2272 case AArch64::CSELWr:
2273 case AArch64::CSELXr:
2274 case AArch64::CSNEGWr:
2275 case AArch64::CSNEGXr:
2276 case AArch64::FCSELSrrr:
2277 case AArch64::FCSELDrrr: {
2278 int Idx =
Instr.findRegisterUseOperandIdx(AArch64::NZCV,
nullptr);
2290 AArch64InstrInfo::findCondCodeUseOperandIdxForBranchOrSelect(Instr);
2292 Instr.getOperand(CCIdx).
getImm())
2345std::optional<UsedNZCV>
2350 if (
MI.getParent() != CmpParent)
2351 return std::nullopt;
2354 return std::nullopt;
2359 if (Instr.readsRegister(AArch64::NZCV, &
TRI)) {
2362 return std::nullopt;
2367 if (Instr.modifiesRegister(AArch64::NZCV, &
TRI))
2370 return NZCVUsedAfterCmp;
2374 return Opcode == AArch64::ADDSWri || Opcode == AArch64::ADDSXri;
2378 return Opcode == AArch64::SUBSWri || Opcode == AArch64::SUBSXri;
2384 case AArch64::ANDSWri:
2385 case AArch64::ANDSWrr:
2386 case AArch64::ANDSWrs:
2387 case AArch64::ANDSXri:
2388 case AArch64::ANDSXrr:
2389 case AArch64::ANDSXrs:
2390 case AArch64::BICSWrr:
2391 case AArch64::BICSXrr:
2392 case AArch64::BICSWrs:
2393 case AArch64::BICSXrs:
2419 const unsigned CmpOpcode = CmpInstr.
getOpcode();
2425 "Caller guarantees that CmpInstr compares with constant 0");
2428 if (!NZVCUsed || NZVCUsed->C)
2449bool AArch64InstrInfo::substituteCmpToZero(
2460 if (NewOpc == AArch64::INSTRUCTION_LIST_END)
2467 MI->setDesc(
get(NewOpc));
2472 MI->addRegisterDefined(AArch64::NZCV, &
TRI);
2484 assert((CmpValue == 0 || CmpValue == 1) &&
2485 "Only comparisons to 0 or 1 considered for removal!");
2488 unsigned MIOpc =
MI.getOpcode();
2489 if (MIOpc == AArch64::CSINCWr) {
2490 if (
MI.getOperand(1).getReg() != AArch64::WZR ||
2491 MI.getOperand(2).getReg() != AArch64::WZR)
2493 }
else if (MIOpc == AArch64::CSINCXr) {
2494 if (
MI.getOperand(1).getReg() != AArch64::XZR ||
2495 MI.getOperand(2).getReg() != AArch64::XZR)
2505 if (
MI.findRegisterDefOperandIdx(AArch64::NZCV,
nullptr,
true) != -1)
2509 const unsigned CmpOpcode = CmpInstr.
getOpcode();
2511 if (CmpValue && !IsSubsRegImm)
2513 if (!CmpValue && !IsSubsRegImm && !
isADDSRegImm(CmpOpcode))
2518 if (MIUsedNZCV.
C || MIUsedNZCV.
V)
2521 std::optional<UsedNZCV> NZCVUsedAfterCmp =
2525 if (!NZCVUsedAfterCmp || NZCVUsedAfterCmp->C || NZCVUsedAfterCmp->V)
2528 if ((MIUsedNZCV.
Z && NZCVUsedAfterCmp->N) ||
2529 (MIUsedNZCV.
N && NZCVUsedAfterCmp->Z))
2532 if (MIUsedNZCV.
N && !CmpValue)
2574bool AArch64InstrInfo::removeCmpToZeroOrOne(
2581 SmallVector<MachineInstr *, 4> CCUseInstrs;
2582 bool IsInvertCC =
false;
2590 for (MachineInstr *CCUseInstr : CCUseInstrs) {
2591 int Idx = findCondCodeUseOperandIdxForBranchOrSelect(*CCUseInstr);
2592 assert(Idx >= 0 &&
"Unexpected instruction using CC.");
2593 MachineOperand &CCOperand = CCUseInstr->getOperand(Idx);
2602bool AArch64InstrInfo::expandPostRAPseudo(
MachineInstr &
MI)
const {
2603 if (
MI.getOpcode() != TargetOpcode::LOAD_STACK_GUARD &&
2604 MI.getOpcode() != AArch64::CATCHRET &&
2605 MI.getOpcode() != AArch64::STACK_GUARD_UNMIX)
2610 auto TRI = Subtarget.getRegisterInfo();
2613 if (
MI.getOpcode() == AArch64::STACK_GUARD_UNMIX) {
2627 if (
MI.getOpcode() == AArch64::CATCHRET) {
2629 const TargetInstrInfo *
TII =
2631 MachineBasicBlock *TargetMBB =
MI.getOperand(0).getMBB();
2636 FirstEpilogSEH = std::prev(FirstEpilogSEH);
2638 FirstEpilogSEH = std::next(FirstEpilogSEH);
2653 if (
M.getStackProtectorGuard() ==
"sysreg") {
2654 const AArch64SysReg::SysReg *SrcReg =
2655 AArch64SysReg::lookupSysRegByName(
M.getStackProtectorGuardReg());
2663 int Offset =
M.getStackProtectorGuardOffset();
2714 const GlobalValue *GV =
2717 unsigned OpFlags = Subtarget.ClassifyGlobalReference(GV, TM);
2720 unsigned GuardWidth =
M.getStackProtectorGuardValueWidth().value_or(
2721 Subtarget.isTargetILP32() ? 4 : 8);
2722 if (GuardWidth != 4 && GuardWidth != 8)
2727 if (GuardWidth == 4) {
2728 unsigned Reg32 =
TRI->getSubReg(
Reg, AArch64::sub_32);
2757 if (GuardWidth == 4) {
2758 unsigned Reg32 =
TRI->getSubReg(
Reg, AArch64::sub_32);
2775 if (GuardWidth == 4) {
2776 unsigned Reg32 =
TRI->getSubReg(
Reg, AArch64::sub_32);
2794 if (Subtarget.getTargetTriple().isOSMSVCRT())
2807 switch (
MI.getOpcode()) {
2810 case AArch64::MOVZWi:
2811 case AArch64::MOVZXi:
2812 if (
MI.getOperand(1).isImm() &&
MI.getOperand(1).getImm() == 0) {
2813 assert(
MI.getDesc().getNumOperands() == 3 &&
2814 MI.getOperand(2).getImm() == 0 &&
"invalid MOVZi operands");
2818 case AArch64::ANDWri:
2819 return MI.getOperand(1).getReg() == AArch64::WZR;
2820 case AArch64::ANDXri:
2821 return MI.getOperand(1).getReg() == AArch64::XZR;
2822 case TargetOpcode::COPY:
2823 return MI.getOperand(1).getReg() == AArch64::WZR;
2831 switch (
MI.getOpcode()) {
2834 case TargetOpcode::COPY: {
2837 return (AArch64::GPR32RegClass.
contains(DstReg) ||
2838 AArch64::GPR64RegClass.
contains(DstReg));
2840 case AArch64::ORRXrs:
2841 if (
MI.getOperand(1).getReg() == AArch64::XZR) {
2842 assert(
MI.getDesc().getNumOperands() == 4 &&
2843 MI.getOperand(3).getImm() == 0 &&
"invalid ORRrs operands");
2847 case AArch64::ADDXri:
2848 if (
MI.getOperand(2).getImm() == 0) {
2849 assert(
MI.getDesc().getNumOperands() == 4 &&
2850 MI.getOperand(3).getImm() == 0 &&
"invalid ADDXri operands");
2861 switch (
MI.getOpcode()) {
2864 case TargetOpcode::COPY: {
2866 return AArch64::FPR128RegClass.contains(DstReg);
2868 case AArch64::ORRv16i8:
2869 if (
MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg()) {
2870 assert(
MI.getDesc().getNumOperands() == 3 &&
MI.getOperand(0).isReg() &&
2871 "invalid ORRv16i8 operands");
2883 case AArch64::LDRWui:
2884 case AArch64::LDRXui:
2885 case AArch64::LDRBui:
2886 case AArch64::LDRHui:
2887 case AArch64::LDRSui:
2888 case AArch64::LDRDui:
2889 case AArch64::LDRQui:
2890 case AArch64::LDR_PXI:
2896 int &FrameIndex)
const {
2900 if (
MI.getOperand(0).getSubReg() == 0 &&
MI.getOperand(1).isFI() &&
2901 MI.getOperand(2).isImm() &&
MI.getOperand(2).getImm() == 0) {
2902 FrameIndex =
MI.getOperand(1).getIndex();
2903 return MI.getOperand(0).getReg();
2912 case AArch64::STRWui:
2913 case AArch64::STRXui:
2914 case AArch64::STRBui:
2915 case AArch64::STRHui:
2916 case AArch64::STRSui:
2917 case AArch64::STRDui:
2918 case AArch64::STRQui:
2919 case AArch64::STR_PXI:
2925 int &FrameIndex)
const {
2929 if (
MI.getOperand(0).getSubReg() == 0 &&
MI.getOperand(1).isFI() &&
2930 MI.getOperand(2).isImm() &&
MI.getOperand(2).getImm() == 0) {
2931 FrameIndex =
MI.getOperand(1).getIndex();
2932 return MI.getOperand(0).getReg();
2938 int &FrameIndex)
const {
2953 return MI.getOperand(0).getReg();
2959 int &FrameIndex)
const {
2974 return MI.getOperand(0).getReg();
2982 return MMO->getFlags() & MOSuppressPair;
2988 if (
MI.memoperands_empty())
2996 return MMO->getFlags() & MOStridedAccess;
3004 case AArch64::STURSi:
3005 case AArch64::STRSpre:
3006 case AArch64::STURDi:
3007 case AArch64::STRDpre:
3008 case AArch64::STURQi:
3009 case AArch64::STRQpre:
3010 case AArch64::STURBBi:
3011 case AArch64::STURHHi:
3012 case AArch64::STURWi:
3013 case AArch64::STRWpre:
3014 case AArch64::STURXi:
3015 case AArch64::STRXpre:
3016 case AArch64::LDURSi:
3017 case AArch64::LDRSpre:
3018 case AArch64::LDURDi:
3019 case AArch64::LDRDpre:
3020 case AArch64::LDURQi:
3021 case AArch64::LDRQpre:
3022 case AArch64::LDURWi:
3023 case AArch64::LDRWpre:
3024 case AArch64::LDURXi:
3025 case AArch64::LDRXpre:
3026 case AArch64::LDRSWpre:
3027 case AArch64::LDURSWi:
3028 case AArch64::LDURHHi:
3029 case AArch64::LDURBBi:
3030 case AArch64::LDURSBWi:
3031 case AArch64::LDURSHWi:
3039 case AArch64::PRFMui:
return AArch64::PRFUMi;
3040 case AArch64::LDRXui:
return AArch64::LDURXi;
3041 case AArch64::LDRWui:
return AArch64::LDURWi;
3042 case AArch64::LDRBui:
return AArch64::LDURBi;
3043 case AArch64::LDRHui:
return AArch64::LDURHi;
3044 case AArch64::LDRSui:
return AArch64::LDURSi;
3045 case AArch64::LDRDui:
return AArch64::LDURDi;
3046 case AArch64::LDRQui:
return AArch64::LDURQi;
3047 case AArch64::LDRBBui:
return AArch64::LDURBBi;
3048 case AArch64::LDRHHui:
return AArch64::LDURHHi;
3049 case AArch64::LDRSBXui:
return AArch64::LDURSBXi;
3050 case AArch64::LDRSBWui:
return AArch64::LDURSBWi;
3051 case AArch64::LDRSHXui:
return AArch64::LDURSHXi;
3052 case AArch64::LDRSHWui:
return AArch64::LDURSHWi;
3053 case AArch64::LDRSWui:
return AArch64::LDURSWi;
3054 case AArch64::STRXui:
return AArch64::STURXi;
3055 case AArch64::STRWui:
return AArch64::STURWi;
3056 case AArch64::STRBui:
return AArch64::STURBi;
3057 case AArch64::STRHui:
return AArch64::STURHi;
3058 case AArch64::STRSui:
return AArch64::STURSi;
3059 case AArch64::STRDui:
return AArch64::STURDi;
3060 case AArch64::STRQui:
return AArch64::STURQi;
3061 case AArch64::STRBBui:
return AArch64::STURBBi;
3062 case AArch64::STRHHui:
return AArch64::STURHHi;
3071 case AArch64::LDAPURBi:
3072 case AArch64::LDAPURHi:
3073 case AArch64::LDAPURi:
3074 case AArch64::LDAPURSBWi:
3075 case AArch64::LDAPURSBXi:
3076 case AArch64::LDAPURSHWi:
3077 case AArch64::LDAPURSHXi:
3078 case AArch64::LDAPURSWi:
3079 case AArch64::LDAPURXi:
3080 case AArch64::LDR_PPXI:
3081 case AArch64::LDR_PXI:
3082 case AArch64::LDR_ZXI:
3083 case AArch64::LDR_ZZXI:
3084 case AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS:
3085 case AArch64::LDR_ZZZXI:
3086 case AArch64::LDR_ZZZZXI:
3087 case AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS:
3088 case AArch64::LDRBBui:
3089 case AArch64::LDRBui:
3090 case AArch64::LDRDui:
3091 case AArch64::LDRHHui:
3092 case AArch64::LDRHui:
3093 case AArch64::LDRQui:
3094 case AArch64::LDRSBWui:
3095 case AArch64::LDRSBXui:
3096 case AArch64::LDRSHWui:
3097 case AArch64::LDRSHXui:
3098 case AArch64::LDRSui:
3099 case AArch64::LDRSWui:
3100 case AArch64::LDRWui:
3101 case AArch64::LDRXui:
3102 case AArch64::LDURBBi:
3103 case AArch64::LDURBi:
3104 case AArch64::LDURDi:
3105 case AArch64::LDURHHi:
3106 case AArch64::LDURHi:
3107 case AArch64::LDURQi:
3108 case AArch64::LDURSBWi:
3109 case AArch64::LDURSBXi:
3110 case AArch64::LDURSHWi:
3111 case AArch64::LDURSHXi:
3112 case AArch64::LDURSi:
3113 case AArch64::LDURSWi:
3114 case AArch64::LDURWi:
3115 case AArch64::LDURXi:
3116 case AArch64::PRFMui:
3117 case AArch64::PRFUMi:
3118 case AArch64::ST2Gi:
3120 case AArch64::STLURBi:
3121 case AArch64::STLURHi:
3122 case AArch64::STLURWi:
3123 case AArch64::STLURXi:
3124 case AArch64::StoreSwiftAsyncContext:
3125 case AArch64::STR_PPXI:
3126 case AArch64::STR_PXI:
3127 case AArch64::STR_ZXI:
3128 case AArch64::STR_ZZXI:
3129 case AArch64::STR_ZZXI_STRIDED_CONTIGUOUS:
3130 case AArch64::STR_ZZZXI:
3131 case AArch64::STR_ZZZZXI:
3132 case AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS:
3133 case AArch64::STRBBui:
3134 case AArch64::STRBui:
3135 case AArch64::STRDui:
3136 case AArch64::STRHHui:
3137 case AArch64::STRHui:
3138 case AArch64::STRQui:
3139 case AArch64::STRSui:
3140 case AArch64::STRWui:
3141 case AArch64::STRXui:
3142 case AArch64::STURBBi:
3143 case AArch64::STURBi:
3144 case AArch64::STURDi:
3145 case AArch64::STURHHi:
3146 case AArch64::STURHi:
3147 case AArch64::STURQi:
3148 case AArch64::STURSi:
3149 case AArch64::STURWi:
3150 case AArch64::STURXi:
3151 case AArch64::STZ2Gi:
3152 case AArch64::STZGi:
3153 case AArch64::TAGPstack:
3155 case AArch64::LD1B_D_IMM:
3156 case AArch64::LD1B_H_IMM:
3157 case AArch64::LD1B_IMM:
3158 case AArch64::LD1B_S_IMM:
3159 case AArch64::LD1D_IMM:
3160 case AArch64::LD1H_D_IMM:
3161 case AArch64::LD1H_IMM:
3162 case AArch64::LD1H_S_IMM:
3163 case AArch64::LD1RB_D_IMM:
3164 case AArch64::LD1RB_H_IMM:
3165 case AArch64::LD1RB_IMM:
3166 case AArch64::LD1RB_S_IMM:
3167 case AArch64::LD1RD_IMM:
3168 case AArch64::LD1RH_D_IMM:
3169 case AArch64::LD1RH_IMM:
3170 case AArch64::LD1RH_S_IMM:
3171 case AArch64::LD1RSB_D_IMM:
3172 case AArch64::LD1RSB_H_IMM:
3173 case AArch64::LD1RSB_S_IMM:
3174 case AArch64::LD1RSH_D_IMM:
3175 case AArch64::LD1RSH_S_IMM:
3176 case AArch64::LD1RSW_IMM:
3177 case AArch64::LD1RW_D_IMM:
3178 case AArch64::LD1RW_IMM:
3179 case AArch64::LD1SB_D_IMM:
3180 case AArch64::LD1SB_H_IMM:
3181 case AArch64::LD1SB_S_IMM:
3182 case AArch64::LD1SH_D_IMM:
3183 case AArch64::LD1SH_S_IMM:
3184 case AArch64::LD1SW_D_IMM:
3185 case AArch64::LD1W_D_IMM:
3186 case AArch64::LD1W_IMM:
3187 case AArch64::LD2B_IMM:
3188 case AArch64::LD2D_IMM:
3189 case AArch64::LD2H_IMM:
3190 case AArch64::LD2W_IMM:
3191 case AArch64::LD3B_IMM:
3192 case AArch64::LD3D_IMM:
3193 case AArch64::LD3H_IMM:
3194 case AArch64::LD3W_IMM:
3195 case AArch64::LD4B_IMM:
3196 case AArch64::LD4D_IMM:
3197 case AArch64::LD4H_IMM:
3198 case AArch64::LD4W_IMM:
3200 case AArch64::LDNF1B_D_IMM:
3201 case AArch64::LDNF1B_H_IMM:
3202 case AArch64::LDNF1B_IMM:
3203 case AArch64::LDNF1B_S_IMM:
3204 case AArch64::LDNF1D_IMM:
3205 case AArch64::LDNF1H_D_IMM:
3206 case AArch64::LDNF1H_IMM:
3207 case AArch64::LDNF1H_S_IMM:
3208 case AArch64::LDNF1SB_D_IMM:
3209 case AArch64::LDNF1SB_H_IMM:
3210 case AArch64::LDNF1SB_S_IMM:
3211 case AArch64::LDNF1SH_D_IMM:
3212 case AArch64::LDNF1SH_S_IMM:
3213 case AArch64::LDNF1SW_D_IMM:
3214 case AArch64::LDNF1W_D_IMM:
3215 case AArch64::LDNF1W_IMM:
3216 case AArch64::LDNPDi:
3217 case AArch64::LDNPQi:
3218 case AArch64::LDNPSi:
3219 case AArch64::LDNPWi:
3220 case AArch64::LDNPXi:
3221 case AArch64::LDNT1B_ZRI:
3222 case AArch64::LDNT1D_ZRI:
3223 case AArch64::LDNT1H_ZRI:
3224 case AArch64::LDNT1W_ZRI:
3225 case AArch64::LDPDi:
3226 case AArch64::LDPQi:
3227 case AArch64::LDPSi:
3228 case AArch64::LDPWi:
3229 case AArch64::LDPXi:
3230 case AArch64::LDRBBpost:
3231 case AArch64::LDRBBpre:
3232 case AArch64::LDRBpost:
3233 case AArch64::LDRBpre:
3234 case AArch64::LDRDpost:
3235 case AArch64::LDRDpre:
3236 case AArch64::LDRHHpost:
3237 case AArch64::LDRHHpre:
3238 case AArch64::LDRHpost:
3239 case AArch64::LDRHpre:
3240 case AArch64::LDRQpost:
3241 case AArch64::LDRQpre:
3242 case AArch64::LDRSpost:
3243 case AArch64::LDRSpre:
3244 case AArch64::LDRWpost:
3245 case AArch64::LDRWpre:
3246 case AArch64::LDRXpost:
3247 case AArch64::LDRXpre:
3248 case AArch64::ST1B_D_IMM:
3249 case AArch64::ST1B_H_IMM:
3250 case AArch64::ST1B_IMM:
3251 case AArch64::ST1B_S_IMM:
3252 case AArch64::ST1D_IMM:
3253 case AArch64::ST1H_D_IMM:
3254 case AArch64::ST1H_IMM:
3255 case AArch64::ST1H_S_IMM:
3256 case AArch64::ST1W_D_IMM:
3257 case AArch64::ST1W_IMM:
3258 case AArch64::ST2B_IMM:
3259 case AArch64::ST2D_IMM:
3260 case AArch64::ST2H_IMM:
3261 case AArch64::ST2W_IMM:
3262 case AArch64::ST3B_IMM:
3263 case AArch64::ST3D_IMM:
3264 case AArch64::ST3H_IMM:
3265 case AArch64::ST3W_IMM:
3266 case AArch64::ST4B_IMM:
3267 case AArch64::ST4D_IMM:
3268 case AArch64::ST4H_IMM:
3269 case AArch64::ST4W_IMM:
3270 case AArch64::STGPi:
3271 case AArch64::STGPreIndex:
3272 case AArch64::STZGPreIndex:
3273 case AArch64::ST2GPreIndex:
3274 case AArch64::STZ2GPreIndex:
3275 case AArch64::STGPostIndex:
3276 case AArch64::STZGPostIndex:
3277 case AArch64::ST2GPostIndex:
3278 case AArch64::STZ2GPostIndex:
3279 case AArch64::STNPDi:
3280 case AArch64::STNPQi:
3281 case AArch64::STNPSi:
3282 case AArch64::STNPWi:
3283 case AArch64::STNPXi:
3284 case AArch64::STNT1B_ZRI:
3285 case AArch64::STNT1D_ZRI:
3286 case AArch64::STNT1H_ZRI:
3287 case AArch64::STNT1W_ZRI:
3288 case AArch64::STPDi:
3289 case AArch64::STPQi:
3290 case AArch64::STPSi:
3291 case AArch64::STPWi:
3292 case AArch64::STPXi:
3293 case AArch64::STRBBpost:
3294 case AArch64::STRBBpre:
3295 case AArch64::STRBpost:
3296 case AArch64::STRBpre:
3297 case AArch64::STRDpost:
3298 case AArch64::STRDpre:
3299 case AArch64::STRHHpost:
3300 case AArch64::STRHHpre:
3301 case AArch64::STRHpost:
3302 case AArch64::STRHpre:
3303 case AArch64::STRQpost:
3304 case AArch64::STRQpre:
3305 case AArch64::STRSpost:
3306 case AArch64::STRSpre:
3307 case AArch64::STRWpost:
3308 case AArch64::STRWpre:
3309 case AArch64::STRXpost:
3310 case AArch64::STRXpre:
3311 case AArch64::LD1B_2Z_IMM:
3312 case AArch64::LD1B_2Z_STRIDED_IMM:
3313 case AArch64::LD1H_2Z_IMM:
3314 case AArch64::LD1H_2Z_STRIDED_IMM:
3315 case AArch64::LD1W_2Z_IMM:
3316 case AArch64::LD1W_2Z_STRIDED_IMM:
3317 case AArch64::LD1D_2Z_IMM:
3318 case AArch64::LD1D_2Z_STRIDED_IMM:
3319 case AArch64::LD1B_4Z_IMM:
3320 case AArch64::LD1B_4Z_STRIDED_IMM:
3321 case AArch64::LD1H_4Z_IMM:
3322 case AArch64::LD1H_4Z_STRIDED_IMM:
3323 case AArch64::LD1W_4Z_IMM:
3324 case AArch64::LD1W_4Z_STRIDED_IMM:
3325 case AArch64::LD1D_4Z_IMM:
3326 case AArch64::LD1D_4Z_STRIDED_IMM:
3327 case AArch64::LD1B_2Z_IMM_PSEUDO:
3328 case AArch64::LD1H_2Z_IMM_PSEUDO:
3329 case AArch64::LD1W_2Z_IMM_PSEUDO:
3330 case AArch64::LD1D_2Z_IMM_PSEUDO:
3331 case AArch64::LD1B_4Z_IMM_PSEUDO:
3332 case AArch64::LD1H_4Z_IMM_PSEUDO:
3333 case AArch64::LD1W_4Z_IMM_PSEUDO:
3334 case AArch64::LD1D_4Z_IMM_PSEUDO:
3335 case AArch64::ST1B_2Z_IMM:
3336 case AArch64::ST1B_2Z_STRIDED_IMM:
3337 case AArch64::ST1H_2Z_IMM:
3338 case AArch64::ST1H_2Z_STRIDED_IMM:
3339 case AArch64::ST1W_2Z_IMM:
3340 case AArch64::ST1W_2Z_STRIDED_IMM:
3341 case AArch64::ST1D_2Z_IMM:
3342 case AArch64::ST1D_2Z_STRIDED_IMM:
3343 case AArch64::LDNT1B_2Z_IMM_PSEUDO:
3344 case AArch64::LDNT1B_2Z_IMM:
3345 case AArch64::LDNT1B_2Z_STRIDED_IMM:
3346 case AArch64::LDNT1H_2Z_IMM_PSEUDO:
3347 case AArch64::LDNT1H_2Z_IMM:
3348 case AArch64::LDNT1H_2Z_STRIDED_IMM:
3349 case AArch64::LDNT1W_2Z_IMM_PSEUDO:
3350 case AArch64::LDNT1W_2Z_IMM:
3351 case AArch64::LDNT1W_2Z_STRIDED_IMM:
3352 case AArch64::LDNT1D_2Z_IMM_PSEUDO:
3353 case AArch64::LDNT1D_2Z_IMM:
3354 case AArch64::LDNT1D_2Z_STRIDED_IMM:
3355 case AArch64::STNT1B_2Z_IMM:
3356 case AArch64::STNT1B_2Z_STRIDED_IMM:
3357 case AArch64::STNT1H_2Z_IMM:
3358 case AArch64::STNT1H_2Z_STRIDED_IMM:
3359 case AArch64::STNT1W_2Z_IMM:
3360 case AArch64::STNT1W_2Z_STRIDED_IMM:
3361 case AArch64::STNT1D_2Z_IMM:
3362 case AArch64::STNT1D_2Z_STRIDED_IMM:
3363 case AArch64::ST1B_2Z_IMM_PSEUDO:
3364 case AArch64::ST1H_2Z_IMM_PSEUDO:
3365 case AArch64::ST1W_2Z_IMM_PSEUDO:
3366 case AArch64::ST1D_2Z_IMM_PSEUDO:
3367 case AArch64::STNT1B_2Z_IMM_PSEUDO:
3368 case AArch64::STNT1H_2Z_IMM_PSEUDO:
3369 case AArch64::STNT1W_2Z_IMM_PSEUDO:
3370 case AArch64::STNT1D_2Z_IMM_PSEUDO:
3371 case AArch64::ST1B_4Z_IMM:
3372 case AArch64::ST1B_4Z_STRIDED_IMM:
3373 case AArch64::ST1H_4Z_IMM:
3374 case AArch64::ST1H_4Z_STRIDED_IMM:
3375 case AArch64::ST1W_4Z_IMM:
3376 case AArch64::ST1W_4Z_STRIDED_IMM:
3377 case AArch64::ST1D_4Z_IMM:
3378 case AArch64::ST1D_4Z_STRIDED_IMM:
3379 case AArch64::LDNT1B_4Z_IMM_PSEUDO:
3380 case AArch64::LDNT1B_4Z_IMM:
3381 case AArch64::LDNT1B_4Z_STRIDED_IMM:
3382 case AArch64::LDNT1H_4Z_IMM_PSEUDO:
3383 case AArch64::LDNT1H_4Z_IMM:
3384 case AArch64::LDNT1H_4Z_STRIDED_IMM:
3385 case AArch64::LDNT1W_4Z_IMM_PSEUDO:
3386 case AArch64::LDNT1W_4Z_IMM:
3387 case AArch64::LDNT1W_4Z_STRIDED_IMM:
3388 case AArch64::LDNT1D_4Z_IMM_PSEUDO:
3389 case AArch64::LDNT1D_4Z_IMM:
3390 case AArch64::LDNT1D_4Z_STRIDED_IMM:
3391 case AArch64::STNT1B_4Z_IMM:
3392 case AArch64::STNT1B_4Z_STRIDED_IMM:
3393 case AArch64::STNT1H_4Z_IMM:
3394 case AArch64::STNT1H_4Z_STRIDED_IMM:
3395 case AArch64::STNT1W_4Z_IMM:
3396 case AArch64::STNT1W_4Z_STRIDED_IMM:
3397 case AArch64::STNT1D_4Z_IMM:
3398 case AArch64::STNT1D_4Z_STRIDED_IMM:
3399 case AArch64::ST1B_4Z_IMM_PSEUDO:
3400 case AArch64::ST1H_4Z_IMM_PSEUDO:
3401 case AArch64::ST1W_4Z_IMM_PSEUDO:
3402 case AArch64::ST1D_4Z_IMM_PSEUDO:
3403 case AArch64::STNT1B_4Z_IMM_PSEUDO:
3404 case AArch64::STNT1H_4Z_IMM_PSEUDO:
3405 case AArch64::STNT1W_4Z_IMM_PSEUDO:
3406 case AArch64::STNT1D_4Z_IMM_PSEUDO:
3408 case AArch64::LDPDpost:
3409 case AArch64::LDPDpre:
3410 case AArch64::LDPQpost:
3411 case AArch64::LDPQpre:
3412 case AArch64::LDPSpost:
3413 case AArch64::LDPSpre:
3414 case AArch64::LDPWpost:
3415 case AArch64::LDPWpre:
3416 case AArch64::LDPXpost:
3417 case AArch64::LDPXpre:
3418 case AArch64::STGPpre:
3419 case AArch64::STGPpost:
3420 case AArch64::STPDpost:
3421 case AArch64::STPDpre:
3422 case AArch64::STPQpost:
3423 case AArch64::STPQpre:
3424 case AArch64::STPSpost:
3425 case AArch64::STPSpre:
3426 case AArch64::STPWpost:
3427 case AArch64::STPWpre:
3428 case AArch64::STPXpost:
3429 case AArch64::STPXpre:
3435 switch (
MI.getOpcode()) {
3439 case AArch64::STRSui:
3440 case AArch64::STRDui:
3441 case AArch64::STRQui:
3442 case AArch64::STRXui:
3443 case AArch64::STRWui:
3444 case AArch64::LDRSui:
3445 case AArch64::LDRDui:
3446 case AArch64::LDRQui:
3447 case AArch64::LDRXui:
3448 case AArch64::LDRWui:
3449 case AArch64::LDRSWui:
3451 case AArch64::STURSi:
3452 case AArch64::STRSpre:
3453 case AArch64::STURDi:
3454 case AArch64::STRDpre:
3455 case AArch64::STURQi:
3456 case AArch64::STRQpre:
3457 case AArch64::STURWi:
3458 case AArch64::STRWpre:
3459 case AArch64::STURXi:
3460 case AArch64::STRXpre:
3461 case AArch64::LDURSi:
3462 case AArch64::LDRSpre:
3463 case AArch64::LDURDi:
3464 case AArch64::LDRDpre:
3465 case AArch64::LDURQi:
3466 case AArch64::LDRQpre:
3467 case AArch64::LDURWi:
3468 case AArch64::LDRWpre:
3469 case AArch64::LDURXi:
3470 case AArch64::LDRXpre:
3471 case AArch64::LDURSWi:
3472 case AArch64::LDRSWpre:
3474 case AArch64::LDR_ZXI:
3475 case AArch64::STR_ZXI:
3481 switch (
MI.getOpcode()) {
3484 "Unexpected instruction - was a new tail call opcode introduced?");
3486 case AArch64::TCRETURNdi:
3487 case AArch64::TCRETURNri:
3488 case AArch64::TCRETURNrix16x17:
3489 case AArch64::TCRETURNrix17:
3490 case AArch64::TCRETURNrinotx16:
3491 case AArch64::TCRETURNriALL:
3492 case AArch64::AUTH_TCRETURN:
3493 case AArch64::AUTH_TCRETURN_BTI:
3503 case AArch64::ADDWri:
3504 return AArch64::ADDSWri;
3505 case AArch64::ADDWrr:
3506 return AArch64::ADDSWrr;
3507 case AArch64::ADDWrs:
3508 return AArch64::ADDSWrs;
3509 case AArch64::ADDWrx:
3510 return AArch64::ADDSWrx;
3511 case AArch64::ANDWri:
3512 return AArch64::ANDSWri;
3513 case AArch64::ANDWrr:
3514 return AArch64::ANDSWrr;
3515 case AArch64::ANDWrs:
3516 return AArch64::ANDSWrs;
3517 case AArch64::BICWrr:
3518 return AArch64::BICSWrr;
3519 case AArch64::BICWrs:
3520 return AArch64::BICSWrs;
3521 case AArch64::SUBWri:
3522 return AArch64::SUBSWri;
3523 case AArch64::SUBWrr:
3524 return AArch64::SUBSWrr;
3525 case AArch64::SUBWrs:
3526 return AArch64::SUBSWrs;
3527 case AArch64::SUBWrx:
3528 return AArch64::SUBSWrx;
3530 case AArch64::ADDXri:
3531 return AArch64::ADDSXri;
3532 case AArch64::ADDXrr:
3533 return AArch64::ADDSXrr;
3534 case AArch64::ADDXrs:
3535 return AArch64::ADDSXrs;
3536 case AArch64::ADDXrx:
3537 return AArch64::ADDSXrx;
3538 case AArch64::ANDXri:
3539 return AArch64::ANDSXri;
3540 case AArch64::ANDXrr:
3541 return AArch64::ANDSXrr;
3542 case AArch64::ANDXrs:
3543 return AArch64::ANDSXrs;
3544 case AArch64::BICXrr:
3545 return AArch64::BICSXrr;
3546 case AArch64::BICXrs:
3547 return AArch64::BICSXrs;
3548 case AArch64::SUBXri:
3549 return AArch64::SUBSXri;
3550 case AArch64::SUBXrr:
3551 return AArch64::SUBSXrr;
3552 case AArch64::SUBXrs:
3553 return AArch64::SUBSXrs;
3554 case AArch64::SUBXrx:
3555 return AArch64::SUBSXrx;
3557 case AArch64::AND_PPzPP:
3558 return AArch64::ANDS_PPzPP;
3559 case AArch64::BIC_PPzPP:
3560 return AArch64::BICS_PPzPP;
3561 case AArch64::EOR_PPzPP:
3562 return AArch64::EORS_PPzPP;
3563 case AArch64::NAND_PPzPP:
3564 return AArch64::NANDS_PPzPP;
3565 case AArch64::NOR_PPzPP:
3566 return AArch64::NORS_PPzPP;
3567 case AArch64::ORN_PPzPP:
3568 return AArch64::ORNS_PPzPP;
3569 case AArch64::ORR_PPzPP:
3570 return AArch64::ORRS_PPzPP;
3571 case AArch64::BRKA_PPzP:
3572 return AArch64::BRKAS_PPzP;
3573 case AArch64::BRKPA_PPzPP:
3574 return AArch64::BRKPAS_PPzPP;
3575 case AArch64::BRKB_PPzP:
3576 return AArch64::BRKBS_PPzP;
3577 case AArch64::BRKPB_PPzPP:
3578 return AArch64::BRKPBS_PPzPP;
3579 case AArch64::BRKN_PPzP:
3580 return AArch64::BRKNS_PPzP;
3581 case AArch64::RDFFR_PPz:
3582 return AArch64::RDFFRS_PPz;
3583 case AArch64::PTRUE_B:
3584 return AArch64::PTRUES_B;
3595 if (
MI.hasOrderedMemoryRef())
3600 assert((
MI.getOperand(IsPreLdSt ? 2 : 1).isReg() ||
3601 MI.getOperand(IsPreLdSt ? 2 : 1).isFI()) &&
3602 "Expected a reg or frame index operand.");
3606 bool IsImmPreLdSt = IsPreLdSt &&
MI.getOperand(3).isImm();
3608 if (!
MI.getOperand(2).isImm() && !IsImmPreLdSt)
3621 if (
MI.getOperand(1).isReg() && !IsPreLdSt) {
3622 Register BaseReg =
MI.getOperand(1).getReg();
3624 if (
MI.modifiesRegister(BaseReg,
TRI))
3630 switch (
MI.getOpcode()) {
3633 case AArch64::LDR_ZXI:
3634 case AArch64::STR_ZXI:
3635 if (!Subtarget.isLittleEndian() ||
3636 Subtarget.getSVEVectorSizeInBits() != 128)
3649 const MCAsmInfo &MAI =
MI.getMF()->getTarget().getMCAsmInfo();
3657 if (Subtarget.isPaired128Slow()) {
3658 switch (
MI.getOpcode()) {
3661 case AArch64::LDURQi:
3662 case AArch64::STURQi:
3663 case AArch64::LDRQui:
3664 case AArch64::STRQui:
3691std::optional<ExtAddrMode>
3696 bool OffsetIsScalable;
3697 if (!getMemOperandWithOffset(MemI,
Base,
Offset, OffsetIsScalable,
TRI))
3698 return std::nullopt;
3701 return std::nullopt;
3716 int64_t OffsetScale = 1;
3721 case AArch64::LDURQi:
3722 case AArch64::STURQi:
3726 case AArch64::LDURDi:
3727 case AArch64::STURDi:
3728 case AArch64::LDURXi:
3729 case AArch64::STURXi:
3733 case AArch64::LDURWi:
3734 case AArch64::LDURSWi:
3735 case AArch64::STURWi:
3739 case AArch64::LDURHi:
3740 case AArch64::STURHi:
3741 case AArch64::LDURHHi:
3742 case AArch64::STURHHi:
3743 case AArch64::LDURSHXi:
3744 case AArch64::LDURSHWi:
3748 case AArch64::LDRBroX:
3749 case AArch64::LDRBBroX:
3750 case AArch64::LDRSBXroX:
3751 case AArch64::LDRSBWroX:
3752 case AArch64::STRBroX:
3753 case AArch64::STRBBroX:
3754 case AArch64::LDURBi:
3755 case AArch64::LDURBBi:
3756 case AArch64::LDURSBXi:
3757 case AArch64::LDURSBWi:
3758 case AArch64::STURBi:
3759 case AArch64::STURBBi:
3760 case AArch64::LDRBui:
3761 case AArch64::LDRBBui:
3762 case AArch64::LDRSBXui:
3763 case AArch64::LDRSBWui:
3764 case AArch64::STRBui:
3765 case AArch64::STRBBui:
3769 case AArch64::LDRQroX:
3770 case AArch64::STRQroX:
3771 case AArch64::LDRQui:
3772 case AArch64::STRQui:
3777 case AArch64::LDRDroX:
3778 case AArch64::STRDroX:
3779 case AArch64::LDRXroX:
3780 case AArch64::STRXroX:
3781 case AArch64::LDRDui:
3782 case AArch64::STRDui:
3783 case AArch64::LDRXui:
3784 case AArch64::STRXui:
3789 case AArch64::LDRWroX:
3790 case AArch64::LDRSWroX:
3791 case AArch64::STRWroX:
3792 case AArch64::LDRWui:
3793 case AArch64::LDRSWui:
3794 case AArch64::STRWui:
3799 case AArch64::LDRHroX:
3800 case AArch64::STRHroX:
3801 case AArch64::LDRHHroX:
3802 case AArch64::STRHHroX:
3803 case AArch64::LDRSHXroX:
3804 case AArch64::LDRSHWroX:
3805 case AArch64::LDRHui:
3806 case AArch64::STRHui:
3807 case AArch64::LDRHHui:
3808 case AArch64::STRHHui:
3809 case AArch64::LDRSHXui:
3810 case AArch64::LDRSHWui:
3818 if (BaseRegOp.
isReg() && BaseRegOp.
getReg() == Reg)
3842 case AArch64::SBFMXri:
3855 AM.
Scale = OffsetScale;
3860 case TargetOpcode::SUBREG_TO_REG: {
3876 if (
DefMI.getOpcode() != AArch64::ORRWrs ||
3877 DefMI.getOperand(1).getReg() != AArch64::WZR ||
3878 DefMI.getOperand(3).getImm() != 0)
3885 AM.
Scale = OffsetScale;
3896 auto validateOffsetForLDP = [](
unsigned NumBytes, int64_t OldOffset,
3897 int64_t NewOffset) ->
bool {
3898 int64_t MinOffset, MaxOffset;
3915 return OldOffset < MinOffset || OldOffset > MaxOffset ||
3916 (NewOffset >= MinOffset && NewOffset <= MaxOffset);
3918 auto canFoldAddSubImmIntoAddrMode = [&](int64_t Disp) ->
bool {
3920 int64_t NewOffset = OldOffset + Disp;
3921 if (!isLegalAddressingMode(NumBytes, NewOffset, 0))
3925 if (!validateOffsetForLDP(NumBytes, OldOffset, NewOffset))
3935 auto canFoldAddRegIntoAddrMode =
3940 if ((
unsigned)Scale != Scale)
3942 if (!isLegalAddressingMode(NumBytes, 0, Scale))
3954 return (Opcode == AArch64::STURQi || Opcode == AArch64::STRQui) &&
3955 Subtarget.isSTRQroSlow();
3964 case AArch64::ADDXri:
3970 return canFoldAddSubImmIntoAddrMode(Disp);
3972 case AArch64::SUBXri:
3978 return canFoldAddSubImmIntoAddrMode(-Disp);
3980 case AArch64::ADDXrs: {
3993 if (Shift != 2 && Shift != 3 && Subtarget.hasAddrLSLSlow14())
3995 if (avoidSlowSTRQ(MemI))
3998 return canFoldAddRegIntoAddrMode(1ULL << Shift);
4001 case AArch64::ADDXrr:
4009 if (!OptSize && avoidSlowSTRQ(MemI))
4011 return canFoldAddRegIntoAddrMode(1);
4013 case AArch64::ADDXrx:
4021 if (!OptSize && avoidSlowSTRQ(MemI))
4030 return canFoldAddRegIntoAddrMode(
4045 case AArch64::LDURQi:
4046 case AArch64::LDRQui:
4047 return AArch64::LDRQroX;
4048 case AArch64::STURQi:
4049 case AArch64::STRQui:
4050 return AArch64::STRQroX;
4051 case AArch64::LDURDi:
4052 case AArch64::LDRDui:
4053 return AArch64::LDRDroX;
4054 case AArch64::STURDi:
4055 case AArch64::STRDui:
4056 return AArch64::STRDroX;
4057 case AArch64::LDURXi:
4058 case AArch64::LDRXui:
4059 return AArch64::LDRXroX;
4060 case AArch64::STURXi:
4061 case AArch64::STRXui:
4062 return AArch64::STRXroX;
4063 case AArch64::LDURWi:
4064 case AArch64::LDRWui:
4065 return AArch64::LDRWroX;
4066 case AArch64::LDURSWi:
4067 case AArch64::LDRSWui:
4068 return AArch64::LDRSWroX;
4069 case AArch64::STURWi:
4070 case AArch64::STRWui:
4071 return AArch64::STRWroX;
4072 case AArch64::LDURHi:
4073 case AArch64::LDRHui:
4074 return AArch64::LDRHroX;
4075 case AArch64::STURHi:
4076 case AArch64::STRHui:
4077 return AArch64::STRHroX;
4078 case AArch64::LDURHHi:
4079 case AArch64::LDRHHui:
4080 return AArch64::LDRHHroX;
4081 case AArch64::STURHHi:
4082 case AArch64::STRHHui:
4083 return AArch64::STRHHroX;
4084 case AArch64::LDURSHXi:
4085 case AArch64::LDRSHXui:
4086 return AArch64::LDRSHXroX;
4087 case AArch64::LDURSHWi:
4088 case AArch64::LDRSHWui:
4089 return AArch64::LDRSHWroX;
4090 case AArch64::LDURBi:
4091 case AArch64::LDRBui:
4092 return AArch64::LDRBroX;
4093 case AArch64::LDURBBi:
4094 case AArch64::LDRBBui:
4095 return AArch64::LDRBBroX;
4096 case AArch64::LDURSBXi:
4097 case AArch64::LDRSBXui:
4098 return AArch64::LDRSBXroX;
4099 case AArch64::LDURSBWi:
4100 case AArch64::LDRSBWui:
4101 return AArch64::LDRSBWroX;
4102 case AArch64::STURBi:
4103 case AArch64::STRBui:
4104 return AArch64::STRBroX;
4105 case AArch64::STURBBi:
4106 case AArch64::STRBBui:
4107 return AArch64::STRBBroX;
4119 case AArch64::LDURQi:
4121 return AArch64::LDRQui;
4122 case AArch64::STURQi:
4124 return AArch64::STRQui;
4125 case AArch64::LDURDi:
4127 return AArch64::LDRDui;
4128 case AArch64::STURDi:
4130 return AArch64::STRDui;
4131 case AArch64::LDURXi:
4133 return AArch64::LDRXui;
4134 case AArch64::STURXi:
4136 return AArch64::STRXui;
4137 case AArch64::LDURWi:
4139 return AArch64::LDRWui;
4140 case AArch64::LDURSWi:
4142 return AArch64::LDRSWui;
4143 case AArch64::STURWi:
4145 return AArch64::STRWui;
4146 case AArch64::LDURHi:
4148 return AArch64::LDRHui;
4149 case AArch64::STURHi:
4151 return AArch64::STRHui;
4152 case AArch64::LDURHHi:
4154 return AArch64::LDRHHui;
4155 case AArch64::STURHHi:
4157 return AArch64::STRHHui;
4158 case AArch64::LDURSHXi:
4160 return AArch64::LDRSHXui;
4161 case AArch64::LDURSHWi:
4163 return AArch64::LDRSHWui;
4164 case AArch64::LDURBi:
4166 return AArch64::LDRBui;
4167 case AArch64::LDURBBi:
4169 return AArch64::LDRBBui;
4170 case AArch64::LDURSBXi:
4172 return AArch64::LDRSBXui;
4173 case AArch64::LDURSBWi:
4175 return AArch64::LDRSBWui;
4176 case AArch64::STURBi:
4178 return AArch64::STRBui;
4179 case AArch64::STURBBi:
4181 return AArch64::STRBBui;
4182 case AArch64::LDRQui:
4183 case AArch64::STRQui:
4186 case AArch64::LDRDui:
4187 case AArch64::STRDui:
4188 case AArch64::LDRXui:
4189 case AArch64::STRXui:
4192 case AArch64::LDRWui:
4193 case AArch64::LDRSWui:
4194 case AArch64::STRWui:
4197 case AArch64::LDRHui:
4198 case AArch64::STRHui:
4199 case AArch64::LDRHHui:
4200 case AArch64::STRHHui:
4201 case AArch64::LDRSHXui:
4202 case AArch64::LDRSHWui:
4205 case AArch64::LDRBui:
4206 case AArch64::LDRBBui:
4207 case AArch64::LDRSBXui:
4208 case AArch64::LDRSBWui:
4209 case AArch64::STRBui:
4210 case AArch64::STRBBui:
4224 case AArch64::LDURQi:
4225 case AArch64::STURQi:
4226 case AArch64::LDURDi:
4227 case AArch64::STURDi:
4228 case AArch64::LDURXi:
4229 case AArch64::STURXi:
4230 case AArch64::LDURWi:
4231 case AArch64::LDURSWi:
4232 case AArch64::STURWi:
4233 case AArch64::LDURHi:
4234 case AArch64::STURHi:
4235 case AArch64::LDURHHi:
4236 case AArch64::STURHHi:
4237 case AArch64::LDURSHXi:
4238 case AArch64::LDURSHWi:
4239 case AArch64::LDURBi:
4240 case AArch64::STURBi:
4241 case AArch64::LDURBBi:
4242 case AArch64::STURBBi:
4243 case AArch64::LDURSBWi:
4244 case AArch64::LDURSBXi:
4246 case AArch64::LDRQui:
4247 return AArch64::LDURQi;
4248 case AArch64::STRQui:
4249 return AArch64::STURQi;
4250 case AArch64::LDRDui:
4251 return AArch64::LDURDi;
4252 case AArch64::STRDui:
4253 return AArch64::STURDi;
4254 case AArch64::LDRXui:
4255 return AArch64::LDURXi;
4256 case AArch64::STRXui:
4257 return AArch64::STURXi;
4258 case AArch64::LDRWui:
4259 return AArch64::LDURWi;
4260 case AArch64::LDRSWui:
4261 return AArch64::LDURSWi;
4262 case AArch64::STRWui:
4263 return AArch64::STURWi;
4264 case AArch64::LDRHui:
4265 return AArch64::LDURHi;
4266 case AArch64::STRHui:
4267 return AArch64::STURHi;
4268 case AArch64::LDRHHui:
4269 return AArch64::LDURHHi;
4270 case AArch64::STRHHui:
4271 return AArch64::STURHHi;
4272 case AArch64::LDRSHXui:
4273 return AArch64::LDURSHXi;
4274 case AArch64::LDRSHWui:
4275 return AArch64::LDURSHWi;
4276 case AArch64::LDRBBui:
4277 return AArch64::LDURBBi;
4278 case AArch64::LDRBui:
4279 return AArch64::LDURBi;
4280 case AArch64::STRBBui:
4281 return AArch64::STURBBi;
4282 case AArch64::STRBui:
4283 return AArch64::STURBi;
4284 case AArch64::LDRSBWui:
4285 return AArch64::LDURSBWi;
4286 case AArch64::LDRSBXui:
4287 return AArch64::LDURSBXi;
4300 case AArch64::LDRQroX:
4301 case AArch64::LDURQi:
4302 case AArch64::LDRQui:
4303 return AArch64::LDRQroW;
4304 case AArch64::STRQroX:
4305 case AArch64::STURQi:
4306 case AArch64::STRQui:
4307 return AArch64::STRQroW;
4308 case AArch64::LDRDroX:
4309 case AArch64::LDURDi:
4310 case AArch64::LDRDui:
4311 return AArch64::LDRDroW;
4312 case AArch64::STRDroX:
4313 case AArch64::STURDi:
4314 case AArch64::STRDui:
4315 return AArch64::STRDroW;
4316 case AArch64::LDRXroX:
4317 case AArch64::LDURXi:
4318 case AArch64::LDRXui:
4319 return AArch64::LDRXroW;
4320 case AArch64::STRXroX:
4321 case AArch64::STURXi:
4322 case AArch64::STRXui:
4323 return AArch64::STRXroW;
4324 case AArch64::LDRWroX:
4325 case AArch64::LDURWi:
4326 case AArch64::LDRWui:
4327 return AArch64::LDRWroW;
4328 case AArch64::LDRSWroX:
4329 case AArch64::LDURSWi:
4330 case AArch64::LDRSWui:
4331 return AArch64::LDRSWroW;
4332 case AArch64::STRWroX:
4333 case AArch64::STURWi:
4334 case AArch64::STRWui:
4335 return AArch64::STRWroW;
4336 case AArch64::LDRHroX:
4337 case AArch64::LDURHi:
4338 case AArch64::LDRHui:
4339 return AArch64::LDRHroW;
4340 case AArch64::STRHroX:
4341 case AArch64::STURHi:
4342 case AArch64::STRHui:
4343 return AArch64::STRHroW;
4344 case AArch64::LDRHHroX:
4345 case AArch64::LDURHHi:
4346 case AArch64::LDRHHui:
4347 return AArch64::LDRHHroW;
4348 case AArch64::STRHHroX:
4349 case AArch64::STURHHi:
4350 case AArch64::STRHHui:
4351 return AArch64::STRHHroW;
4352 case AArch64::LDRSHXroX:
4353 case AArch64::LDURSHXi:
4354 case AArch64::LDRSHXui:
4355 return AArch64::LDRSHXroW;
4356 case AArch64::LDRSHWroX:
4357 case AArch64::LDURSHWi:
4358 case AArch64::LDRSHWui:
4359 return AArch64::LDRSHWroW;
4360 case AArch64::LDRBroX:
4361 case AArch64::LDURBi:
4362 case AArch64::LDRBui:
4363 return AArch64::LDRBroW;
4364 case AArch64::LDRBBroX:
4365 case AArch64::LDURBBi:
4366 case AArch64::LDRBBui:
4367 return AArch64::LDRBBroW;
4368 case AArch64::LDRSBXroX:
4369 case AArch64::LDURSBXi:
4370 case AArch64::LDRSBXui:
4371 return AArch64::LDRSBXroW;
4372 case AArch64::LDRSBWroX:
4373 case AArch64::LDURSBWi:
4374 case AArch64::LDRSBWui:
4375 return AArch64::LDRSBWroW;
4376 case AArch64::STRBroX:
4377 case AArch64::STURBi:
4378 case AArch64::STRBui:
4379 return AArch64::STRBroW;
4380 case AArch64::STRBBroX:
4381 case AArch64::STURBBi:
4382 case AArch64::STRBBui:
4383 return AArch64::STRBBroW;
4408 return B.getInstr();
4412 "Addressing mode not supported for folding");
4429 return B.getInstr();
4436 "Address offset can be a register or an immediate, but not both");
4457 return B.getInstr();
4461 "Function must not be called with an addressing mode it can't handle");
4470 case AArch64::LD1Fourv16b_POST:
4471 case AArch64::LD1Fourv1d_POST:
4472 case AArch64::LD1Fourv2d_POST:
4473 case AArch64::LD1Fourv2s_POST:
4474 case AArch64::LD1Fourv4h_POST:
4475 case AArch64::LD1Fourv4s_POST:
4476 case AArch64::LD1Fourv8b_POST:
4477 case AArch64::LD1Fourv8h_POST:
4478 case AArch64::LD1Onev16b_POST:
4479 case AArch64::LD1Onev1d_POST:
4480 case AArch64::LD1Onev2d_POST:
4481 case AArch64::LD1Onev2s_POST:
4482 case AArch64::LD1Onev4h_POST:
4483 case AArch64::LD1Onev4s_POST:
4484 case AArch64::LD1Onev8b_POST:
4485 case AArch64::LD1Onev8h_POST:
4486 case AArch64::LD1Rv16b_POST:
4487 case AArch64::LD1Rv1d_POST:
4488 case AArch64::LD1Rv2d_POST:
4489 case AArch64::LD1Rv2s_POST:
4490 case AArch64::LD1Rv4h_POST:
4491 case AArch64::LD1Rv4s_POST:
4492 case AArch64::LD1Rv8b_POST:
4493 case AArch64::LD1Rv8h_POST:
4494 case AArch64::LD1Threev16b_POST:
4495 case AArch64::LD1Threev1d_POST:
4496 case AArch64::LD1Threev2d_POST:
4497 case AArch64::LD1Threev2s_POST:
4498 case AArch64::LD1Threev4h_POST:
4499 case AArch64::LD1Threev4s_POST:
4500 case AArch64::LD1Threev8b_POST:
4501 case AArch64::LD1Threev8h_POST:
4502 case AArch64::LD1Twov16b_POST:
4503 case AArch64::LD1Twov1d_POST:
4504 case AArch64::LD1Twov2d_POST:
4505 case AArch64::LD1Twov2s_POST:
4506 case AArch64::LD1Twov4h_POST:
4507 case AArch64::LD1Twov4s_POST:
4508 case AArch64::LD1Twov8b_POST:
4509 case AArch64::LD1Twov8h_POST:
4510 case AArch64::LD1i16_POST:
4511 case AArch64::LD1i32_POST:
4512 case AArch64::LD1i64_POST:
4513 case AArch64::LD1i8_POST:
4514 case AArch64::LD2Rv16b_POST:
4515 case AArch64::LD2Rv1d_POST:
4516 case AArch64::LD2Rv2d_POST:
4517 case AArch64::LD2Rv2s_POST:
4518 case AArch64::LD2Rv4h_POST:
4519 case AArch64::LD2Rv4s_POST:
4520 case AArch64::LD2Rv8b_POST:
4521 case AArch64::LD2Rv8h_POST:
4522 case AArch64::LD2Twov16b_POST:
4523 case AArch64::LD2Twov2d_POST:
4524 case AArch64::LD2Twov2s_POST:
4525 case AArch64::LD2Twov4h_POST:
4526 case AArch64::LD2Twov4s_POST:
4527 case AArch64::LD2Twov8b_POST:
4528 case AArch64::LD2Twov8h_POST:
4529 case AArch64::LD2i16_POST:
4530 case AArch64::LD2i32_POST:
4531 case AArch64::LD2i64_POST:
4532 case AArch64::LD2i8_POST:
4533 case AArch64::LD3Rv16b_POST:
4534 case AArch64::LD3Rv1d_POST:
4535 case AArch64::LD3Rv2d_POST:
4536 case AArch64::LD3Rv2s_POST:
4537 case AArch64::LD3Rv4h_POST:
4538 case AArch64::LD3Rv4s_POST:
4539 case AArch64::LD3Rv8b_POST:
4540 case AArch64::LD3Rv8h_POST:
4541 case AArch64::LD3Threev16b_POST:
4542 case AArch64::LD3Threev2d_POST:
4543 case AArch64::LD3Threev2s_POST:
4544 case AArch64::LD3Threev4h_POST:
4545 case AArch64::LD3Threev4s_POST:
4546 case AArch64::LD3Threev8b_POST:
4547 case AArch64::LD3Threev8h_POST:
4548 case AArch64::LD3i16_POST:
4549 case AArch64::LD3i32_POST:
4550 case AArch64::LD3i64_POST:
4551 case AArch64::LD3i8_POST:
4552 case AArch64::LD4Fourv16b_POST:
4553 case AArch64::LD4Fourv2d_POST:
4554 case AArch64::LD4Fourv2s_POST:
4555 case AArch64::LD4Fourv4h_POST:
4556 case AArch64::LD4Fourv4s_POST:
4557 case AArch64::LD4Fourv8b_POST:
4558 case AArch64::LD4Fourv8h_POST:
4559 case AArch64::LD4Rv16b_POST:
4560 case AArch64::LD4Rv1d_POST:
4561 case AArch64::LD4Rv2d_POST:
4562 case AArch64::LD4Rv2s_POST:
4563 case AArch64::LD4Rv4h_POST:
4564 case AArch64::LD4Rv4s_POST:
4565 case AArch64::LD4Rv8b_POST:
4566 case AArch64::LD4Rv8h_POST:
4567 case AArch64::LD4i16_POST:
4568 case AArch64::LD4i32_POST:
4569 case AArch64::LD4i64_POST:
4570 case AArch64::LD4i8_POST:
4571 case AArch64::LDAPRWpost:
4572 case AArch64::LDAPRXpost:
4573 case AArch64::LDIAPPWpost:
4574 case AArch64::LDIAPPXpost:
4575 case AArch64::LDPDpost:
4576 case AArch64::LDPQpost:
4577 case AArch64::LDPSWpost:
4578 case AArch64::LDPSpost:
4579 case AArch64::LDPWpost:
4580 case AArch64::LDPXpost:
4581 case AArch64::LDRBBpost:
4582 case AArch64::LDRBpost:
4583 case AArch64::LDRDpost:
4584 case AArch64::LDRHHpost:
4585 case AArch64::LDRHpost:
4586 case AArch64::LDRQpost:
4587 case AArch64::LDRSBWpost:
4588 case AArch64::LDRSBXpost:
4589 case AArch64::LDRSHWpost:
4590 case AArch64::LDRSHXpost:
4591 case AArch64::LDRSWpost:
4592 case AArch64::LDRSpost:
4593 case AArch64::LDRWpost:
4594 case AArch64::LDRXpost:
4595 case AArch64::ST1Fourv16b_POST:
4596 case AArch64::ST1Fourv1d_POST:
4597 case AArch64::ST1Fourv2d_POST:
4598 case AArch64::ST1Fourv2s_POST:
4599 case AArch64::ST1Fourv4h_POST:
4600 case AArch64::ST1Fourv4s_POST:
4601 case AArch64::ST1Fourv8b_POST:
4602 case AArch64::ST1Fourv8h_POST:
4603 case AArch64::ST1Onev16b_POST:
4604 case AArch64::ST1Onev1d_POST:
4605 case AArch64::ST1Onev2d_POST:
4606 case AArch64::ST1Onev2s_POST:
4607 case AArch64::ST1Onev4h_POST:
4608 case AArch64::ST1Onev4s_POST:
4609 case AArch64::ST1Onev8b_POST:
4610 case AArch64::ST1Onev8h_POST:
4611 case AArch64::ST1Threev16b_POST:
4612 case AArch64::ST1Threev1d_POST:
4613 case AArch64::ST1Threev2d_POST:
4614 case AArch64::ST1Threev2s_POST:
4615 case AArch64::ST1Threev4h_POST:
4616 case AArch64::ST1Threev4s_POST:
4617 case AArch64::ST1Threev8b_POST:
4618 case AArch64::ST1Threev8h_POST:
4619 case AArch64::ST1Twov16b_POST:
4620 case AArch64::ST1Twov1d_POST:
4621 case AArch64::ST1Twov2d_POST:
4622 case AArch64::ST1Twov2s_POST:
4623 case AArch64::ST1Twov4h_POST:
4624 case AArch64::ST1Twov4s_POST:
4625 case AArch64::ST1Twov8b_POST:
4626 case AArch64::ST1Twov8h_POST:
4627 case AArch64::ST1i16_POST:
4628 case AArch64::ST1i32_POST:
4629 case AArch64::ST1i64_POST:
4630 case AArch64::ST1i8_POST:
4631 case AArch64::ST2GPostIndex:
4632 case AArch64::ST2Twov16b_POST:
4633 case AArch64::ST2Twov2d_POST:
4634 case AArch64::ST2Twov2s_POST:
4635 case AArch64::ST2Twov4h_POST:
4636 case AArch64::ST2Twov4s_POST:
4637 case AArch64::ST2Twov8b_POST:
4638 case AArch64::ST2Twov8h_POST:
4639 case AArch64::ST2i16_POST:
4640 case AArch64::ST2i32_POST:
4641 case AArch64::ST2i64_POST:
4642 case AArch64::ST2i8_POST:
4643 case AArch64::ST3Threev16b_POST:
4644 case AArch64::ST3Threev2d_POST:
4645 case AArch64::ST3Threev2s_POST:
4646 case AArch64::ST3Threev4h_POST:
4647 case AArch64::ST3Threev4s_POST:
4648 case AArch64::ST3Threev8b_POST:
4649 case AArch64::ST3Threev8h_POST:
4650 case AArch64::ST3i16_POST:
4651 case AArch64::ST3i32_POST:
4652 case AArch64::ST3i64_POST:
4653 case AArch64::ST3i8_POST:
4654 case AArch64::ST4Fourv16b_POST:
4655 case AArch64::ST4Fourv2d_POST:
4656 case AArch64::ST4Fourv2s_POST:
4657 case AArch64::ST4Fourv4h_POST:
4658 case AArch64::ST4Fourv4s_POST:
4659 case AArch64::ST4Fourv8b_POST:
4660 case AArch64::ST4Fourv8h_POST:
4661 case AArch64::ST4i16_POST:
4662 case AArch64::ST4i32_POST:
4663 case AArch64::ST4i64_POST:
4664 case AArch64::ST4i8_POST:
4665 case AArch64::STGPostIndex:
4666 case AArch64::STGPpost:
4667 case AArch64::STPDpost:
4668 case AArch64::STPQpost:
4669 case AArch64::STPSpost:
4670 case AArch64::STPWpost:
4671 case AArch64::STPXpost:
4672 case AArch64::STRBBpost:
4673 case AArch64::STRBpost:
4674 case AArch64::STRDpost:
4675 case AArch64::STRHHpost:
4676 case AArch64::STRHpost:
4677 case AArch64::STRQpost:
4678 case AArch64::STRSpost:
4679 case AArch64::STRWpost:
4680 case AArch64::STRXpost:
4681 case AArch64::STZ2GPostIndex:
4682 case AArch64::STZGPostIndex:
4689 bool &OffsetIsScalable,
TypeSize &Width,
4710 int64_t Dummy1, Dummy2;
4732 return BaseOp->
isReg() || BaseOp->
isFI();
4739 assert(OfsOp.
isImm() &&
"Offset operand wasn't immediate.");
4744 TypeSize &Width, int64_t &MinOffset,
4745 int64_t &MaxOffset) {
4750 MinOffset = MaxOffset = 0;
4753 case AArch64::LDRQui:
4754 case AArch64::STRQui:
4759 case AArch64::LDRXui:
4760 case AArch64::LDRDui:
4761 case AArch64::STRXui:
4762 case AArch64::STRDui:
4763 case AArch64::PRFMui:
4768 case AArch64::LDRWui:
4769 case AArch64::LDRSui:
4770 case AArch64::LDRSWui:
4771 case AArch64::STRWui:
4772 case AArch64::STRSui:
4777 case AArch64::LDRHui:
4778 case AArch64::LDRHHui:
4779 case AArch64::LDRSHWui:
4780 case AArch64::LDRSHXui:
4781 case AArch64::STRHui:
4782 case AArch64::STRHHui:
4787 case AArch64::LDRBui:
4788 case AArch64::LDRBBui:
4789 case AArch64::LDRSBWui:
4790 case AArch64::LDRSBXui:
4791 case AArch64::STRBui:
4792 case AArch64::STRBBui:
4798 case AArch64::STRQpre:
4799 case AArch64::LDRQpost:
4805 case AArch64::LDRDpost:
4806 case AArch64::LDRDpre:
4807 case AArch64::LDRXpost:
4808 case AArch64::LDRXpre:
4809 case AArch64::STRDpost:
4810 case AArch64::STRDpre:
4811 case AArch64::STRXpost:
4812 case AArch64::STRXpre:
4818 case AArch64::STRWpost:
4819 case AArch64::STRWpre:
4820 case AArch64::LDRWpost:
4821 case AArch64::LDRWpre:
4822 case AArch64::STRSpost:
4823 case AArch64::STRSpre:
4824 case AArch64::LDRSpost:
4825 case AArch64::LDRSpre:
4831 case AArch64::LDRHpost:
4832 case AArch64::LDRHpre:
4833 case AArch64::STRHpost:
4834 case AArch64::STRHpre:
4835 case AArch64::LDRHHpost:
4836 case AArch64::LDRHHpre:
4837 case AArch64::STRHHpost:
4838 case AArch64::STRHHpre:
4844 case AArch64::LDRBpost:
4845 case AArch64::LDRBpre:
4846 case AArch64::STRBpost:
4847 case AArch64::STRBpre:
4848 case AArch64::LDRBBpost:
4849 case AArch64::LDRBBpre:
4850 case AArch64::STRBBpost:
4851 case AArch64::STRBBpre:
4857 case AArch64::LDURQi:
4858 case AArch64::STURQi:
4864 case AArch64::LDURXi:
4865 case AArch64::LDURDi:
4866 case AArch64::LDAPURXi:
4867 case AArch64::STURXi:
4868 case AArch64::STURDi:
4869 case AArch64::STLURXi:
4870 case AArch64::PRFUMi:
4876 case AArch64::LDURWi:
4877 case AArch64::LDURSi:
4878 case AArch64::LDURSWi:
4879 case AArch64::LDAPURi:
4880 case AArch64::LDAPURSWi:
4881 case AArch64::STURWi:
4882 case AArch64::STURSi:
4883 case AArch64::STLURWi:
4889 case AArch64::LDURHi:
4890 case AArch64::LDURHHi:
4891 case AArch64::LDURSHXi:
4892 case AArch64::LDURSHWi:
4893 case AArch64::LDAPURHi:
4894 case AArch64::LDAPURSHWi:
4895 case AArch64::LDAPURSHXi:
4896 case AArch64::STURHi:
4897 case AArch64::STURHHi:
4898 case AArch64::STLURHi:
4904 case AArch64::LDURBi:
4905 case AArch64::LDURBBi:
4906 case AArch64::LDURSBXi:
4907 case AArch64::LDURSBWi:
4908 case AArch64::LDAPURBi:
4909 case AArch64::LDAPURSBWi:
4910 case AArch64::LDAPURSBXi:
4911 case AArch64::STURBi:
4912 case AArch64::STURBBi:
4913 case AArch64::STLURBi:
4919 case AArch64::LDPQi:
4920 case AArch64::LDNPQi:
4921 case AArch64::STPQi:
4922 case AArch64::STNPQi:
4923 case AArch64::LDPQpost:
4924 case AArch64::LDPQpre:
4925 case AArch64::STPQpost:
4926 case AArch64::STPQpre:
4932 case AArch64::LDPXi:
4933 case AArch64::LDPDi:
4934 case AArch64::LDNPXi:
4935 case AArch64::LDNPDi:
4936 case AArch64::STPXi:
4937 case AArch64::STPDi:
4938 case AArch64::STNPXi:
4939 case AArch64::STNPDi:
4940 case AArch64::LDPDpost:
4941 case AArch64::LDPDpre:
4942 case AArch64::LDPXpost:
4943 case AArch64::LDPXpre:
4944 case AArch64::STPDpost:
4945 case AArch64::STPDpre:
4946 case AArch64::STPXpost:
4947 case AArch64::STPXpre:
4953 case AArch64::LDPWi:
4954 case AArch64::LDPSi:
4955 case AArch64::LDNPWi:
4956 case AArch64::LDNPSi:
4957 case AArch64::STPWi:
4958 case AArch64::STPSi:
4959 case AArch64::STNPWi:
4960 case AArch64::STNPSi:
4961 case AArch64::LDPSpost:
4962 case AArch64::LDPSpre:
4963 case AArch64::LDPWpost:
4964 case AArch64::LDPWpre:
4965 case AArch64::STPSpost:
4966 case AArch64::STPSpre:
4967 case AArch64::STPWpost:
4968 case AArch64::STPWpre:
4974 case AArch64::StoreSwiftAsyncContext:
4987 case AArch64::TAGPstack:
4997 case AArch64::STGPreIndex:
4998 case AArch64::STGPostIndex:
4999 case AArch64::STZGi:
5000 case AArch64::STZGPreIndex:
5001 case AArch64::STZGPostIndex:
5007 case AArch64::STR_ZZZZXI:
5008 case AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS:
5009 case AArch64::LDR_ZZZZXI:
5010 case AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS:
5016 case AArch64::STR_ZZZXI:
5017 case AArch64::LDR_ZZZXI:
5023 case AArch64::STR_ZZXI:
5024 case AArch64::STR_ZZXI_STRIDED_CONTIGUOUS:
5025 case AArch64::LDR_ZZXI:
5026 case AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS:
5032 case AArch64::LDR_PXI:
5033 case AArch64::STR_PXI:
5038 case AArch64::LDR_PPXI:
5039 case AArch64::STR_PPXI:
5045 case AArch64::LDR_ZXI:
5046 case AArch64::STR_ZXI:
5051 case AArch64::LD1B_IMM:
5052 case AArch64::LD1H_IMM:
5053 case AArch64::LD1W_IMM:
5054 case AArch64::LD1D_IMM:
5055 case AArch64::LDNT1B_ZRI:
5056 case AArch64::LDNT1H_ZRI:
5057 case AArch64::LDNT1W_ZRI:
5058 case AArch64::LDNT1D_ZRI:
5059 case AArch64::ST1B_IMM:
5060 case AArch64::ST1H_IMM:
5061 case AArch64::ST1W_IMM:
5062 case AArch64::ST1D_IMM:
5063 case AArch64::STNT1B_ZRI:
5064 case AArch64::STNT1H_ZRI:
5065 case AArch64::STNT1W_ZRI:
5066 case AArch64::STNT1D_ZRI:
5067 case AArch64::LDNF1B_IMM:
5068 case AArch64::LDNF1H_IMM:
5069 case AArch64::LDNF1W_IMM:
5070 case AArch64::LDNF1D_IMM:
5077 case AArch64::LD2B_IMM:
5078 case AArch64::LD2H_IMM:
5079 case AArch64::LD2W_IMM:
5080 case AArch64::LD2D_IMM:
5081 case AArch64::ST2B_IMM:
5082 case AArch64::ST2H_IMM:
5083 case AArch64::ST2W_IMM:
5084 case AArch64::ST2D_IMM:
5085 case AArch64::LD1B_2Z_IMM:
5086 case AArch64::LD1B_2Z_STRIDED_IMM:
5087 case AArch64::LD1H_2Z_IMM:
5088 case AArch64::LD1H_2Z_STRIDED_IMM:
5089 case AArch64::LD1W_2Z_IMM:
5090 case AArch64::LD1W_2Z_STRIDED_IMM:
5091 case AArch64::LD1D_2Z_IMM:
5092 case AArch64::LD1D_2Z_STRIDED_IMM:
5093 case AArch64::LD1B_2Z_IMM_PSEUDO:
5094 case AArch64::LD1H_2Z_IMM_PSEUDO:
5095 case AArch64::LD1W_2Z_IMM_PSEUDO:
5096 case AArch64::LD1D_2Z_IMM_PSEUDO:
5097 case AArch64::ST1B_2Z_IMM:
5098 case AArch64::ST1B_2Z_STRIDED_IMM:
5099 case AArch64::ST1H_2Z_IMM:
5100 case AArch64::ST1H_2Z_STRIDED_IMM:
5101 case AArch64::ST1W_2Z_IMM:
5102 case AArch64::ST1W_2Z_STRIDED_IMM:
5103 case AArch64::ST1D_2Z_IMM:
5104 case AArch64::ST1D_2Z_STRIDED_IMM:
5105 case AArch64::LDNT1B_2Z_IMM_PSEUDO:
5106 case AArch64::LDNT1B_2Z_IMM:
5107 case AArch64::LDNT1B_2Z_STRIDED_IMM:
5108 case AArch64::LDNT1H_2Z_IMM_PSEUDO:
5109 case AArch64::LDNT1H_2Z_IMM:
5110 case AArch64::LDNT1H_2Z_STRIDED_IMM:
5111 case AArch64::LDNT1W_2Z_IMM_PSEUDO:
5112 case AArch64::LDNT1W_2Z_IMM:
5113 case AArch64::LDNT1W_2Z_STRIDED_IMM:
5114 case AArch64::LDNT1D_2Z_IMM_PSEUDO:
5115 case AArch64::LDNT1D_2Z_IMM:
5116 case AArch64::LDNT1D_2Z_STRIDED_IMM:
5117 case AArch64::STNT1B_2Z_IMM:
5118 case AArch64::STNT1B_2Z_STRIDED_IMM:
5119 case AArch64::STNT1H_2Z_IMM:
5120 case AArch64::STNT1H_2Z_STRIDED_IMM:
5121 case AArch64::STNT1W_2Z_IMM:
5122 case AArch64::STNT1W_2Z_STRIDED_IMM:
5123 case AArch64::STNT1D_2Z_IMM:
5124 case AArch64::STNT1D_2Z_STRIDED_IMM:
5125 case AArch64::ST1B_2Z_IMM_PSEUDO:
5126 case AArch64::ST1H_2Z_IMM_PSEUDO:
5127 case AArch64::ST1W_2Z_IMM_PSEUDO:
5128 case AArch64::ST1D_2Z_IMM_PSEUDO:
5129 case AArch64::STNT1B_2Z_IMM_PSEUDO:
5130 case AArch64::STNT1H_2Z_IMM_PSEUDO:
5131 case AArch64::STNT1W_2Z_IMM_PSEUDO:
5132 case AArch64::STNT1D_2Z_IMM_PSEUDO:
5137 case AArch64::LD3B_IMM:
5138 case AArch64::LD3H_IMM:
5139 case AArch64::LD3W_IMM:
5140 case AArch64::LD3D_IMM:
5141 case AArch64::ST3B_IMM:
5142 case AArch64::ST3H_IMM:
5143 case AArch64::ST3W_IMM:
5144 case AArch64::ST3D_IMM:
5149 case AArch64::LD4B_IMM:
5150 case AArch64::LD4H_IMM:
5151 case AArch64::LD4W_IMM:
5152 case AArch64::LD4D_IMM:
5153 case AArch64::ST4B_IMM:
5154 case AArch64::ST4H_IMM:
5155 case AArch64::ST4W_IMM:
5156 case AArch64::ST4D_IMM:
5157 case AArch64::LD1B_4Z_IMM:
5158 case AArch64::LD1B_4Z_STRIDED_IMM:
5159 case AArch64::LD1H_4Z_IMM:
5160 case AArch64::LD1H_4Z_STRIDED_IMM:
5161 case AArch64::LD1W_4Z_IMM:
5162 case AArch64::LD1W_4Z_STRIDED_IMM:
5163 case AArch64::LD1D_4Z_IMM:
5164 case AArch64::LD1D_4Z_STRIDED_IMM:
5165 case AArch64::LD1B_4Z_IMM_PSEUDO:
5166 case AArch64::LD1H_4Z_IMM_PSEUDO:
5167 case AArch64::LD1W_4Z_IMM_PSEUDO:
5168 case AArch64::LD1D_4Z_IMM_PSEUDO:
5169 case AArch64::ST1B_4Z_IMM:
5170 case AArch64::ST1B_4Z_STRIDED_IMM:
5171 case AArch64::ST1H_4Z_IMM:
5172 case AArch64::ST1H_4Z_STRIDED_IMM:
5173 case AArch64::ST1W_4Z_IMM:
5174 case AArch64::ST1W_4Z_STRIDED_IMM:
5175 case AArch64::ST1D_4Z_IMM:
5176 case AArch64::ST1D_4Z_STRIDED_IMM:
5177 case AArch64::LDNT1B_4Z_IMM_PSEUDO:
5178 case AArch64::LDNT1B_4Z_IMM:
5179 case AArch64::LDNT1B_4Z_STRIDED_IMM:
5180 case AArch64::LDNT1H_4Z_IMM_PSEUDO:
5181 case AArch64::LDNT1H_4Z_IMM:
5182 case AArch64::LDNT1H_4Z_STRIDED_IMM:
5183 case AArch64::LDNT1W_4Z_IMM_PSEUDO:
5184 case AArch64::LDNT1W_4Z_IMM:
5185 case AArch64::LDNT1W_4Z_STRIDED_IMM:
5186 case AArch64::LDNT1D_4Z_IMM_PSEUDO:
5187 case AArch64::LDNT1D_4Z_IMM:
5188 case AArch64::LDNT1D_4Z_STRIDED_IMM:
5189 case AArch64::STNT1B_4Z_IMM:
5190 case AArch64::STNT1B_4Z_STRIDED_IMM:
5191 case AArch64::STNT1H_4Z_IMM:
5192 case AArch64::STNT1H_4Z_STRIDED_IMM:
5193 case AArch64::STNT1W_4Z_IMM:
5194 case AArch64::STNT1W_4Z_STRIDED_IMM:
5195 case AArch64::STNT1D_4Z_IMM:
5196 case AArch64::STNT1D_4Z_STRIDED_IMM:
5197 case AArch64::ST1B_4Z_IMM_PSEUDO:
5198 case AArch64::ST1H_4Z_IMM_PSEUDO:
5199 case AArch64::ST1W_4Z_IMM_PSEUDO:
5200 case AArch64::ST1D_4Z_IMM_PSEUDO:
5201 case AArch64::STNT1B_4Z_IMM_PSEUDO:
5202 case AArch64::STNT1H_4Z_IMM_PSEUDO:
5203 case AArch64::STNT1W_4Z_IMM_PSEUDO:
5204 case AArch64::STNT1D_4Z_IMM_PSEUDO:
5209 case AArch64::LD1B_H_IMM:
5210 case AArch64::LD1SB_H_IMM:
5211 case AArch64::LD1H_S_IMM:
5212 case AArch64::LD1SH_S_IMM:
5213 case AArch64::LD1W_D_IMM:
5214 case AArch64::LD1SW_D_IMM:
5215 case AArch64::ST1B_H_IMM:
5216 case AArch64::ST1H_S_IMM:
5217 case AArch64::ST1W_D_IMM:
5218 case AArch64::LDNF1B_H_IMM:
5219 case AArch64::LDNF1SB_H_IMM:
5220 case AArch64::LDNF1H_S_IMM:
5221 case AArch64::LDNF1SH_S_IMM:
5222 case AArch64::LDNF1W_D_IMM:
5223 case AArch64::LDNF1SW_D_IMM:
5230 case AArch64::LD1B_S_IMM:
5231 case AArch64::LD1SB_S_IMM:
5232 case AArch64::LD1H_D_IMM:
5233 case AArch64::LD1SH_D_IMM:
5234 case AArch64::ST1B_S_IMM:
5235 case AArch64::ST1H_D_IMM:
5236 case AArch64::LDNF1B_S_IMM:
5237 case AArch64::LDNF1SB_S_IMM:
5238 case AArch64::LDNF1H_D_IMM:
5239 case AArch64::LDNF1SH_D_IMM:
5246 case AArch64::LD1B_D_IMM:
5247 case AArch64::LD1SB_D_IMM:
5248 case AArch64::ST1B_D_IMM:
5249 case AArch64::LDNF1B_D_IMM:
5250 case AArch64::LDNF1SB_D_IMM:
5257 case AArch64::ST2Gi:
5258 case AArch64::ST2GPreIndex:
5259 case AArch64::ST2GPostIndex:
5260 case AArch64::STZ2Gi:
5261 case AArch64::STZ2GPreIndex:
5262 case AArch64::STZ2GPostIndex:
5268 case AArch64::STGPi:
5269 case AArch64::STGPpost:
5270 case AArch64::STGPpre:
5275 case AArch64::LD1RB_IMM:
5276 case AArch64::LD1RB_H_IMM:
5277 case AArch64::LD1RB_S_IMM:
5278 case AArch64::LD1RB_D_IMM:
5279 case AArch64::LD1RSB_H_IMM:
5280 case AArch64::LD1RSB_S_IMM:
5281 case AArch64::LD1RSB_D_IMM:
5286 case AArch64::LD1RH_IMM:
5287 case AArch64::LD1RH_S_IMM:
5288 case AArch64::LD1RH_D_IMM:
5289 case AArch64::LD1RSH_S_IMM:
5290 case AArch64::LD1RSH_D_IMM:
5295 case AArch64::LD1RW_IMM:
5296 case AArch64::LD1RW_D_IMM:
5297 case AArch64::LD1RSW_IMM:
5302 case AArch64::LD1RD_IMM:
5317 case AArch64::LDRBui:
5318 case AArch64::LDRBBui:
5319 case AArch64::LDURBBi:
5320 case AArch64::LDRSBWui:
5321 case AArch64::LDURSBWi:
5322 case AArch64::STRBui:
5323 case AArch64::STRBBui:
5324 case AArch64::STURBBi:
5326 case AArch64::LDRHui:
5327 case AArch64::LDRHHui:
5328 case AArch64::LDURHHi:
5329 case AArch64::LDRSHWui:
5330 case AArch64::LDURSHWi:
5331 case AArch64::STRHui:
5332 case AArch64::STRHHui:
5333 case AArch64::STURHHi:
5335 case AArch64::LDRSui:
5336 case AArch64::LDURSi:
5337 case AArch64::LDRSpre:
5338 case AArch64::LDRSWui:
5339 case AArch64::LDURSWi:
5340 case AArch64::LDRSWpre:
5341 case AArch64::LDRWpre:
5342 case AArch64::LDRWui:
5343 case AArch64::LDURWi:
5344 case AArch64::STRSui:
5345 case AArch64::STURSi:
5346 case AArch64::STRSpre:
5347 case AArch64::STRWui:
5348 case AArch64::STURWi:
5349 case AArch64::STRWpre:
5350 case AArch64::LDPSi:
5351 case AArch64::LDPSWi:
5352 case AArch64::LDPWi:
5353 case AArch64::STPSi:
5354 case AArch64::STPWi:
5356 case AArch64::LDRDui:
5357 case AArch64::LDURDi:
5358 case AArch64::LDRDpre:
5359 case AArch64::LDRXui:
5360 case AArch64::LDURXi:
5361 case AArch64::LDRXpre:
5362 case AArch64::STRDui:
5363 case AArch64::STURDi:
5364 case AArch64::STRDpre:
5365 case AArch64::STRXui:
5366 case AArch64::STURXi:
5367 case AArch64::STRXpre:
5368 case AArch64::LDPDi:
5369 case AArch64::LDPXi:
5370 case AArch64::STPDi:
5371 case AArch64::STPXi:
5373 case AArch64::LDRQui:
5374 case AArch64::LDURQi:
5375 case AArch64::STRQui:
5376 case AArch64::STURQi:
5377 case AArch64::STRQpre:
5378 case AArch64::LDPQi:
5379 case AArch64::LDRQpre:
5380 case AArch64::STPQi:
5382 case AArch64::STZGi:
5383 case AArch64::ST2Gi:
5384 case AArch64::STZ2Gi:
5385 case AArch64::STGPi:
5391 switch (
MI.getOpcode()) {
5394 case AArch64::LDRWpre:
5395 case AArch64::LDRXpre:
5396 case AArch64::LDRSWpre:
5397 case AArch64::LDRSpre:
5398 case AArch64::LDRDpre:
5399 case AArch64::LDRQpre:
5405 switch (
MI.getOpcode()) {
5408 case AArch64::STRWpre:
5409 case AArch64::STRXpre:
5410 case AArch64::STRSpre:
5411 case AArch64::STRDpre:
5412 case AArch64::STRQpre:
5422 switch (
MI.getOpcode()) {
5425 case AArch64::LDURBBi:
5426 case AArch64::LDURHHi:
5427 case AArch64::LDURWi:
5428 case AArch64::LDRBBui:
5429 case AArch64::LDRHHui:
5430 case AArch64::LDRWui:
5431 case AArch64::LDRBBroX:
5432 case AArch64::LDRHHroX:
5433 case AArch64::LDRWroX:
5434 case AArch64::LDRBBroW:
5435 case AArch64::LDRHHroW:
5436 case AArch64::LDRWroW:
5442 switch (
MI.getOpcode()) {
5445 case AArch64::LDURSBWi:
5446 case AArch64::LDURSHWi:
5447 case AArch64::LDURSBXi:
5448 case AArch64::LDURSHXi:
5449 case AArch64::LDURSWi:
5450 case AArch64::LDRSBWui:
5451 case AArch64::LDRSHWui:
5452 case AArch64::LDRSBXui:
5453 case AArch64::LDRSHXui:
5454 case AArch64::LDRSWui:
5455 case AArch64::LDRSBWroX:
5456 case AArch64::LDRSHWroX:
5457 case AArch64::LDRSBXroX:
5458 case AArch64::LDRSHXroX:
5459 case AArch64::LDRSWroX:
5460 case AArch64::LDRSBWroW:
5461 case AArch64::LDRSHWroW:
5462 case AArch64::LDRSBXroW:
5463 case AArch64::LDRSHXroW:
5464 case AArch64::LDRSWroW:
5470 switch (
MI.getOpcode()) {
5473 case AArch64::LDPSi:
5474 case AArch64::LDPSWi:
5475 case AArch64::LDPDi:
5476 case AArch64::LDPQi:
5477 case AArch64::LDPWi:
5478 case AArch64::LDPXi:
5479 case AArch64::STPSi:
5480 case AArch64::STPDi:
5481 case AArch64::STPQi:
5482 case AArch64::STPWi:
5483 case AArch64::STPXi:
5484 case AArch64::STGPi:
5490 assert(
MI.mayLoadOrStore() &&
"Load or store instruction expected");
5494 return MI.getOperand(Idx);
5499 assert(
MI.mayLoadOrStore() &&
"Load or store instruction expected");
5503 return MI.getOperand(Idx);
5508 switch (
MI.getOpcode()) {
5511 case AArch64::LDRBroX:
5512 case AArch64::LDRBBroX:
5513 case AArch64::LDRSBXroX:
5514 case AArch64::LDRSBWroX:
5515 case AArch64::LDRHroX:
5516 case AArch64::LDRHHroX:
5517 case AArch64::LDRSHXroX:
5518 case AArch64::LDRSHWroX:
5519 case AArch64::LDRWroX:
5520 case AArch64::LDRSroX:
5521 case AArch64::LDRSWroX:
5522 case AArch64::LDRDroX:
5523 case AArch64::LDRXroX:
5524 case AArch64::LDRQroX:
5525 return MI.getOperand(4);
5531 if (
MI.getParent() ==
nullptr)
5541 auto Reg =
Op.getReg();
5542 if (Reg.isPhysical())
5543 return AArch64::FPR16RegClass.contains(Reg);
5545 return TRC == &AArch64::FPR16RegClass ||
5546 TRC == &AArch64::FPR16_loRegClass;
5555 auto Reg =
Op.getReg();
5556 if (Reg.isPhysical())
5557 return AArch64::FPR128RegClass.contains(Reg);
5559 return TRC == &AArch64::FPR128RegClass ||
5560 TRC == &AArch64::FPR128_loRegClass;
5566 switch (
MI.getOpcode()) {
5569 case AArch64::PACIASP:
5570 case AArch64::PACIBSP:
5573 case AArch64::PAUTH_PROLOGUE:
5576 case AArch64::HINT: {
5577 unsigned Imm =
MI.getOperand(0).getImm();
5582 if (
Imm == 25 ||
Imm == 27)
5594 assert(Reg.isPhysical() &&
"Expected physical register in isFpOrNEON");
5595 return AArch64::FPR128RegClass.contains(Reg) ||
5596 AArch64::FPR64RegClass.contains(Reg) ||
5597 AArch64::FPR32RegClass.contains(Reg) ||
5598 AArch64::FPR16RegClass.contains(Reg) ||
5599 AArch64::FPR8RegClass.contains(Reg);
5606 auto Reg =
Op.getReg();
5607 if (Reg.isPhysical())
5611 return TRC == &AArch64::FPR128RegClass ||
5612 TRC == &AArch64::FPR128_loRegClass ||
5613 TRC == &AArch64::FPR64RegClass ||
5614 TRC == &AArch64::FPR64_loRegClass ||
5615 TRC == &AArch64::FPR32RegClass || TRC == &AArch64::FPR16RegClass ||
5616 TRC == &AArch64::FPR8RegClass;
5638 if (FirstOpc == SecondOpc)
5644 case AArch64::STRSui:
5645 case AArch64::STURSi:
5646 return SecondOpc == AArch64::STRSui || SecondOpc == AArch64::STURSi;
5647 case AArch64::STRDui:
5648 case AArch64::STURDi:
5649 return SecondOpc == AArch64::STRDui || SecondOpc == AArch64::STURDi;
5650 case AArch64::STRQui:
5651 case AArch64::STURQi:
5652 return SecondOpc == AArch64::STRQui || SecondOpc == AArch64::STURQi;
5653 case AArch64::STRWui:
5654 case AArch64::STURWi:
5655 return SecondOpc == AArch64::STRWui || SecondOpc == AArch64::STURWi;
5656 case AArch64::STRXui:
5657 case AArch64::STURXi:
5658 return SecondOpc == AArch64::STRXui || SecondOpc == AArch64::STURXi;
5659 case AArch64::LDRSui:
5660 case AArch64::LDURSi:
5661 return SecondOpc == AArch64::LDRSui || SecondOpc == AArch64::LDURSi;
5662 case AArch64::LDRDui:
5663 case AArch64::LDURDi:
5664 return SecondOpc == AArch64::LDRDui || SecondOpc == AArch64::LDURDi;
5665 case AArch64::LDRQui:
5666 case AArch64::LDURQi:
5667 return SecondOpc == AArch64::LDRQui || SecondOpc == AArch64::LDURQi;
5668 case AArch64::LDRWui:
5669 case AArch64::LDURWi:
5670 return SecondOpc == AArch64::LDRSWui || SecondOpc == AArch64::LDURSWi;
5671 case AArch64::LDRSWui:
5672 case AArch64::LDURSWi:
5673 return SecondOpc == AArch64::LDRWui || SecondOpc == AArch64::LDURWi;
5674 case AArch64::LDRXui:
5675 case AArch64::LDURXi:
5676 return SecondOpc == AArch64::LDRXui || SecondOpc == AArch64::LDURXi;
5683 int64_t Offset1,
unsigned Opcode1,
int FI2,
5684 int64_t Offset2,
unsigned Opcode2) {
5690 assert(ObjectOffset1 <= ObjectOffset2 &&
"Object offsets are not ordered.");
5693 if (ObjectOffset1 % Scale1 != 0)
5695 ObjectOffset1 /= Scale1;
5697 if (ObjectOffset2 % Scale2 != 0)
5699 ObjectOffset2 /= Scale2;
5700 ObjectOffset1 += Offset1;
5701 ObjectOffset2 += Offset2;
5702 return ObjectOffset1 + 1 == ObjectOffset2;
5714 int64_t OpOffset2,
bool OffsetIsScalable2,
unsigned ClusterSize,
5715 unsigned NumBytes)
const {
5725 "Only base registers and frame indices are supported.");
5732 if (ClusterSize > 2)
5739 unsigned FirstOpc = FirstLdSt.
getOpcode();
5740 unsigned SecondOpc = SecondLdSt.
getOpcode();
5760 if (Offset1 > 63 || Offset1 < -64)
5765 if (BaseOp1.
isFI()) {
5767 "Caller should have ordered offsets.");
5772 BaseOp2.
getIndex(), Offset2, SecondOpc);
5775 assert(Offset1 <= Offset2 &&
"Caller should have ordered offsets.");
5777 return Offset1 + 1 == Offset2;
5787 if (
Reg.isPhysical())
5797 assert(Subtarget.hasNEON() &&
"Unexpected register copy without NEON");
5799 uint16_t DestEncoding =
TRI->getEncodingValue(DestReg);
5800 uint16_t SrcEncoding =
TRI->getEncodingValue(SrcReg);
5801 unsigned NumRegs = Indices.
size();
5802 MCRegister DestSubReg =
TRI->getSubReg(DestReg, Indices[0]);
5804 "Unexpected predicate tuple copy");
5805 unsigned MaxRegs = AArch64::PPRRegClass.contains(DestSubReg) ? 15 : 31;
5807 int SubReg = 0, End = NumRegs, Incr = 1;
5809 if (((DestEncoding - SrcEncoding) & MaxRegs) < NumRegs) {
5810 SubReg = NumRegs - 1;
5815 for (; SubReg != End; SubReg += Incr) {
5816 DestSubReg =
TRI->getSubReg(DestReg, Indices[SubReg]);
5817 MCRegister SrcSubReg =
TRI->getSubReg(SrcReg, Indices[SubReg]);
5826 unsigned Opcode,
unsigned ZeroReg,
5829 unsigned NumRegs = Indices.
size();
5832 uint16_t DestEncoding =
TRI->getEncodingValue(DestReg);
5833 uint16_t SrcEncoding =
TRI->getEncodingValue(SrcReg);
5834 assert(DestEncoding % NumRegs == 0 && SrcEncoding % NumRegs == 0 &&
5835 "GPR reg sequences should not be able to overlap");
5838 for (
unsigned SubReg = 0; SubReg != NumRegs; ++SubReg) {
5859 unsigned Opc =
MI.getOpcode();
5860 if (
Opc == AArch64::MSRpstatesvcrImm1 ||
Opc == AArch64::MSRpstatePseudo) {
5862 int64_t PState =
MI.getOperand(0).getImm();
5863 if (PState == AArch64SVCR::SVCRSM || PState == AArch64SVCR::SVCRSMZA) {
5865 return MI.getOperand(1).getImm() == 1;
5884 bool RenamableSrc)
const {
5885 if (AArch64::GPR32spRegClass.
contains(DestReg) &&
5886 AArch64::GPR32spRegClass.
contains(SrcReg)) {
5887 if (DestReg == AArch64::WSP || SrcReg == AArch64::WSP) {
5889 if (Subtarget.hasZeroCycleRegMoveGPR64() &&
5890 !Subtarget.hasZeroCycleRegMoveGPR32()) {
5892 MCRegister DestRegX = RI.getMatchingSuperReg(DestReg, AArch64::sub_32,
5893 &AArch64::GPR64spRegClass);
5894 MCRegister SrcRegX = RI.getMatchingSuperReg(SrcReg, AArch64::sub_32,
5895 &AArch64::GPR64spRegClass);
5905 ++NumZCRegMoveInstrsGPR;
5911 if (Subtarget.hasZeroCycleRegMoveGPR32())
5912 ++NumZCRegMoveInstrsGPR;
5914 }
else if (Subtarget.hasZeroCycleRegMoveGPR64() &&
5915 !Subtarget.hasZeroCycleRegMoveGPR32()) {
5917 MCRegister DestRegX = RI.getMatchingSuperReg(DestReg, AArch64::sub_32,
5918 &AArch64::GPR64spRegClass);
5919 assert(DestRegX.
isValid() &&
"Destination super-reg not valid");
5920 MCRegister SrcRegX = RI.getMatchingSuperReg(SrcReg, AArch64::sub_32,
5921 &AArch64::GPR64spRegClass);
5931 ++NumZCRegMoveInstrsGPR;
5937 if (Subtarget.hasZeroCycleRegMoveGPR32())
5938 ++NumZCRegMoveInstrsGPR;
5944 if (AArch64::GPR32spRegClass.
contains(DestReg) && SrcReg == AArch64::WZR) {
5945 if (Subtarget.hasZeroCycleZeroingGPR64() &&
5946 !Subtarget.hasZeroCycleZeroingGPR32()) {
5947 MCRegister DestRegX = RI.getMatchingSuperReg(DestReg, AArch64::sub_32,
5948 &AArch64::GPR64spRegClass);
5949 assert(DestRegX.
isValid() &&
"Destination super-reg not valid");
5953 ++NumZCZeroingInstrsGPR;
5954 }
else if (Subtarget.hasZeroCycleZeroingGPR32()) {
5958 ++NumZCZeroingInstrsGPR;
5967 if (AArch64::GPR64spRegClass.
contains(DestReg) &&
5968 AArch64::GPR64spRegClass.
contains(SrcReg)) {
5969 if (DestReg == AArch64::SP || SrcReg == AArch64::SP) {
5975 if (Subtarget.hasZeroCycleRegMoveGPR64())
5976 ++NumZCRegMoveInstrsGPR;
5982 if (Subtarget.hasZeroCycleRegMoveGPR64())
5983 ++NumZCRegMoveInstrsGPR;
5989 if (AArch64::GPR64spRegClass.
contains(DestReg) && SrcReg == AArch64::XZR) {
5990 if (Subtarget.hasZeroCycleZeroingGPR64()) {
5994 ++NumZCZeroingInstrsGPR;
6004 if (AArch64::PPRRegClass.
contains(DestReg) &&
6005 AArch64::PPRRegClass.
contains(SrcReg)) {
6006 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6007 "Unexpected SVE register.");
6017 bool DestIsPNR = AArch64::PNRRegClass.contains(DestReg);
6018 bool SrcIsPNR = AArch64::PNRRegClass.contains(SrcReg);
6019 if (DestIsPNR || SrcIsPNR) {
6021 return (R - AArch64::PN0) + AArch64::P0;
6026 if (PPRSrcReg != PPRDestReg) {
6038 if (AArch64::PPR2RegClass.
contains(DestReg) &&
6039 AArch64::PPR2RegClass.
contains(SrcReg)) {
6040 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6041 "Unexpected SVE predicate register.");
6042 static const unsigned Indices[] = {AArch64::psub0, AArch64::psub1};
6048 if (AArch64::ZPRRegClass.
contains(DestReg) &&
6049 AArch64::ZPRRegClass.
contains(SrcReg)) {
6050 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6051 "Unexpected SVE register.");
6059 if ((AArch64::ZPR2RegClass.
contains(DestReg) ||
6060 AArch64::ZPR2StridedOrContiguousRegClass.
contains(DestReg)) &&
6061 (AArch64::ZPR2RegClass.
contains(SrcReg) ||
6062 AArch64::ZPR2StridedOrContiguousRegClass.
contains(SrcReg))) {
6063 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6064 "Unexpected SVE register.");
6065 static const unsigned Indices[] = {AArch64::zsub0, AArch64::zsub1};
6071 if (AArch64::ZPR3RegClass.
contains(DestReg) &&
6072 AArch64::ZPR3RegClass.
contains(SrcReg)) {
6073 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6074 "Unexpected SVE register.");
6075 static const unsigned Indices[] = {AArch64::zsub0, AArch64::zsub1,
6082 if ((AArch64::ZPR4RegClass.
contains(DestReg) ||
6083 AArch64::ZPR4StridedOrContiguousRegClass.
contains(DestReg)) &&
6084 (AArch64::ZPR4RegClass.
contains(SrcReg) ||
6085 AArch64::ZPR4StridedOrContiguousRegClass.
contains(SrcReg))) {
6086 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6087 "Unexpected SVE register.");
6088 static const unsigned Indices[] = {AArch64::zsub0, AArch64::zsub1,
6089 AArch64::zsub2, AArch64::zsub3};
6095 if (AArch64::DDDDRegClass.
contains(DestReg) &&
6096 AArch64::DDDDRegClass.
contains(SrcReg)) {
6097 static const unsigned Indices[] = {AArch64::dsub0, AArch64::dsub1,
6098 AArch64::dsub2, AArch64::dsub3};
6104 if (AArch64::DDDRegClass.
contains(DestReg) &&
6105 AArch64::DDDRegClass.
contains(SrcReg)) {
6106 static const unsigned Indices[] = {AArch64::dsub0, AArch64::dsub1,
6113 if (AArch64::DDRegClass.
contains(DestReg) &&
6114 AArch64::DDRegClass.
contains(SrcReg)) {
6115 static const unsigned Indices[] = {AArch64::dsub0, AArch64::dsub1};
6121 if (AArch64::QQQQRegClass.
contains(DestReg) &&
6122 AArch64::QQQQRegClass.
contains(SrcReg)) {
6123 static const unsigned Indices[] = {AArch64::qsub0, AArch64::qsub1,
6124 AArch64::qsub2, AArch64::qsub3};
6130 if (AArch64::QQQRegClass.
contains(DestReg) &&
6131 AArch64::QQQRegClass.
contains(SrcReg)) {
6132 static const unsigned Indices[] = {AArch64::qsub0, AArch64::qsub1,
6139 if (AArch64::QQRegClass.
contains(DestReg) &&
6140 AArch64::QQRegClass.
contains(SrcReg)) {
6141 static const unsigned Indices[] = {AArch64::qsub0, AArch64::qsub1};
6146 if (AArch64::XSeqPairsClassRegClass.
contains(DestReg) &&
6147 AArch64::XSeqPairsClassRegClass.
contains(SrcReg)) {
6148 static const unsigned Indices[] = {AArch64::sube64, AArch64::subo64};
6150 AArch64::XZR, Indices);
6154 if (AArch64::WSeqPairsClassRegClass.
contains(DestReg) &&
6155 AArch64::WSeqPairsClassRegClass.
contains(SrcReg)) {
6156 static const unsigned Indices[] = {AArch64::sube32, AArch64::subo32};
6158 AArch64::WZR, Indices);
6162 if (AArch64::FPR128RegClass.
contains(DestReg) &&
6163 AArch64::FPR128RegClass.
contains(SrcReg)) {
6167 if ((Subtarget.isSVEorStreamingSVEAvailable() &&
6168 !Subtarget.isNeonAvailable()) ||
6172 .
addReg(AArch64::Z0 + (SrcReg - AArch64::Q0))
6173 .
addReg(AArch64::Z0 + (SrcReg - AArch64::Q0));
6174 }
else if (Subtarget.isNeonAvailable()) {
6178 if (Subtarget.hasZeroCycleRegMoveFPR128())
6179 ++NumZCRegMoveInstrsFPR;
6195 if (AArch64::FPR64RegClass.
contains(DestReg) &&
6196 AArch64::FPR64RegClass.
contains(SrcReg)) {
6197 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
6198 !Subtarget.hasZeroCycleRegMoveFPR64() &&
6199 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
6201 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::dsub,
6202 &AArch64::FPR128RegClass);
6203 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::dsub,
6204 &AArch64::FPR128RegClass);
6213 ++NumZCRegMoveInstrsFPR;
6217 if (Subtarget.hasZeroCycleRegMoveFPR64())
6218 ++NumZCRegMoveInstrsFPR;
6223 if (AArch64::FPR32RegClass.
contains(DestReg) &&
6224 AArch64::FPR32RegClass.
contains(SrcReg)) {
6225 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
6226 !Subtarget.hasZeroCycleRegMoveFPR64() &&
6227 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
6229 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::ssub,
6230 &AArch64::FPR128RegClass);
6231 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::ssub,
6232 &AArch64::FPR128RegClass);
6241 ++NumZCRegMoveInstrsFPR;
6242 }
else if (Subtarget.hasZeroCycleRegMoveFPR64() &&
6243 !Subtarget.hasZeroCycleRegMoveFPR32()) {
6244 MCRegister DestRegD = RI.getMatchingSuperReg(DestReg, AArch64::ssub,
6245 &AArch64::FPR64RegClass);
6246 MCRegister SrcRegD = RI.getMatchingSuperReg(SrcReg, AArch64::ssub,
6247 &AArch64::FPR64RegClass);
6255 ++NumZCRegMoveInstrsFPR;
6259 if (Subtarget.hasZeroCycleRegMoveFPR32())
6260 ++NumZCRegMoveInstrsFPR;
6265 if (AArch64::FPR16RegClass.
contains(DestReg) &&
6266 AArch64::FPR16RegClass.
contains(SrcReg)) {
6267 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
6268 !Subtarget.hasZeroCycleRegMoveFPR64() &&
6269 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
6271 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
6272 &AArch64::FPR128RegClass);
6273 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
6274 &AArch64::FPR128RegClass);
6283 }
else if (Subtarget.hasZeroCycleRegMoveFPR64() &&
6284 !Subtarget.hasZeroCycleRegMoveFPR32()) {
6285 MCRegister DestRegD = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
6286 &AArch64::FPR64RegClass);
6287 MCRegister SrcRegD = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
6288 &AArch64::FPR64RegClass);
6297 DestReg = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
6298 &AArch64::FPR32RegClass);
6299 SrcReg = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
6300 &AArch64::FPR32RegClass);
6307 if (AArch64::FPR8RegClass.
contains(DestReg) &&
6308 AArch64::FPR8RegClass.
contains(SrcReg)) {
6309 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
6310 !Subtarget.hasZeroCycleRegMoveFPR64() &&
6311 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
6313 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
6314 &AArch64::FPR128RegClass);
6315 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
6316 &AArch64::FPR128RegClass);
6325 }
else if (Subtarget.hasZeroCycleRegMoveFPR64() &&
6326 !Subtarget.hasZeroCycleRegMoveFPR32()) {
6327 MCRegister DestRegD = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
6328 &AArch64::FPR64RegClass);
6329 MCRegister SrcRegD = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
6330 &AArch64::FPR64RegClass);
6339 DestReg = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
6340 &AArch64::FPR32RegClass);
6341 SrcReg = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
6342 &AArch64::FPR32RegClass);
6350 if (AArch64::FPR64RegClass.
contains(DestReg) &&
6351 AArch64::GPR64RegClass.
contains(SrcReg)) {
6352 if (AArch64::XZR == SrcReg) {
6360 if (AArch64::GPR64RegClass.
contains(DestReg) &&
6361 AArch64::FPR64RegClass.
contains(SrcReg)) {
6367 if (AArch64::FPR32RegClass.
contains(DestReg) &&
6368 AArch64::GPR32RegClass.
contains(SrcReg)) {
6369 if (AArch64::WZR == SrcReg) {
6377 if (AArch64::GPR32RegClass.
contains(DestReg) &&
6378 AArch64::FPR32RegClass.
contains(SrcReg)) {
6384 if (DestReg == AArch64::NZCV) {
6385 assert(AArch64::GPR64RegClass.
contains(SrcReg) &&
"Invalid NZCV copy");
6387 .
addImm(AArch64SysReg::NZCV)
6393 if (SrcReg == AArch64::NZCV) {
6394 assert(AArch64::GPR64RegClass.
contains(DestReg) &&
"Invalid NZCV copy");
6396 .
addImm(AArch64SysReg::NZCV)
6402 errs() << RI.getRegAsmName(DestReg) <<
" = COPY " << RI.getRegAsmName(SrcReg)
6413 bool RenamableSrc)
const {
6425 unsigned SubIdx0,
unsigned SubIdx1,
int FI,
6430 SrcReg0 =
TRI.getSubReg(SrcReg, SubIdx0);
6432 SrcReg1 =
TRI.getSubReg(SrcReg, SubIdx1);
6445 Register SrcReg,
bool isKill,
int FI,
6460 switch (RI.getSpillSize(*RC)) {
6462 if (AArch64::FPR8RegClass.hasSubClassEq(RC))
6463 Opc = AArch64::STRBui;
6466 if (AArch64::FPR16RegClass.hasSubClassEq(RC))
6467 Opc = AArch64::STRHui;
6468 else if (AArch64::PNRRegClass.hasSubClassEq(RC) ||
6469 AArch64::PPRRegClass.hasSubClassEq(RC)) {
6470 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6471 "Unexpected register store without SVE store instructions");
6472 Opc = AArch64::STR_PXI;
6478 if (AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
6479 Opc = AArch64::STRWui;
6483 assert(SrcReg != AArch64::WSP);
6484 }
else if (AArch64::FPR32RegClass.hasSubClassEq(RC))
6485 Opc = AArch64::STRSui;
6486 else if (AArch64::PPR2RegClass.hasSubClassEq(RC)) {
6487 Opc = AArch64::STR_PPXI;
6492 if (AArch64::GPR64allRegClass.hasSubClassEq(RC)) {
6493 Opc = AArch64::STRXui;
6497 assert(SrcReg != AArch64::SP);
6498 }
else if (AArch64::FPR64RegClass.hasSubClassEq(RC)) {
6499 Opc = AArch64::STRDui;
6500 }
else if (AArch64::WSeqPairsClassRegClass.hasSubClassEq(RC)) {
6502 get(AArch64::STPWi), SrcReg, isKill,
6503 AArch64::sube32, AArch64::subo32, FI, MMO);
6508 if (AArch64::FPR128RegClass.hasSubClassEq(RC))
6509 Opc = AArch64::STRQui;
6510 else if (AArch64::DDRegClass.hasSubClassEq(RC)) {
6511 assert(Subtarget.hasNEON() &&
"Unexpected register store without NEON");
6512 Opc = AArch64::ST1Twov1d;
6514 }
else if (AArch64::XSeqPairsClassRegClass.hasSubClassEq(RC)) {
6516 get(AArch64::STPXi), SrcReg, isKill,
6517 AArch64::sube64, AArch64::subo64, FI, MMO);
6519 }
else if (AArch64::ZPRRegClass.hasSubClassEq(RC)) {
6520 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6521 "Unexpected register store without SVE store instructions");
6522 Opc = AArch64::STR_ZXI;
6527 if (AArch64::DDDRegClass.hasSubClassEq(RC)) {
6528 assert(Subtarget.hasNEON() &&
"Unexpected register store without NEON");
6529 Opc = AArch64::ST1Threev1d;
6534 if (AArch64::DDDDRegClass.hasSubClassEq(RC)) {
6535 assert(Subtarget.hasNEON() &&
"Unexpected register store without NEON");
6536 Opc = AArch64::ST1Fourv1d;
6538 }
else if (AArch64::QQRegClass.hasSubClassEq(RC)) {
6539 assert(Subtarget.hasNEON() &&
"Unexpected register store without NEON");
6540 Opc = AArch64::ST1Twov2d;
6542 }
else if (AArch64::ZPR2StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6543 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6544 "Unexpected register store without SVE store instructions");
6545 Opc = AArch64::STR_ZZXI_STRIDED_CONTIGUOUS;
6547 }
else if (AArch64::ZPR2RegClass.hasSubClassEq(RC)) {
6548 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6549 "Unexpected register store without SVE store instructions");
6550 Opc = AArch64::STR_ZZXI;
6555 if (AArch64::QQQRegClass.hasSubClassEq(RC)) {
6556 assert(Subtarget.hasNEON() &&
"Unexpected register store without NEON");
6557 Opc = AArch64::ST1Threev2d;
6559 }
else if (AArch64::ZPR3RegClass.hasSubClassEq(RC)) {
6560 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6561 "Unexpected register store without SVE store instructions");
6562 Opc = AArch64::STR_ZZZXI;
6567 if (AArch64::QQQQRegClass.hasSubClassEq(RC)) {
6568 assert(Subtarget.hasNEON() &&
"Unexpected register store without NEON");
6569 Opc = AArch64::ST1Fourv2d;
6571 }
else if (AArch64::ZPR4StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6572 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6573 "Unexpected register store without SVE store instructions");
6574 Opc = AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS;
6576 }
else if (AArch64::ZPR4RegClass.hasSubClassEq(RC)) {
6577 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6578 "Unexpected register store without SVE store instructions");
6579 Opc = AArch64::STR_ZZZZXI;
6584 assert(
Opc &&
"Unknown register class");
6595 MI.addMemOperand(MMO);
6602 Register DestReg,
unsigned SubIdx0,
6603 unsigned SubIdx1,
int FI,
6607 bool IsUndef =
true;
6609 DestReg0 =
TRI.getSubReg(DestReg, SubIdx0);
6611 DestReg1 =
TRI.getSubReg(DestReg, SubIdx1);
6640 switch (
TRI.getSpillSize(*RC)) {
6642 if (AArch64::FPR8RegClass.hasSubClassEq(RC))
6643 Opc = AArch64::LDRBui;
6646 bool IsPNR = AArch64::PNRRegClass.hasSubClassEq(RC);
6647 if (AArch64::FPR16RegClass.hasSubClassEq(RC))
6648 Opc = AArch64::LDRHui;
6649 else if (IsPNR || AArch64::PPRRegClass.hasSubClassEq(RC)) {
6650 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6651 "Unexpected register load without SVE load instructions");
6654 Opc = AArch64::LDR_PXI;
6660 if (AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
6661 Opc = AArch64::LDRWui;
6665 assert(DestReg != AArch64::WSP);
6666 }
else if (AArch64::FPR32RegClass.hasSubClassEq(RC))
6667 Opc = AArch64::LDRSui;
6668 else if (AArch64::PPR2RegClass.hasSubClassEq(RC)) {
6669 Opc = AArch64::LDR_PPXI;
6674 if (AArch64::GPR64allRegClass.hasSubClassEq(RC)) {
6675 Opc = AArch64::LDRXui;
6679 assert(DestReg != AArch64::SP);
6680 }
else if (AArch64::FPR64RegClass.hasSubClassEq(RC)) {
6681 Opc = AArch64::LDRDui;
6682 }
else if (AArch64::WSeqPairsClassRegClass.hasSubClassEq(RC)) {
6684 get(AArch64::LDPWi), DestReg, AArch64::sube32,
6685 AArch64::subo32, FI, MMO);
6690 if (AArch64::FPR128RegClass.hasSubClassEq(RC))
6691 Opc = AArch64::LDRQui;
6692 else if (AArch64::DDRegClass.hasSubClassEq(RC)) {
6693 assert(Subtarget.hasNEON() &&
"Unexpected register load without NEON");
6694 Opc = AArch64::LD1Twov1d;
6696 }
else if (AArch64::XSeqPairsClassRegClass.hasSubClassEq(RC)) {
6698 get(AArch64::LDPXi), DestReg, AArch64::sube64,
6699 AArch64::subo64, FI, MMO);
6701 }
else if (AArch64::ZPRRegClass.hasSubClassEq(RC)) {
6702 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6703 "Unexpected register load without SVE load instructions");
6704 Opc = AArch64::LDR_ZXI;
6709 if (AArch64::DDDRegClass.hasSubClassEq(RC)) {
6710 assert(Subtarget.hasNEON() &&
"Unexpected register load without NEON");
6711 Opc = AArch64::LD1Threev1d;
6716 if (AArch64::DDDDRegClass.hasSubClassEq(RC)) {
6717 assert(Subtarget.hasNEON() &&
"Unexpected register load without NEON");
6718 Opc = AArch64::LD1Fourv1d;
6720 }
else if (AArch64::QQRegClass.hasSubClassEq(RC)) {
6721 assert(Subtarget.hasNEON() &&
"Unexpected register load without NEON");
6722 Opc = AArch64::LD1Twov2d;
6724 }
else if (AArch64::ZPR2StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6725 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6726 "Unexpected register load without SVE load instructions");
6727 Opc = AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS;
6729 }
else if (AArch64::ZPR2RegClass.hasSubClassEq(RC)) {
6730 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6731 "Unexpected register load without SVE load instructions");
6732 Opc = AArch64::LDR_ZZXI;
6737 if (AArch64::QQQRegClass.hasSubClassEq(RC)) {
6738 assert(Subtarget.hasNEON() &&
"Unexpected register load without NEON");
6739 Opc = AArch64::LD1Threev2d;
6741 }
else if (AArch64::ZPR3RegClass.hasSubClassEq(RC)) {
6742 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6743 "Unexpected register load without SVE load instructions");
6744 Opc = AArch64::LDR_ZZZXI;
6749 if (AArch64::QQQQRegClass.hasSubClassEq(RC)) {
6750 assert(Subtarget.hasNEON() &&
"Unexpected register load without NEON");
6751 Opc = AArch64::LD1Fourv2d;
6753 }
else if (AArch64::ZPR4StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6754 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6755 "Unexpected register load without SVE load instructions");
6756 Opc = AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS;
6758 }
else if (AArch64::ZPR4RegClass.hasSubClassEq(RC)) {
6759 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6760 "Unexpected register load without SVE load instructions");
6761 Opc = AArch64::LDR_ZZZZXI;
6767 assert(
Opc &&
"Unknown register class");
6777 MI.addMemOperand(MMO);
6784 UseMI.getIterator()),
6786 return I.modifiesRegister(AArch64::NZCV, TRI) ||
6787 I.readsRegister(AArch64::NZCV, TRI);
6791void AArch64InstrInfo::decomposeStackOffsetForDwarfOffsets(
6796 assert(
Offset.getScalable() % 2 == 0 &&
"Invalid frame offset");
6803 ByteSized =
Offset.getFixed();
6804 VGSized =
Offset.getScalable() / 2;
6810void AArch64InstrInfo::decomposeStackOffsetForFrameOffsets(
6812 int64_t &NumDataVectors) {
6816 assert(
Offset.getScalable() % 2 == 0 &&
"Invalid frame offset");
6818 NumBytes =
Offset.getFixed();
6820 NumPredicateVectors =
Offset.getScalable() / 2;
6825 if (NumPredicateVectors % 8 == 0 || NumPredicateVectors < -64 ||
6826 NumPredicateVectors > 62) {
6827 NumDataVectors = NumPredicateVectors / 8;
6828 NumPredicateVectors -= NumDataVectors * 8;
6854 Expr.
push_back((
char)dwarf::DW_OP_bregx);
6862 int64_t OffsetFromDefCFA) {
6876 Comment << (NumBytes < 0 ?
" - " :
" + ") << std::abs(NumBytes);
6877 if (!RegScale.empty())
6887 int64_t NumBytes, NumVGScaledBytes;
6888 AArch64InstrInfo::decomposeStackOffsetForDwarfOffsets(
Offset, NumBytes,
6890 std::string CommentBuffer;
6893 if (
Reg == AArch64::SP)
6895 else if (
Reg == AArch64::FP)
6902 unsigned DwarfReg =
TRI.getDwarfRegNum(
Reg,
true);
6903 assert(DwarfReg <= 31 &&
"DwarfReg out of bounds (0..31)");
6905 Expr.
push_back(dwarf::DW_OP_breg0 + DwarfReg);
6908 if (NumVGScaledBytes) {
6918 DefCfaExpr.
push_back(dwarf::DW_CFA_def_cfa_expression);
6926 unsigned FrameReg,
unsigned Reg,
6928 bool LastAdjustmentWasScalable) {
6929 if (
Offset.getScalable())
6932 if (FrameReg == Reg && !LastAdjustmentWasScalable)
6935 unsigned DwarfReg =
TRI.getDwarfRegNum(Reg,
true);
6942 std::optional<int64_t> IncomingVGOffsetFromDefCFA) {
6943 int64_t NumBytes, NumVGScaledBytes;
6944 AArch64InstrInfo::decomposeStackOffsetForDwarfOffsets(
6945 OffsetFromDefCFA, NumBytes, NumVGScaledBytes);
6947 unsigned DwarfReg =
TRI.getDwarfRegNum(Reg,
true);
6950 if (!NumVGScaledBytes)
6953 std::string CommentBuffer;
6958 assert(NumVGScaledBytes &&
"Expected scalable offset");
6962 if (IncomingVGOffsetFromDefCFA) {
6964 VGRegScale =
"* IncomingVG";
6967 VGRegScale =
"* VG";
6971 OffsetExpr.
push_back(dwarf::DW_OP_plus);
6980 CfaExpr.
push_back(dwarf::DW_CFA_expression);
6995 unsigned SrcReg, int64_t
Offset,
unsigned Opc,
6998 bool *HasWinCFI,
bool EmitCFAOffset,
7001 unsigned MaxEncoding, ShiftSize;
7003 case AArch64::ADDXri:
7004 case AArch64::ADDSXri:
7005 case AArch64::SUBXri:
7006 case AArch64::SUBSXri:
7007 MaxEncoding = 0xfff;
7010 case AArch64::ADDVL_XXI:
7011 case AArch64::ADDPL_XXI:
7012 case AArch64::ADDSVL_XXI:
7013 case AArch64::ADDSPL_XXI:
7028 if (
Opc == AArch64::ADDVL_XXI ||
Opc == AArch64::ADDSVL_XXI)
7030 else if (
Opc == AArch64::ADDPL_XXI ||
Opc == AArch64::ADDSPL_XXI)
7044 const unsigned MaxEncodableValue = MaxEncoding << ShiftSize;
7046 if (TmpReg == AArch64::XZR)
7047 TmpReg =
MBB.getParent()->getRegInfo().createVirtualRegister(
7048 &AArch64::GPR64RegClass);
7050 uint64_t ThisVal = std::min<uint64_t>(
Offset, MaxEncodableValue);
7051 unsigned LocalShiftSize = 0;
7052 if (ThisVal > MaxEncoding) {
7053 ThisVal = ThisVal >> ShiftSize;
7054 LocalShiftSize = ShiftSize;
7056 assert((ThisVal >> ShiftSize) <= MaxEncoding &&
7057 "Encoding cannot handle value that big");
7059 Offset -= ThisVal << LocalShiftSize;
7064 .
addImm(Sign * (
int)ThisVal);
7074 if (Sign == -1 ||
Opc == AArch64::SUBXri ||
Opc == AArch64::SUBSXri)
7075 CFAOffset += Change;
7077 CFAOffset -= Change;
7078 if (EmitCFAOffset && DestReg == TmpReg) {
7091 int Imm = (int)(ThisVal << LocalShiftSize);
7092 if (VScale != 1 && DestReg == AArch64::SP) {
7098 }
else if ((DestReg == AArch64::FP && SrcReg == AArch64::SP) ||
7099 (SrcReg == AArch64::FP && DestReg == AArch64::SP)) {
7100 assert(VScale == 1 &&
"Expected non-scalable operation");
7109 assert(
Offset == 0 &&
"Expected remaining offset to be zero to "
7110 "emit a single SEH directive");
7111 }
else if (DestReg == AArch64::SP) {
7112 assert(VScale == 1 &&
"Expected non-scalable operation");
7115 assert(SrcReg == AArch64::SP &&
"Unexpected SrcReg for SEH_StackAlloc");
7128 unsigned DestReg,
unsigned SrcReg,
7131 bool NeedsWinCFI,
bool *HasWinCFI,
7133 unsigned FrameReg) {
7140 bool UseSVL =
F.hasFnAttribute(
"aarch64_pstate_sm_body");
7142 int64_t Bytes, NumPredicateVectors, NumDataVectors;
7143 AArch64InstrInfo::decomposeStackOffsetForFrameOffsets(
7144 Offset, Bytes, NumPredicateVectors, NumDataVectors);
7147 bool NeedsFinalDefNZCV = SetNZCV && (NumPredicateVectors || NumDataVectors);
7148 if (NeedsFinalDefNZCV)
7152 if (Bytes || (!
Offset && SrcReg != DestReg)) {
7153 assert((DestReg != AArch64::SP || Bytes % 8 == 0) &&
7154 "SP increment/decrement not 8-byte aligned");
7155 unsigned Opc = SetNZCV ? AArch64::ADDSXri : AArch64::ADDXri;
7158 Opc = SetNZCV ? AArch64::SUBSXri : AArch64::SUBXri;
7161 NeedsWinCFI, HasWinCFI, EmitCFAOffset, CFAOffset,
7163 CFAOffset += (
Opc == AArch64::ADDXri ||
Opc == AArch64::ADDSXri)
7170 assert(!(NeedsWinCFI && NumPredicateVectors) &&
7171 "WinCFI can't allocate fractions of an SVE data vector");
7173 if (NumDataVectors) {
7175 UseSVL ? AArch64::ADDSVL_XXI : AArch64::ADDVL_XXI,
TII,
7176 Flag, NeedsWinCFI, HasWinCFI, EmitCFAOffset, CFAOffset,
7182 if (NumPredicateVectors) {
7183 assert(DestReg != AArch64::SP &&
"Unaligned access to SP");
7185 UseSVL ? AArch64::ADDSPL_XXI : AArch64::ADDPL_XXI,
TII,
7186 Flag, NeedsWinCFI, HasWinCFI, EmitCFAOffset, CFAOffset,
7190 if (NeedsFinalDefNZCV)
7212 if (
MI.isFullCopy()) {
7215 if (SrcReg == AArch64::SP && DstReg.
isVirtual()) {
7219 if (DstReg == AArch64::SP && SrcReg.
isVirtual()) {
7224 if (SrcReg == AArch64::NZCV || DstReg == AArch64::NZCV)
7252 if (
MI.isCopy() &&
Ops.size() == 1 &&
7254 (
Ops[0] == 0 ||
Ops[0] == 1)) {
7255 bool IsSpill =
Ops[0] == 0;
7256 bool IsFill = !IsSpill;
7268 :
TRI.getMinimalPhysRegClass(Reg);
7274 "Mismatched register size in non subreg COPY");
7281 return &*--InsertPt;
7293 if (IsSpill && DstMO.
isUndef() && SrcReg == AArch64::WZR &&
7296 "Unexpected subreg on physical register");
7298 FrameIndex, &AArch64::GPR64RegClass,
Register());
7299 return &*--InsertPt;
7316 case AArch64::sub_32:
7317 if (AArch64::GPR64RegClass.hasSubClassEq(
getRegClass(DstReg)))
7318 FillRC = &AArch64::GPR32RegClass;
7321 FillRC = &AArch64::FPR32RegClass;
7324 FillRC = &AArch64::FPR64RegClass;
7330 TRI.getRegSizeInBits(*FillRC) &&
7331 "Mismatched regclass size on folded subreg COPY");
7350 bool *OutUseUnscaledOp,
7351 unsigned *OutUnscaledOp,
7352 int64_t *EmittableOffset) {
7354 if (EmittableOffset)
7355 *EmittableOffset = 0;
7356 if (OutUseUnscaledOp)
7357 *OutUseUnscaledOp =
false;
7363 switch (
MI.getOpcode()) {
7366 case AArch64::LD1Rv1d:
7367 case AArch64::LD1Rv2s:
7368 case AArch64::LD1Rv2d:
7369 case AArch64::LD1Rv4h:
7370 case AArch64::LD1Rv4s:
7371 case AArch64::LD1Rv8b:
7372 case AArch64::LD1Rv8h:
7373 case AArch64::LD1Rv16b:
7374 case AArch64::LD1Twov2d:
7375 case AArch64::LD1Threev2d:
7376 case AArch64::LD1Fourv2d:
7377 case AArch64::LD1Twov1d:
7378 case AArch64::LD1Threev1d:
7379 case AArch64::LD1Fourv1d:
7380 case AArch64::ST1Twov2d:
7381 case AArch64::ST1Threev2d:
7382 case AArch64::ST1Fourv2d:
7383 case AArch64::ST1Twov1d:
7384 case AArch64::ST1Threev1d:
7385 case AArch64::ST1Fourv1d:
7386 case AArch64::ST1i8:
7387 case AArch64::ST1i16:
7388 case AArch64::ST1i32:
7389 case AArch64::ST1i64:
7391 case AArch64::IRGstack:
7392 case AArch64::STGloop:
7393 case AArch64::STZGloop:
7398 TypeSize ScaleValue(0U,
false), Width(0U,
false);
7399 int64_t MinOff, MaxOff;
7405 bool IsMulVL = ScaleValue.isScalable();
7406 unsigned Scale = ScaleValue.getKnownMinValue();
7416 std::optional<unsigned> UnscaledOp =
7418 bool useUnscaledOp = UnscaledOp && (
Offset % Scale ||
Offset < 0);
7419 if (useUnscaledOp &&
7424 Scale = ScaleValue.getKnownMinValue();
7425 assert(IsMulVL == ScaleValue.isScalable() &&
7426 "Unscaled opcode has different value for scalable");
7428 int64_t Remainder =
Offset % Scale;
7429 assert(!(Remainder && useUnscaledOp) &&
7430 "Cannot have remainder when using unscaled op");
7432 assert(MinOff < MaxOff &&
"Unexpected Min/Max offsets");
7433 int64_t NewOffset =
Offset / Scale;
7434 if (MinOff <= NewOffset && NewOffset <= MaxOff)
7442 int64_t HighPart =
Offset & ~0xFFF;
7443 int64_t LowPart =
Offset & 0xFFF;
7444 int64_t LowScaled = LowPart / Scale;
7445 if (!IsMulVL && NewOffset >= 0 && LowPart % Scale == 0 &&
7446 MinOff <= LowScaled && LowScaled <= MaxOff &&
7448 NewOffset = LowScaled;
7453 NewOffset = NewOffset < 0 ? MinOff : MaxOff;
7458 if (EmittableOffset)
7459 *EmittableOffset = NewOffset;
7460 if (OutUseUnscaledOp)
7461 *OutUseUnscaledOp = useUnscaledOp;
7462 if (OutUnscaledOp && UnscaledOp)
7463 *OutUnscaledOp = *UnscaledOp;
7476 unsigned Opcode =
MI.getOpcode();
7477 unsigned ImmIdx = FrameRegIdx + 1;
7479 if (Opcode == AArch64::ADDSXri || Opcode == AArch64::ADDXri) {
7484 MI.eraseFromParent();
7490 unsigned UnscaledOp;
7493 &UnscaledOp, &NewOffset);
7497 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg,
false);
7499 MI.setDesc(
TII->get(UnscaledOp));
7501 MI.getOperand(ImmIdx).ChangeToImmediate(NewOffset);
7517bool AArch64InstrInfo::useMachineCombiner()
const {
return true; }
7522 case AArch64::ADDSWrr:
7523 case AArch64::ADDSWri:
7524 case AArch64::ADDSXrr:
7525 case AArch64::ADDSXri:
7526 case AArch64::SUBSWrr:
7527 case AArch64::SUBSXrr:
7529 case AArch64::SUBSWri:
7530 case AArch64::SUBSXri:
7541 case AArch64::ADDWrr:
7542 case AArch64::ADDWri:
7543 case AArch64::SUBWrr:
7544 case AArch64::ADDSWrr:
7545 case AArch64::ADDSWri:
7546 case AArch64::SUBSWrr:
7548 case AArch64::SUBWri:
7549 case AArch64::SUBSWri:
7560 case AArch64::ADDXrr:
7561 case AArch64::ADDXri:
7562 case AArch64::SUBXrr:
7563 case AArch64::ADDSXrr:
7564 case AArch64::ADDSXri:
7565 case AArch64::SUBSXrr:
7567 case AArch64::SUBXri:
7568 case AArch64::SUBSXri:
7569 case AArch64::ADDv8i8:
7570 case AArch64::ADDv16i8:
7571 case AArch64::ADDv4i16:
7572 case AArch64::ADDv8i16:
7573 case AArch64::ADDv2i32:
7574 case AArch64::ADDv4i32:
7575 case AArch64::SUBv8i8:
7576 case AArch64::SUBv16i8:
7577 case AArch64::SUBv4i16:
7578 case AArch64::SUBv8i16:
7579 case AArch64::SUBv2i32:
7580 case AArch64::SUBv4i32:
7593 case AArch64::FADDHrr:
7594 case AArch64::FADDSrr:
7595 case AArch64::FADDDrr:
7596 case AArch64::FADDv4f16:
7597 case AArch64::FADDv8f16:
7598 case AArch64::FADDv2f32:
7599 case AArch64::FADDv2f64:
7600 case AArch64::FADDv4f32:
7601 case AArch64::FSUBHrr:
7602 case AArch64::FSUBSrr:
7603 case AArch64::FSUBDrr:
7604 case AArch64::FSUBv4f16:
7605 case AArch64::FSUBv8f16:
7606 case AArch64::FSUBv2f32:
7607 case AArch64::FSUBv2f64:
7608 case AArch64::FSUBv4f32:
7625 unsigned CombineOpc,
unsigned ZeroReg = 0,
7626 bool CheckZeroReg =
false) {
7633 if (!
MI ||
MI->getParent() != &
MBB ||
MI->getOpcode() != CombineOpc)
7640 assert(
MI->getNumOperands() >= 4 &&
MI->getOperand(0).isReg() &&
7641 MI->getOperand(1).isReg() &&
MI->getOperand(2).isReg() &&
7642 MI->getOperand(3).isReg() &&
"MAdd/MSub must have a least 4 regs");
7644 if (
MI->getOperand(3).getReg() != ZeroReg)
7649 MI->findRegisterDefOperandIdx(AArch64::NZCV,
nullptr,
true) == -1)
7658 unsigned MulOpc,
unsigned ZeroReg) {
7673bool AArch64InstrInfo::isAssociativeAndCommutative(
const MachineInstr &Inst,
7674 bool Invert)
const {
7680 case AArch64::FADDHrr:
7681 case AArch64::FADDSrr:
7682 case AArch64::FADDDrr:
7683 case AArch64::FMULHrr:
7684 case AArch64::FMULSrr:
7685 case AArch64::FMULDrr:
7686 case AArch64::FMULX16:
7687 case AArch64::FMULX32:
7688 case AArch64::FMULX64:
7690 case AArch64::FADDv4f16:
7691 case AArch64::FADDv8f16:
7692 case AArch64::FADDv2f32:
7693 case AArch64::FADDv4f32:
7694 case AArch64::FADDv2f64:
7695 case AArch64::FMULv4f16:
7696 case AArch64::FMULv8f16:
7697 case AArch64::FMULv2f32:
7698 case AArch64::FMULv4f32:
7699 case AArch64::FMULv2f64:
7700 case AArch64::FMULXv4f16:
7701 case AArch64::FMULXv8f16:
7702 case AArch64::FMULXv2f32:
7703 case AArch64::FMULXv4f32:
7704 case AArch64::FMULXv2f64:
7708 case AArch64::FADD_ZZZ_H:
7709 case AArch64::FADD_ZZZ_S:
7710 case AArch64::FADD_ZZZ_D:
7711 case AArch64::FMUL_ZZZ_H:
7712 case AArch64::FMUL_ZZZ_S:
7713 case AArch64::FMUL_ZZZ_D:
7724 case AArch64::ADDWrr:
7725 case AArch64::ADDXrr:
7726 case AArch64::ANDWrr:
7727 case AArch64::ANDXrr:
7728 case AArch64::ORRWrr:
7729 case AArch64::ORRXrr:
7730 case AArch64::EORWrr:
7731 case AArch64::EORXrr:
7732 case AArch64::EONWrr:
7733 case AArch64::EONXrr:
7737 case AArch64::ADDv8i8:
7738 case AArch64::ADDv16i8:
7739 case AArch64::ADDv4i16:
7740 case AArch64::ADDv8i16:
7741 case AArch64::ADDv2i32:
7742 case AArch64::ADDv4i32:
7743 case AArch64::ADDv1i64:
7744 case AArch64::ADDv2i64:
7745 case AArch64::MULv8i8:
7746 case AArch64::MULv16i8:
7747 case AArch64::MULv4i16:
7748 case AArch64::MULv8i16:
7749 case AArch64::MULv2i32:
7750 case AArch64::MULv4i32:
7751 case AArch64::ANDv8i8:
7752 case AArch64::ANDv16i8:
7753 case AArch64::ORRv8i8:
7754 case AArch64::ORRv16i8:
7755 case AArch64::EORv8i8:
7756 case AArch64::EORv16i8:
7758 case AArch64::ADD_ZZZ_B:
7759 case AArch64::ADD_ZZZ_H:
7760 case AArch64::ADD_ZZZ_S:
7761 case AArch64::ADD_ZZZ_D:
7762 case AArch64::MUL_ZZZ_B:
7763 case AArch64::MUL_ZZZ_H:
7764 case AArch64::MUL_ZZZ_S:
7765 case AArch64::MUL_ZZZ_D:
7766 case AArch64::AND_ZZZ:
7767 case AArch64::ORR_ZZZ:
7768 case AArch64::EOR_ZZZ:
7799 auto setFound = [&](
int Opcode,
int Operand,
unsigned ZeroReg,
7807 auto setVFound = [&](
int Opcode,
int Operand,
unsigned Pattern) {
7819 case AArch64::ADDWrr:
7821 "ADDWrr does not have register operands");
7822 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULADDW_OP1);
7823 setFound(AArch64::MADDWrrr, 2, AArch64::WZR, MCP::MULADDW_OP2);
7825 case AArch64::ADDXrr:
7826 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULADDX_OP1);
7827 setFound(AArch64::MADDXrrr, 2, AArch64::XZR, MCP::MULADDX_OP2);
7829 case AArch64::SUBWrr:
7830 setFound(AArch64::MADDWrrr, 2, AArch64::WZR, MCP::MULSUBW_OP2);
7831 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULSUBW_OP1);
7833 case AArch64::SUBXrr:
7834 setFound(AArch64::MADDXrrr, 2, AArch64::XZR, MCP::MULSUBX_OP2);
7835 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULSUBX_OP1);
7837 case AArch64::ADDWri:
7838 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULADDWI_OP1);
7840 case AArch64::ADDXri:
7841 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULADDXI_OP1);
7843 case AArch64::SUBWri:
7844 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULSUBWI_OP1);
7846 case AArch64::SUBXri:
7847 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULSUBXI_OP1);
7849 case AArch64::ADDv8i8:
7850 setVFound(AArch64::MULv8i8, 1, MCP::MULADDv8i8_OP1);
7851 setVFound(AArch64::MULv8i8, 2, MCP::MULADDv8i8_OP2);
7853 case AArch64::ADDv16i8:
7854 setVFound(AArch64::MULv16i8, 1, MCP::MULADDv16i8_OP1);
7855 setVFound(AArch64::MULv16i8, 2, MCP::MULADDv16i8_OP2);
7857 case AArch64::ADDv4i16:
7858 setVFound(AArch64::MULv4i16, 1, MCP::MULADDv4i16_OP1);
7859 setVFound(AArch64::MULv4i16, 2, MCP::MULADDv4i16_OP2);
7860 setVFound(AArch64::MULv4i16_indexed, 1, MCP::MULADDv4i16_indexed_OP1);
7861 setVFound(AArch64::MULv4i16_indexed, 2, MCP::MULADDv4i16_indexed_OP2);
7863 case AArch64::ADDv8i16:
7864 setVFound(AArch64::MULv8i16, 1, MCP::MULADDv8i16_OP1);
7865 setVFound(AArch64::MULv8i16, 2, MCP::MULADDv8i16_OP2);
7866 setVFound(AArch64::MULv8i16_indexed, 1, MCP::MULADDv8i16_indexed_OP1);
7867 setVFound(AArch64::MULv8i16_indexed, 2, MCP::MULADDv8i16_indexed_OP2);
7869 case AArch64::ADDv2i32:
7870 setVFound(AArch64::MULv2i32, 1, MCP::MULADDv2i32_OP1);
7871 setVFound(AArch64::MULv2i32, 2, MCP::MULADDv2i32_OP2);
7872 setVFound(AArch64::MULv2i32_indexed, 1, MCP::MULADDv2i32_indexed_OP1);
7873 setVFound(AArch64::MULv2i32_indexed, 2, MCP::MULADDv2i32_indexed_OP2);
7875 case AArch64::ADDv4i32:
7876 setVFound(AArch64::MULv4i32, 1, MCP::MULADDv4i32_OP1);
7877 setVFound(AArch64::MULv4i32, 2, MCP::MULADDv4i32_OP2);
7878 setVFound(AArch64::MULv4i32_indexed, 1, MCP::MULADDv4i32_indexed_OP1);
7879 setVFound(AArch64::MULv4i32_indexed, 2, MCP::MULADDv4i32_indexed_OP2);
7881 case AArch64::SUBv8i8:
7882 setVFound(AArch64::MULv8i8, 1, MCP::MULSUBv8i8_OP1);
7883 setVFound(AArch64::MULv8i8, 2, MCP::MULSUBv8i8_OP2);
7885 case AArch64::SUBv16i8:
7886 setVFound(AArch64::MULv16i8, 1, MCP::MULSUBv16i8_OP1);
7887 setVFound(AArch64::MULv16i8, 2, MCP::MULSUBv16i8_OP2);
7889 case AArch64::SUBv4i16:
7890 setVFound(AArch64::MULv4i16, 1, MCP::MULSUBv4i16_OP1);
7891 setVFound(AArch64::MULv4i16, 2, MCP::MULSUBv4i16_OP2);
7892 setVFound(AArch64::MULv4i16_indexed, 1, MCP::MULSUBv4i16_indexed_OP1);
7893 setVFound(AArch64::MULv4i16_indexed, 2, MCP::MULSUBv4i16_indexed_OP2);
7895 case AArch64::SUBv8i16:
7896 setVFound(AArch64::MULv8i16, 1, MCP::MULSUBv8i16_OP1);
7897 setVFound(AArch64::MULv8i16, 2, MCP::MULSUBv8i16_OP2);
7898 setVFound(AArch64::MULv8i16_indexed, 1, MCP::MULSUBv8i16_indexed_OP1);
7899 setVFound(AArch64::MULv8i16_indexed, 2, MCP::MULSUBv8i16_indexed_OP2);
7901 case AArch64::SUBv2i32:
7902 setVFound(AArch64::MULv2i32, 1, MCP::MULSUBv2i32_OP1);
7903 setVFound(AArch64::MULv2i32, 2, MCP::MULSUBv2i32_OP2);
7904 setVFound(AArch64::MULv2i32_indexed, 1, MCP::MULSUBv2i32_indexed_OP1);
7905 setVFound(AArch64::MULv2i32_indexed, 2, MCP::MULSUBv2i32_indexed_OP2);
7907 case AArch64::SUBv4i32:
7908 setVFound(AArch64::MULv4i32, 1, MCP::MULSUBv4i32_OP1);
7909 setVFound(AArch64::MULv4i32, 2, MCP::MULSUBv4i32_OP2);
7910 setVFound(AArch64::MULv4i32_indexed, 1, MCP::MULSUBv4i32_indexed_OP1);
7911 setVFound(AArch64::MULv4i32_indexed, 2, MCP::MULSUBv4i32_indexed_OP2);
7917bool AArch64InstrInfo::isAccumulationOpcode(
unsigned Opcode)
const {
7921 case AArch64::UABALB_ZZZ_D:
7922 case AArch64::UABALB_ZZZ_H:
7923 case AArch64::UABALB_ZZZ_S:
7924 case AArch64::UABALT_ZZZ_D:
7925 case AArch64::UABALT_ZZZ_H:
7926 case AArch64::UABALT_ZZZ_S:
7927 case AArch64::SABALB_ZZZ_D:
7928 case AArch64::SABALB_ZZZ_S:
7929 case AArch64::SABALB_ZZZ_H:
7930 case AArch64::SABALT_ZZZ_D:
7931 case AArch64::SABALT_ZZZ_S:
7932 case AArch64::SABALT_ZZZ_H:
7933 case AArch64::UABALv16i8_v8i16:
7934 case AArch64::UABALv2i32_v2i64:
7935 case AArch64::UABALv4i16_v4i32:
7936 case AArch64::UABALv4i32_v2i64:
7937 case AArch64::UABALv8i16_v4i32:
7938 case AArch64::UABALv8i8_v8i16:
7939 case AArch64::UABAv16i8:
7940 case AArch64::UABAv2i32:
7941 case AArch64::UABAv4i16:
7942 case AArch64::UABAv4i32:
7943 case AArch64::UABAv8i16:
7944 case AArch64::UABAv8i8:
7945 case AArch64::SABALv16i8_v8i16:
7946 case AArch64::SABALv2i32_v2i64:
7947 case AArch64::SABALv4i16_v4i32:
7948 case AArch64::SABALv4i32_v2i64:
7949 case AArch64::SABALv8i16_v4i32:
7950 case AArch64::SABALv8i8_v8i16:
7951 case AArch64::SABAv16i8:
7952 case AArch64::SABAv2i32:
7953 case AArch64::SABAv4i16:
7954 case AArch64::SABAv4i32:
7955 case AArch64::SABAv8i16:
7956 case AArch64::SABAv8i8:
7963unsigned AArch64InstrInfo::getAccumulationStartOpcode(
7964 unsigned AccumulationOpcode)
const {
7965 switch (AccumulationOpcode) {
7968 case AArch64::UABALB_ZZZ_D:
7969 return AArch64::UABDLB_ZZZ_D;
7970 case AArch64::UABALB_ZZZ_H:
7971 return AArch64::UABDLB_ZZZ_H;
7972 case AArch64::UABALB_ZZZ_S:
7973 return AArch64::UABDLB_ZZZ_S;
7974 case AArch64::UABALT_ZZZ_D:
7975 return AArch64::UABDLT_ZZZ_D;
7976 case AArch64::UABALT_ZZZ_H:
7977 return AArch64::UABDLT_ZZZ_H;
7978 case AArch64::UABALT_ZZZ_S:
7979 return AArch64::UABDLT_ZZZ_S;
7980 case AArch64::UABALv16i8_v8i16:
7981 return AArch64::UABDLv16i8_v8i16;
7982 case AArch64::UABALv2i32_v2i64:
7983 return AArch64::UABDLv2i32_v2i64;
7984 case AArch64::UABALv4i16_v4i32:
7985 return AArch64::UABDLv4i16_v4i32;
7986 case AArch64::UABALv4i32_v2i64:
7987 return AArch64::UABDLv4i32_v2i64;
7988 case AArch64::UABALv8i16_v4i32:
7989 return AArch64::UABDLv8i16_v4i32;
7990 case AArch64::UABALv8i8_v8i16:
7991 return AArch64::UABDLv8i8_v8i16;
7992 case AArch64::UABAv16i8:
7993 return AArch64::UABDv16i8;
7994 case AArch64::UABAv2i32:
7995 return AArch64::UABDv2i32;
7996 case AArch64::UABAv4i16:
7997 return AArch64::UABDv4i16;
7998 case AArch64::UABAv4i32:
7999 return AArch64::UABDv4i32;
8000 case AArch64::UABAv8i16:
8001 return AArch64::UABDv8i16;
8002 case AArch64::UABAv8i8:
8003 return AArch64::UABDv8i8;
8004 case AArch64::SABALB_ZZZ_D:
8005 return AArch64::SABDLB_ZZZ_D;
8006 case AArch64::SABALB_ZZZ_S:
8007 return AArch64::SABDLB_ZZZ_S;
8008 case AArch64::SABALB_ZZZ_H:
8009 return AArch64::SABDLB_ZZZ_H;
8010 case AArch64::SABALT_ZZZ_D:
8011 return AArch64::SABDLT_ZZZ_D;
8012 case AArch64::SABALT_ZZZ_S:
8013 return AArch64::SABDLT_ZZZ_S;
8014 case AArch64::SABALT_ZZZ_H:
8015 return AArch64::SABDLT_ZZZ_H;
8016 case AArch64::SABALv16i8_v8i16:
8017 return AArch64::SABDLv16i8_v8i16;
8018 case AArch64::SABALv2i32_v2i64:
8019 return AArch64::SABDLv2i32_v2i64;
8020 case AArch64::SABALv4i16_v4i32:
8021 return AArch64::SABDLv4i16_v4i32;
8022 case AArch64::SABALv4i32_v2i64:
8023 return AArch64::SABDLv4i32_v2i64;
8024 case AArch64::SABALv8i16_v4i32:
8025 return AArch64::SABDLv8i16_v4i32;
8026 case AArch64::SABALv8i8_v8i16:
8027 return AArch64::SABDLv8i8_v8i16;
8028 case AArch64::SABAv16i8:
8029 return AArch64::SABDv16i8;
8030 case AArch64::SABAv2i32:
8031 return AArch64::SABAv2i32;
8032 case AArch64::SABAv4i16:
8033 return AArch64::SABDv4i16;
8034 case AArch64::SABAv4i32:
8035 return AArch64::SABDv4i32;
8036 case AArch64::SABAv8i16:
8037 return AArch64::SABDv8i16;
8038 case AArch64::SABAv8i8:
8039 return AArch64::SABDv8i8;
8055 auto Match = [&](
int Opcode,
int Operand,
unsigned Pattern) ->
bool {
8067 assert(
false &&
"Unsupported FP instruction in combiner\n");
8069 case AArch64::FADDHrr:
8071 "FADDHrr does not have register operands");
8073 Found = Match(AArch64::FMULHrr, 1, MCP::FMULADDH_OP1);
8074 Found |= Match(AArch64::FMULHrr, 2, MCP::FMULADDH_OP2);
8076 case AArch64::FADDSrr:
8078 "FADDSrr does not have register operands");
8080 Found |= Match(AArch64::FMULSrr, 1, MCP::FMULADDS_OP1) ||
8081 Match(AArch64::FMULv1i32_indexed, 1, MCP::FMLAv1i32_indexed_OP1);
8083 Found |= Match(AArch64::FMULSrr, 2, MCP::FMULADDS_OP2) ||
8084 Match(AArch64::FMULv1i32_indexed, 2, MCP::FMLAv1i32_indexed_OP2);
8086 case AArch64::FADDDrr:
8087 Found |= Match(AArch64::FMULDrr, 1, MCP::FMULADDD_OP1) ||
8088 Match(AArch64::FMULv1i64_indexed, 1, MCP::FMLAv1i64_indexed_OP1);
8090 Found |= Match(AArch64::FMULDrr, 2, MCP::FMULADDD_OP2) ||
8091 Match(AArch64::FMULv1i64_indexed, 2, MCP::FMLAv1i64_indexed_OP2);
8093 case AArch64::FADDv4f16:
8094 Found |= Match(AArch64::FMULv4i16_indexed, 1, MCP::FMLAv4i16_indexed_OP1) ||
8095 Match(AArch64::FMULv4f16, 1, MCP::FMLAv4f16_OP1);
8097 Found |= Match(AArch64::FMULv4i16_indexed, 2, MCP::FMLAv4i16_indexed_OP2) ||
8098 Match(AArch64::FMULv4f16, 2, MCP::FMLAv4f16_OP2);
8100 case AArch64::FADDv8f16:
8101 Found |= Match(AArch64::FMULv8i16_indexed, 1, MCP::FMLAv8i16_indexed_OP1) ||
8102 Match(AArch64::FMULv8f16, 1, MCP::FMLAv8f16_OP1);
8104 Found |= Match(AArch64::FMULv8i16_indexed, 2, MCP::FMLAv8i16_indexed_OP2) ||
8105 Match(AArch64::FMULv8f16, 2, MCP::FMLAv8f16_OP2);
8107 case AArch64::FADDv2f32:
8108 Found |= Match(AArch64::FMULv2i32_indexed, 1, MCP::FMLAv2i32_indexed_OP1) ||
8109 Match(AArch64::FMULv2f32, 1, MCP::FMLAv2f32_OP1);
8111 Found |= Match(AArch64::FMULv2i32_indexed, 2, MCP::FMLAv2i32_indexed_OP2) ||
8112 Match(AArch64::FMULv2f32, 2, MCP::FMLAv2f32_OP2);
8114 case AArch64::FADDv2f64:
8115 Found |= Match(AArch64::FMULv2i64_indexed, 1, MCP::FMLAv2i64_indexed_OP1) ||
8116 Match(AArch64::FMULv2f64, 1, MCP::FMLAv2f64_OP1);
8118 Found |= Match(AArch64::FMULv2i64_indexed, 2, MCP::FMLAv2i64_indexed_OP2) ||
8119 Match(AArch64::FMULv2f64, 2, MCP::FMLAv2f64_OP2);
8121 case AArch64::FADDv4f32:
8122 Found |= Match(AArch64::FMULv4i32_indexed, 1, MCP::FMLAv4i32_indexed_OP1) ||
8123 Match(AArch64::FMULv4f32, 1, MCP::FMLAv4f32_OP1);
8125 Found |= Match(AArch64::FMULv4i32_indexed, 2, MCP::FMLAv4i32_indexed_OP2) ||
8126 Match(AArch64::FMULv4f32, 2, MCP::FMLAv4f32_OP2);
8128 case AArch64::FSUBHrr:
8129 Found = Match(AArch64::FMULHrr, 1, MCP::FMULSUBH_OP1);
8130 Found |= Match(AArch64::FMULHrr, 2, MCP::FMULSUBH_OP2);
8131 Found |= Match(AArch64::FNMULHrr, 1, MCP::FNMULSUBH_OP1);
8133 case AArch64::FSUBSrr:
8134 Found = Match(AArch64::FMULSrr, 1, MCP::FMULSUBS_OP1);
8136 Found |= Match(AArch64::FMULSrr, 2, MCP::FMULSUBS_OP2) ||
8137 Match(AArch64::FMULv1i32_indexed, 2, MCP::FMLSv1i32_indexed_OP2);
8139 Found |= Match(AArch64::FNMULSrr, 1, MCP::FNMULSUBS_OP1);
8141 case AArch64::FSUBDrr:
8142 Found = Match(AArch64::FMULDrr, 1, MCP::FMULSUBD_OP1);
8144 Found |= Match(AArch64::FMULDrr, 2, MCP::FMULSUBD_OP2) ||
8145 Match(AArch64::FMULv1i64_indexed, 2, MCP::FMLSv1i64_indexed_OP2);
8147 Found |= Match(AArch64::FNMULDrr, 1, MCP::FNMULSUBD_OP1);
8149 case AArch64::FSUBv4f16:
8150 Found |= Match(AArch64::FMULv4i16_indexed, 2, MCP::FMLSv4i16_indexed_OP2) ||
8151 Match(AArch64::FMULv4f16, 2, MCP::FMLSv4f16_OP2);
8153 Found |= Match(AArch64::FMULv4i16_indexed, 1, MCP::FMLSv4i16_indexed_OP1) ||
8154 Match(AArch64::FMULv4f16, 1, MCP::FMLSv4f16_OP1);
8156 case AArch64::FSUBv8f16:
8157 Found |= Match(AArch64::FMULv8i16_indexed, 2, MCP::FMLSv8i16_indexed_OP2) ||
8158 Match(AArch64::FMULv8f16, 2, MCP::FMLSv8f16_OP2);
8160 Found |= Match(AArch64::FMULv8i16_indexed, 1, MCP::FMLSv8i16_indexed_OP1) ||
8161 Match(AArch64::FMULv8f16, 1, MCP::FMLSv8f16_OP1);
8163 case AArch64::FSUBv2f32:
8164 Found |= Match(AArch64::FMULv2i32_indexed, 2, MCP::FMLSv2i32_indexed_OP2) ||
8165 Match(AArch64::FMULv2f32, 2, MCP::FMLSv2f32_OP2);
8167 Found |= Match(AArch64::FMULv2i32_indexed, 1, MCP::FMLSv2i32_indexed_OP1) ||
8168 Match(AArch64::FMULv2f32, 1, MCP::FMLSv2f32_OP1);
8170 case AArch64::FSUBv2f64:
8171 Found |= Match(AArch64::FMULv2i64_indexed, 2, MCP::FMLSv2i64_indexed_OP2) ||
8172 Match(AArch64::FMULv2f64, 2, MCP::FMLSv2f64_OP2);
8174 Found |= Match(AArch64::FMULv2i64_indexed, 1, MCP::FMLSv2i64_indexed_OP1) ||
8175 Match(AArch64::FMULv2f64, 1, MCP::FMLSv2f64_OP1);
8177 case AArch64::FSUBv4f32:
8178 Found |= Match(AArch64::FMULv4i32_indexed, 2, MCP::FMLSv4i32_indexed_OP2) ||
8179 Match(AArch64::FMULv4f32, 2, MCP::FMLSv4f32_OP2);
8181 Found |= Match(AArch64::FMULv4i32_indexed, 1, MCP::FMLSv4i32_indexed_OP1) ||
8182 Match(AArch64::FMULv4f32, 1, MCP::FMLSv4f32_OP1);
8193 auto Match = [&](
unsigned Opcode,
int Operand,
unsigned Pattern) ->
bool {
8200 if (
MI &&
MI->getOpcode() == TargetOpcode::COPY &&
8201 MI->getOperand(1).getReg().isVirtual())
8203 if (
MI &&
MI->getOpcode() == Opcode) {
8215 case AArch64::FMULv2f32:
8216 Found = Match(AArch64::DUPv2i32lane, 1, MCP::FMULv2i32_indexed_OP1);
8217 Found |= Match(AArch64::DUPv2i32lane, 2, MCP::FMULv2i32_indexed_OP2);
8219 case AArch64::FMULv2f64:
8220 Found = Match(AArch64::DUPv2i64lane, 1, MCP::FMULv2i64_indexed_OP1);
8221 Found |= Match(AArch64::DUPv2i64lane, 2, MCP::FMULv2i64_indexed_OP2);
8223 case AArch64::FMULv4f16:
8224 Found = Match(AArch64::DUPv4i16lane, 1, MCP::FMULv4i16_indexed_OP1);
8225 Found |= Match(AArch64::DUPv4i16lane, 2, MCP::FMULv4i16_indexed_OP2);
8227 case AArch64::FMULv4f32:
8228 Found = Match(AArch64::DUPv4i32lane, 1, MCP::FMULv4i32_indexed_OP1);
8229 Found |= Match(AArch64::DUPv4i32lane, 2, MCP::FMULv4i32_indexed_OP2);
8231 case AArch64::FMULv8f16:
8232 Found = Match(AArch64::DUPv8i16lane, 1, MCP::FMULv8i16_indexed_OP1);
8233 Found |= Match(AArch64::DUPv8i16lane, 2, MCP::FMULv8i16_indexed_OP2);
8246 auto Match = [&](
unsigned Opcode,
unsigned Pattern) ->
bool {
8249 if (
MI !=
nullptr && (
MI->getOpcode() == Opcode) &&
8264 case AArch64::FNEGDr:
8266 case AArch64::FNEGSr:
8398 case AArch64::SUBWrr:
8399 case AArch64::SUBSWrr:
8400 case AArch64::SUBXrr:
8401 case AArch64::SUBSXrr:
8446 unsigned LoadLaneOpCode,
unsigned NumLanes) {
8469 while (!RemainingLanes.
empty() && CurrInstr &&
8470 CurrInstr->getOpcode() == LoadLaneOpCode &&
8472 CurrInstr->getNumOperands() == 4) {
8473 RemainingLanes.
erase(CurrInstr->getOperand(2).getImm());
8479 if (!RemainingLanes.
empty())
8483 if (CurrInstr->getOpcode() != TargetOpcode::SUBREG_TO_REG)
8487 auto Lane0LoadReg = CurrInstr->getOperand(1).getReg();
8488 unsigned SingleLaneSizeInBits = 128 / NumLanes;
8489 if (
TRI->getRegSizeInBits(Lane0LoadReg, MRI) != SingleLaneSizeInBits)
8505 RemainingLoadInstrs.
insert(LoadInstrs.
begin(), LoadInstrs.
end());
8508 for (; MBBItr !=
MBB->begin() && RemainingSteps > 0 &&
8509 !RemainingLoadInstrs.
empty();
8510 --MBBItr, --RemainingSteps) {
8514 RemainingLoadInstrs.
erase(&CurrInstr);
8524 if (RemainingSteps == 0 && !RemainingLoadInstrs.
empty())
8550 case AArch64::LD1i32:
8552 case AArch64::LD1i16:
8554 case AArch64::LD1i8:
8570 unsigned Pattern,
unsigned NumLanes) {
8578 for (
unsigned i = 0; i < NumLanes - 1; ++i) {
8586 return A->getOperand(2).getImm() >
B->getOperand(2).getImm();
8592 auto LoadToLaneInstrsAscending =
llvm::reverse(LoadToLaneInstrs);
8598 auto CreateLD1Instruction = [&](
MachineInstr *OriginalInstr,
8599 Register SrcRegister,
unsigned Lane,
8601 bool OffsetRegisterKillState) {
8610 InstrIdxForVirtReg.
insert(std::make_pair(NewRegister, InsInstrs.
size()));
8611 InsInstrs.
push_back(LoadIndexIntoRegister);
8617 auto CreateLDRInstruction =
8623 Opcode = AArch64::LDRSui;
8626 Opcode = AArch64::LDRHui;
8629 Opcode = AArch64::LDRBui;
8633 "Got unsupported number of lanes in machine-combiner gather pattern");
8643 auto LanesToLoadToReg0 =
8645 LoadToLaneInstrsAscending.begin() + NumLanes / 2);
8646 Register PrevReg = SubregToReg->getOperand(0).getReg();
8648 const MachineOperand &OffsetRegOperand = LoadInstr->getOperand(3);
8649 PrevReg = CreateLD1Instruction(LoadInstr, PrevReg, Index + 1,
8650 OffsetRegOperand.
getReg(),
8651 OffsetRegOperand.
isKill());
8658 MachineInstr *Lane0Load = *LoadToLaneInstrsAscending.begin();
8660 *std::next(LoadToLaneInstrsAscending.begin(), NumLanes / 2);
8667 CreateLDRInstruction(NumLanes, DestRegForMiddleIndex,
8668 OriginalSplitToLoadOffsetOperand.
getReg(),
8671 InstrIdxForVirtReg.
insert(
8672 std::make_pair(DestRegForMiddleIndex, InsInstrs.
size()));
8673 InsInstrs.
push_back(MiddleIndexLoadInstr);
8678 unsigned SubregType;
8681 SubregType = AArch64::ssub;
8684 SubregType = AArch64::hsub;
8687 SubregType = AArch64::bsub;
8691 "Got invalid NumLanes for machine-combiner gather pattern");
8694 auto SubRegToRegInstr =
8696 DestRegForSubregToReg)
8699 InstrIdxForVirtReg.
insert(
8700 std::make_pair(DestRegForSubregToReg, InsInstrs.
size()));
8704 auto LanesToLoadToReg1 =
8706 LoadToLaneInstrsAscending.end());
8707 PrevReg = SubRegToRegInstr->getOperand(0).getReg();
8709 const MachineOperand &OffsetRegOperand = LoadInstr->getOperand(3);
8710 PrevReg = CreateLD1Instruction(LoadInstr, PrevReg, Index + 1,
8711 OffsetRegOperand.
getReg(),
8712 OffsetRegOperand.
isKill());
8715 if (Index == NumLanes / 2 - 2) {
8750bool AArch64InstrInfo::getMachineCombinerPatterns(
8752 bool DoRegPressureReduce)
const {
8773 DoRegPressureReduce);
8802 const Register *ReplacedAddend =
nullptr) {
8803 assert(IdxMulOpd == 1 || IdxMulOpd == 2);
8805 unsigned IdxOtherOpd = IdxMulOpd == 1 ? 2 : 1;
8808 Register SrcReg0 = MUL->getOperand(1).getReg();
8809 bool Src0IsKill = MUL->getOperand(1).isKill();
8810 Register SrcReg1 = MUL->getOperand(2).getReg();
8811 bool Src1IsKill = MUL->getOperand(2).isKill();
8815 if (ReplacedAddend) {
8817 SrcReg2 = *ReplacedAddend;
8844 .
addImm(MUL->getOperand(3).getImm());
8851 assert(
false &&
"Invalid FMA instruction kind \n");
8865 if (AArch64::FPR32RegClass.hasSubClassEq(RC))
8866 Opc = AArch64::FNMADDSrrr;
8867 else if (AArch64::FPR64RegClass.hasSubClassEq(RC))
8868 Opc = AArch64::FNMADDDrrr;
8902 unsigned IdxDupOp,
unsigned MulOpc,
8904 assert(((IdxDupOp == 1) || (IdxDupOp == 2)) &&
8905 "Invalid index of FMUL operand");
8913 if (Dup->
getOpcode() == TargetOpcode::COPY)
8922 unsigned IdxMulOp = IdxDupOp == 1 ? 2 : 1;
8963 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
8978 genNeg(MF, MRI,
TII, Root, InsInstrs, InstrIdxForVirtReg, MnegOpc, RC);
9005 genNeg(MF, MRI,
TII, Root, InsInstrs, InstrIdxForVirtReg, MnegOpc, RC);
9033 unsigned IdxMulOpd,
unsigned MaddOpc,
unsigned VR,
9035 assert(IdxMulOpd == 1 || IdxMulOpd == 2);
9039 Register SrcReg0 = MUL->getOperand(1).getReg();
9040 bool Src0IsKill = MUL->getOperand(1).isKill();
9041 Register SrcReg1 = MUL->getOperand(2).getReg();
9042 bool Src1IsKill = MUL->getOperand(2).isKill();
9072 assert(IdxOpd1 == 1 || IdxOpd1 == 2);
9073 unsigned IdxOtherOpd = IdxOpd1 == 1 ? 2 : 1;
9087 if (Opcode == AArch64::SUBSWrr)
9088 Opcode = AArch64::SUBWrr;
9089 else if (Opcode == AArch64::SUBSXrr)
9090 Opcode = AArch64::SUBXrr;
9092 assert((Opcode == AArch64::SUBWrr || Opcode == AArch64::SUBXrr) &&
9093 "Unexpected instruction opcode.");
9110 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
9117unsigned AArch64InstrInfo::getReduceOpcodeForAccumulator(
9118 unsigned int AccumulatorOpCode)
const {
9119 switch (AccumulatorOpCode) {
9120 case AArch64::UABALB_ZZZ_D:
9121 case AArch64::SABALB_ZZZ_D:
9122 case AArch64::UABALT_ZZZ_D:
9123 case AArch64::SABALT_ZZZ_D:
9124 return AArch64::ADD_ZZZ_D;
9125 case AArch64::UABALB_ZZZ_H:
9126 case AArch64::SABALB_ZZZ_H:
9127 case AArch64::UABALT_ZZZ_H:
9128 case AArch64::SABALT_ZZZ_H:
9129 return AArch64::ADD_ZZZ_H;
9130 case AArch64::UABALB_ZZZ_S:
9131 case AArch64::SABALB_ZZZ_S:
9132 case AArch64::UABALT_ZZZ_S:
9133 case AArch64::SABALT_ZZZ_S:
9134 return AArch64::ADD_ZZZ_S;
9135 case AArch64::UABALv16i8_v8i16:
9136 case AArch64::SABALv8i8_v8i16:
9137 case AArch64::SABAv8i16:
9138 case AArch64::UABAv8i16:
9139 return AArch64::ADDv8i16;
9140 case AArch64::SABALv2i32_v2i64:
9141 case AArch64::UABALv2i32_v2i64:
9142 case AArch64::SABALv4i32_v2i64:
9143 return AArch64::ADDv2i64;
9144 case AArch64::UABALv4i16_v4i32:
9145 case AArch64::SABALv4i16_v4i32:
9146 case AArch64::SABALv8i16_v4i32:
9147 case AArch64::SABAv4i32:
9148 case AArch64::UABAv4i32:
9149 return AArch64::ADDv4i32;
9150 case AArch64::UABALv4i32_v2i64:
9151 return AArch64::ADDv2i64;
9152 case AArch64::UABALv8i16_v4i32:
9153 return AArch64::ADDv4i32;
9154 case AArch64::UABALv8i8_v8i16:
9155 case AArch64::SABALv16i8_v8i16:
9156 return AArch64::ADDv8i16;
9157 case AArch64::UABAv16i8:
9158 case AArch64::SABAv16i8:
9159 return AArch64::ADDv16i8;
9160 case AArch64::UABAv4i16:
9161 case AArch64::SABAv4i16:
9162 return AArch64::ADDv4i16;
9163 case AArch64::UABAv2i32:
9164 case AArch64::SABAv2i32:
9165 return AArch64::ADDv2i32;
9166 case AArch64::UABAv8i8:
9167 case AArch64::SABAv8i8:
9168 return AArch64::ADDv8i8;
9177void AArch64InstrInfo::genAlternativeCodeSequence(
9187 MachineInstr *
MUL =
nullptr;
9194 DelInstrs, InstrIdxForVirtReg);
9200 InstrIdxForVirtReg);
9206 InstrIdxForVirtReg);
9215 Opc = AArch64::MADDWrrr;
9216 RC = &AArch64::GPR32RegClass;
9218 Opc = AArch64::MADDXrrr;
9219 RC = &AArch64::GPR64RegClass;
9230 Opc = AArch64::MADDWrrr;
9231 RC = &AArch64::GPR32RegClass;
9233 Opc = AArch64::MADDXrrr;
9234 RC = &AArch64::GPR64RegClass;
9248 unsigned BitSize, MovImm;
9251 MovImm = AArch64::MOVi32imm;
9252 RC = &AArch64::GPR32spRegClass;
9254 Opc = AArch64::MADDWrrr;
9255 RC = &AArch64::GPR32RegClass;
9257 MovImm = AArch64::MOVi64imm;
9258 RC = &AArch64::GPR64spRegClass;
9260 Opc = AArch64::MADDXrrr;
9261 RC = &AArch64::GPR64RegClass;
9276 if (Insn.
size() != 1)
9278 MachineInstrBuilder MIB1 =
9279 BuildMI(MF, MIMetadata(Root),
TII->get(MovImm), NewVR)
9282 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
9294 unsigned SubOpc, ZeroReg;
9296 SubOpc = AArch64::SUBWrr;
9297 SubRC = &AArch64::GPR32spRegClass;
9298 ZeroReg = AArch64::WZR;
9299 Opc = AArch64::MADDWrrr;
9300 RC = &AArch64::GPR32RegClass;
9302 SubOpc = AArch64::SUBXrr;
9303 SubRC = &AArch64::GPR64spRegClass;
9304 ZeroReg = AArch64::XZR;
9305 Opc = AArch64::MADDXrrr;
9306 RC = &AArch64::GPR64RegClass;
9310 MachineInstrBuilder MIB1 =
9311 BuildMI(MF, MIMetadata(Root),
TII->get(SubOpc), NewVR)
9315 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
9326 Opc = AArch64::MSUBWrrr;
9327 RC = &AArch64::GPR32RegClass;
9329 Opc = AArch64::MSUBXrrr;
9330 RC = &AArch64::GPR64RegClass;
9335 Opc = AArch64::MLAv8i8;
9336 RC = &AArch64::FPR64RegClass;
9340 Opc = AArch64::MLAv8i8;
9341 RC = &AArch64::FPR64RegClass;
9345 Opc = AArch64::MLAv16i8;
9346 RC = &AArch64::FPR128RegClass;
9350 Opc = AArch64::MLAv16i8;
9351 RC = &AArch64::FPR128RegClass;
9355 Opc = AArch64::MLAv4i16;
9356 RC = &AArch64::FPR64RegClass;
9360 Opc = AArch64::MLAv4i16;
9361 RC = &AArch64::FPR64RegClass;
9365 Opc = AArch64::MLAv8i16;
9366 RC = &AArch64::FPR128RegClass;
9370 Opc = AArch64::MLAv8i16;
9371 RC = &AArch64::FPR128RegClass;
9375 Opc = AArch64::MLAv2i32;
9376 RC = &AArch64::FPR64RegClass;
9380 Opc = AArch64::MLAv2i32;
9381 RC = &AArch64::FPR64RegClass;
9385 Opc = AArch64::MLAv4i32;
9386 RC = &AArch64::FPR128RegClass;
9390 Opc = AArch64::MLAv4i32;
9391 RC = &AArch64::FPR128RegClass;
9396 Opc = AArch64::MLAv8i8;
9397 RC = &AArch64::FPR64RegClass;
9399 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv8i8,
9403 Opc = AArch64::MLSv8i8;
9404 RC = &AArch64::FPR64RegClass;
9408 Opc = AArch64::MLAv16i8;
9409 RC = &AArch64::FPR128RegClass;
9411 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv16i8,
9415 Opc = AArch64::MLSv16i8;
9416 RC = &AArch64::FPR128RegClass;
9420 Opc = AArch64::MLAv4i16;
9421 RC = &AArch64::FPR64RegClass;
9423 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv4i16,
9427 Opc = AArch64::MLSv4i16;
9428 RC = &AArch64::FPR64RegClass;
9432 Opc = AArch64::MLAv8i16;
9433 RC = &AArch64::FPR128RegClass;
9435 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv8i16,
9439 Opc = AArch64::MLSv8i16;
9440 RC = &AArch64::FPR128RegClass;
9444 Opc = AArch64::MLAv2i32;
9445 RC = &AArch64::FPR64RegClass;
9447 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv2i32,
9451 Opc = AArch64::MLSv2i32;
9452 RC = &AArch64::FPR64RegClass;
9456 Opc = AArch64::MLAv4i32;
9457 RC = &AArch64::FPR128RegClass;
9459 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv4i32,
9463 Opc = AArch64::MLSv4i32;
9464 RC = &AArch64::FPR128RegClass;
9469 Opc = AArch64::MLAv4i16_indexed;
9470 RC = &AArch64::FPR64RegClass;
9474 Opc = AArch64::MLAv4i16_indexed;
9475 RC = &AArch64::FPR64RegClass;
9479 Opc = AArch64::MLAv8i16_indexed;
9480 RC = &AArch64::FPR128RegClass;
9484 Opc = AArch64::MLAv8i16_indexed;
9485 RC = &AArch64::FPR128RegClass;
9489 Opc = AArch64::MLAv2i32_indexed;
9490 RC = &AArch64::FPR64RegClass;
9494 Opc = AArch64::MLAv2i32_indexed;
9495 RC = &AArch64::FPR64RegClass;
9499 Opc = AArch64::MLAv4i32_indexed;
9500 RC = &AArch64::FPR128RegClass;
9504 Opc = AArch64::MLAv4i32_indexed;
9505 RC = &AArch64::FPR128RegClass;
9510 Opc = AArch64::MLAv4i16_indexed;
9511 RC = &AArch64::FPR64RegClass;
9513 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv4i16,
9517 Opc = AArch64::MLSv4i16_indexed;
9518 RC = &AArch64::FPR64RegClass;
9522 Opc = AArch64::MLAv8i16_indexed;
9523 RC = &AArch64::FPR128RegClass;
9525 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv8i16,
9529 Opc = AArch64::MLSv8i16_indexed;
9530 RC = &AArch64::FPR128RegClass;
9534 Opc = AArch64::MLAv2i32_indexed;
9535 RC = &AArch64::FPR64RegClass;
9537 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv2i32,
9541 Opc = AArch64::MLSv2i32_indexed;
9542 RC = &AArch64::FPR64RegClass;
9546 Opc = AArch64::MLAv4i32_indexed;
9547 RC = &AArch64::FPR128RegClass;
9549 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv4i32,
9553 Opc = AArch64::MLSv4i32_indexed;
9554 RC = &AArch64::FPR128RegClass;
9560 Opc = AArch64::FMADDHrrr;
9561 RC = &AArch64::FPR16RegClass;
9565 Opc = AArch64::FMADDSrrr;
9566 RC = &AArch64::FPR32RegClass;
9570 Opc = AArch64::FMADDDrrr;
9571 RC = &AArch64::FPR64RegClass;
9576 Opc = AArch64::FMADDHrrr;
9577 RC = &AArch64::FPR16RegClass;
9581 Opc = AArch64::FMADDSrrr;
9582 RC = &AArch64::FPR32RegClass;
9586 Opc = AArch64::FMADDDrrr;
9587 RC = &AArch64::FPR64RegClass;
9592 Opc = AArch64::FMLAv1i32_indexed;
9593 RC = &AArch64::FPR32RegClass;
9598 Opc = AArch64::FMLAv1i32_indexed;
9599 RC = &AArch64::FPR32RegClass;
9605 Opc = AArch64::FMLAv1i64_indexed;
9606 RC = &AArch64::FPR64RegClass;
9611 Opc = AArch64::FMLAv1i64_indexed;
9612 RC = &AArch64::FPR64RegClass;
9618 RC = &AArch64::FPR64RegClass;
9619 Opc = AArch64::FMLAv4i16_indexed;
9624 RC = &AArch64::FPR64RegClass;
9625 Opc = AArch64::FMLAv4f16;
9630 RC = &AArch64::FPR64RegClass;
9631 Opc = AArch64::FMLAv4i16_indexed;
9636 RC = &AArch64::FPR64RegClass;
9637 Opc = AArch64::FMLAv4f16;
9644 RC = &AArch64::FPR64RegClass;
9646 Opc = AArch64::FMLAv2i32_indexed;
9650 Opc = AArch64::FMLAv2f32;
9657 RC = &AArch64::FPR64RegClass;
9659 Opc = AArch64::FMLAv2i32_indexed;
9663 Opc = AArch64::FMLAv2f32;
9670 RC = &AArch64::FPR128RegClass;
9671 Opc = AArch64::FMLAv8i16_indexed;
9676 RC = &AArch64::FPR128RegClass;
9677 Opc = AArch64::FMLAv8f16;
9682 RC = &AArch64::FPR128RegClass;
9683 Opc = AArch64::FMLAv8i16_indexed;
9688 RC = &AArch64::FPR128RegClass;
9689 Opc = AArch64::FMLAv8f16;
9696 RC = &AArch64::FPR128RegClass;
9698 Opc = AArch64::FMLAv2i64_indexed;
9702 Opc = AArch64::FMLAv2f64;
9709 RC = &AArch64::FPR128RegClass;
9711 Opc = AArch64::FMLAv2i64_indexed;
9715 Opc = AArch64::FMLAv2f64;
9723 RC = &AArch64::FPR128RegClass;
9725 Opc = AArch64::FMLAv4i32_indexed;
9729 Opc = AArch64::FMLAv4f32;
9737 RC = &AArch64::FPR128RegClass;
9739 Opc = AArch64::FMLAv4i32_indexed;
9743 Opc = AArch64::FMLAv4f32;
9750 Opc = AArch64::FNMSUBHrrr;
9751 RC = &AArch64::FPR16RegClass;
9755 Opc = AArch64::FNMSUBSrrr;
9756 RC = &AArch64::FPR32RegClass;
9760 Opc = AArch64::FNMSUBDrrr;
9761 RC = &AArch64::FPR64RegClass;
9766 Opc = AArch64::FNMADDHrrr;
9767 RC = &AArch64::FPR16RegClass;
9771 Opc = AArch64::FNMADDSrrr;
9772 RC = &AArch64::FPR32RegClass;
9776 Opc = AArch64::FNMADDDrrr;
9777 RC = &AArch64::FPR64RegClass;
9782 Opc = AArch64::FMSUBHrrr;
9783 RC = &AArch64::FPR16RegClass;
9787 Opc = AArch64::FMSUBSrrr;
9788 RC = &AArch64::FPR32RegClass;
9792 Opc = AArch64::FMSUBDrrr;
9793 RC = &AArch64::FPR64RegClass;
9798 Opc = AArch64::FMLSv1i32_indexed;
9799 RC = &AArch64::FPR32RegClass;
9805 Opc = AArch64::FMLSv1i64_indexed;
9806 RC = &AArch64::FPR64RegClass;
9813 RC = &AArch64::FPR64RegClass;
9815 MachineInstrBuilder MIB1 =
9816 BuildMI(MF, MIMetadata(Root),
TII->get(AArch64::FNEGv4f16), NewVR)
9819 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
9821 Opc = AArch64::FMLAv4f16;
9825 Opc = AArch64::FMLAv4i16_indexed;
9832 RC = &AArch64::FPR64RegClass;
9833 Opc = AArch64::FMLSv4f16;
9838 RC = &AArch64::FPR64RegClass;
9839 Opc = AArch64::FMLSv4i16_indexed;
9846 RC = &AArch64::FPR64RegClass;
9848 Opc = AArch64::FMLSv2i32_indexed;
9852 Opc = AArch64::FMLSv2f32;
9860 RC = &AArch64::FPR128RegClass;
9862 MachineInstrBuilder MIB1 =
9863 BuildMI(MF, MIMetadata(Root),
TII->get(AArch64::FNEGv8f16), NewVR)
9866 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
9868 Opc = AArch64::FMLAv8f16;
9872 Opc = AArch64::FMLAv8i16_indexed;
9879 RC = &AArch64::FPR128RegClass;
9880 Opc = AArch64::FMLSv8f16;
9885 RC = &AArch64::FPR128RegClass;
9886 Opc = AArch64::FMLSv8i16_indexed;
9893 RC = &AArch64::FPR128RegClass;
9895 Opc = AArch64::FMLSv2i64_indexed;
9899 Opc = AArch64::FMLSv2f64;
9907 RC = &AArch64::FPR128RegClass;
9909 Opc = AArch64::FMLSv4i32_indexed;
9913 Opc = AArch64::FMLSv4f32;
9920 RC = &AArch64::FPR64RegClass;
9922 MachineInstrBuilder MIB1 =
9923 BuildMI(MF, MIMetadata(Root),
TII->get(AArch64::FNEGv2f32), NewVR)
9926 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
9928 Opc = AArch64::FMLAv2i32_indexed;
9932 Opc = AArch64::FMLAv2f32;
9940 RC = &AArch64::FPR128RegClass;
9942 MachineInstrBuilder MIB1 =
9943 BuildMI(MF, MIMetadata(Root),
TII->get(AArch64::FNEGv4f32), NewVR)
9946 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
9948 Opc = AArch64::FMLAv4i32_indexed;
9952 Opc = AArch64::FMLAv4f32;
9960 RC = &AArch64::FPR128RegClass;
9962 MachineInstrBuilder MIB1 =
9963 BuildMI(MF, MIMetadata(Root),
TII->get(AArch64::FNEGv2f64), NewVR)
9966 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
9968 Opc = AArch64::FMLAv2i64_indexed;
9972 Opc = AArch64::FMLAv2f64;
9984 &AArch64::FPR128RegClass, MRI);
9993 &AArch64::FPR128RegClass, MRI);
10002 &AArch64::FPR128_loRegClass, MRI);
10007 unsigned IdxDupOp =
10011 &AArch64::FPR128RegClass, MRI);
10016 unsigned IdxDupOp =
10020 &AArch64::FPR128_loRegClass, MRI);
10054 for (
auto *
MI : InsInstrs)
10055 MI->setFlags(Flags);
10096 bool IsNegativeBranch =
false;
10097 bool IsTestAndBranch =
false;
10098 unsigned TargetBBInMI = 0;
10099 switch (
MI.getOpcode()) {
10103 case AArch64::CBWPri:
10104 case AArch64::CBXPri:
10105 case AArch64::CBBAssertExt:
10106 case AArch64::CBHAssertExt:
10107 case AArch64::CBWPrr:
10108 case AArch64::CBXPrr:
10110 case AArch64::CBZW:
10111 case AArch64::CBZX:
10114 case AArch64::CBNZW:
10115 case AArch64::CBNZX:
10117 IsNegativeBranch =
true;
10119 case AArch64::TBZW:
10120 case AArch64::TBZX:
10122 IsTestAndBranch =
true;
10124 case AArch64::TBNZW:
10125 case AArch64::TBNZX:
10127 IsNegativeBranch =
true;
10128 IsTestAndBranch =
true;
10134 if (IsTestAndBranch &&
MI.getOperand(1).getImm())
10138 assert(
MI.getParent() &&
"Incomplete machine instruction\n");
10151 while (
DefMI->isCopy()) {
10162 switch (
DefMI->getOpcode()) {
10166 case AArch64::ANDWri:
10167 case AArch64::ANDXri: {
10168 if (IsTestAndBranch)
10175 bool Is32Bit = (
DefMI->getOpcode() == AArch64::ANDWri);
10177 DefMI->getOperand(2).getImm(), Is32Bit ? 32 : 64);
10193 unsigned Opc = (
Imm < 32)
10194 ? (IsNegativeBranch ? AArch64::TBNZW : AArch64::TBZW)
10195 : (IsNegativeBranch ? AArch64::TBNZX : AArch64::TBZX);
10208 if (!Is32Bit &&
Imm < 32)
10210 MI.eraseFromParent();
10214 case AArch64::CSINCWr:
10215 case AArch64::CSINCXr: {
10216 if (!(
DefMI->getOperand(1).getReg() == AArch64::WZR &&
10217 DefMI->getOperand(2).getReg() == AArch64::WZR) &&
10218 !(
DefMI->getOperand(1).getReg() == AArch64::XZR &&
10219 DefMI->getOperand(2).getReg() == AArch64::XZR))
10222 if (
DefMI->findRegisterDefOperandIdx(AArch64::NZCV,
nullptr,
10235 if (IsNegativeBranch)
10238 MI.eraseFromParent();
10244std::pair<unsigned, unsigned>
10245AArch64InstrInfo::decomposeMachineOperandsTargetFlags(
unsigned TF)
const {
10247 return std::make_pair(TF & Mask, TF & ~Mask);
10251AArch64InstrInfo::getSerializableDirectMachineOperandTargetFlags()
const {
10254 static const std::pair<unsigned, const char *> TargetFlags[] = {
10255 {MO_PAGE,
"aarch64-page"}, {
MO_PAGEOFF,
"aarch64-pageoff"},
10256 {
MO_G3,
"aarch64-g3"}, {
MO_G2,
"aarch64-g2"},
10257 {
MO_G1,
"aarch64-g1"}, {
MO_G0,
"aarch64-g0"},
10263AArch64InstrInfo::getSerializableBitmaskMachineOperandTargetFlags()
const {
10264 using namespace AArch64II;
10266 static const std::pair<unsigned, const char *> TargetFlags[] = {
10268 {
MO_GOT,
"aarch64-got"},
10269 {
MO_NC,
"aarch64-nc"},
10270 {
MO_S,
"aarch64-s"},
10271 {
MO_TLS,
"aarch64-tls"},
10281AArch64InstrInfo::getSerializableMachineMemOperandTargetFlags()
const {
10282 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10416 std::vector<outliner::Candidate> &RepeatedSequenceLocs,
10431 return C.isAvailableInsideSeq(AArch64::FP,
TRI);
10439 const AArch64RegisterInfo *ARI =
10440 static_cast<const AArch64RegisterInfo *
>(&
TRI);
10443 for (
unsigned Reg : AArch64::GPR64RegClass) {
10445 Reg != AArch64::LR &&
10446 Reg != AArch64::X16 &&
10447 Reg != AArch64::X17 &&
10448 C.isAvailableAcrossAndOutOfSeq(
Reg,
TRI) &&
10449 C.isAvailableInsideSeq(
Reg,
TRI))
10480 return SubtargetA.hasV8_3aOps() == SubtargetB.hasV8_3aOps();
10483std::optional<std::unique_ptr<outliner::OutlinedFunction>>
10484AArch64InstrInfo::getOutliningCandidateInfo(
10486 std::vector<outliner::Candidate> &RepeatedSequenceLocs,
10487 unsigned MinRepeats)
const {
10488 unsigned SequenceSize = 0;
10489 for (
auto &
MI : RepeatedSequenceLocs[0])
10492 unsigned NumBytesToCreateFrame = 0;
10498 MachineInstr &LastMI = RepeatedSequenceLocs[0].back();
10499 MachineInstr &FirstMI = RepeatedSequenceLocs[0].front();
10500 if (LastMI.
getOpcode() == AArch64::ADRP &&
10503 return std::nullopt;
10508 if ((FirstMI.
getOpcode() == AArch64::ADDXri ||
10509 FirstMI.
getOpcode() == AArch64::LDRXui) &&
10512 return std::nullopt;
10523 if (std::adjacent_find(
10524 RepeatedSequenceLocs.begin(), RepeatedSequenceLocs.end(),
10525 [](
const outliner::Candidate &a,
const outliner::Candidate &b) {
10528 if (outliningCandidatesSigningScopeConsensus(a, b) &&
10529 outliningCandidatesSigningKeyConsensus(a, b) &&
10530 outliningCandidatesV8_3OpsConsensus(a, b)) {
10534 }) != RepeatedSequenceLocs.end()) {
10535 return std::nullopt;
10552 unsigned NumBytesToCheckLRInTCEpilogue = 0;
10553 const auto RASignCondition = RepeatedSequenceLocs[0]
10556 ->getSignReturnAddressCondition();
10559 NumBytesToCreateFrame += 8;
10562 auto LRCheckMethod = Subtarget.getAuthenticatedLRCheckMethod(
10563 *RepeatedSequenceLocs[0].getMF());
10564 NumBytesToCheckLRInTCEpilogue =
10568 if (isTailCallReturnInst(RepeatedSequenceLocs[0].
back()))
10569 SequenceSize += NumBytesToCheckLRInTCEpilogue;
10577 for (
auto &
MI :
C) {
10578 if (
MI.modifiesRegister(AArch64::SP, &
TRI)) {
10579 switch (
MI.getOpcode()) {
10580 case AArch64::ADDXri:
10581 case AArch64::ADDWri:
10582 assert(
MI.getNumOperands() == 4 &&
"Wrong number of operands");
10583 assert(
MI.getOperand(2).isImm() &&
10584 "Expected operand to be immediate");
10585 assert(
MI.getOperand(1).isReg() &&
10586 "Expected operand to be a register");
10590 if (
MI.getOperand(1).getReg() == AArch64::SP)
10591 SPValue +=
MI.getOperand(2).getImm();
10595 case AArch64::SUBXri:
10596 case AArch64::SUBWri:
10597 assert(
MI.getNumOperands() == 4 &&
"Wrong number of operands");
10598 assert(
MI.getOperand(2).isImm() &&
10599 "Expected operand to be immediate");
10600 assert(
MI.getOperand(1).isReg() &&
10601 "Expected operand to be a register");
10605 if (
MI.getOperand(1).getReg() == AArch64::SP)
10606 SPValue -=
MI.getOperand(2).getImm();
10623 if (RepeatedSequenceLocs.size() < MinRepeats)
10624 return std::nullopt;
10628 unsigned FlagsSetInAll = 0xF;
10632 FlagsSetInAll &=
C.Flags;
10634 unsigned LastInstrOpcode = RepeatedSequenceLocs[0].back().getOpcode();
10637 auto SetCandidateCallInfo =
10638 [&RepeatedSequenceLocs](
unsigned CallID,
unsigned NumBytesForCall) {
10640 C.setCallInfo(CallID, NumBytesForCall);
10644 NumBytesToCreateFrame += 4;
10652 unsigned CFICount = 0;
10653 for (
auto &
I : RepeatedSequenceLocs[0]) {
10654 if (
I.isCFIInstruction())
10664 std::vector<MCCFIInstruction> CFIInstructions =
10665 C.getMF()->getFrameInstructions();
10667 if (CFICount > 0 && CFICount != CFIInstructions.size())
10668 return std::nullopt;
10676 if (!
MI.modifiesRegister(AArch64::SP, &
TRI) &&
10677 !
MI.readsRegister(AArch64::SP, &
TRI))
10683 if (
MI.modifiesRegister(AArch64::SP, &
TRI))
10688 if (
MI.mayLoadOrStore()) {
10691 bool OffsetIsScalable;
10695 if (!getMemOperandWithOffset(
MI,
Base,
Offset, OffsetIsScalable, &
TRI) ||
10696 !
Base->isReg() ||
Base->getReg() != AArch64::SP)
10700 if (OffsetIsScalable)
10708 TypeSize Scale(0U,
false), DummyWidth(0U,
false);
10709 getMemOpInfo(
MI.getOpcode(), Scale, DummyWidth, MinOffset, MaxOffset);
10712 if (
Offset < MinOffset * (int64_t)Scale.getFixedValue() ||
10713 Offset > MaxOffset * (int64_t)Scale.getFixedValue())
10728 bool AllStackInstrsSafe =
10733 if (RepeatedSequenceLocs[0].
back().isTerminator()) {
10735 NumBytesToCreateFrame = 0;
10736 unsigned NumBytesForCall = 4 + NumBytesToCheckLRInTCEpilogue;
10740 else if (LastInstrOpcode == AArch64::BL ||
10741 ((LastInstrOpcode == AArch64::BLR ||
10742 LastInstrOpcode == AArch64::BLRNoIP) &&
10746 NumBytesToCreateFrame = NumBytesToCheckLRInTCEpilogue;
10754 unsigned NumBytesNoStackCalls = 0;
10755 std::vector<outliner::Candidate> CandidatesWithoutStackFixups;
10761 ?
C.isAvailableAcrossAndOutOfSeq(AArch64::LR,
TRI)
10770 C.getMF()->getFunction().hasFnAttribute(Attribute::NoReturn);
10773 if (LRAvailable && !IsNoReturn) {
10774 NumBytesNoStackCalls += 4;
10776 CandidatesWithoutStackFixups.push_back(
C);
10781 else if (findRegisterToSaveLRTo(
C)) {
10782 NumBytesNoStackCalls += 12;
10784 CandidatesWithoutStackFixups.push_back(
C);
10789 else if (
C.isAvailableInsideSeq(AArch64::SP,
TRI)) {
10790 NumBytesNoStackCalls += 12;
10792 CandidatesWithoutStackFixups.push_back(
C);
10798 NumBytesNoStackCalls += SequenceSize;
10805 if (!AllStackInstrsSafe ||
10806 NumBytesNoStackCalls <= RepeatedSequenceLocs.size() * 12) {
10807 RepeatedSequenceLocs = CandidatesWithoutStackFixups;
10809 if (RepeatedSequenceLocs.size() < MinRepeats)
10810 return std::nullopt;
10863 (!
C.isAvailableAcrossAndOutOfSeq(AArch64::LR,
TRI) ||
10864 !findRegisterToSaveLRTo(
C));
10870 if (RepeatedSequenceLocs.size() < MinRepeats)
10871 return std::nullopt;
10880 bool ModStackToSaveLR =
false;
10883 ModStackToSaveLR =
true;
10892 ModStackToSaveLR =
true;
10894 if (ModStackToSaveLR) {
10896 if (!AllStackInstrsSafe)
10897 return std::nullopt;
10900 NumBytesToCreateFrame += 8;
10904 RepeatedSequenceLocs,
TRI))
10905 NumBytesToCreateFrame += 4;
10912 return std::nullopt;
10914 return std::make_unique<outliner::OutlinedFunction>(
10915 RepeatedSequenceLocs, SequenceSize, NumBytesToCreateFrame, FrameID);
10918void AArch64InstrInfo::mergeOutliningCandidateAttributes(
10919 Function &
F, std::vector<outliner::Candidate> &Candidates)
const {
10923 const auto &CFn = Candidates.front().getMF()->getFunction();
10925 if (CFn.hasFnAttribute(
"ptrauth-returns"))
10926 F.addFnAttr(CFn.getFnAttribute(
"ptrauth-returns"));
10927 if (CFn.hasFnAttribute(
"ptrauth-auth-traps"))
10928 F.addFnAttr(CFn.getFnAttribute(
"ptrauth-auth-traps"));
10931 if (CFn.hasFnAttribute(
"sign-return-address"))
10932 F.addFnAttr(CFn.getFnAttribute(
"sign-return-address"));
10933 if (CFn.hasFnAttribute(
"sign-return-address-key"))
10934 F.addFnAttr(CFn.getFnAttribute(
"sign-return-address-key"));
10936 AArch64GenInstrInfo::mergeOutliningCandidateAttributes(
F, Candidates);
10939bool AArch64InstrInfo::isFunctionSafeToOutlineFrom(
10944 if (!OutlineFromLinkOnceODRs &&
F.hasLinkOnceODRLinkage())
10951 if (
F.hasSection())
10957 AArch64FunctionInfo *AFI = MF.
getInfo<AArch64FunctionInfo>();
10958 if (!AFI || AFI->
hasRedZone().value_or(
true))
10978 unsigned &Flags)
const {
10980 "Must track liveness!");
10982 std::pair<MachineBasicBlock::iterator, MachineBasicBlock::iterator>>
10997 auto AreAllUnsafeRegsDead = [&LRU]() {
10998 return LRU.available(AArch64::W16) && LRU.available(AArch64::W17) &&
10999 LRU.available(AArch64::NZCV);
11014 bool LRAvailableEverywhere =
true;
11016 LRU.addLiveOuts(
MBB);
11018 auto UpdateWholeMBBFlags = [&
Flags](
const MachineInstr &
MI) {
11019 if (
MI.isCall() && !
MI.isTerminator())
11025 auto CreateNewRangeStartingAt =
11026 [&RangeBegin, &RangeEnd,
11028 RangeBegin = NewBegin;
11029 RangeEnd = std::next(RangeBegin);
11032 auto SaveRangeIfNonEmpty = [&RangeLen, &
Ranges, &RangeBegin, &RangeEnd]() {
11038 if (!RangeBegin.isEnd() && RangeBegin->isBundledWithPred())
11040 if (!RangeEnd.isEnd() && RangeEnd->isBundledWithPred())
11042 Ranges.emplace_back(RangeBegin, RangeEnd);
11050 for (; FirstPossibleEndPt !=
MBB.
instr_rend(); ++FirstPossibleEndPt) {
11051 if (!FirstPossibleEndPt->isDebugInstr())
11052 LRU.stepBackward(*FirstPossibleEndPt);
11055 UpdateWholeMBBFlags(*FirstPossibleEndPt);
11056 if (AreAllUnsafeRegsDead())
11063 CreateNewRangeStartingAt(FirstPossibleEndPt->getIterator());
11068 if (!
MI.isDebugInstr())
11069 LRU.stepBackward(
MI);
11070 UpdateWholeMBBFlags(
MI);
11071 if (!AreAllUnsafeRegsDead()) {
11072 SaveRangeIfNonEmpty();
11073 CreateNewRangeStartingAt(
MI.getIterator());
11076 LRAvailableEverywhere &= LRU.available(AArch64::LR);
11080 RangeBegin =
MI.getIterator();
11081 if (!
MI.isDebugInstr())
11086 if (AreAllUnsafeRegsDead())
11087 SaveRangeIfNonEmpty();
11095 if (!LRAvailableEverywhere)
11103 unsigned Flags)
const {
11104 MachineInstr &
MI = *MIT;
11108 switch (
MI.getOpcode()) {
11109 case AArch64::PACM:
11110 case AArch64::PACIASP:
11111 case AArch64::PACIBSP:
11112 case AArch64::PACIASPPC:
11113 case AArch64::PACIBSPPC:
11114 case AArch64::AUTIASP:
11115 case AArch64::AUTIBSP:
11116 case AArch64::AUTIASPPCi:
11117 case AArch64::AUTIASPPCr:
11118 case AArch64::AUTIBSPPCi:
11119 case AArch64::AUTIBSPPCr:
11120 case AArch64::RETAA:
11121 case AArch64::RETAB:
11122 case AArch64::RETAASPPCi:
11123 case AArch64::RETAASPPCr:
11124 case AArch64::RETABSPPCi:
11125 case AArch64::RETABSPPCr:
11126 case AArch64::EMITBKEY:
11127 case AArch64::PAUTH_PROLOGUE:
11128 case AArch64::PAUTH_EPILOGUE:
11138 if (
MI.isCFIInstruction())
11142 if (
MI.isTerminator())
11148 for (
const MachineOperand &MOP :
MI.operands()) {
11151 assert(!MOP.isCFIIndex());
11154 if (MOP.isReg() && !MOP.isImplicit() &&
11155 (MOP.getReg() == AArch64::LR || MOP.getReg() == AArch64::W30))
11162 if (
MI.getOpcode() == AArch64::ADRP)
11182 for (
const MachineOperand &MOP :
MI.operands()) {
11183 if (MOP.isGlobal()) {
11191 if (Callee &&
Callee->getName() ==
"\01_mcount")
11199 if (
MI.getOpcode() == AArch64::BLR ||
11200 MI.getOpcode() == AArch64::BLRNoIP ||
MI.getOpcode() == AArch64::BL)
11204 return UnknownCallOutlineType;
11212 return UnknownCallOutlineType;
11220 return UnknownCallOutlineType;
11241 for (MachineInstr &
MI :
MBB) {
11242 const MachineOperand *
Base;
11243 TypeSize Width(0,
false);
11245 bool OffsetIsScalable;
11248 if (!
MI.mayLoadOrStore() ||
11251 (
Base->isReg() &&
Base->getReg() != AArch64::SP))
11255 TypeSize Scale(0U,
false);
11256 int64_t Dummy1, Dummy2;
11259 assert(StackOffsetOperand.
isImm() &&
"Stack offset wasn't immediate!");
11261 assert(Scale != 0 &&
"Unexpected opcode!");
11262 assert(!OffsetIsScalable &&
"Expected offset to be a byte offset");
11267 int64_t NewImm = (
Offset + 16) / (int64_t)Scale.getFixedValue();
11268 StackOffsetOperand.
setImm(NewImm);
11274 bool ShouldSignReturnAddr) {
11275 if (!ShouldSignReturnAddr)
11283void AArch64InstrInfo::buildOutlinedFrame(
11287 AArch64FunctionInfo *FI = MF.
getInfo<AArch64FunctionInfo>();
11295 unsigned TailOpcode;
11297 TailOpcode = AArch64::TCRETURNdi;
11301 TailOpcode = AArch64::TCRETURNriALL;
11312 bool IsLeafFunction =
true;
11315 auto IsNonTailCall = [](
const MachineInstr &
MI) {
11316 return MI.isCall() && !
MI.isReturn();
11326 "Can only fix up stack references once");
11327 fixupPostOutline(
MBB);
11329 IsLeafFunction =
false;
11340 Et = std::prev(
MBB.
end());
11371 CFIBuilder.buildDefCFA(AArch64::FP, 16);
11372 CFIBuilder.buildOffset(AArch64::LR, -8);
11373 CFIBuilder.buildOffset(AArch64::FP, -16);
11392 if (MF.
getInfo<AArch64FunctionInfo>()->needsDwarfUnwindInfo(MF)) {
11396 CFIBuilder.buildDefCFAOffset(16);
11400 CFIBuilder.buildOffset(AArch64::LR, -16);
11415 RASignCondition, !IsLeafFunction);
11444 fixupPostOutline(
MBB);
11455 .addGlobalAddress(
M.getNamedValue(MF.
getName()))
11465 .addGlobalAddress(
M.getNamedValue(MF.
getName())));
11474 MachineInstr *Save;
11475 MachineInstr *Restore;
11481 assert(
Reg &&
"No callee-saved register available?");
11515 .addGlobalAddress(
M.getNamedValue(MF.
getName())));
11523bool AArch64InstrInfo::shouldOutlineFromFunctionByDefault(
11531 bool AllowSideEffects)
const {
11533 const AArch64Subtarget &STI = MF.
getSubtarget<AArch64Subtarget>();
11536 if (
TRI.isGeneralPurposeRegister(MF,
Reg)) {
11549 assert(STI.hasFPARMv8() &&
"Expected FP to be available.");
11555std::optional<DestSourcePair>
11560 if ((
MI.getOpcode() == AArch64::ORRWrs &&
11561 MI.getOperand(1).getReg() == AArch64::WZR &&
11562 MI.getOperand(3).getImm() == 0x0) ||
11563 (
MI.getOpcode() == AArch64::ORRWrr &&
11564 MI.getOperand(1).getReg() == AArch64::WZR)) {
11566 if ((
MI.getOperand(0).getReg().isPhysical() &&
11567 MI.findRegisterDefOperandIdx(
11570 (
MI.getOperand(0).getReg().isVirtual() &&
11571 !
MI.getOperand(0).getSubReg()))
11575 if (
MI.getOpcode() == AArch64::ORRXrs &&
11576 MI.getOperand(1).getReg() == AArch64::XZR &&
11577 MI.getOperand(3).getImm() == 0x0)
11580 return std::nullopt;
11583std::optional<DestSourcePair>
11585 if ((
MI.getOpcode() == AArch64::ORRWrs &&
11586 MI.getOperand(1).getReg() == AArch64::WZR &&
11587 MI.getOperand(3).getImm() == 0x0) ||
11588 (
MI.getOpcode() == AArch64::ORRWrr &&
11589 MI.getOperand(1).getReg() == AArch64::WZR))
11591 return std::nullopt;
11594std::optional<RegImmPair>
11603 return std::nullopt;
11605 switch (
MI.getOpcode()) {
11607 return std::nullopt;
11608 case AArch64::SUBWri:
11609 case AArch64::SUBXri:
11610 case AArch64::SUBSWri:
11611 case AArch64::SUBSXri:
11614 case AArch64::ADDSWri:
11615 case AArch64::ADDSXri:
11616 case AArch64::ADDWri:
11617 case AArch64::ADDXri: {
11619 if (!
MI.getOperand(0).isReg() || !
MI.getOperand(1).isReg() ||
11620 !
MI.getOperand(2).isImm())
11621 return std::nullopt;
11622 int Shift =
MI.getOperand(3).getImm();
11623 assert((Shift == 0 || Shift == 12) &&
"Shift can be either 0 or 12");
11627 return RegImmPair{
MI.getOperand(1).getReg(),
Offset};
11633static std::optional<ParamLoadedValue>
11637 auto DestSrc =
TII->isCopyLikeInstr(
MI);
11639 return std::nullopt;
11641 Register DestReg = DestSrc->Destination->getReg();
11642 Register SrcReg = DestSrc->Source->getReg();
11645 return std::nullopt;
11650 if (DestReg == DescribedReg)
11654 if (
MI.getOpcode() == AArch64::ORRWrs &&
11655 TRI->isSuperRegister(DestReg, DescribedReg))
11659 if (
MI.getOpcode() == AArch64::ORRXrs &&
11660 TRI->isSubRegister(DestReg, DescribedReg)) {
11661 Register SrcSubReg =
TRI->getSubReg(SrcReg, AArch64::sub_32);
11665 assert(!
TRI->isSuperOrSubRegisterEq(DestReg, DescribedReg) &&
11666 "Unhandled ORR[XW]rs copy case");
11668 return std::nullopt;
11671bool AArch64InstrInfo::isFunctionSafeToSplit(
const MachineFunction &MF)
const {
11676 if (MF.
getInfo<AArch64FunctionInfo>()->hasRedZone().value_or(
true))
11682bool AArch64InstrInfo::isMBBSafeToSplitToCold(
11686 auto isAsmGoto = [](
const MachineInstr &
MI) {
11687 return MI.getOpcode() == AArch64::INLINEASM_BR;
11697 auto containsMBB = [&
MBB](
const MachineJumpTableEntry &JTE) {
11704 for (
const MachineInstr &
MI :
MBB) {
11705 switch (
MI.getOpcode()) {
11706 case TargetOpcode::G_BRJT:
11707 case AArch64::JumpTableDest32:
11708 case AArch64::JumpTableDest16:
11709 case AArch64::JumpTableDest8:
11720std::optional<ParamLoadedValue>
11725 switch (
MI.getOpcode()) {
11726 case AArch64::MOVZWi:
11727 case AArch64::MOVZXi: {
11730 if (!
TRI->isSuperRegisterEq(
MI.getOperand(0).getReg(),
Reg))
11731 return std::nullopt;
11733 if (!
MI.getOperand(1).isImm())
11734 return std::nullopt;
11735 int64_t Immediate =
MI.getOperand(1).getImm();
11736 int Shift =
MI.getOperand(2).getImm();
11740 case AArch64::ORRWrs:
11741 case AArch64::ORRXrs:
11748bool AArch64InstrInfo::isExtendLikelyToBeFolded(
11751 ExtMI.
getOpcode() == TargetOpcode::G_ZEXT ||
11752 ExtMI.
getOpcode() == TargetOpcode::G_ANYEXT);
11755 if (ExtMI.
getOpcode() == TargetOpcode::G_ANYEXT)
11765 return UserMI->
getOpcode() == TargetOpcode::G_PTR_ADD;
11768uint64_t AArch64InstrInfo::getElementSizeForOpcode(
unsigned Opc)
const {
11772bool AArch64InstrInfo::isPTestLikeOpcode(
unsigned Opc)
const {
11776bool AArch64InstrInfo::isWhileOpcode(
unsigned Opc)
const {
11781AArch64InstrInfo::getTailDuplicateSize(
CodeGenOptLevel OptLevel)
const {
11785bool AArch64InstrInfo::isLegalAddressingMode(
unsigned NumBytes, int64_t
Offset,
11786 unsigned Scale)
const {
11797 unsigned Shift =
Log2_64(NumBytes);
11798 if (NumBytes &&
Offset > 0 && (
Offset / NumBytes) <= (1LL << 12) - 1 &&
11806 return Scale == 1 || (Scale > 0 && Scale == NumBytes);
11811 return AArch64::BLRNoIP;
11813 return AArch64::BLR;
11819 auto Builder =
BuildMI(
MBB, InsertPt,
DL,
get(AArch64::PAUTH_EPILOGUE))
11840 Register TargetReg,
bool FrameSetup)
const {
11841 assert(TargetReg != AArch64::SP &&
"New top of stack cannot already be in SP");
11853 MF.
insert(MBBInsertPoint, LoopTestMBB);
11856 MF.
insert(MBBInsertPoint, LoopBodyMBB);
11858 MF.
insert(MBBInsertPoint, ExitMBB);
11868 BuildMI(*LoopTestMBB, LoopTestMBB->
end(),
DL,
TII->get(AArch64::SUBSXrx64),
11876 BuildMI(*LoopTestMBB, LoopTestMBB->
end(),
DL,
TII->get(AArch64::Bcc))
11882 BuildMI(*LoopBodyMBB, LoopBodyMBB->
end(),
DL,
TII->get(AArch64::LDRXui))
11899 BuildMI(*ExitMBB, ExitMBB->
end(),
DL,
TII->get(AArch64::ADDXri), AArch64::SP)
11918 MBB.addSuccessor(LoopTestMBB);
11924 return ExitMBB->
begin();
11930 const TargetInstrInfo *
TII;
11931 const TargetRegisterInfo *
TRI;
11932 MachineRegisterInfo &MRI;
11935 MachineBasicBlock *LoopBB;
11937 MachineInstr *CondBranch;
11939 MachineInstr *Comp;
11941 unsigned CompCounterOprNum;
11943 MachineInstr *Update;
11945 unsigned UpdateCounterOprNum;
11949 bool IsUpdatePriorComp;
11952 SmallVector<MachineOperand, 4>
Cond;
11955 AArch64PipelinerLoopInfo(MachineBasicBlock *LoopBB, MachineInstr *CondBranch,
11956 MachineInstr *Comp,
unsigned CompCounterOprNum,
11957 MachineInstr *Update,
unsigned UpdateCounterOprNum,
11958 Register Init,
bool IsUpdatePriorComp,
11959 const SmallVectorImpl<MachineOperand> &
Cond)
11961 TII(MF->getSubtarget().getInstrInfo()),
11962 TRI(MF->getSubtarget().getRegisterInfo()), MRI(MF->getRegInfo()),
11963 LoopBB(LoopBB), CondBranch(CondBranch), Comp(Comp),
11964 CompCounterOprNum(CompCounterOprNum), Update(Update),
11965 UpdateCounterOprNum(UpdateCounterOprNum), Init(Init),
11968 bool shouldIgnoreForPipelining(
const MachineInstr *
MI)
const override {
11974 std::optional<bool> createTripCountGreaterCondition(
11975 int TC, MachineBasicBlock &
MBB,
11976 SmallVectorImpl<MachineOperand> &CondParam)
override {
11984 void createRemainingIterationsGreaterCondition(
11985 int TC, MachineBasicBlock &
MBB, SmallVectorImpl<MachineOperand> &
Cond,
11986 DenseMap<MachineInstr *, MachineInstr *> &LastStage0Insts)
override;
11988 void setPreheader(MachineBasicBlock *NewPreheader)
override {}
11990 void adjustTripCount(
int TripCountAdjust)
override {}
11992 bool isMVEExpanderSupported()
override {
return true; }
12011 }
else if (
I == ReplaceOprNum) {
12016 MBB.insert(InsertTo, NewMI);
12020void AArch64PipelinerLoopInfo::createRemainingIterationsGreaterCondition(
12036 assert(CondBranch->getOpcode() == AArch64::Bcc);
12040 if (CondBranch->getOperand(1).getMBB() == LoopBB)
12047 auto AccumulateCond = [&](
Register CurCond,
12058 if (!LastStage0Insts.
empty() && LastStage0Insts[Comp]->getParent() == &
MBB) {
12062 for (
int I = 0;
I <= TC; ++
I) {
12068 AccCond = AccumulateCond(AccCond, CC);
12072 if (Update != Comp && IsUpdatePriorComp) {
12074 LastStage0Insts[Comp]->getOperand(CompCounterOprNum).getReg();
12075 NextCounter =
cloneInstr(Update, UpdateCounterOprNum, Counter,
MBB,
12079 NextCounter = LastStage0Insts[Update]->getOperand(0).getReg();
12081 }
else if (Update != Comp) {
12086 Counter = NextCounter;
12090 if (LastStage0Insts.
empty()) {
12094 if (IsUpdatePriorComp)
12099 Counter = LastStage0Insts[Comp]->getOperand(CompCounterOprNum).getReg();
12102 for (
int I = 0;
I <= TC; ++
I) {
12106 AccCond = AccumulateCond(AccCond, CC);
12107 if (
I != TC && Update != Comp)
12110 Counter = NextCounter;
12126 assert(Phi.getNumOperands() == 5);
12127 if (Phi.getOperand(2).getMBB() ==
MBB) {
12128 RegMBB = Phi.getOperand(1).getReg();
12129 RegOther = Phi.getOperand(3).getReg();
12131 assert(Phi.getOperand(4).getMBB() ==
MBB);
12132 RegMBB = Phi.getOperand(3).getReg();
12133 RegOther = Phi.getOperand(1).getReg();
12138 if (!
Reg.isVirtual())
12147 unsigned &UpdateCounterOprNum,
Register &InitReg,
12148 bool &IsUpdatePriorComp) {
12162 if (!
Reg.isVirtual())
12165 UpdateInst =
nullptr;
12166 UpdateCounterOprNum = 0;
12168 IsUpdatePriorComp =
true;
12172 if (Def->getParent() != LoopBB)
12174 if (Def->isCopy()) {
12176 if (Def->getOperand(0).getSubReg() || Def->getOperand(1).getSubReg())
12178 CurReg = Def->getOperand(1).getReg();
12179 }
else if (Def->isPHI()) {
12183 IsUpdatePriorComp =
false;
12188 switch (Def->getOpcode()) {
12189 case AArch64::ADDSXri:
12190 case AArch64::ADDSWri:
12191 case AArch64::SUBSXri:
12192 case AArch64::SUBSWri:
12193 case AArch64::ADDXri:
12194 case AArch64::ADDWri:
12195 case AArch64::SUBXri:
12196 case AArch64::SUBWri:
12198 UpdateCounterOprNum = 1;
12200 case AArch64::ADDSXrr:
12201 case AArch64::ADDSWrr:
12202 case AArch64::SUBSXrr:
12203 case AArch64::SUBSWrr:
12204 case AArch64::ADDXrr:
12205 case AArch64::ADDWrr:
12206 case AArch64::SUBXrr:
12207 case AArch64::SUBWrr:
12210 UpdateCounterOprNum = 1;
12212 UpdateCounterOprNum = 2;
12219 CurReg = Def->getOperand(UpdateCounterOprNum).getReg();
12234std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
12245 if (
MI.isCall() ||
MI.hasUnmodeledSideEffects())
12256 if (
TBB == LoopBB && FBB == LoopBB)
12260 if (
TBB != LoopBB && FBB ==
nullptr)
12263 assert((
TBB == LoopBB || FBB == LoopBB) &&
12264 "The Loop must be a single-basic-block loop");
12269 if (CondBranch->
getOpcode() != AArch64::Bcc)
12277 unsigned CompCounterOprNum = 0;
12279 if (
MI.modifiesRegister(AArch64::NZCV, &
TRI)) {
12283 switch (
MI.getOpcode()) {
12284 case AArch64::SUBSXri:
12285 case AArch64::SUBSWri:
12286 case AArch64::ADDSXri:
12287 case AArch64::ADDSWri:
12289 CompCounterOprNum = 1;
12291 case AArch64::ADDSWrr:
12292 case AArch64::ADDSXrr:
12293 case AArch64::SUBSWrr:
12294 case AArch64::SUBSXrr:
12298 if (isWhileOpcode(
MI.getOpcode())) {
12305 if (CompCounterOprNum == 0) {
12307 CompCounterOprNum = 2;
12309 CompCounterOprNum = 1;
12321 bool IsUpdatePriorComp;
12322 unsigned UpdateCounterOprNum;
12324 Update, UpdateCounterOprNum,
Init, IsUpdatePriorComp))
12327 return std::make_unique<AArch64PipelinerLoopInfo>(
12328 LoopBB, CondBranch, Comp, CompCounterOprNum, Update, UpdateCounterOprNum,
12338 TypeSize Scale(0U,
false), Width(0U,
false);
12339 int64_t MinOffset, MaxOffset;
12340 if (
getMemOpInfo(
MI.getOpcode(), Scale, Width, MinOffset, MaxOffset)) {
12342 if (
MI.getOperand(ImmIdx).isImm() && !
MI.getOperand(ImmIdx - 1).isFI()) {
12343 int64_t
Imm =
MI.getOperand(ImmIdx).getImm();
12345 ErrInfo =
"Unexpected immediate on load/store instruction";
12351 const MCInstrDesc &MCID =
MI.getDesc();
12353 const MachineOperand &MO =
MI.getOperand(
Op);
12357 ErrInfo =
"OPERAND_IMPLICIT_IMM_0 should be 0";
12366 ErrInfo =
"OPERAND_SHIFT_MSL should be msl shift of 8 or 16";
12372 ErrInfo =
"OPERAND_IMM_UINT1 should be 0 or 1";
12378 ErrInfo =
"OPERAND_IMM_UINT4plus1 should be in the range 1 to 16";
12384 ErrInfo =
"OPERAND_IMM_UINT5 should be in the range 0 to 31";
12390 ErrInfo =
"OPERAND_IMM_UINT8 should be in the range 0 to 255";
12401#define GET_INSTRINFO_HELPERS
12402#define GET_INSTRMAP_INFO
12403#include "AArch64GenInstrInfo.inc"
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
static cl::opt< unsigned > BCCDisplacementBits("aarch64-bcc-offset-bits", cl::Hidden, cl::init(19), cl::desc("Restrict range of Bcc instructions (DEBUG)"))
static Register genNeg(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, DenseMap< Register, unsigned > &InstrIdxForVirtReg, unsigned MnegOpc, const TargetRegisterClass *RC)
genNeg - Helper to generate an intermediate negation of the second operand of Root
static bool isFrameStoreOpcode(int Opcode)
static cl::opt< unsigned > GatherOptSearchLimit("aarch64-search-limit", cl::Hidden, cl::init(2048), cl::desc("Restrict range of instructions to search for the " "machine-combiner gather pattern optimization"))
static bool getMaddPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns)
Find instructions that can be turned into madd.
static AArch64CC::CondCode findCondCodeUsedByInstr(const MachineInstr &Instr)
Find a condition code used by the instruction.
static MachineInstr * genFusedMultiplyAcc(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, unsigned IdxMulOpd, unsigned MaddOpc, const TargetRegisterClass *RC)
genFusedMultiplyAcc - Helper to generate fused multiply accumulate instructions.
static MachineInstr * genFusedMultiplyAccNeg(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, DenseMap< Register, unsigned > &InstrIdxForVirtReg, unsigned IdxMulOpd, unsigned MaddOpc, unsigned MnegOpc, const TargetRegisterClass *RC)
genFusedMultiplyAccNeg - Helper to generate fused multiply accumulate instructions with an additional...
static bool isCombineInstrCandidate64(unsigned Opc)
static bool isFrameLoadOpcode(int Opcode)
static unsigned removeCopies(const MachineRegisterInfo &MRI, unsigned VReg)
static bool areCFlagsAccessedBetweenInstrs(MachineBasicBlock::iterator From, MachineBasicBlock::iterator To, const TargetRegisterInfo *TRI, const AccessKind AccessToCheck=AK_All)
True when condition flags are accessed (either by writing or reading) on the instruction trace starti...
static bool getFMAPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns)
Floating-Point Support.
static bool isADDSRegImm(unsigned Opcode)
static bool isCheapCopy(const MachineInstr &MI, const AArch64RegisterInfo &RI)
static bool isANDOpcode(MachineInstr &MI)
static bool predictCompactUnwindFrameRecordForOutlinedFunction(std::vector< outliner::Candidate > &RepeatedSequenceLocs, const TargetRegisterInfo &TRI)
Predict what the above will answer, for use while costing candidates.
static void appendOffsetComment(int NumBytes, llvm::raw_string_ostream &Comment, StringRef RegScale={})
static unsigned sForm(MachineInstr &Instr)
Get opcode of S version of Instr.
static bool isCombineInstrSettingFlag(unsigned Opc)
static bool getFNEGPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns)
static bool getIndVarInfo(Register Reg, const MachineBasicBlock *LoopBB, MachineInstr *&UpdateInst, unsigned &UpdateCounterOprNum, Register &InitReg, bool &IsUpdatePriorComp)
If Reg is an induction variable, return true and set some parameters.
static bool canPairLdStOpc(unsigned FirstOpc, unsigned SecondOpc)
static bool mustAvoidNeonAtMBBI(const AArch64Subtarget &Subtarget, MachineBasicBlock &MBB, MachineBasicBlock::iterator I)
Returns true if in a streaming call site region without SME-FA64.
static bool isPostIndexLdStOpcode(unsigned Opcode)
Return true if the opcode is a post-index ld/st instruction, which really loads from base+0.
static std::optional< unsigned > getLFIInstSizeInBytes(const MachineInstr &MI)
Return the maximum number of bytes of code the specified instruction may be after LFI rewriting.
static unsigned getBranchDisplacementBits(unsigned Opc)
static cl::opt< unsigned > CBDisplacementBits("aarch64-cb-offset-bits", cl::Hidden, cl::init(9), cl::desc("Restrict range of CB instructions (DEBUG)"))
static std::optional< ParamLoadedValue > describeORRLoadedValue(const MachineInstr &MI, Register DescribedReg, const TargetInstrInfo *TII, const TargetRegisterInfo *TRI)
If the given ORR instruction is a copy, and DescribedReg overlaps with the destination register then,...
static bool getFMULPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns)
static void appendReadRegExpr(SmallVectorImpl< char > &Expr, unsigned RegNum)
static MachineInstr * genMaddR(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, unsigned IdxMulOpd, unsigned MaddOpc, unsigned VR, const TargetRegisterClass *RC)
genMaddR - Generate madd instruction and combine mul and add using an extra virtual register Example ...
static Register cloneInstr(const MachineInstr *MI, unsigned ReplaceOprNum, Register ReplaceReg, MachineBasicBlock &MBB, MachineBasicBlock::iterator InsertTo)
Clone an instruction from MI.
static bool scaleOffset(unsigned Opc, int64_t &Offset)
static bool canCombineWithFMUL(MachineBasicBlock &MBB, MachineOperand &MO, unsigned MulOpc)
unsigned scaledOffsetOpcode(unsigned Opcode, unsigned &Scale)
static MachineInstr * genFusedMultiplyIdx(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, unsigned IdxMulOpd, unsigned MaddOpc, const TargetRegisterClass *RC)
genFusedMultiplyIdx - Helper to generate fused multiply accumulate instructions.
static MachineInstr * genIndexedMultiply(MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, unsigned IdxDupOp, unsigned MulOpc, const TargetRegisterClass *RC, MachineRegisterInfo &MRI)
Fold (FMUL x (DUP y lane)) into (FMUL_indexed x y lane)
static cl::opt< bool > UseCompactUnwindFrameRecordForOutlinedFunctions("aarch64-outliner-compact-unwind-frame", cl::Hidden, cl::init(true), cl::desc("Use a frame record for Mach-O non-leaf outlined functions"))
static bool shouldUseCompactUnwindFrameRecordForOutlinedFunction(const MachineBasicBlock &MBB)
Return true if the outlined function in MBB should save FP and LR as a frame record instead of saving...
static bool isSUBSRegImm(unsigned Opcode)
static bool UpdateOperandRegClass(MachineInstr &Instr)
static const TargetRegisterClass * getRegClass(const MachineInstr &MI, Register Reg)
static bool isInStreamingCallSiteRegion(MachineBasicBlock &MBB, MachineBasicBlock::iterator I)
Returns true if the instruction at I is in a streaming call site region, within a single basic block.
static bool canCmpInstrBeRemoved(MachineInstr &MI, MachineInstr &CmpInstr, int CmpValue, const TargetRegisterInfo &TRI, SmallVectorImpl< MachineInstr * > &CCUseInstrs, bool &IsInvertCC)
unsigned unscaledOffsetOpcode(unsigned Opcode)
static bool getLoadPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns)
Search for patterns of LD instructions we can optimize.
static bool canInstrSubstituteCmpInstr(MachineInstr &MI, MachineInstr &CmpInstr, const TargetRegisterInfo &TRI)
Check if CmpInstr can be substituted by MI.
static UsedNZCV getUsedNZCV(AArch64CC::CondCode CC)
static bool isCombineInstrCandidateFP(const MachineInstr &Inst)
static bool isCompactUnwindFrameRecordEnabled(const MachineFunction &MF)
Return true if the frame-record form of the outlined prologue is enabled for the target of MF.
static void appendLoadRegExpr(SmallVectorImpl< char > &Expr, int64_t OffsetFromDefCFA)
static void appendConstantExpr(SmallVectorImpl< char > &Expr, int64_t Constant, dwarf::LocationAtom Operation)
static unsigned convertToNonFlagSettingOpc(const MachineInstr &MI)
Return the opcode that does not set flags when possible - otherwise return the original opcode.
static bool outliningCandidatesV8_3OpsConsensus(const outliner::Candidate &a, const outliner::Candidate &b)
static bool isCombineInstrCandidate32(unsigned Opc)
static void parseCondBranch(MachineInstr *LastInst, MachineBasicBlock *&Target, SmallVectorImpl< MachineOperand > &Cond)
static unsigned offsetExtendOpcode(unsigned Opcode)
static void loadRegPairFromStackSlot(const TargetRegisterInfo &TRI, MachineBasicBlock &MBB, MachineBasicBlock::iterator InsertBefore, const MCInstrDesc &MCID, Register DestReg, unsigned SubIdx0, unsigned SubIdx1, int FI, MachineMemOperand *MMO)
static void generateGatherLanePattern(MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, SmallVectorImpl< MachineInstr * > &DelInstrs, DenseMap< Register, unsigned > &InstrIdxForVirtReg, unsigned Pattern, unsigned NumLanes)
Generate optimized instruction sequence for gather load patterns to improve Memory-Level Parallelism ...
static bool getMiscPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns)
Find other MI combine patterns.
static bool outliningCandidatesSigningKeyConsensus(const outliner::Candidate &a, const outliner::Candidate &b)
static const MachineInstrBuilder & AddSubReg(const MachineInstrBuilder &MIB, MCRegister Reg, unsigned SubIdx, RegState State, const TargetRegisterInfo *TRI)
static bool outliningCandidatesSigningScopeConsensus(const outliner::Candidate &a, const outliner::Candidate &b)
static bool shouldClusterFI(const MachineFrameInfo &MFI, int FI1, int64_t Offset1, unsigned Opcode1, int FI2, int64_t Offset2, unsigned Opcode2)
static bool isValidCBExtend(int64_t Opc, AArch64_AM::ShiftExtendType Ext)
static cl::opt< unsigned > TBZDisplacementBits("aarch64-tbz-offset-bits", cl::Hidden, cl::init(14), cl::desc("Restrict range of TB[N]Z instructions (DEBUG)"))
static void extractPhiReg(const MachineInstr &Phi, const MachineBasicBlock *MBB, Register &RegMBB, Register &RegOther)
static MCCFIInstruction createDefCFAExpression(const TargetRegisterInfo &TRI, unsigned Reg, const StackOffset &Offset)
static bool isDefinedOutside(Register Reg, const MachineBasicBlock *BB)
static MachineInstr * genFusedMultiply(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, unsigned IdxMulOpd, unsigned MaddOpc, const TargetRegisterClass *RC, FMAInstKind kind=FMAInstKind::Default, const Register *ReplacedAddend=nullptr)
genFusedMultiply - Generate fused multiply instructions.
static bool getGatherLanePattern(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns, unsigned LoadLaneOpCode, unsigned NumLanes)
Check if the given instruction forms a gather load pattern that can be optimized for better Memory-Le...
static MachineInstr * genFusedMultiplyIdxNeg(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, DenseMap< Register, unsigned > &InstrIdxForVirtReg, unsigned IdxMulOpd, unsigned MaddOpc, unsigned MnegOpc, const TargetRegisterClass *RC)
genFusedMultiplyAccNeg - Helper to generate fused multiply accumulate instructions with an additional...
static bool isCombineInstrCandidate(unsigned Opc)
static unsigned regOffsetOpcode(unsigned Opcode)
MachineOutlinerClass
Constants defining how certain sequences should be outlined.
@ MachineOutlinerTailCall
Emit a save, restore, call, and return.
@ MachineOutlinerRegSave
Emit a call and tail-call.
@ MachineOutlinerNoLRSave
Only emit a branch.
@ MachineOutlinerThunk
Emit a call and return.
static cl::opt< unsigned > BDisplacementBits("aarch64-b-offset-bits", cl::Hidden, cl::init(26), cl::desc("Restrict range of B instructions (DEBUG)"))
static bool areCFlagsAliveInSuccessors(const MachineBasicBlock *MBB)
Check if AArch64::NZCV should be alive in successors of MBB.
static void emitFrameOffsetAdj(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, int64_t Offset, unsigned Opc, const TargetInstrInfo *TII, MachineInstr::MIFlag Flag, bool NeedsWinCFI, bool *HasWinCFI, bool EmitCFAOffset, StackOffset CFAOffset, unsigned FrameReg)
static bool isCheapImmediate(const MachineInstr &MI, unsigned BitSize)
static cl::opt< unsigned > CBZDisplacementBits("aarch64-cbz-offset-bits", cl::Hidden, cl::init(19), cl::desc("Restrict range of CB[N]Z instructions (DEBUG)"))
static void genSubAdd2SubSub(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, SmallVectorImpl< MachineInstr * > &DelInstrs, unsigned IdxOpd1, DenseMap< Register, unsigned > &InstrIdxForVirtReg)
Do the following transformation A - (B + C) ==> (A - B) - C A - (B + C) ==> (A - C) - B.
static unsigned canFoldIntoCSel(const MachineRegisterInfo &MRI, unsigned VReg, unsigned *NewReg=nullptr)
static void signOutlinedFunction(MachineFunction &MF, MachineBasicBlock &MBB, const AArch64InstrInfo *TII, bool ShouldSignReturnAddr)
static MachineInstr * genFNegatedMAD(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs)
static bool canCombineWithMUL(MachineBasicBlock &MBB, MachineOperand &MO, unsigned MulOpc, unsigned ZeroReg)
static void storeRegPairToStackSlot(const TargetRegisterInfo &TRI, MachineBasicBlock &MBB, MachineBasicBlock::iterator InsertBefore, const MCInstrDesc &MCID, Register SrcReg, bool IsKill, unsigned SubIdx0, unsigned SubIdx1, int FI, MachineMemOperand *MMO)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static const Function * getParent(const Value *V)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
DXIL Forward Handle Accesses
const HexagonInstrInfo * TII
Module.h This file contains the declarations for the Module class.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
PowerPC Reduce CR logical Operation
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
This file declares the machine register scavenger class.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
This file defines the SmallSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
#define DEBUG_WITH_TYPE(TYPE,...)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
static bool canCombine(MachineBasicBlock &MBB, MachineOperand &MO, unsigned CombineOpc=0)
AArch64FunctionInfo - This class is derived from MachineFunctionInfo and contains private AArch64-spe...
bool branchTargetEnforcement() const
unsigned getArgumentStackToRestore() const
SignReturnAddress getSignReturnAddressCondition() const
bool hasStreamingModeChanges() const
void setOutliningStyle(const std::string &Style)
bool branchProtectionPAuthLR() const
bool needsDwarfUnwindInfo(const MachineFunction &MF) const
std::optional< bool > hasRedZone() const
static bool shouldSignReturnAddress(SignReturnAddress Condition, bool IsLRSpilled)
bool shouldSignWithBKey() const
static bool isHForm(const MachineInstr &MI)
Returns whether the instruction is in H form (16 bit operands)
void insertSelect(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, Register DstReg, ArrayRef< MachineOperand > Cond, Register TrueReg, Register FalseReg) const override
static bool hasBTISemantics(const MachineInstr &MI)
Returns whether the instruction can be compatible with non-zero BTYPE.
static bool isQForm(const MachineInstr &MI)
Returns whether the instruction is in Q form (128 bit operands)
static bool getMemOpInfo(unsigned Opcode, TypeSize &Scale, TypeSize &Width, int64_t &MinOffset, int64_t &MaxOffset)
Returns true if opcode Opc is a memory operation.
static bool isTailCallReturnInst(const MachineInstr &MI)
Returns true if MI is one of the TCRETURN* instructions.
static bool isFPRCopy(const MachineInstr &MI)
Does this instruction rename an FPR without modifying bits?
MachineInstr * emitLdStWithAddr(MachineInstr &MemI, const ExtAddrMode &AM) const override
std::optional< DestSourcePair > isCopyInstrImpl(const MachineInstr &MI) const override
If the specific machine instruction is an instruction that moves/copies value from one register to an...
MachineBasicBlock * getBranchDestBlock(const MachineInstr &MI) const override
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
GetInstSize - Return the number of bytes of code the specified instruction may be.
static bool isZExtLoad(const MachineInstr &MI)
Returns whether the instruction is a zero-extending load.
bool areMemAccessesTriviallyDisjoint(const MachineInstr &MIa, const MachineInstr &MIb) const override
void copyPhysRegImpl(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DestReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DestReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
static bool isGPRCopy(const MachineInstr &MI)
Does this instruction rename a GPR without modifying bits?
static unsigned convertToFlagSettingOpc(unsigned Opc)
Return the opcode that set flags when possible.
void createPauthEpilogueInstr(MachineBasicBlock &MBB, DebugLoc DL) const
Return true when there is potentially a faster code sequence for an instruction chain ending in Root.
bool isBranchOffsetInRange(unsigned BranchOpc, int64_t BrOffset) const override
bool canInsertSelect(const MachineBasicBlock &, ArrayRef< MachineOperand > Cond, Register, Register, Register, int &, int &, int &) const override
Register isLoadFromStackSlotPostFE(const MachineInstr &MI, int &FrameIndex) const override
Check for post-frame ptr elimination stack locations as well.
static const MachineOperand & getLdStOffsetOp(const MachineInstr &MI)
Returns the immediate offset operator of a load/store.
bool isCoalescableExtInstr(const MachineInstr &MI, Register &SrcReg, Register &DstReg, unsigned &SubIdx) const override
static std::optional< unsigned > getUnscaledLdSt(unsigned Opc)
Returns the unscaled load/store for the scaled load/store opcode, if there is a corresponding unscale...
static bool hasUnscaledLdStOffset(unsigned Opc)
Return true if it has an unscaled load/store offset.
static const MachineOperand & getLdStAmountOp(const MachineInstr &MI)
Returns the shift amount operator of a load/store.
static bool isPreLdSt(const MachineInstr &MI)
Returns whether the instruction is a pre-indexed load/store.
std::optional< ExtAddrMode > getAddrModeFromMemoryOp(const MachineInstr &MemI, const TargetRegisterInfo *TRI) const override
bool getMemOperandsWithOffsetWidth(const MachineInstr &MI, SmallVectorImpl< const MachineOperand * > &BaseOps, int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width, const TargetRegisterInfo *TRI) const override
bool analyzeBranchPredicate(MachineBasicBlock &MBB, MachineBranchPredicate &MBP, bool AllowModify) const override
void insertIndirectBranch(MachineBasicBlock &MBB, MachineBasicBlock &NewDestBB, MachineBasicBlock &RestoreBB, const DebugLoc &DL, int64_t BrOffset, RegScavenger *RS) const override
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, Register VReg, unsigned SubReg=0, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
static bool isPairableLdStInst(const MachineInstr &MI)
Return true if pairing the given load or store may be paired with another.
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
static bool isSExtLoad(const MachineInstr &MI)
Returns whether the instruction is a sign-extending load.
const AArch64RegisterInfo & getRegisterInfo() const
getRegisterInfo - TargetInstrInfo is a superset of MRegister info.
static bool isPreSt(const MachineInstr &MI)
Returns whether the instruction is a pre-indexed store.
void insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const override
AArch64InstrInfo(const AArch64Subtarget &STI)
static bool isPairedLdSt(const MachineInstr &MI)
Returns whether the instruction is a paired load/store.
MachineInstr * foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, ArrayRef< unsigned > Ops, int FrameIndex, MachineInstr *&CopyMI, LiveIntervals *LIS=nullptr, VirtRegMap *VRM=nullptr) const override
bool getMemOperandWithOffsetWidth(const MachineInstr &MI, const MachineOperand *&BaseOp, int64_t &Offset, bool &OffsetIsScalable, TypeSize &Width, const TargetRegisterInfo *TRI) const
If OffsetIsScalable is set to 'true', the offset is scaled by vscale.
Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const override
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
static bool isStridedAccess(const MachineInstr &MI)
Return true if the given load or store is a strided memory access.
bool shouldClusterMemOps(ArrayRef< const MachineOperand * > BaseOps1, int64_t Offset1, bool OffsetIsScalable1, ArrayRef< const MachineOperand * > BaseOps2, int64_t Offset2, bool OffsetIsScalable2, unsigned ClusterSize, unsigned NumBytes) const override
Detect opportunities for ldp/stp formation.
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
bool isThroughputPattern(unsigned Pattern) const override
Return true when a code sequence can improve throughput.
MachineOperand & getMemOpBaseRegImmOfsOffsetOperand(MachineInstr &LdSt) const
Return the immediate offset of the base register in a load/store LdSt.
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify=false) const override
bool canFoldIntoAddrMode(const MachineInstr &MemI, Register Reg, const MachineInstr &AddrI, ExtAddrMode &AM) const override
static bool isLdStPairSuppressed(const MachineInstr &MI)
Return true if pairing the given load or store is hinted to be unprofitable.
Register isStoreToStackSlotPostFE(const MachineInstr &MI, int &FrameIndex) const override
Check for post-frame ptr elimination stack locations as well.
std::unique_ptr< TargetInstrInfo::PipelinerLoopInfo > analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const override
void copyPhysRegTuple(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, llvm::ArrayRef< unsigned > Indices) const
bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const override
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const override
AArch64CC::CondCode insertCmpForCondBr(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, ArrayRef< MachineOperand > Cond) const
Inserts the compare instruction needed to un-fuse a fused conditional branch instruction and returns ...
bool optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask, int64_t CmpValue, const MachineRegisterInfo *MRI) const override
optimizeCompareInstr - Convert the instruction supplying the argument to the comparison into one that...
static unsigned getLoadStoreImmIdx(unsigned Opc)
Returns the index for the immediate for a given instruction.
static bool isGPRZero(const MachineInstr &MI)
Does this instruction set its full destination register to zero?
void copyGPRRegTuple(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, unsigned Opcode, unsigned ZeroReg, llvm::ArrayRef< unsigned > Indices) const
bool analyzeCompare(const MachineInstr &MI, Register &SrcReg, Register &SrcReg2, int64_t &CmpMask, int64_t &CmpValue) const override
analyzeCompare - For a comparison instruction, return the source registers in SrcReg and SrcReg2,...
CombinerObjective getCombinerObjective(unsigned Pattern) const override
static bool isFpOrNEON(Register Reg)
Returns whether the physical register is FP or NEON.
bool isAsCheapAsAMove(const MachineInstr &MI) const override
std::optional< DestSourcePair > isCopyLikeInstrImpl(const MachineInstr &MI) const override
static void suppressLdStPair(MachineInstr &MI)
Hint that pairing the given load or store is unprofitable.
Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override
static bool isPreLd(const MachineInstr &MI)
Returns whether the instruction is a pre-indexed load.
bool optimizeCondBranch(MachineInstr &MI) const override
Replace csincr-branch sequence by simple conditional branch.
static int getMemScale(unsigned Opc)
Scaling factor for (scaled or unscaled) load or store.
bool isCandidateToMergeOrPair(const MachineInstr &MI) const
Return true if this is a load/store that can be potentially paired/merged.
MCInst getNop() const override
static const MachineOperand & getLdStBaseOp(const MachineInstr &MI)
Returns the base register operator of a load/store.
bool isReservedReg(const MachineFunction &MF, MCRegister Reg) const
const AArch64RegisterInfo * getRegisterInfo() const override
bool isNeonAvailable() const
Returns true if the target has NEON and the function at runtime is known to have NEON enabled (e....
bool isSVEorStreamingSVEAvailable() const
Returns true if the target has access to either the full range of SVE instructions,...
Represent a constant reference to an array (0 or more elements consecutively in memory),...
const T & front() const
Get the first element.
size_t size() const
Get the array size.
This is an important base class in LLVM.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
Module * getParent()
Get the module that this global value is contained inside of...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
A set of register units used to track register liveness.
bool available(MCRegister Reg) const
Returns true if no part of physical register Reg is live.
LLVM_ABI void accumulate(const MachineInstr &MI)
Adds all register units used, defined or clobbered in MI.
static LocationSize precise(uint64_t Value)
This class is intended to be used as a base class for asm properties and features specific to the tar...
bool usesWindowsCFI() const
static MCCFIInstruction cfiDefCfa(MCSymbol *L, unsigned Register, int64_t Offset, SMLoc Loc={})
.cfi_def_cfa defines a rule for computing CFA as: take address from Register and add Offset to it.
static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, int64_t Offset, SMLoc Loc={})
.cfi_offset Previous value of Register is saved at offset Offset from CFA.
static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int64_t Offset, SMLoc Loc={})
.cfi_def_cfa_offset modifies a rule for computing CFA.
static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals, SMLoc Loc={}, StringRef Comment="")
.cfi_escape Allows the user to add arbitrary bytes to the unwind info.
Instances of this class represent a single low-level machine instruction.
Describe properties that are true of each instruction in the target description file.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
ArrayRef< MCOperandInfo > operands() const
bool hasSuperClassEq(const MCRegisterClass *RC) const
Returns true if RC is a super-class of or equal to this class.
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
bool hasSubClassEq(const MCRegisterClass *RC) const
Returns true if RC is a sub-class of or equal to this class.
Wrapper class representing physical registers. Should be passed by value.
constexpr bool isValid() const
static constexpr unsigned NoRegister
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
bool isInlineAsmBrIndirectTarget() const
Returns true if this is the indirect dest of an INLINEASM_BR.
unsigned pred_size() const
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
LLVM_ABI instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
reverse_instr_iterator instr_rbegin()
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
reverse_instr_iterator instr_rend()
Instructions::iterator instr_iterator
instr_iterator instr_end()
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
iterator insertAfter(iterator I, MachineInstr *MI)
Insert MI into the instruction list after I.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
void setMachineBlockAddressTaken()
Set this block to indicate that its address is used as something other than the target of a terminato...
LLVM_ABI bool isLiveIn(MCRegister Reg, LaneBitmask LaneMask=LaneBitmask::getAll()) const
Return true if the specified register is in the live in set.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
void setStackID(int ObjectIdx, uint8_t ID)
bool isCalleeSavedInfoValid() const
Has the callee saved info been calculated yet?
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
unsigned getNumObjects() const
Return the number of objects.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
unsigned addFrameInst(const MCCFIInstruction &Inst)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
const MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & setMemRefs(ArrayRef< MachineMemOperand * > MMOs) const
const MachineInstrBuilder & addCFIIndex(unsigned CFIIndex) const
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addSym(MCSymbol *Sym, unsigned char TargetFlags=0) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
reverse_iterator getReverse() const
Get a reverse iterator to the same node.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool mayLoadOrStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read or modify memory.
const MachineBasicBlock * getParent() const
bool isCall(QueryType Type=AnyInBundle) const
bool getFlag(MIFlag Flag) const
Return whether an MI flag is set.
LLVM_ABI uint32_t mergeFlagsWith(const MachineInstr &Other) const
Return the MIFlags which represent both MachineInstrs.
unsigned getNumOperands() const
Retuns the total number of operands.
LLVM_ABI unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
LLVM_ABI bool hasUnmodeledSideEffects() const
Return true if this instruction has side effects that are not modeled by mayLoad / mayStore,...
bool registerDefIsDead(Register Reg, const TargetRegisterInfo *TRI) const
Returns true if the register is dead in this machine instruction.
bool definesRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr fully defines the specified register.
LLVM_ABI void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
LLVM_ABI bool hasOrderedMemoryRef() const
Return true if this instruction may have an ordered or volatile memory reference, or if the informati...
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
ArrayRef< MachineMemOperand * > memoperands() const
Access to memory operands of the instruction.
LLVM_ABI bool isLoadFoldBarrier() const
Returns true if it is illegal to fold a load across this instruction.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
LLVM_ABI void removeOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with.
LLVM_ABI void addRegisterDefined(Register Reg, const TargetRegisterInfo *RegInfo=nullptr)
We have determined MI defines a register.
const MachineOperand & getOperand(unsigned i) const
uint32_t getFlags() const
Return the MI flags bitvector.
LLVM_ABI int findRegisterDefOperandIdx(Register Reg, const TargetRegisterInfo *TRI, bool isDead=false, bool Overlap=false) const
Returns the operand index that is a def of the specified register or -1 if it is not found.
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const std::vector< MachineJumpTableEntry > & getJumpTables() const
A description of a memory reference used in the backend.
@ MOVolatile
The memory access is volatile.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
This class contains meta information specific to a module.
LLVM_ABI MachineFunction * getMachineFunction(const Function &F) const
Returns the MachineFunction associated to IR function F if there is one, otherwise nullptr.
MachineOperand class - Representation of each machine instruction operand.
void setSubReg(unsigned subReg)
unsigned getSubReg() const
void setImm(int64_t immVal)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
void setIsDead(bool Val=true)
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
void setIsKill(bool Val=true)
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
unsigned getTargetFlags() const
static MachineOperand CreateImm(int64_t Val)
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
bool isFI() const
isFI - Tests if this is a MO_FrameIndex operand.
LLVM_ABI bool isIdenticalTo(const MachineOperand &Other) const
Returns true if this operand is identical to the specified operand except for liveness related flags ...
static MachineOperand CreateReg(Register 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 isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
bool tracksLiveness() const
tracksLiveness - Returns true when tracking register liveness accurately.
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI void clearKillFlags(Register Reg) const
clearKillFlags - Iterate over all the uses of the given register and clear the kill flag from the Mac...
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
bool use_nodbg_empty(Register RegNo) const
use_nodbg_empty - Return true if there are no non-Debug instructions using the specified register.
MachineBasicBlock * getDefBlock(Register Reg) const
Return the machine basic block in which the specified virtual register is defined,...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
bool reservedRegsFrozen() const
reservedRegsFrozen - Returns true after freezeReservedRegs() was called to ensure the set of reserved...
use_instr_nodbg_iterator use_instr_nodbg_begin(Register RegNo) const
const TargetRegisterClass * getRegClassOrNull(Register Reg) const
Return the register class of Reg, or null if Reg has not been assigned a register class yet.
LLVM_ABI const TargetRegisterClass * constrainRegClass(Register Reg, const TargetRegisterClass *RC, unsigned MinNumRegs=0)
constrainRegClass - Constrain the register class of the specified virtual register to be a common sub...
LLVM_ABI LLVM_READONLY MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
A Module instance is used to store all the information related to an LLVM module.
MI-level patchpoint operands.
uint32_t getNumPatchBytes() const
Return the number of patchable bytes the given patchpoint should emit.
Wrapper class representing virtual and physical registers.
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
constexpr bool isValid() const
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
static constexpr bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Represents a location in source code.
bool erase(PtrType Ptr)
Remove pointer from the set.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
void append(StringRef RHS)
Append from a StringRef.
StringRef str() const
Explicit conversion to StringRef.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
MI-level stackmap operands.
uint32_t getNumPatchBytes() const
Return the number of patchable bytes the given stackmap should emit.
StackOffset holds a fixed and a scalable offset in bytes.
int64_t getFixed() const
Returns the fixed component of the stack.
int64_t getScalable() const
Returns the scalable component of the stack.
static StackOffset get(int64_t Fixed, int64_t Scalable)
static StackOffset getScalable(int64_t Scalable)
static StackOffset getFixed(int64_t Fixed)
MI-level Statepoint operands.
uint32_t getNumPatchBytes() const
Return the number of patchable bytes the given statepoint should emit.
Represent a constant reference to a string, i.e.
Object returned by analyzeLoopForPipelining.
TargetInstrInfo - Interface to description of machine instruction set.
virtual void genAlternativeCodeSequence(MachineInstr &Root, unsigned Pattern, SmallVectorImpl< MachineInstr * > &InsInstrs, SmallVectorImpl< MachineInstr * > &DelInstrs, DenseMap< Register, unsigned > &InstIdxForVirtReg) const
When getMachineCombinerPatterns() finds patterns, this function generates the instructions that could...
virtual std::optional< ParamLoadedValue > describeLoadedValue(const MachineInstr &MI, Register Reg) const
Produce the expression describing the MI loading a value into the physical register Reg.
virtual bool getMachineCombinerPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns, bool DoRegPressureReduce) const
Return true when there is potentially a faster code sequence for an instruction chain ending in Root.
virtual bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const
Test if the given instruction should be considered a scheduling boundary.
virtual CombinerObjective getCombinerObjective(unsigned Pattern) const
Return the objective of a combiner pattern.
virtual bool isFunctionSafeToSplit(const MachineFunction &MF) const
Return true if the function is a viable candidate for machine function splitting.
const Triple & getTargetTriple() const
const MCAsmInfo & getMCAsmInfo() const
Return target specific asm information.
CodeModel::Model getCodeModel() const
Returns the code model.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
TargetSubtargetInfo - Generic base class for all target subtargets.
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
Target - Wrapper for Target specific information.
bool isOSBinFormatMachO() const
Tests whether the environment is MachO.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
static constexpr TypeSize getScalable(ScalarTy MinimumSize)
Value * getOperand(unsigned i) const
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
self_iterator getIterator()
A raw_ostream that writes to an std::string.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static CondCode getInvertedCondCode(CondCode Code)
@ MO_DLLIMPORT
MO_DLLIMPORT - On a symbol operand, this represents that the reference to the symbol is for an import...
@ MO_NC
MO_NC - Indicates whether the linker is expected to check the symbol reference for overflow.
@ MO_G1
MO_G1 - A symbol operand with this flag (granule 1) represents the bits 16-31 of a 64-bit address,...
@ MO_S
MO_S - Indicates that the bits of the symbol operand represented by MO_G0 etc are signed.
@ MO_PAGEOFF
MO_PAGEOFF - A symbol operand with this flag represents the offset of that symbol within a 4K page.
@ MO_GOT
MO_GOT - This flag indicates that a symbol operand represents the address of the GOT entry for the sy...
@ MO_PREL
MO_PREL - Indicates that the bits of the symbol operand represented by MO_G0 etc are PC relative.
@ MO_G0
MO_G0 - A symbol operand with this flag (granule 0) represents the bits 0-15 of a 64-bit address,...
@ MO_ARM64EC_CALLMANGLE
MO_ARM64EC_CALLMANGLE - Operand refers to the Arm64EC-mangled version of a symbol,...
@ MO_PAGE
MO_PAGE - A symbol operand with this flag represents the pc-relative offset of the 4K page containing...
@ MO_HI12
MO_HI12 - This flag indicates that a symbol operand represents the bits 13-24 of a 64-bit address,...
@ MO_TLS
MO_TLS - Indicates that the operand being accessed is some kind of thread-local symbol.
@ MO_G2
MO_G2 - A symbol operand with this flag (granule 2) represents the bits 32-47 of a 64-bit address,...
@ MO_TAGGED
MO_TAGGED - With MO_PAGE, indicates that the page includes a memory tag in bits 56-63.
@ MO_G3
MO_G3 - A symbol operand with this flag (granule 3) represents the high 16-bits of a 64-bit address,...
@ MO_COFFSTUB
MO_COFFSTUB - On a symbol operand "FOO", this indicates that the reference is actually to the "....
unsigned getCheckerSizeInBytes(AuthCheckMethod Method)
Returns the number of bytes added by checkAuthenticatedRegister.
static uint64_t decodeLogicalImmediate(uint64_t val, unsigned regSize)
decodeLogicalImmediate - Decode a logical immediate value in the form "N:immr:imms" (where the immr a...
static unsigned getShiftValue(unsigned Imm)
getShiftValue - Extract the shift value.
static unsigned getArithExtendImm(AArch64_AM::ShiftExtendType ET, unsigned Imm)
getArithExtendImm - Encode the extend type and shift amount for an arithmetic instruction: imm: 3-bit...
constexpr bool isLegalArithImmed(const uint64_t C)
isLegalArithImmed -
static unsigned getArithShiftValue(unsigned Imm)
getArithShiftValue - get the arithmetic shift value.
static uint64_t encodeLogicalImmediate(uint64_t imm, unsigned regSize)
encodeLogicalImmediate - Return the encoded immediate value for a logical immediate instruction of th...
static AArch64_AM::ShiftExtendType getExtendType(unsigned Imm)
getExtendType - Extract the extend type for operands of arithmetic ops.
static AArch64_AM::ShiftExtendType getArithExtendType(unsigned Imm)
static AArch64_AM::ShiftExtendType getShiftType(unsigned Imm)
getShiftType - Extract the shift type.
static unsigned getShifterImm(AArch64_AM::ShiftExtendType ST, unsigned Imm)
getShifterImm - Encode the shift type and amount: imm: 6-bit shift amount shifter: 000 ==> lsl 001 ==...
void expandMOVAddr(unsigned Opcode, unsigned TargetFlags, bool IsTargetMachO, SmallVectorImpl< AddrInsnModel > &Insn)
void expandMOVImm(uint64_t Imm, unsigned BitSize, SmallVectorImpl< ImmInsnModel > &Insn)
Expand a MOVi32imm or MOVi64imm pseudo instruction to one or more real move-immediate instructions to...
static const uint64_t InstrFlagIsWhile
static const uint64_t InstrFlagIsPTestLike
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ ScalablePredicateVector
initializer< Ty > init(const Ty &Val)
InstrType
Represents how an instruction should be mapped by the outliner.
NodeAddr< InstrNode * > Instr
LLVM_ABI Instruction & back() const
LLVM_ABI iterator begin() const
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
static bool isCondBranchOpcode(int Opc)
MCCFIInstruction createDefCFA(const TargetRegisterInfo &TRI, unsigned FrameReg, unsigned Reg, const StackOffset &Offset, bool LastAdjustmentWasScalable=true)
static bool isPTrueOpcode(unsigned Opc)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
bool succeeded(LogicalResult Result)
Utility function that returns true if the provided LogicalResult corresponds to a success value.
int isAArch64FrameOffsetLegal(const MachineInstr &MI, StackOffset &Offset, bool *OutUseUnscaledOp=nullptr, unsigned *OutUnscaledOp=nullptr, int64_t *EmittableOffset=nullptr)
Check if the Offset is a valid frame offset for MI.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
RegState
Flags to represent properties of register accesses.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
@ Define
Register definition.
@ Renamable
Register that may be renamed.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
constexpr RegState getKillRegState(bool B)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
static bool isIndirectBranchOpcode(int Opc)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
unsigned getBLRCallOpcode(const MachineFunction &MF)
Return opcode to be used for indirect calls.
@ AArch64FrameOffsetIsLegal
Offset is legal.
@ AArch64FrameOffsetCanUpdate
Offset can apply, at least partly.
@ AArch64FrameOffsetCannotUpdate
Offset cannot apply.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
static bool isSEHInstruction(const MachineInstr &MI)
bool isLFIPrePostMemAccess(unsigned Opcode)
Returns true if Opcode is a pre- or post-indexed memory access that the LFI rewriter expands with a b...
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
auto reverse(ContainerTy &&C)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void sort(IteratorTy Start, IteratorTy End)
AArch64MachineCombinerPattern
@ MULSUBv2i32_indexed_OP1
@ MULADDv4i16_indexed_OP2
@ MULSUBv8i16_indexed_OP2
@ MULSUBv4i16_indexed_OP2
@ MULSUBv4i32_indexed_OP2
@ MULADDv2i32_indexed_OP1
@ MULADDv4i32_indexed_OP1
@ MULADDv2i32_indexed_OP2
@ MULSUBv4i16_indexed_OP1
@ MULADDv4i32_indexed_OP2
@ MULSUBv8i16_indexed_OP1
@ MULSUBv2i32_indexed_OP2
@ MULADDv8i16_indexed_OP1
@ MULSUBv4i32_indexed_OP1
@ MULADDv8i16_indexed_OP2
@ MULADDv4i16_indexed_OP1
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void emitFrameOffset(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, StackOffset Offset, const TargetInstrInfo *TII, MachineInstr::MIFlag=MachineInstr::NoFlags, bool SetNZCV=false, bool NeedsWinCFI=false, bool *HasWinCFI=nullptr, bool EmitCFAOffset=false, StackOffset InitialOffset={}, unsigned FrameReg=AArch64::SP)
emitFrameOffset - Emit instructions as needed to set DestReg to SrcReg plus Offset.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr RegState getDefRegState(bool B)
CombinerObjective
The combiner's goal may differ based on which pattern it is attempting to optimize.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
std::optional< UsedNZCV > examineCFlagsUse(MachineInstr &MI, MachineInstr &CmpInstr, const TargetRegisterInfo &TRI, SmallVectorImpl< MachineInstr * > *CCUseInstrs=nullptr)
CodeGenOptLevel
Code generation optimization level.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
auto instructionsWithoutDebug(IterT It, IterT End, bool SkipPseudoOp=true)
Construct a range iterator which begins at It and moves forwards until End is reached,...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
auto drop_end(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the last N elements excluded.
static MCRegister getXRegFromWReg(MCRegister Reg)
MCCFIInstruction createCFAOffset(const TargetRegisterInfo &MRI, unsigned Reg, const StackOffset &OffsetFromDefCFA, std::optional< int64_t > IncomingVGOffsetFromDefCFA)
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
static bool isUncondBranchOpcode(int Opc)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
bool rewriteAArch64FrameIndex(MachineInstr &MI, unsigned FrameRegIdx, unsigned FrameReg, StackOffset &Offset, const AArch64InstrInfo *TII)
rewriteAArch64FrameIndex - Rewrite MI to access 'Offset' bytes from the FP.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
static const MachineMemOperand::Flags MOSuppressPair
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
void appendLEB128(SmallVectorImpl< U > &Buffer, T Value)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
bool optimizeTerminators(MachineBasicBlock *MBB, const TargetInstrInfo &TII)
std::pair< MachineOperand, DIExpression * > ParamLoadedValue
bool isNZCVTouchedInInstructionRange(const MachineInstr &DefMI, const MachineInstr &UseMI, const TargetRegisterInfo *TRI)
Return true if there is an instruction /after/ DefMI and before UseMI which either reads or clobbers ...
static const MachineMemOperand::Flags MOStridedAccess
constexpr RegState getUndefRegState(bool B)
void fullyRecomputeLiveIns(ArrayRef< MachineBasicBlock * > MBBs)
Convenience function for recomputing live-in's for a set of MBBs until the computation converges.
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
MCRegisterClass TargetRegisterClass
This struct is a compact representation of a valid (non-zero power of two) alignment.
Used to describe addressing mode similar to ExtAddrMode in CodeGenPrepare.
LLVM_ABI static const MBBSectionID ColdSectionID
This class contains a discriminated union of information about pointers in memory operands,...
static LLVM_ABI MachinePointerInfo getUnknownStack(MachineFunction &MF)
Stack memory without other information.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
An individual sequence of instructions to be replaced with a call to an outlined function.
MachineFunction * getMF() const
The information necessary to create an outlined function for some class of candidate.