65#define GET_INSTRINFO_CTOR_DTOR
66#include "AArch64GenInstrInfo.inc"
70 cl::desc(
"Restrict range of CB instructions (DEBUG)"));
74 cl::desc(
"Restrict range of TB[N]Z instructions (DEBUG)"));
78 cl::desc(
"Restrict range of CB[N]Z instructions (DEBUG)"));
82 cl::desc(
"Restrict range of Bcc instructions (DEBUG)"));
86 cl::desc(
"Restrict range of B instructions (DEBUG)"));
90 cl::desc(
"Restrict range of instructions to search for the "
91 "machine-combiner gather pattern optimization"));
96 RI(STI.getTargetTriple(), STI.getHwMode()), Subtarget(STI) {}
107 auto Op =
MI.getOpcode();
108 if (
Op == AArch64::INLINEASM ||
Op == AArch64::INLINEASM_BR)
109 return getInlineAsmLength(
MI.getOperand(0).getSymbolName(), *MAI);
113 if (
MI.isMetaInstruction())
118 unsigned NumBytes = 0;
122 NumBytes =
Desc.getSize() ?
Desc.getSize() : 4;
125 if (!MFI->shouldSignReturnAddress(*MF))
129 auto Method = STI.getAuthenticatedLRCheckMethod(*MF);
137 switch (
Desc.getOpcode()) {
140 return Desc.getSize();
147 case TargetOpcode::STACKMAP:
150 assert(NumBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
152 case TargetOpcode::PATCHPOINT:
155 assert(NumBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
157 case TargetOpcode::STATEPOINT:
159 assert(NumBytes % 4 == 0 &&
"Invalid number of NOP bytes requested!");
164 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
169 F.getFnAttributeAsParsedInteger(
"patchable-function-entry", 9) * 4;
171 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
172 case TargetOpcode::PATCHABLE_TAIL_CALL:
173 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
177 case TargetOpcode::PATCHABLE_EVENT_CALL:
183 NumBytes =
MI.getOperand(1).getImm();
185 case TargetOpcode::BUNDLE:
186 NumBytes = getInstBundleLength(
MI);
193unsigned AArch64InstrInfo::getInstBundleLength(
const MachineInstr &
MI)
const {
197 while (++
I != E &&
I->isInsideBundle()) {
198 assert(!
I->isBundle() &&
"No nested bundle!");
233 case AArch64::CBWPri:
234 case AArch64::CBXPri:
235 case AArch64::CBWPrr:
236 case AArch64::CBXPrr:
265 case AArch64::CBWPri:
266 case AArch64::CBXPri:
267 case AArch64::CBWPrr:
268 case AArch64::CBXPrr:
274 int64_t BrOffset)
const {
276 assert(Bits >= 3 &&
"max branch displacement must be enough to jump"
277 "over conditional branch expansion");
278 return isIntN(Bits, BrOffset / 4);
283 switch (
MI.getOpcode()) {
287 return MI.getOperand(0).getMBB();
292 return MI.getOperand(2).getMBB();
298 return MI.getOperand(1).getMBB();
299 case AArch64::CBWPri:
300 case AArch64::CBXPri:
301 case AArch64::CBWPrr:
302 case AArch64::CBXPrr:
303 return MI.getOperand(3).getMBB();
313 assert(RS &&
"RegScavenger required for long branching");
315 "new block should be inserted for expanding unconditional branch");
318 "restore block should be inserted for restoring clobbered registers");
325 "Branch offsets outside of the signed 33-bit range not supported");
336 RS->enterBasicBlockEnd(
MBB);
339 constexpr Register Reg = AArch64::X16;
340 if (!RS->isRegUsed(Reg)) {
341 insertUnconditionalBranch(
MBB, &NewDestBB,
DL);
348 Register Scavenged = RS->FindUnusedReg(&AArch64::GPR64RegClass);
349 if (Scavenged != AArch64::NoRegister &&
351 buildIndirectBranch(Scavenged, NewDestBB);
352 RS->setRegUsed(Scavenged);
361 "Unable to insert indirect branch inside function that has red zone");
384 bool AllowModify)
const {
391 if (
I->getOpcode() == AArch64::SpeculationBarrierISBDSBEndBB ||
392 I->getOpcode() == AArch64::SpeculationBarrierSBEndBB) {
396 if (!isUnpredicatedTerminator(*
I))
403 unsigned LastOpc = LastInst->
getOpcode();
404 if (
I ==
MBB.begin() || !isUnpredicatedTerminator(*--
I)) {
419 unsigned SecondLastOpc = SecondLastInst->
getOpcode();
426 LastInst = SecondLastInst;
428 if (
I ==
MBB.begin() || !isUnpredicatedTerminator(*--
I)) {
433 SecondLastInst = &*
I;
434 SecondLastOpc = SecondLastInst->
getOpcode();
445 LastInst = SecondLastInst;
447 if (
I ==
MBB.begin() || !isUnpredicatedTerminator(*--
I)) {
449 "unreachable unconditional branches removed above");
458 SecondLastInst = &*
I;
459 SecondLastOpc = SecondLastInst->
getOpcode();
463 if (SecondLastInst &&
I !=
MBB.begin() && isUnpredicatedTerminator(*--
I))
479 I->eraseFromParent();
488 I->eraseFromParent();
497 MachineBranchPredicate &MBP,
498 bool AllowModify)
const {
508 if (
I->getOpcode() == AArch64::SpeculationBarrierISBDSBEndBB ||
509 I->getOpcode() == AArch64::SpeculationBarrierSBEndBB) {
513 if (!isUnpredicatedTerminator(*
I))
518 unsigned LastOpc = LastInst->
getOpcode();
533 assert(MBP.TrueDest &&
"expected!");
534 MBP.FalseDest =
MBB.getNextNode();
536 MBP.ConditionDef =
nullptr;
537 MBP.SingleUseCondition =
false;
541 MBP.Predicate = (LastOpc == AArch64::CBNZX || LastOpc == AArch64::CBNZW)
542 ? MachineBranchPredicate::PRED_NE
543 : MachineBranchPredicate::PRED_EQ;
559 Cond[1].setImm(AArch64::CBNZW);
562 Cond[1].setImm(AArch64::CBZW);
565 Cond[1].setImm(AArch64::CBNZX);
568 Cond[1].setImm(AArch64::CBZX);
571 Cond[1].setImm(AArch64::TBNZW);
574 Cond[1].setImm(AArch64::TBZW);
577 Cond[1].setImm(AArch64::TBNZX);
580 Cond[1].setImm(AArch64::TBZX);
584 case AArch64::CBWPri:
585 case AArch64::CBXPri:
586 case AArch64::CBWPrr:
587 case AArch64::CBXPrr: {
600 int *BytesRemoved)
const {
610 I->eraseFromParent();
614 if (
I ==
MBB.begin()) {
627 I->eraseFromParent();
634void AArch64InstrInfo::instantiateCondBranch(
664 assert(
TBB &&
"insertBranch must not be told to insert a fallthrough");
692 if (!
DefMI->isFullCopy())
694 VReg =
DefMI->getOperand(1).getReg();
703 unsigned *NewReg =
nullptr) {
708 bool Is64Bit = AArch64::GPR64allRegClass.hasSubClassEq(
MRI.getRegClass(VReg));
712 switch (
DefMI->getOpcode()) {
713 case AArch64::SUBREG_TO_REG:
717 if (!
DefMI->getOperand(1).isImm() ||
DefMI->getOperand(1).getImm() != 0)
719 if (!
DefMI->getOperand(2).isReg())
721 if (!
DefMI->getOperand(3).isImm() ||
722 DefMI->getOperand(3).getImm() != AArch64::sub_32)
725 if (
DefMI->getOpcode() != AArch64::MOVi32imm)
727 if (!
DefMI->getOperand(1).isImm() ||
DefMI->getOperand(1).getImm() != 1)
730 SrcReg = AArch64::XZR;
731 Opc = AArch64::CSINCXr;
734 case AArch64::MOVi32imm:
735 case AArch64::MOVi64imm:
736 if (!
DefMI->getOperand(1).isImm() ||
DefMI->getOperand(1).getImm() != 1)
738 SrcReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
739 Opc = Is64Bit ? AArch64::CSINCXr : AArch64::CSINCWr;
742 case AArch64::ADDSXri:
743 case AArch64::ADDSWri:
745 if (
DefMI->findRegisterDefOperandIdx(AArch64::NZCV,
nullptr,
750 case AArch64::ADDXri:
751 case AArch64::ADDWri:
753 if (!
DefMI->getOperand(2).isImm() ||
DefMI->getOperand(2).getImm() != 1 ||
754 DefMI->getOperand(3).getImm() != 0)
756 SrcReg =
DefMI->getOperand(1).getReg();
757 Opc = Is64Bit ? AArch64::CSINCXr : AArch64::CSINCWr;
760 case AArch64::ORNXrr:
761 case AArch64::ORNWrr: {
764 if (ZReg != AArch64::XZR && ZReg != AArch64::WZR)
766 SrcReg =
DefMI->getOperand(2).getReg();
767 Opc = Is64Bit ? AArch64::CSINVXr : AArch64::CSINVWr;
771 case AArch64::SUBSXrr:
772 case AArch64::SUBSWrr:
774 if (
DefMI->findRegisterDefOperandIdx(AArch64::NZCV,
nullptr,
779 case AArch64::SUBXrr:
780 case AArch64::SUBWrr: {
783 if (ZReg != AArch64::XZR && ZReg != AArch64::WZR)
785 SrcReg =
DefMI->getOperand(2).getReg();
786 Opc = Is64Bit ? AArch64::CSNEGXr : AArch64::CSNEGWr;
792 assert(
Opc && SrcReg &&
"Missing parameters");
804 int &FalseCycles)
const {
808 RI.getCommonSubClass(
MRI.getRegClass(TrueReg),
MRI.getRegClass(FalseReg));
815 if (!RI.getCommonSubClass(RC,
MRI.getRegClass(DstReg)))
819 unsigned ExtraCondLat =
Cond.size() != 1;
823 if (AArch64::GPR64allRegClass.hasSubClassEq(RC) ||
824 AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
826 CondCycles = 1 + ExtraCondLat;
827 TrueCycles = FalseCycles = 1;
837 if (AArch64::FPR64RegClass.hasSubClassEq(RC) ||
838 AArch64::FPR32RegClass.hasSubClassEq(RC)) {
839 CondCycles = 5 + ExtraCondLat;
840 TrueCycles = FalseCycles = 2;
857 switch (
Cond.size()) {
889 MRI.constrainRegClass(SrcReg, &AArch64::GPR64spRegClass);
895 MRI.constrainRegClass(SrcReg, &AArch64::GPR32spRegClass);
934 unsigned SUBSOpC, SUBSDestReg;
940 case AArch64::CBWPri:
941 SUBSOpC = AArch64::SUBSWri;
942 SUBSDestReg = AArch64::WZR;
945 case AArch64::CBXPri:
946 SUBSOpC = AArch64::SUBSXri;
947 SUBSDestReg = AArch64::XZR;
950 case AArch64::CBWPrr:
951 SUBSOpC = AArch64::SUBSWrr;
952 SUBSDestReg = AArch64::WZR;
955 case AArch64::CBXPrr:
956 SUBSOpC = AArch64::SUBSXrr;
957 SUBSDestReg = AArch64::XZR;
976 bool TryFold =
false;
977 if (
MRI.constrainRegClass(DstReg, &AArch64::GPR64RegClass)) {
978 RC = &AArch64::GPR64RegClass;
979 Opc = AArch64::CSELXr;
981 }
else if (
MRI.constrainRegClass(DstReg, &AArch64::GPR32RegClass)) {
982 RC = &AArch64::GPR32RegClass;
983 Opc = AArch64::CSELWr;
985 }
else if (
MRI.constrainRegClass(DstReg, &AArch64::FPR64RegClass)) {
986 RC = &AArch64::FPR64RegClass;
987 Opc = AArch64::FCSELDrrr;
988 }
else if (
MRI.constrainRegClass(DstReg, &AArch64::FPR32RegClass)) {
989 RC = &AArch64::FPR32RegClass;
990 Opc = AArch64::FCSELSrrr;
992 assert(RC &&
"Unsupported regclass");
1011 MRI.clearKillFlags(NewReg);
1016 MRI.constrainRegClass(TrueReg, RC);
1019 (FalseReg.
isVirtual() || FalseReg == AArch64::WZR ||
1020 FalseReg == AArch64::XZR) &&
1021 "FalseReg was folded into a non-virtual register other than WZR or XZR");
1023 MRI.constrainRegClass(FalseReg, RC);
1038 assert(BitSize == 64 &&
"Only bit sizes of 32 or 64 allowed");
1043 return Is.
size() <= 2;
1049 if (Subtarget.hasExynosCheapAsMoveHandling()) {
1050 if (isExynosCheapAsMove(
MI))
1052 return MI.isAsCheapAsAMove();
1055 switch (
MI.getOpcode()) {
1057 return MI.isAsCheapAsAMove();
1059 case AArch64::ADDWrs:
1060 case AArch64::ADDXrs:
1061 case AArch64::SUBWrs:
1062 case AArch64::SUBXrs:
1063 return Subtarget.hasALULSLFast() &&
MI.getOperand(3).getImm() <= 4;
1068 case AArch64::MOVi32imm:
1070 case AArch64::MOVi64imm:
1075bool AArch64InstrInfo::isFalkorShiftExtFast(
const MachineInstr &
MI) {
1076 switch (
MI.getOpcode()) {
1080 case AArch64::ADDWrs:
1081 case AArch64::ADDXrs:
1082 case AArch64::ADDSWrs:
1083 case AArch64::ADDSXrs: {
1084 unsigned Imm =
MI.getOperand(3).getImm();
1091 case AArch64::ADDWrx:
1092 case AArch64::ADDXrx:
1093 case AArch64::ADDXrx64:
1094 case AArch64::ADDSWrx:
1095 case AArch64::ADDSXrx:
1096 case AArch64::ADDSXrx64: {
1097 unsigned Imm =
MI.getOperand(3).getImm();
1109 case AArch64::SUBWrs:
1110 case AArch64::SUBSWrs: {
1111 unsigned Imm =
MI.getOperand(3).getImm();
1113 return ShiftVal == 0 ||
1117 case AArch64::SUBXrs:
1118 case AArch64::SUBSXrs: {
1119 unsigned Imm =
MI.getOperand(3).getImm();
1121 return ShiftVal == 0 ||
1125 case AArch64::SUBWrx:
1126 case AArch64::SUBXrx:
1127 case AArch64::SUBXrx64:
1128 case AArch64::SUBSWrx:
1129 case AArch64::SUBSXrx:
1130 case AArch64::SUBSXrx64: {
1131 unsigned Imm =
MI.getOperand(3).getImm();
1143 case AArch64::LDRBBroW:
1144 case AArch64::LDRBBroX:
1145 case AArch64::LDRBroW:
1146 case AArch64::LDRBroX:
1147 case AArch64::LDRDroW:
1148 case AArch64::LDRDroX:
1149 case AArch64::LDRHHroW:
1150 case AArch64::LDRHHroX:
1151 case AArch64::LDRHroW:
1152 case AArch64::LDRHroX:
1153 case AArch64::LDRQroW:
1154 case AArch64::LDRQroX:
1155 case AArch64::LDRSBWroW:
1156 case AArch64::LDRSBWroX:
1157 case AArch64::LDRSBXroW:
1158 case AArch64::LDRSBXroX:
1159 case AArch64::LDRSHWroW:
1160 case AArch64::LDRSHWroX:
1161 case AArch64::LDRSHXroW:
1162 case AArch64::LDRSHXroX:
1163 case AArch64::LDRSWroW:
1164 case AArch64::LDRSWroX:
1165 case AArch64::LDRSroW:
1166 case AArch64::LDRSroX:
1167 case AArch64::LDRWroW:
1168 case AArch64::LDRWroX:
1169 case AArch64::LDRXroW:
1170 case AArch64::LDRXroX:
1171 case AArch64::PRFMroW:
1172 case AArch64::PRFMroX:
1173 case AArch64::STRBBroW:
1174 case AArch64::STRBBroX:
1175 case AArch64::STRBroW:
1176 case AArch64::STRBroX:
1177 case AArch64::STRDroW:
1178 case AArch64::STRDroX:
1179 case AArch64::STRHHroW:
1180 case AArch64::STRHHroX:
1181 case AArch64::STRHroW:
1182 case AArch64::STRHroX:
1183 case AArch64::STRQroW:
1184 case AArch64::STRQroX:
1185 case AArch64::STRSroW:
1186 case AArch64::STRSroX:
1187 case AArch64::STRWroW:
1188 case AArch64::STRWroX:
1189 case AArch64::STRXroW:
1190 case AArch64::STRXroX: {
1191 unsigned IsSigned =
MI.getOperand(3).getImm();
1198 unsigned Opc =
MI.getOpcode();
1202 case AArch64::SEH_StackAlloc:
1203 case AArch64::SEH_SaveFPLR:
1204 case AArch64::SEH_SaveFPLR_X:
1205 case AArch64::SEH_SaveReg:
1206 case AArch64::SEH_SaveReg_X:
1207 case AArch64::SEH_SaveRegP:
1208 case AArch64::SEH_SaveRegP_X:
1209 case AArch64::SEH_SaveFReg:
1210 case AArch64::SEH_SaveFReg_X:
1211 case AArch64::SEH_SaveFRegP:
1212 case AArch64::SEH_SaveFRegP_X:
1213 case AArch64::SEH_SetFP:
1214 case AArch64::SEH_AddFP:
1215 case AArch64::SEH_Nop:
1216 case AArch64::SEH_PrologEnd:
1217 case AArch64::SEH_EpilogStart:
1218 case AArch64::SEH_EpilogEnd:
1219 case AArch64::SEH_PACSignLR:
1220 case AArch64::SEH_SaveAnyRegI:
1221 case AArch64::SEH_SaveAnyRegIP:
1222 case AArch64::SEH_SaveAnyRegQP:
1223 case AArch64::SEH_SaveAnyRegQPX:
1224 case AArch64::SEH_AllocZ:
1225 case AArch64::SEH_SaveZReg:
1226 case AArch64::SEH_SavePReg:
1233 unsigned &SubIdx)
const {
1234 switch (
MI.getOpcode()) {
1237 case AArch64::SBFMXri:
1238 case AArch64::UBFMXri:
1241 if (
MI.getOperand(2).getImm() != 0 ||
MI.getOperand(3).getImm() != 31)
1244 SrcReg =
MI.getOperand(1).getReg();
1245 DstReg =
MI.getOperand(0).getReg();
1246 SubIdx = AArch64::sub_32;
1255 int64_t OffsetA = 0, OffsetB = 0;
1256 TypeSize WidthA(0,
false), WidthB(0,
false);
1257 bool OffsetAIsScalable =
false, OffsetBIsScalable =
false;
1278 OffsetAIsScalable == OffsetBIsScalable) {
1279 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
1280 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
1281 TypeSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
1282 if (LowWidth.
isScalable() == OffsetAIsScalable &&
1300 switch (
MI.getOpcode()) {
1303 if (
MI.getOperand(0).getImm() == 0x14)
1310 case AArch64::MSRpstatesvcrImm1:
1317 auto Next = std::next(
MI.getIterator());
1318 return Next !=
MBB->end() &&
Next->isCFIInstruction();
1325 Register &SrcReg2, int64_t &CmpMask,
1326 int64_t &CmpValue)
const {
1330 assert(
MI.getNumOperands() >= 2 &&
"All AArch64 cmps should have 2 operands");
1331 if (!
MI.getOperand(1).isReg() ||
MI.getOperand(1).getSubReg())
1334 switch (
MI.getOpcode()) {
1337 case AArch64::PTEST_PP:
1338 case AArch64::PTEST_PP_ANY:
1339 case AArch64::PTEST_PP_FIRST:
1340 SrcReg =
MI.getOperand(0).getReg();
1341 SrcReg2 =
MI.getOperand(1).getReg();
1342 if (
MI.getOperand(2).getSubReg())
1349 case AArch64::SUBSWrr:
1350 case AArch64::SUBSWrs:
1351 case AArch64::SUBSWrx:
1352 case AArch64::SUBSXrr:
1353 case AArch64::SUBSXrs:
1354 case AArch64::SUBSXrx:
1355 case AArch64::ADDSWrr:
1356 case AArch64::ADDSWrs:
1357 case AArch64::ADDSWrx:
1358 case AArch64::ADDSXrr:
1359 case AArch64::ADDSXrs:
1360 case AArch64::ADDSXrx:
1362 SrcReg =
MI.getOperand(1).getReg();
1363 SrcReg2 =
MI.getOperand(2).getReg();
1366 if (
MI.getOperand(2).getSubReg())
1372 case AArch64::SUBSWri:
1373 case AArch64::ADDSWri:
1374 case AArch64::SUBSXri:
1375 case AArch64::ADDSXri:
1376 SrcReg =
MI.getOperand(1).getReg();
1379 CmpValue =
MI.getOperand(2).getImm();
1381 case AArch64::ANDSWri:
1382 case AArch64::ANDSXri:
1385 SrcReg =
MI.getOperand(1).getReg();
1389 MI.getOperand(2).getImm(),
1390 MI.getOpcode() == AArch64::ANDSWri ? 32 : 64);
1399 assert(
MBB &&
"Can't get MachineBasicBlock here");
1401 assert(MF &&
"Can't get MachineFunction here");
1406 for (
unsigned OpIdx = 0, EndIdx = Instr.getNumOperands();
OpIdx < EndIdx;
1413 if (!OpRegCstraints)
1421 "Operand has register constraints without being a register!");
1424 if (
Reg.isPhysical()) {
1428 !
MRI->constrainRegClass(
Reg, OpRegCstraints))
1441 bool MIDefinesZeroReg =
false;
1442 if (
MI.definesRegister(AArch64::WZR,
nullptr) ||
1443 MI.definesRegister(AArch64::XZR,
nullptr))
1444 MIDefinesZeroReg =
true;
1446 switch (
MI.getOpcode()) {
1448 return MI.getOpcode();
1449 case AArch64::ADDSWrr:
1450 return AArch64::ADDWrr;
1451 case AArch64::ADDSWri:
1452 return MIDefinesZeroReg ? AArch64::ADDSWri : AArch64::ADDWri;
1453 case AArch64::ADDSWrs:
1454 return MIDefinesZeroReg ? AArch64::ADDSWrs : AArch64::ADDWrs;
1455 case AArch64::ADDSWrx:
1456 return AArch64::ADDWrx;
1457 case AArch64::ADDSXrr:
1458 return AArch64::ADDXrr;
1459 case AArch64::ADDSXri:
1460 return MIDefinesZeroReg ? AArch64::ADDSXri : AArch64::ADDXri;
1461 case AArch64::ADDSXrs:
1462 return MIDefinesZeroReg ? AArch64::ADDSXrs : AArch64::ADDXrs;
1463 case AArch64::ADDSXrx:
1464 return AArch64::ADDXrx;
1465 case AArch64::SUBSWrr:
1466 return AArch64::SUBWrr;
1467 case AArch64::SUBSWri:
1468 return MIDefinesZeroReg ? AArch64::SUBSWri : AArch64::SUBWri;
1469 case AArch64::SUBSWrs:
1470 return MIDefinesZeroReg ? AArch64::SUBSWrs : AArch64::SUBWrs;
1471 case AArch64::SUBSWrx:
1472 return AArch64::SUBWrx;
1473 case AArch64::SUBSXrr:
1474 return AArch64::SUBXrr;
1475 case AArch64::SUBSXri:
1476 return MIDefinesZeroReg ? AArch64::SUBSXri : AArch64::SUBXri;
1477 case AArch64::SUBSXrs:
1478 return MIDefinesZeroReg ? AArch64::SUBSXrs : AArch64::SUBXrs;
1479 case AArch64::SUBSXrx:
1480 return AArch64::SUBXrx;
1495 if (To == To->getParent()->begin())
1500 if (To->getParent() != From->getParent())
1512 Instr.modifiesRegister(AArch64::NZCV,
TRI)) ||
1513 ((AccessToCheck &
AK_Read) && Instr.readsRegister(AArch64::NZCV,
TRI)))
1519std::optional<unsigned>
1523 unsigned MaskOpcode =
Mask->getOpcode();
1524 unsigned PredOpcode = Pred->
getOpcode();
1525 bool PredIsPTestLike = isPTestLikeOpcode(PredOpcode);
1526 bool PredIsWhileLike = isWhileOpcode(PredOpcode);
1528 if (PredIsWhileLike) {
1532 if ((Mask == Pred) && PTest->
getOpcode() == AArch64::PTEST_PP_ANY)
1539 getElementSizeForOpcode(MaskOpcode) ==
1540 getElementSizeForOpcode(PredOpcode))
1546 if (PTest->
getOpcode() == AArch64::PTEST_PP_FIRST &&
1553 if (PredIsPTestLike) {
1558 if ((Mask == Pred) && PTest->
getOpcode() == AArch64::PTEST_PP_ANY)
1566 if (Mask != PTestLikeMask && PTestLikeMask->isFullCopy() &&
1567 PTestLikeMask->getOperand(1).getReg().isVirtual())
1569 MRI->getUniqueVRegDef(PTestLikeMask->getOperand(1).getReg());
1575 getElementSizeForOpcode(MaskOpcode) ==
1576 getElementSizeForOpcode(PredOpcode)) {
1577 if (Mask == PTestLikeMask || PTest->
getOpcode() == AArch64::PTEST_PP_ANY)
1603 uint64_t PredElementSize = getElementSizeForOpcode(PredOpcode);
1605 PTest->
getOpcode() == AArch64::PTEST_PP_ANY))
1613 switch (PredOpcode) {
1614 case AArch64::AND_PPzPP:
1615 case AArch64::BIC_PPzPP:
1616 case AArch64::EOR_PPzPP:
1617 case AArch64::NAND_PPzPP:
1618 case AArch64::NOR_PPzPP:
1619 case AArch64::ORN_PPzPP:
1620 case AArch64::ORR_PPzPP:
1621 case AArch64::BRKA_PPzP:
1622 case AArch64::BRKPA_PPzPP:
1623 case AArch64::BRKB_PPzP:
1624 case AArch64::BRKPB_PPzPP:
1625 case AArch64::RDFFR_PPz: {
1629 if (Mask != PredMask)
1633 case AArch64::BRKN_PPzP: {
1637 if ((MaskOpcode != AArch64::PTRUE_B) ||
1638 (
Mask->getOperand(1).getImm() != 31))
1642 case AArch64::PTRUE_B:
1655bool AArch64InstrInfo::optimizePTestInstr(
1656 MachineInstr *PTest,
unsigned MaskReg,
unsigned PredReg,
1658 auto *
Mask =
MRI->getUniqueVRegDef(MaskReg);
1659 auto *Pred =
MRI->getUniqueVRegDef(PredReg);
1661 if (Pred->
isCopy() && PTest->
getOpcode() == AArch64::PTEST_PP_FIRST) {
1665 if (
Op.isReg() &&
Op.getReg().isVirtual() &&
1666 Op.getSubReg() == AArch64::psub0)
1667 Pred =
MRI->getUniqueVRegDef(
Op.getReg());
1670 unsigned PredOpcode = Pred->
getOpcode();
1671 auto NewOp = canRemovePTestInstr(PTest, Mask, Pred,
MRI);
1687 if (*NewOp != PredOpcode) {
1698 for (; i !=
e; ++i) {
1729 if (DeadNZCVIdx != -1) {
1748 if (CmpInstr.
getOpcode() == AArch64::PTEST_PP ||
1749 CmpInstr.
getOpcode() == AArch64::PTEST_PP_ANY ||
1750 CmpInstr.
getOpcode() == AArch64::PTEST_PP_FIRST)
1751 return optimizePTestInstr(&CmpInstr, SrcReg, SrcReg2,
MRI);
1760 if (CmpValue == 0 && substituteCmpToZero(CmpInstr, SrcReg, *
MRI))
1762 return (CmpValue == 0 || CmpValue == 1) &&
1763 removeCmpToZeroOrOne(CmpInstr, SrcReg, CmpValue, *
MRI);
1771 switch (Instr.getOpcode()) {
1773 return AArch64::INSTRUCTION_LIST_END;
1775 case AArch64::ADDSWrr:
1776 case AArch64::ADDSWri:
1777 case AArch64::ADDSXrr:
1778 case AArch64::ADDSXri:
1779 case AArch64::SUBSWrr:
1780 case AArch64::SUBSWri:
1781 case AArch64::SUBSXrr:
1782 case AArch64::SUBSXri:
1783 return Instr.getOpcode();
1785 case AArch64::ADDWrr:
1786 return AArch64::ADDSWrr;
1787 case AArch64::ADDWri:
1788 return AArch64::ADDSWri;
1789 case AArch64::ADDXrr:
1790 return AArch64::ADDSXrr;
1791 case AArch64::ADDXri:
1792 return AArch64::ADDSXri;
1793 case AArch64::ADCWr:
1794 return AArch64::ADCSWr;
1795 case AArch64::ADCXr:
1796 return AArch64::ADCSXr;
1797 case AArch64::SUBWrr:
1798 return AArch64::SUBSWrr;
1799 case AArch64::SUBWri:
1800 return AArch64::SUBSWri;
1801 case AArch64::SUBXrr:
1802 return AArch64::SUBSXrr;
1803 case AArch64::SUBXri:
1804 return AArch64::SUBSXri;
1805 case AArch64::SBCWr:
1806 return AArch64::SBCSWr;
1807 case AArch64::SBCXr:
1808 return AArch64::SBCSXr;
1809 case AArch64::ANDWri:
1810 return AArch64::ANDSWri;
1811 case AArch64::ANDXri:
1812 return AArch64::ANDSXri;
1818 for (
auto *BB :
MBB->successors())
1819 if (BB->isLiveIn(AArch64::NZCV))
1828 switch (Instr.getOpcode()) {
1832 case AArch64::Bcc: {
1833 int Idx = Instr.findRegisterUseOperandIdx(AArch64::NZCV,
nullptr);
1838 case AArch64::CSINVWr:
1839 case AArch64::CSINVXr:
1840 case AArch64::CSINCWr:
1841 case AArch64::CSINCXr:
1842 case AArch64::CSELWr:
1843 case AArch64::CSELXr:
1844 case AArch64::CSNEGWr:
1845 case AArch64::CSNEGXr:
1846 case AArch64::FCSELSrrr:
1847 case AArch64::FCSELDrrr: {
1848 int Idx = Instr.findRegisterUseOperandIdx(AArch64::NZCV,
nullptr);
1861 Instr.getOperand(CCIdx).
getImm())
1914std::optional<UsedNZCV>
1919 if (
MI.getParent() != CmpParent)
1920 return std::nullopt;
1923 return std::nullopt;
1928 if (Instr.readsRegister(AArch64::NZCV, &
TRI)) {
1931 return std::nullopt;
1936 if (Instr.modifiesRegister(AArch64::NZCV, &
TRI))
1939 return NZCVUsedAfterCmp;
1943 return Opcode == AArch64::ADDSWri || Opcode == AArch64::ADDSXri;
1947 return Opcode == AArch64::SUBSWri || Opcode == AArch64::SUBSXri;
1969 const unsigned CmpOpcode = CmpInstr.
getOpcode();
1975 "Caller guarantees that CmpInstr compares with constant 0");
1978 if (!NZVCUsed || NZVCUsed->C)
2000bool AArch64InstrInfo::substituteCmpToZero(
2004 MachineInstr *
MI =
MRI.getUniqueVRegDef(SrcReg);
2011 if (NewOpc == AArch64::INSTRUCTION_LIST_END)
2018 MI->setDesc(
get(NewOpc));
2023 MI->addRegisterDefined(AArch64::NZCV, &
TRI);
2035 assert((CmpValue == 0 || CmpValue == 1) &&
2036 "Only comparisons to 0 or 1 considered for removal!");
2039 unsigned MIOpc =
MI.getOpcode();
2040 if (MIOpc == AArch64::CSINCWr) {
2041 if (
MI.getOperand(1).getReg() != AArch64::WZR ||
2042 MI.getOperand(2).getReg() != AArch64::WZR)
2044 }
else if (MIOpc == AArch64::CSINCXr) {
2045 if (
MI.getOperand(1).getReg() != AArch64::XZR ||
2046 MI.getOperand(2).getReg() != AArch64::XZR)
2056 if (
MI.findRegisterDefOperandIdx(AArch64::NZCV,
nullptr,
true) != -1)
2060 const unsigned CmpOpcode = CmpInstr.
getOpcode();
2062 if (CmpValue && !IsSubsRegImm)
2064 if (!CmpValue && !IsSubsRegImm && !
isADDSRegImm(CmpOpcode))
2069 if (MIUsedNZCV.
C || MIUsedNZCV.
V)
2072 std::optional<UsedNZCV> NZCVUsedAfterCmp =
2076 if (!NZCVUsedAfterCmp || NZCVUsedAfterCmp->C || NZCVUsedAfterCmp->V)
2079 if ((MIUsedNZCV.
Z && NZCVUsedAfterCmp->N) ||
2080 (MIUsedNZCV.
N && NZCVUsedAfterCmp->Z))
2083 if (MIUsedNZCV.
N && !CmpValue)
2125bool AArch64InstrInfo::removeCmpToZeroOrOne(
2128 MachineInstr *
MI =
MRI.getUniqueVRegDef(SrcReg);
2132 SmallVector<MachineInstr *, 4> CCUseInstrs;
2133 bool IsInvertCC =
false;
2141 for (MachineInstr *CCUseInstr : CCUseInstrs) {
2143 assert(Idx >= 0 &&
"Unexpected instruction using CC.");
2144 MachineOperand &CCOperand = CCUseInstr->getOperand(Idx);
2153bool AArch64InstrInfo::expandPostRAPseudo(
MachineInstr &
MI)
const {
2154 if (
MI.getOpcode() != TargetOpcode::LOAD_STACK_GUARD &&
2155 MI.getOpcode() != AArch64::CATCHRET)
2158 MachineBasicBlock &
MBB = *
MI.getParent();
2160 auto TRI = Subtarget.getRegisterInfo();
2163 if (
MI.getOpcode() == AArch64::CATCHRET) {
2165 const TargetInstrInfo *
TII =
2167 MachineBasicBlock *TargetMBB =
MI.getOperand(0).getMBB();
2172 FirstEpilogSEH = std::prev(FirstEpilogSEH);
2174 FirstEpilogSEH = std::next(FirstEpilogSEH);
2189 if (
M.getStackProtectorGuard() ==
"sysreg") {
2190 const AArch64SysReg::SysReg *SrcReg =
2191 AArch64SysReg::lookupSysRegByName(
M.getStackProtectorGuardReg());
2199 int Offset =
M.getStackProtectorGuardOffset();
2250 const GlobalValue *GV =
2253 unsigned OpFlags = Subtarget.ClassifyGlobalReference(GV, TM);
2259 if (Subtarget.isTargetILP32()) {
2260 unsigned Reg32 =
TRI->getSubReg(
Reg, AArch64::sub_32);
2274 assert(!Subtarget.isTargetILP32() &&
"how can large exist in ILP32?");
2301 if (Subtarget.isTargetILP32()) {
2302 unsigned Reg32 =
TRI->getSubReg(
Reg, AArch64::sub_32);
2325 switch (
MI.getOpcode()) {
2328 case AArch64::MOVZWi:
2329 case AArch64::MOVZXi:
2330 if (
MI.getOperand(1).isImm() &&
MI.getOperand(1).getImm() == 0) {
2331 assert(
MI.getDesc().getNumOperands() == 3 &&
2332 MI.getOperand(2).getImm() == 0 &&
"invalid MOVZi operands");
2336 case AArch64::ANDWri:
2337 return MI.getOperand(1).getReg() == AArch64::WZR;
2338 case AArch64::ANDXri:
2339 return MI.getOperand(1).getReg() == AArch64::XZR;
2340 case TargetOpcode::COPY:
2341 return MI.getOperand(1).getReg() == AArch64::WZR;
2349 switch (
MI.getOpcode()) {
2352 case TargetOpcode::COPY: {
2355 return (AArch64::GPR32RegClass.
contains(DstReg) ||
2356 AArch64::GPR64RegClass.
contains(DstReg));
2358 case AArch64::ORRXrs:
2359 if (
MI.getOperand(1).getReg() == AArch64::XZR) {
2360 assert(
MI.getDesc().getNumOperands() == 4 &&
2361 MI.getOperand(3).getImm() == 0 &&
"invalid ORRrs operands");
2365 case AArch64::ADDXri:
2366 if (
MI.getOperand(2).getImm() == 0) {
2367 assert(
MI.getDesc().getNumOperands() == 4 &&
2368 MI.getOperand(3).getImm() == 0 &&
"invalid ADDXri operands");
2379 switch (
MI.getOpcode()) {
2382 case TargetOpcode::COPY: {
2384 return AArch64::FPR128RegClass.contains(DstReg);
2386 case AArch64::ORRv16i8:
2387 if (
MI.getOperand(1).getReg() ==
MI.getOperand(2).getReg()) {
2388 assert(
MI.getDesc().getNumOperands() == 3 &&
MI.getOperand(0).isReg() &&
2389 "invalid ORRv16i8 operands");
2398 int &FrameIndex)
const {
2399 switch (
MI.getOpcode()) {
2402 case AArch64::LDRWui:
2403 case AArch64::LDRXui:
2404 case AArch64::LDRBui:
2405 case AArch64::LDRHui:
2406 case AArch64::LDRSui:
2407 case AArch64::LDRDui:
2408 case AArch64::LDRQui:
2409 case AArch64::LDR_PXI:
2410 if (
MI.getOperand(0).getSubReg() == 0 &&
MI.getOperand(1).isFI() &&
2411 MI.getOperand(2).isImm() &&
MI.getOperand(2).getImm() == 0) {
2412 FrameIndex =
MI.getOperand(1).getIndex();
2413 return MI.getOperand(0).getReg();
2422 int &FrameIndex)
const {
2423 switch (
MI.getOpcode()) {
2426 case AArch64::STRWui:
2427 case AArch64::STRXui:
2428 case AArch64::STRBui:
2429 case AArch64::STRHui:
2430 case AArch64::STRSui:
2431 case AArch64::STRDui:
2432 case AArch64::STRQui:
2433 case AArch64::STR_PXI:
2434 if (
MI.getOperand(0).getSubReg() == 0 &&
MI.getOperand(1).isFI() &&
2435 MI.getOperand(2).isImm() &&
MI.getOperand(2).getImm() == 0) {
2436 FrameIndex =
MI.getOperand(1).getIndex();
2437 return MI.getOperand(0).getReg();
2447 return MMO->getFlags() & MOSuppressPair;
2453 if (
MI.memoperands_empty())
2461 return MMO->getFlags() & MOStridedAccess;
2469 case AArch64::STURSi:
2470 case AArch64::STRSpre:
2471 case AArch64::STURDi:
2472 case AArch64::STRDpre:
2473 case AArch64::STURQi:
2474 case AArch64::STRQpre:
2475 case AArch64::STURBBi:
2476 case AArch64::STURHHi:
2477 case AArch64::STURWi:
2478 case AArch64::STRWpre:
2479 case AArch64::STURXi:
2480 case AArch64::STRXpre:
2481 case AArch64::LDURSi:
2482 case AArch64::LDRSpre:
2483 case AArch64::LDURDi:
2484 case AArch64::LDRDpre:
2485 case AArch64::LDURQi:
2486 case AArch64::LDRQpre:
2487 case AArch64::LDURWi:
2488 case AArch64::LDRWpre:
2489 case AArch64::LDURXi:
2490 case AArch64::LDRXpre:
2491 case AArch64::LDRSWpre:
2492 case AArch64::LDURSWi:
2493 case AArch64::LDURHHi:
2494 case AArch64::LDURBBi:
2495 case AArch64::LDURSBWi:
2496 case AArch64::LDURSHWi:
2504 case AArch64::PRFMui:
return AArch64::PRFUMi;
2505 case AArch64::LDRXui:
return AArch64::LDURXi;
2506 case AArch64::LDRWui:
return AArch64::LDURWi;
2507 case AArch64::LDRBui:
return AArch64::LDURBi;
2508 case AArch64::LDRHui:
return AArch64::LDURHi;
2509 case AArch64::LDRSui:
return AArch64::LDURSi;
2510 case AArch64::LDRDui:
return AArch64::LDURDi;
2511 case AArch64::LDRQui:
return AArch64::LDURQi;
2512 case AArch64::LDRBBui:
return AArch64::LDURBBi;
2513 case AArch64::LDRHHui:
return AArch64::LDURHHi;
2514 case AArch64::LDRSBXui:
return AArch64::LDURSBXi;
2515 case AArch64::LDRSBWui:
return AArch64::LDURSBWi;
2516 case AArch64::LDRSHXui:
return AArch64::LDURSHXi;
2517 case AArch64::LDRSHWui:
return AArch64::LDURSHWi;
2518 case AArch64::LDRSWui:
return AArch64::LDURSWi;
2519 case AArch64::STRXui:
return AArch64::STURXi;
2520 case AArch64::STRWui:
return AArch64::STURWi;
2521 case AArch64::STRBui:
return AArch64::STURBi;
2522 case AArch64::STRHui:
return AArch64::STURHi;
2523 case AArch64::STRSui:
return AArch64::STURSi;
2524 case AArch64::STRDui:
return AArch64::STURDi;
2525 case AArch64::STRQui:
return AArch64::STURQi;
2526 case AArch64::STRBBui:
return AArch64::STURBBi;
2527 case AArch64::STRHHui:
return AArch64::STURHHi;
2536 case AArch64::LDAPURBi:
2537 case AArch64::LDAPURHi:
2538 case AArch64::LDAPURi:
2539 case AArch64::LDAPURSBWi:
2540 case AArch64::LDAPURSBXi:
2541 case AArch64::LDAPURSHWi:
2542 case AArch64::LDAPURSHXi:
2543 case AArch64::LDAPURSWi:
2544 case AArch64::LDAPURXi:
2545 case AArch64::LDR_PPXI:
2546 case AArch64::LDR_PXI:
2547 case AArch64::LDR_ZXI:
2548 case AArch64::LDR_ZZXI:
2549 case AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS:
2550 case AArch64::LDR_ZZZXI:
2551 case AArch64::LDR_ZZZZXI:
2552 case AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS:
2553 case AArch64::LDRBBui:
2554 case AArch64::LDRBui:
2555 case AArch64::LDRDui:
2556 case AArch64::LDRHHui:
2557 case AArch64::LDRHui:
2558 case AArch64::LDRQui:
2559 case AArch64::LDRSBWui:
2560 case AArch64::LDRSBXui:
2561 case AArch64::LDRSHWui:
2562 case AArch64::LDRSHXui:
2563 case AArch64::LDRSui:
2564 case AArch64::LDRSWui:
2565 case AArch64::LDRWui:
2566 case AArch64::LDRXui:
2567 case AArch64::LDURBBi:
2568 case AArch64::LDURBi:
2569 case AArch64::LDURDi:
2570 case AArch64::LDURHHi:
2571 case AArch64::LDURHi:
2572 case AArch64::LDURQi:
2573 case AArch64::LDURSBWi:
2574 case AArch64::LDURSBXi:
2575 case AArch64::LDURSHWi:
2576 case AArch64::LDURSHXi:
2577 case AArch64::LDURSi:
2578 case AArch64::LDURSWi:
2579 case AArch64::LDURWi:
2580 case AArch64::LDURXi:
2581 case AArch64::PRFMui:
2582 case AArch64::PRFUMi:
2583 case AArch64::ST2Gi:
2585 case AArch64::STLURBi:
2586 case AArch64::STLURHi:
2587 case AArch64::STLURWi:
2588 case AArch64::STLURXi:
2589 case AArch64::StoreSwiftAsyncContext:
2590 case AArch64::STR_PPXI:
2591 case AArch64::STR_PXI:
2592 case AArch64::STR_ZXI:
2593 case AArch64::STR_ZZXI:
2594 case AArch64::STR_ZZXI_STRIDED_CONTIGUOUS:
2595 case AArch64::STR_ZZZXI:
2596 case AArch64::STR_ZZZZXI:
2597 case AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS:
2598 case AArch64::STRBBui:
2599 case AArch64::STRBui:
2600 case AArch64::STRDui:
2601 case AArch64::STRHHui:
2602 case AArch64::STRHui:
2603 case AArch64::STRQui:
2604 case AArch64::STRSui:
2605 case AArch64::STRWui:
2606 case AArch64::STRXui:
2607 case AArch64::STURBBi:
2608 case AArch64::STURBi:
2609 case AArch64::STURDi:
2610 case AArch64::STURHHi:
2611 case AArch64::STURHi:
2612 case AArch64::STURQi:
2613 case AArch64::STURSi:
2614 case AArch64::STURWi:
2615 case AArch64::STURXi:
2616 case AArch64::STZ2Gi:
2617 case AArch64::STZGi:
2618 case AArch64::TAGPstack:
2620 case AArch64::LD1B_D_IMM:
2621 case AArch64::LD1B_H_IMM:
2622 case AArch64::LD1B_IMM:
2623 case AArch64::LD1B_S_IMM:
2624 case AArch64::LD1D_IMM:
2625 case AArch64::LD1H_D_IMM:
2626 case AArch64::LD1H_IMM:
2627 case AArch64::LD1H_S_IMM:
2628 case AArch64::LD1RB_D_IMM:
2629 case AArch64::LD1RB_H_IMM:
2630 case AArch64::LD1RB_IMM:
2631 case AArch64::LD1RB_S_IMM:
2632 case AArch64::LD1RD_IMM:
2633 case AArch64::LD1RH_D_IMM:
2634 case AArch64::LD1RH_IMM:
2635 case AArch64::LD1RH_S_IMM:
2636 case AArch64::LD1RSB_D_IMM:
2637 case AArch64::LD1RSB_H_IMM:
2638 case AArch64::LD1RSB_S_IMM:
2639 case AArch64::LD1RSH_D_IMM:
2640 case AArch64::LD1RSH_S_IMM:
2641 case AArch64::LD1RSW_IMM:
2642 case AArch64::LD1RW_D_IMM:
2643 case AArch64::LD1RW_IMM:
2644 case AArch64::LD1SB_D_IMM:
2645 case AArch64::LD1SB_H_IMM:
2646 case AArch64::LD1SB_S_IMM:
2647 case AArch64::LD1SH_D_IMM:
2648 case AArch64::LD1SH_S_IMM:
2649 case AArch64::LD1SW_D_IMM:
2650 case AArch64::LD1W_D_IMM:
2651 case AArch64::LD1W_IMM:
2652 case AArch64::LD2B_IMM:
2653 case AArch64::LD2D_IMM:
2654 case AArch64::LD2H_IMM:
2655 case AArch64::LD2W_IMM:
2656 case AArch64::LD3B_IMM:
2657 case AArch64::LD3D_IMM:
2658 case AArch64::LD3H_IMM:
2659 case AArch64::LD3W_IMM:
2660 case AArch64::LD4B_IMM:
2661 case AArch64::LD4D_IMM:
2662 case AArch64::LD4H_IMM:
2663 case AArch64::LD4W_IMM:
2665 case AArch64::LDNF1B_D_IMM:
2666 case AArch64::LDNF1B_H_IMM:
2667 case AArch64::LDNF1B_IMM:
2668 case AArch64::LDNF1B_S_IMM:
2669 case AArch64::LDNF1D_IMM:
2670 case AArch64::LDNF1H_D_IMM:
2671 case AArch64::LDNF1H_IMM:
2672 case AArch64::LDNF1H_S_IMM:
2673 case AArch64::LDNF1SB_D_IMM:
2674 case AArch64::LDNF1SB_H_IMM:
2675 case AArch64::LDNF1SB_S_IMM:
2676 case AArch64::LDNF1SH_D_IMM:
2677 case AArch64::LDNF1SH_S_IMM:
2678 case AArch64::LDNF1SW_D_IMM:
2679 case AArch64::LDNF1W_D_IMM:
2680 case AArch64::LDNF1W_IMM:
2681 case AArch64::LDNPDi:
2682 case AArch64::LDNPQi:
2683 case AArch64::LDNPSi:
2684 case AArch64::LDNPWi:
2685 case AArch64::LDNPXi:
2686 case AArch64::LDNT1B_ZRI:
2687 case AArch64::LDNT1D_ZRI:
2688 case AArch64::LDNT1H_ZRI:
2689 case AArch64::LDNT1W_ZRI:
2690 case AArch64::LDPDi:
2691 case AArch64::LDPQi:
2692 case AArch64::LDPSi:
2693 case AArch64::LDPWi:
2694 case AArch64::LDPXi:
2695 case AArch64::LDRBBpost:
2696 case AArch64::LDRBBpre:
2697 case AArch64::LDRBpost:
2698 case AArch64::LDRBpre:
2699 case AArch64::LDRDpost:
2700 case AArch64::LDRDpre:
2701 case AArch64::LDRHHpost:
2702 case AArch64::LDRHHpre:
2703 case AArch64::LDRHpost:
2704 case AArch64::LDRHpre:
2705 case AArch64::LDRQpost:
2706 case AArch64::LDRQpre:
2707 case AArch64::LDRSpost:
2708 case AArch64::LDRSpre:
2709 case AArch64::LDRWpost:
2710 case AArch64::LDRWpre:
2711 case AArch64::LDRXpost:
2712 case AArch64::LDRXpre:
2713 case AArch64::ST1B_D_IMM:
2714 case AArch64::ST1B_H_IMM:
2715 case AArch64::ST1B_IMM:
2716 case AArch64::ST1B_S_IMM:
2717 case AArch64::ST1D_IMM:
2718 case AArch64::ST1H_D_IMM:
2719 case AArch64::ST1H_IMM:
2720 case AArch64::ST1H_S_IMM:
2721 case AArch64::ST1W_D_IMM:
2722 case AArch64::ST1W_IMM:
2723 case AArch64::ST2B_IMM:
2724 case AArch64::ST2D_IMM:
2725 case AArch64::ST2H_IMM:
2726 case AArch64::ST2W_IMM:
2727 case AArch64::ST3B_IMM:
2728 case AArch64::ST3D_IMM:
2729 case AArch64::ST3H_IMM:
2730 case AArch64::ST3W_IMM:
2731 case AArch64::ST4B_IMM:
2732 case AArch64::ST4D_IMM:
2733 case AArch64::ST4H_IMM:
2734 case AArch64::ST4W_IMM:
2735 case AArch64::STGPi:
2736 case AArch64::STGPreIndex:
2737 case AArch64::STZGPreIndex:
2738 case AArch64::ST2GPreIndex:
2739 case AArch64::STZ2GPreIndex:
2740 case AArch64::STGPostIndex:
2741 case AArch64::STZGPostIndex:
2742 case AArch64::ST2GPostIndex:
2743 case AArch64::STZ2GPostIndex:
2744 case AArch64::STNPDi:
2745 case AArch64::STNPQi:
2746 case AArch64::STNPSi:
2747 case AArch64::STNPWi:
2748 case AArch64::STNPXi:
2749 case AArch64::STNT1B_ZRI:
2750 case AArch64::STNT1D_ZRI:
2751 case AArch64::STNT1H_ZRI:
2752 case AArch64::STNT1W_ZRI:
2753 case AArch64::STPDi:
2754 case AArch64::STPQi:
2755 case AArch64::STPSi:
2756 case AArch64::STPWi:
2757 case AArch64::STPXi:
2758 case AArch64::STRBBpost:
2759 case AArch64::STRBBpre:
2760 case AArch64::STRBpost:
2761 case AArch64::STRBpre:
2762 case AArch64::STRDpost:
2763 case AArch64::STRDpre:
2764 case AArch64::STRHHpost:
2765 case AArch64::STRHHpre:
2766 case AArch64::STRHpost:
2767 case AArch64::STRHpre:
2768 case AArch64::STRQpost:
2769 case AArch64::STRQpre:
2770 case AArch64::STRSpost:
2771 case AArch64::STRSpre:
2772 case AArch64::STRWpost:
2773 case AArch64::STRWpre:
2774 case AArch64::STRXpost:
2775 case AArch64::STRXpre:
2777 case AArch64::LDPDpost:
2778 case AArch64::LDPDpre:
2779 case AArch64::LDPQpost:
2780 case AArch64::LDPQpre:
2781 case AArch64::LDPSpost:
2782 case AArch64::LDPSpre:
2783 case AArch64::LDPWpost:
2784 case AArch64::LDPWpre:
2785 case AArch64::LDPXpost:
2786 case AArch64::LDPXpre:
2787 case AArch64::STGPpre:
2788 case AArch64::STGPpost:
2789 case AArch64::STPDpost:
2790 case AArch64::STPDpre:
2791 case AArch64::STPQpost:
2792 case AArch64::STPQpre:
2793 case AArch64::STPSpost:
2794 case AArch64::STPSpre:
2795 case AArch64::STPWpost:
2796 case AArch64::STPWpre:
2797 case AArch64::STPXpost:
2798 case AArch64::STPXpre:
2804 switch (
MI.getOpcode()) {
2808 case AArch64::STRSui:
2809 case AArch64::STRDui:
2810 case AArch64::STRQui:
2811 case AArch64::STRXui:
2812 case AArch64::STRWui:
2813 case AArch64::LDRSui:
2814 case AArch64::LDRDui:
2815 case AArch64::LDRQui:
2816 case AArch64::LDRXui:
2817 case AArch64::LDRWui:
2818 case AArch64::LDRSWui:
2820 case AArch64::STURSi:
2821 case AArch64::STRSpre:
2822 case AArch64::STURDi:
2823 case AArch64::STRDpre:
2824 case AArch64::STURQi:
2825 case AArch64::STRQpre:
2826 case AArch64::STURWi:
2827 case AArch64::STRWpre:
2828 case AArch64::STURXi:
2829 case AArch64::STRXpre:
2830 case AArch64::LDURSi:
2831 case AArch64::LDRSpre:
2832 case AArch64::LDURDi:
2833 case AArch64::LDRDpre:
2834 case AArch64::LDURQi:
2835 case AArch64::LDRQpre:
2836 case AArch64::LDURWi:
2837 case AArch64::LDRWpre:
2838 case AArch64::LDURXi:
2839 case AArch64::LDRXpre:
2840 case AArch64::LDURSWi:
2841 case AArch64::LDRSWpre:
2843 case AArch64::LDR_ZXI:
2844 case AArch64::STR_ZXI:
2850 switch (
MI.getOpcode()) {
2853 "Unexpected instruction - was a new tail call opcode introduced?");
2855 case AArch64::TCRETURNdi:
2856 case AArch64::TCRETURNri:
2857 case AArch64::TCRETURNrix16x17:
2858 case AArch64::TCRETURNrix17:
2859 case AArch64::TCRETURNrinotx16:
2860 case AArch64::TCRETURNriALL:
2861 case AArch64::AUTH_TCRETURN:
2862 case AArch64::AUTH_TCRETURN_BTI:
2872 case AArch64::ADDWri:
2873 return AArch64::ADDSWri;
2874 case AArch64::ADDWrr:
2875 return AArch64::ADDSWrr;
2876 case AArch64::ADDWrs:
2877 return AArch64::ADDSWrs;
2878 case AArch64::ADDWrx:
2879 return AArch64::ADDSWrx;
2880 case AArch64::ANDWri:
2881 return AArch64::ANDSWri;
2882 case AArch64::ANDWrr:
2883 return AArch64::ANDSWrr;
2884 case AArch64::ANDWrs:
2885 return AArch64::ANDSWrs;
2886 case AArch64::BICWrr:
2887 return AArch64::BICSWrr;
2888 case AArch64::BICWrs:
2889 return AArch64::BICSWrs;
2890 case AArch64::SUBWri:
2891 return AArch64::SUBSWri;
2892 case AArch64::SUBWrr:
2893 return AArch64::SUBSWrr;
2894 case AArch64::SUBWrs:
2895 return AArch64::SUBSWrs;
2896 case AArch64::SUBWrx:
2897 return AArch64::SUBSWrx;
2899 case AArch64::ADDXri:
2900 return AArch64::ADDSXri;
2901 case AArch64::ADDXrr:
2902 return AArch64::ADDSXrr;
2903 case AArch64::ADDXrs:
2904 return AArch64::ADDSXrs;
2905 case AArch64::ADDXrx:
2906 return AArch64::ADDSXrx;
2907 case AArch64::ANDXri:
2908 return AArch64::ANDSXri;
2909 case AArch64::ANDXrr:
2910 return AArch64::ANDSXrr;
2911 case AArch64::ANDXrs:
2912 return AArch64::ANDSXrs;
2913 case AArch64::BICXrr:
2914 return AArch64::BICSXrr;
2915 case AArch64::BICXrs:
2916 return AArch64::BICSXrs;
2917 case AArch64::SUBXri:
2918 return AArch64::SUBSXri;
2919 case AArch64::SUBXrr:
2920 return AArch64::SUBSXrr;
2921 case AArch64::SUBXrs:
2922 return AArch64::SUBSXrs;
2923 case AArch64::SUBXrx:
2924 return AArch64::SUBSXrx;
2926 case AArch64::AND_PPzPP:
2927 return AArch64::ANDS_PPzPP;
2928 case AArch64::BIC_PPzPP:
2929 return AArch64::BICS_PPzPP;
2930 case AArch64::EOR_PPzPP:
2931 return AArch64::EORS_PPzPP;
2932 case AArch64::NAND_PPzPP:
2933 return AArch64::NANDS_PPzPP;
2934 case AArch64::NOR_PPzPP:
2935 return AArch64::NORS_PPzPP;
2936 case AArch64::ORN_PPzPP:
2937 return AArch64::ORNS_PPzPP;
2938 case AArch64::ORR_PPzPP:
2939 return AArch64::ORRS_PPzPP;
2940 case AArch64::BRKA_PPzP:
2941 return AArch64::BRKAS_PPzP;
2942 case AArch64::BRKPA_PPzPP:
2943 return AArch64::BRKPAS_PPzPP;
2944 case AArch64::BRKB_PPzP:
2945 return AArch64::BRKBS_PPzP;
2946 case AArch64::BRKPB_PPzPP:
2947 return AArch64::BRKPBS_PPzPP;
2948 case AArch64::BRKN_PPzP:
2949 return AArch64::BRKNS_PPzP;
2950 case AArch64::RDFFR_PPz:
2951 return AArch64::RDFFRS_PPz;
2952 case AArch64::PTRUE_B:
2953 return AArch64::PTRUES_B;
2964 if (
MI.hasOrderedMemoryRef())
2969 assert((
MI.getOperand(IsPreLdSt ? 2 : 1).isReg() ||
2970 MI.getOperand(IsPreLdSt ? 2 : 1).isFI()) &&
2971 "Expected a reg or frame index operand.");
2975 bool IsImmPreLdSt = IsPreLdSt &&
MI.getOperand(3).isImm();
2977 if (!
MI.getOperand(2).isImm() && !IsImmPreLdSt)
2990 if (
MI.getOperand(1).isReg() && !IsPreLdSt) {
2991 Register BaseReg =
MI.getOperand(1).getReg();
2993 if (
MI.modifiesRegister(BaseReg,
TRI))
2999 switch (
MI.getOpcode()) {
3002 case AArch64::LDR_ZXI:
3003 case AArch64::STR_ZXI:
3004 if (!Subtarget.isLittleEndian() ||
3005 Subtarget.getSVEVectorSizeInBits() != 128)
3018 const MCAsmInfo *MAI =
MI.getMF()->getTarget().getMCAsmInfo();
3020 MI.getMF()->getFunction().needsUnwindTableEntry();
3026 if (Subtarget.isPaired128Slow()) {
3027 switch (
MI.getOpcode()) {
3030 case AArch64::LDURQi:
3031 case AArch64::STURQi:
3032 case AArch64::LDRQui:
3033 case AArch64::STRQui:
3060std::optional<ExtAddrMode>
3065 bool OffsetIsScalable;
3066 if (!getMemOperandWithOffset(MemI,
Base,
Offset, OffsetIsScalable,
TRI))
3067 return std::nullopt;
3070 return std::nullopt;
3085 int64_t OffsetScale = 1;
3090 case AArch64::LDURQi:
3091 case AArch64::STURQi:
3095 case AArch64::LDURDi:
3096 case AArch64::STURDi:
3097 case AArch64::LDURXi:
3098 case AArch64::STURXi:
3102 case AArch64::LDURWi:
3103 case AArch64::LDURSWi:
3104 case AArch64::STURWi:
3108 case AArch64::LDURHi:
3109 case AArch64::STURHi:
3110 case AArch64::LDURHHi:
3111 case AArch64::STURHHi:
3112 case AArch64::LDURSHXi:
3113 case AArch64::LDURSHWi:
3117 case AArch64::LDRBroX:
3118 case AArch64::LDRBBroX:
3119 case AArch64::LDRSBXroX:
3120 case AArch64::LDRSBWroX:
3121 case AArch64::STRBroX:
3122 case AArch64::STRBBroX:
3123 case AArch64::LDURBi:
3124 case AArch64::LDURBBi:
3125 case AArch64::LDURSBXi:
3126 case AArch64::LDURSBWi:
3127 case AArch64::STURBi:
3128 case AArch64::STURBBi:
3129 case AArch64::LDRBui:
3130 case AArch64::LDRBBui:
3131 case AArch64::LDRSBXui:
3132 case AArch64::LDRSBWui:
3133 case AArch64::STRBui:
3134 case AArch64::STRBBui:
3138 case AArch64::LDRQroX:
3139 case AArch64::STRQroX:
3140 case AArch64::LDRQui:
3141 case AArch64::STRQui:
3146 case AArch64::LDRDroX:
3147 case AArch64::STRDroX:
3148 case AArch64::LDRXroX:
3149 case AArch64::STRXroX:
3150 case AArch64::LDRDui:
3151 case AArch64::STRDui:
3152 case AArch64::LDRXui:
3153 case AArch64::STRXui:
3158 case AArch64::LDRWroX:
3159 case AArch64::LDRSWroX:
3160 case AArch64::STRWroX:
3161 case AArch64::LDRWui:
3162 case AArch64::LDRSWui:
3163 case AArch64::STRWui:
3168 case AArch64::LDRHroX:
3169 case AArch64::STRHroX:
3170 case AArch64::LDRHHroX:
3171 case AArch64::STRHHroX:
3172 case AArch64::LDRSHXroX:
3173 case AArch64::LDRSHWroX:
3174 case AArch64::LDRHui:
3175 case AArch64::STRHui:
3176 case AArch64::LDRHHui:
3177 case AArch64::STRHHui:
3178 case AArch64::LDRSHXui:
3179 case AArch64::LDRSHWui:
3187 if (BaseRegOp.
isReg() && BaseRegOp.
getReg() == Reg)
3211 case AArch64::SBFMXri:
3224 AM.
Scale = OffsetScale;
3229 case TargetOpcode::SUBREG_TO_REG: {
3242 if (!OffsetReg.
isVirtual() || !
MRI.hasOneNonDBGUse(OffsetReg))
3246 if (
DefMI.getOpcode() != AArch64::ORRWrs ||
3247 DefMI.getOperand(1).getReg() != AArch64::WZR ||
3248 DefMI.getOperand(3).getImm() != 0)
3255 AM.
Scale = OffsetScale;
3266 auto validateOffsetForLDP = [](
unsigned NumBytes, int64_t OldOffset,
3267 int64_t NewOffset) ->
bool {
3268 int64_t MinOffset, MaxOffset;
3285 return OldOffset < MinOffset || OldOffset > MaxOffset ||
3286 (NewOffset >= MinOffset && NewOffset <= MaxOffset);
3288 auto canFoldAddSubImmIntoAddrMode = [&](int64_t Disp) ->
bool {
3290 int64_t NewOffset = OldOffset + Disp;
3291 if (!isLegalAddressingMode(NumBytes, NewOffset, 0))
3295 if (!validateOffsetForLDP(NumBytes, OldOffset, NewOffset))
3305 auto canFoldAddRegIntoAddrMode =
3310 if ((
unsigned)Scale != Scale)
3312 if (!isLegalAddressingMode(NumBytes, 0, Scale))
3324 return (Opcode == AArch64::STURQi || Opcode == AArch64::STRQui) &&
3325 Subtarget.isSTRQroSlow();
3334 case AArch64::ADDXri:
3340 return canFoldAddSubImmIntoAddrMode(Disp);
3342 case AArch64::SUBXri:
3348 return canFoldAddSubImmIntoAddrMode(-Disp);
3350 case AArch64::ADDXrs: {
3363 if (Shift != 2 && Shift != 3 && Subtarget.hasAddrLSLSlow14())
3365 if (avoidSlowSTRQ(MemI))
3368 return canFoldAddRegIntoAddrMode(1ULL << Shift);
3371 case AArch64::ADDXrr:
3379 if (!OptSize && avoidSlowSTRQ(MemI))
3381 return canFoldAddRegIntoAddrMode(1);
3383 case AArch64::ADDXrx:
3391 if (!OptSize && avoidSlowSTRQ(MemI))
3400 return canFoldAddRegIntoAddrMode(
3415 case AArch64::LDURQi:
3416 case AArch64::LDRQui:
3417 return AArch64::LDRQroX;
3418 case AArch64::STURQi:
3419 case AArch64::STRQui:
3420 return AArch64::STRQroX;
3421 case AArch64::LDURDi:
3422 case AArch64::LDRDui:
3423 return AArch64::LDRDroX;
3424 case AArch64::STURDi:
3425 case AArch64::STRDui:
3426 return AArch64::STRDroX;
3427 case AArch64::LDURXi:
3428 case AArch64::LDRXui:
3429 return AArch64::LDRXroX;
3430 case AArch64::STURXi:
3431 case AArch64::STRXui:
3432 return AArch64::STRXroX;
3433 case AArch64::LDURWi:
3434 case AArch64::LDRWui:
3435 return AArch64::LDRWroX;
3436 case AArch64::LDURSWi:
3437 case AArch64::LDRSWui:
3438 return AArch64::LDRSWroX;
3439 case AArch64::STURWi:
3440 case AArch64::STRWui:
3441 return AArch64::STRWroX;
3442 case AArch64::LDURHi:
3443 case AArch64::LDRHui:
3444 return AArch64::LDRHroX;
3445 case AArch64::STURHi:
3446 case AArch64::STRHui:
3447 return AArch64::STRHroX;
3448 case AArch64::LDURHHi:
3449 case AArch64::LDRHHui:
3450 return AArch64::LDRHHroX;
3451 case AArch64::STURHHi:
3452 case AArch64::STRHHui:
3453 return AArch64::STRHHroX;
3454 case AArch64::LDURSHXi:
3455 case AArch64::LDRSHXui:
3456 return AArch64::LDRSHXroX;
3457 case AArch64::LDURSHWi:
3458 case AArch64::LDRSHWui:
3459 return AArch64::LDRSHWroX;
3460 case AArch64::LDURBi:
3461 case AArch64::LDRBui:
3462 return AArch64::LDRBroX;
3463 case AArch64::LDURBBi:
3464 case AArch64::LDRBBui:
3465 return AArch64::LDRBBroX;
3466 case AArch64::LDURSBXi:
3467 case AArch64::LDRSBXui:
3468 return AArch64::LDRSBXroX;
3469 case AArch64::LDURSBWi:
3470 case AArch64::LDRSBWui:
3471 return AArch64::LDRSBWroX;
3472 case AArch64::STURBi:
3473 case AArch64::STRBui:
3474 return AArch64::STRBroX;
3475 case AArch64::STURBBi:
3476 case AArch64::STRBBui:
3477 return AArch64::STRBBroX;
3489 case AArch64::LDURQi:
3491 return AArch64::LDRQui;
3492 case AArch64::STURQi:
3494 return AArch64::STRQui;
3495 case AArch64::LDURDi:
3497 return AArch64::LDRDui;
3498 case AArch64::STURDi:
3500 return AArch64::STRDui;
3501 case AArch64::LDURXi:
3503 return AArch64::LDRXui;
3504 case AArch64::STURXi:
3506 return AArch64::STRXui;
3507 case AArch64::LDURWi:
3509 return AArch64::LDRWui;
3510 case AArch64::LDURSWi:
3512 return AArch64::LDRSWui;
3513 case AArch64::STURWi:
3515 return AArch64::STRWui;
3516 case AArch64::LDURHi:
3518 return AArch64::LDRHui;
3519 case AArch64::STURHi:
3521 return AArch64::STRHui;
3522 case AArch64::LDURHHi:
3524 return AArch64::LDRHHui;
3525 case AArch64::STURHHi:
3527 return AArch64::STRHHui;
3528 case AArch64::LDURSHXi:
3530 return AArch64::LDRSHXui;
3531 case AArch64::LDURSHWi:
3533 return AArch64::LDRSHWui;
3534 case AArch64::LDURBi:
3536 return AArch64::LDRBui;
3537 case AArch64::LDURBBi:
3539 return AArch64::LDRBBui;
3540 case AArch64::LDURSBXi:
3542 return AArch64::LDRSBXui;
3543 case AArch64::LDURSBWi:
3545 return AArch64::LDRSBWui;
3546 case AArch64::STURBi:
3548 return AArch64::STRBui;
3549 case AArch64::STURBBi:
3551 return AArch64::STRBBui;
3552 case AArch64::LDRQui:
3553 case AArch64::STRQui:
3556 case AArch64::LDRDui:
3557 case AArch64::STRDui:
3558 case AArch64::LDRXui:
3559 case AArch64::STRXui:
3562 case AArch64::LDRWui:
3563 case AArch64::LDRSWui:
3564 case AArch64::STRWui:
3567 case AArch64::LDRHui:
3568 case AArch64::STRHui:
3569 case AArch64::LDRHHui:
3570 case AArch64::STRHHui:
3571 case AArch64::LDRSHXui:
3572 case AArch64::LDRSHWui:
3575 case AArch64::LDRBui:
3576 case AArch64::LDRBBui:
3577 case AArch64::LDRSBXui:
3578 case AArch64::LDRSBWui:
3579 case AArch64::STRBui:
3580 case AArch64::STRBBui:
3594 case AArch64::LDURQi:
3595 case AArch64::STURQi:
3596 case AArch64::LDURDi:
3597 case AArch64::STURDi:
3598 case AArch64::LDURXi:
3599 case AArch64::STURXi:
3600 case AArch64::LDURWi:
3601 case AArch64::LDURSWi:
3602 case AArch64::STURWi:
3603 case AArch64::LDURHi:
3604 case AArch64::STURHi:
3605 case AArch64::LDURHHi:
3606 case AArch64::STURHHi:
3607 case AArch64::LDURSHXi:
3608 case AArch64::LDURSHWi:
3609 case AArch64::LDURBi:
3610 case AArch64::STURBi:
3611 case AArch64::LDURBBi:
3612 case AArch64::STURBBi:
3613 case AArch64::LDURSBWi:
3614 case AArch64::LDURSBXi:
3616 case AArch64::LDRQui:
3617 return AArch64::LDURQi;
3618 case AArch64::STRQui:
3619 return AArch64::STURQi;
3620 case AArch64::LDRDui:
3621 return AArch64::LDURDi;
3622 case AArch64::STRDui:
3623 return AArch64::STURDi;
3624 case AArch64::LDRXui:
3625 return AArch64::LDURXi;
3626 case AArch64::STRXui:
3627 return AArch64::STURXi;
3628 case AArch64::LDRWui:
3629 return AArch64::LDURWi;
3630 case AArch64::LDRSWui:
3631 return AArch64::LDURSWi;
3632 case AArch64::STRWui:
3633 return AArch64::STURWi;
3634 case AArch64::LDRHui:
3635 return AArch64::LDURHi;
3636 case AArch64::STRHui:
3637 return AArch64::STURHi;
3638 case AArch64::LDRHHui:
3639 return AArch64::LDURHHi;
3640 case AArch64::STRHHui:
3641 return AArch64::STURHHi;
3642 case AArch64::LDRSHXui:
3643 return AArch64::LDURSHXi;
3644 case AArch64::LDRSHWui:
3645 return AArch64::LDURSHWi;
3646 case AArch64::LDRBBui:
3647 return AArch64::LDURBBi;
3648 case AArch64::LDRBui:
3649 return AArch64::LDURBi;
3650 case AArch64::STRBBui:
3651 return AArch64::STURBBi;
3652 case AArch64::STRBui:
3653 return AArch64::STURBi;
3654 case AArch64::LDRSBWui:
3655 return AArch64::LDURSBWi;
3656 case AArch64::LDRSBXui:
3657 return AArch64::LDURSBXi;
3670 case AArch64::LDRQroX:
3671 case AArch64::LDURQi:
3672 case AArch64::LDRQui:
3673 return AArch64::LDRQroW;
3674 case AArch64::STRQroX:
3675 case AArch64::STURQi:
3676 case AArch64::STRQui:
3677 return AArch64::STRQroW;
3678 case AArch64::LDRDroX:
3679 case AArch64::LDURDi:
3680 case AArch64::LDRDui:
3681 return AArch64::LDRDroW;
3682 case AArch64::STRDroX:
3683 case AArch64::STURDi:
3684 case AArch64::STRDui:
3685 return AArch64::STRDroW;
3686 case AArch64::LDRXroX:
3687 case AArch64::LDURXi:
3688 case AArch64::LDRXui:
3689 return AArch64::LDRXroW;
3690 case AArch64::STRXroX:
3691 case AArch64::STURXi:
3692 case AArch64::STRXui:
3693 return AArch64::STRXroW;
3694 case AArch64::LDRWroX:
3695 case AArch64::LDURWi:
3696 case AArch64::LDRWui:
3697 return AArch64::LDRWroW;
3698 case AArch64::LDRSWroX:
3699 case AArch64::LDURSWi:
3700 case AArch64::LDRSWui:
3701 return AArch64::LDRSWroW;
3702 case AArch64::STRWroX:
3703 case AArch64::STURWi:
3704 case AArch64::STRWui:
3705 return AArch64::STRWroW;
3706 case AArch64::LDRHroX:
3707 case AArch64::LDURHi:
3708 case AArch64::LDRHui:
3709 return AArch64::LDRHroW;
3710 case AArch64::STRHroX:
3711 case AArch64::STURHi:
3712 case AArch64::STRHui:
3713 return AArch64::STRHroW;
3714 case AArch64::LDRHHroX:
3715 case AArch64::LDURHHi:
3716 case AArch64::LDRHHui:
3717 return AArch64::LDRHHroW;
3718 case AArch64::STRHHroX:
3719 case AArch64::STURHHi:
3720 case AArch64::STRHHui:
3721 return AArch64::STRHHroW;
3722 case AArch64::LDRSHXroX:
3723 case AArch64::LDURSHXi:
3724 case AArch64::LDRSHXui:
3725 return AArch64::LDRSHXroW;
3726 case AArch64::LDRSHWroX:
3727 case AArch64::LDURSHWi:
3728 case AArch64::LDRSHWui:
3729 return AArch64::LDRSHWroW;
3730 case AArch64::LDRBroX:
3731 case AArch64::LDURBi:
3732 case AArch64::LDRBui:
3733 return AArch64::LDRBroW;
3734 case AArch64::LDRBBroX:
3735 case AArch64::LDURBBi:
3736 case AArch64::LDRBBui:
3737 return AArch64::LDRBBroW;
3738 case AArch64::LDRSBXroX:
3739 case AArch64::LDURSBXi:
3740 case AArch64::LDRSBXui:
3741 return AArch64::LDRSBXroW;
3742 case AArch64::LDRSBWroX:
3743 case AArch64::LDURSBWi:
3744 case AArch64::LDRSBWui:
3745 return AArch64::LDRSBWroW;
3746 case AArch64::STRBroX:
3747 case AArch64::STURBi:
3748 case AArch64::STRBui:
3749 return AArch64::STRBroW;
3750 case AArch64::STRBBroX:
3751 case AArch64::STURBBi:
3752 case AArch64::STRBBui:
3753 return AArch64::STRBBroW;
3768 MRI.constrainRegClass(AM.
BaseReg, &AArch64::GPR64spRegClass);
3778 return B.getInstr();
3782 "Addressing mode not supported for folding");
3799 return B.getInstr();
3806 "Address offset can be a register or an immediate, but not both");
3808 MRI.constrainRegClass(AM.
BaseReg, &AArch64::GPR64spRegClass);
3813 OffsetReg =
MRI.createVirtualRegister(&AArch64::GPR32RegClass);
3827 return B.getInstr();
3831 "Function must not be called with an addressing mode it can't handle");
3840 case AArch64::LD1Fourv16b_POST:
3841 case AArch64::LD1Fourv1d_POST:
3842 case AArch64::LD1Fourv2d_POST:
3843 case AArch64::LD1Fourv2s_POST:
3844 case AArch64::LD1Fourv4h_POST:
3845 case AArch64::LD1Fourv4s_POST:
3846 case AArch64::LD1Fourv8b_POST:
3847 case AArch64::LD1Fourv8h_POST:
3848 case AArch64::LD1Onev16b_POST:
3849 case AArch64::LD1Onev1d_POST:
3850 case AArch64::LD1Onev2d_POST:
3851 case AArch64::LD1Onev2s_POST:
3852 case AArch64::LD1Onev4h_POST:
3853 case AArch64::LD1Onev4s_POST:
3854 case AArch64::LD1Onev8b_POST:
3855 case AArch64::LD1Onev8h_POST:
3856 case AArch64::LD1Rv16b_POST:
3857 case AArch64::LD1Rv1d_POST:
3858 case AArch64::LD1Rv2d_POST:
3859 case AArch64::LD1Rv2s_POST:
3860 case AArch64::LD1Rv4h_POST:
3861 case AArch64::LD1Rv4s_POST:
3862 case AArch64::LD1Rv8b_POST:
3863 case AArch64::LD1Rv8h_POST:
3864 case AArch64::LD1Threev16b_POST:
3865 case AArch64::LD1Threev1d_POST:
3866 case AArch64::LD1Threev2d_POST:
3867 case AArch64::LD1Threev2s_POST:
3868 case AArch64::LD1Threev4h_POST:
3869 case AArch64::LD1Threev4s_POST:
3870 case AArch64::LD1Threev8b_POST:
3871 case AArch64::LD1Threev8h_POST:
3872 case AArch64::LD1Twov16b_POST:
3873 case AArch64::LD1Twov1d_POST:
3874 case AArch64::LD1Twov2d_POST:
3875 case AArch64::LD1Twov2s_POST:
3876 case AArch64::LD1Twov4h_POST:
3877 case AArch64::LD1Twov4s_POST:
3878 case AArch64::LD1Twov8b_POST:
3879 case AArch64::LD1Twov8h_POST:
3880 case AArch64::LD1i16_POST:
3881 case AArch64::LD1i32_POST:
3882 case AArch64::LD1i64_POST:
3883 case AArch64::LD1i8_POST:
3884 case AArch64::LD2Rv16b_POST:
3885 case AArch64::LD2Rv1d_POST:
3886 case AArch64::LD2Rv2d_POST:
3887 case AArch64::LD2Rv2s_POST:
3888 case AArch64::LD2Rv4h_POST:
3889 case AArch64::LD2Rv4s_POST:
3890 case AArch64::LD2Rv8b_POST:
3891 case AArch64::LD2Rv8h_POST:
3892 case AArch64::LD2Twov16b_POST:
3893 case AArch64::LD2Twov2d_POST:
3894 case AArch64::LD2Twov2s_POST:
3895 case AArch64::LD2Twov4h_POST:
3896 case AArch64::LD2Twov4s_POST:
3897 case AArch64::LD2Twov8b_POST:
3898 case AArch64::LD2Twov8h_POST:
3899 case AArch64::LD2i16_POST:
3900 case AArch64::LD2i32_POST:
3901 case AArch64::LD2i64_POST:
3902 case AArch64::LD2i8_POST:
3903 case AArch64::LD3Rv16b_POST:
3904 case AArch64::LD3Rv1d_POST:
3905 case AArch64::LD3Rv2d_POST:
3906 case AArch64::LD3Rv2s_POST:
3907 case AArch64::LD3Rv4h_POST:
3908 case AArch64::LD3Rv4s_POST:
3909 case AArch64::LD3Rv8b_POST:
3910 case AArch64::LD3Rv8h_POST:
3911 case AArch64::LD3Threev16b_POST:
3912 case AArch64::LD3Threev2d_POST:
3913 case AArch64::LD3Threev2s_POST:
3914 case AArch64::LD3Threev4h_POST:
3915 case AArch64::LD3Threev4s_POST:
3916 case AArch64::LD3Threev8b_POST:
3917 case AArch64::LD3Threev8h_POST:
3918 case AArch64::LD3i16_POST:
3919 case AArch64::LD3i32_POST:
3920 case AArch64::LD3i64_POST:
3921 case AArch64::LD3i8_POST:
3922 case AArch64::LD4Fourv16b_POST:
3923 case AArch64::LD4Fourv2d_POST:
3924 case AArch64::LD4Fourv2s_POST:
3925 case AArch64::LD4Fourv4h_POST:
3926 case AArch64::LD4Fourv4s_POST:
3927 case AArch64::LD4Fourv8b_POST:
3928 case AArch64::LD4Fourv8h_POST:
3929 case AArch64::LD4Rv16b_POST:
3930 case AArch64::LD4Rv1d_POST:
3931 case AArch64::LD4Rv2d_POST:
3932 case AArch64::LD4Rv2s_POST:
3933 case AArch64::LD4Rv4h_POST:
3934 case AArch64::LD4Rv4s_POST:
3935 case AArch64::LD4Rv8b_POST:
3936 case AArch64::LD4Rv8h_POST:
3937 case AArch64::LD4i16_POST:
3938 case AArch64::LD4i32_POST:
3939 case AArch64::LD4i64_POST:
3940 case AArch64::LD4i8_POST:
3941 case AArch64::LDAPRWpost:
3942 case AArch64::LDAPRXpost:
3943 case AArch64::LDIAPPWpost:
3944 case AArch64::LDIAPPXpost:
3945 case AArch64::LDPDpost:
3946 case AArch64::LDPQpost:
3947 case AArch64::LDPSWpost:
3948 case AArch64::LDPSpost:
3949 case AArch64::LDPWpost:
3950 case AArch64::LDPXpost:
3951 case AArch64::LDRBBpost:
3952 case AArch64::LDRBpost:
3953 case AArch64::LDRDpost:
3954 case AArch64::LDRHHpost:
3955 case AArch64::LDRHpost:
3956 case AArch64::LDRQpost:
3957 case AArch64::LDRSBWpost:
3958 case AArch64::LDRSBXpost:
3959 case AArch64::LDRSHWpost:
3960 case AArch64::LDRSHXpost:
3961 case AArch64::LDRSWpost:
3962 case AArch64::LDRSpost:
3963 case AArch64::LDRWpost:
3964 case AArch64::LDRXpost:
3965 case AArch64::ST1Fourv16b_POST:
3966 case AArch64::ST1Fourv1d_POST:
3967 case AArch64::ST1Fourv2d_POST:
3968 case AArch64::ST1Fourv2s_POST:
3969 case AArch64::ST1Fourv4h_POST:
3970 case AArch64::ST1Fourv4s_POST:
3971 case AArch64::ST1Fourv8b_POST:
3972 case AArch64::ST1Fourv8h_POST:
3973 case AArch64::ST1Onev16b_POST:
3974 case AArch64::ST1Onev1d_POST:
3975 case AArch64::ST1Onev2d_POST:
3976 case AArch64::ST1Onev2s_POST:
3977 case AArch64::ST1Onev4h_POST:
3978 case AArch64::ST1Onev4s_POST:
3979 case AArch64::ST1Onev8b_POST:
3980 case AArch64::ST1Onev8h_POST:
3981 case AArch64::ST1Threev16b_POST:
3982 case AArch64::ST1Threev1d_POST:
3983 case AArch64::ST1Threev2d_POST:
3984 case AArch64::ST1Threev2s_POST:
3985 case AArch64::ST1Threev4h_POST:
3986 case AArch64::ST1Threev4s_POST:
3987 case AArch64::ST1Threev8b_POST:
3988 case AArch64::ST1Threev8h_POST:
3989 case AArch64::ST1Twov16b_POST:
3990 case AArch64::ST1Twov1d_POST:
3991 case AArch64::ST1Twov2d_POST:
3992 case AArch64::ST1Twov2s_POST:
3993 case AArch64::ST1Twov4h_POST:
3994 case AArch64::ST1Twov4s_POST:
3995 case AArch64::ST1Twov8b_POST:
3996 case AArch64::ST1Twov8h_POST:
3997 case AArch64::ST1i16_POST:
3998 case AArch64::ST1i32_POST:
3999 case AArch64::ST1i64_POST:
4000 case AArch64::ST1i8_POST:
4001 case AArch64::ST2GPostIndex:
4002 case AArch64::ST2Twov16b_POST:
4003 case AArch64::ST2Twov2d_POST:
4004 case AArch64::ST2Twov2s_POST:
4005 case AArch64::ST2Twov4h_POST:
4006 case AArch64::ST2Twov4s_POST:
4007 case AArch64::ST2Twov8b_POST:
4008 case AArch64::ST2Twov8h_POST:
4009 case AArch64::ST2i16_POST:
4010 case AArch64::ST2i32_POST:
4011 case AArch64::ST2i64_POST:
4012 case AArch64::ST2i8_POST:
4013 case AArch64::ST3Threev16b_POST:
4014 case AArch64::ST3Threev2d_POST:
4015 case AArch64::ST3Threev2s_POST:
4016 case AArch64::ST3Threev4h_POST:
4017 case AArch64::ST3Threev4s_POST:
4018 case AArch64::ST3Threev8b_POST:
4019 case AArch64::ST3Threev8h_POST:
4020 case AArch64::ST3i16_POST:
4021 case AArch64::ST3i32_POST:
4022 case AArch64::ST3i64_POST:
4023 case AArch64::ST3i8_POST:
4024 case AArch64::ST4Fourv16b_POST:
4025 case AArch64::ST4Fourv2d_POST:
4026 case AArch64::ST4Fourv2s_POST:
4027 case AArch64::ST4Fourv4h_POST:
4028 case AArch64::ST4Fourv4s_POST:
4029 case AArch64::ST4Fourv8b_POST:
4030 case AArch64::ST4Fourv8h_POST:
4031 case AArch64::ST4i16_POST:
4032 case AArch64::ST4i32_POST:
4033 case AArch64::ST4i64_POST:
4034 case AArch64::ST4i8_POST:
4035 case AArch64::STGPostIndex:
4036 case AArch64::STGPpost:
4037 case AArch64::STPDpost:
4038 case AArch64::STPQpost:
4039 case AArch64::STPSpost:
4040 case AArch64::STPWpost:
4041 case AArch64::STPXpost:
4042 case AArch64::STRBBpost:
4043 case AArch64::STRBpost:
4044 case AArch64::STRDpost:
4045 case AArch64::STRHHpost:
4046 case AArch64::STRHpost:
4047 case AArch64::STRQpost:
4048 case AArch64::STRSpost:
4049 case AArch64::STRWpost:
4050 case AArch64::STRXpost:
4051 case AArch64::STZ2GPostIndex:
4052 case AArch64::STZGPostIndex:
4059 bool &OffsetIsScalable,
TypeSize &Width,
4080 int64_t Dummy1, Dummy2;
4102 return BaseOp->
isReg() || BaseOp->
isFI();
4109 assert(OfsOp.
isImm() &&
"Offset operand wasn't immediate.");
4114 TypeSize &Width, int64_t &MinOffset,
4115 int64_t &MaxOffset) {
4121 MinOffset = MaxOffset = 0;
4124 case AArch64::LDRQui:
4125 case AArch64::STRQui:
4131 case AArch64::LDRXui:
4132 case AArch64::LDRDui:
4133 case AArch64::STRXui:
4134 case AArch64::STRDui:
4135 case AArch64::PRFMui:
4141 case AArch64::LDRWui:
4142 case AArch64::LDRSui:
4143 case AArch64::LDRSWui:
4144 case AArch64::STRWui:
4145 case AArch64::STRSui:
4151 case AArch64::LDRHui:
4152 case AArch64::LDRHHui:
4153 case AArch64::LDRSHWui:
4154 case AArch64::LDRSHXui:
4155 case AArch64::STRHui:
4156 case AArch64::STRHHui:
4162 case AArch64::LDRBui:
4163 case AArch64::LDRBBui:
4164 case AArch64::LDRSBWui:
4165 case AArch64::LDRSBXui:
4166 case AArch64::STRBui:
4167 case AArch64::STRBBui:
4174 case AArch64::STRQpre:
4175 case AArch64::LDRQpost:
4181 case AArch64::LDRDpost:
4182 case AArch64::LDRDpre:
4183 case AArch64::LDRXpost:
4184 case AArch64::LDRXpre:
4185 case AArch64::STRDpost:
4186 case AArch64::STRDpre:
4187 case AArch64::STRXpost:
4188 case AArch64::STRXpre:
4194 case AArch64::STRWpost:
4195 case AArch64::STRWpre:
4196 case AArch64::LDRWpost:
4197 case AArch64::LDRWpre:
4198 case AArch64::STRSpost:
4199 case AArch64::STRSpre:
4200 case AArch64::LDRSpost:
4201 case AArch64::LDRSpre:
4207 case AArch64::LDRHpost:
4208 case AArch64::LDRHpre:
4209 case AArch64::STRHpost:
4210 case AArch64::STRHpre:
4211 case AArch64::LDRHHpost:
4212 case AArch64::LDRHHpre:
4213 case AArch64::STRHHpost:
4214 case AArch64::STRHHpre:
4220 case AArch64::LDRBpost:
4221 case AArch64::LDRBpre:
4222 case AArch64::STRBpost:
4223 case AArch64::STRBpre:
4224 case AArch64::LDRBBpost:
4225 case AArch64::LDRBBpre:
4226 case AArch64::STRBBpost:
4227 case AArch64::STRBBpre:
4234 case AArch64::LDURQi:
4235 case AArch64::STURQi:
4241 case AArch64::LDURXi:
4242 case AArch64::LDURDi:
4243 case AArch64::LDAPURXi:
4244 case AArch64::STURXi:
4245 case AArch64::STURDi:
4246 case AArch64::STLURXi:
4247 case AArch64::PRFUMi:
4253 case AArch64::LDURWi:
4254 case AArch64::LDURSi:
4255 case AArch64::LDURSWi:
4256 case AArch64::LDAPURi:
4257 case AArch64::LDAPURSWi:
4258 case AArch64::STURWi:
4259 case AArch64::STURSi:
4260 case AArch64::STLURWi:
4266 case AArch64::LDURHi:
4267 case AArch64::LDURHHi:
4268 case AArch64::LDURSHXi:
4269 case AArch64::LDURSHWi:
4270 case AArch64::LDAPURHi:
4271 case AArch64::LDAPURSHWi:
4272 case AArch64::LDAPURSHXi:
4273 case AArch64::STURHi:
4274 case AArch64::STURHHi:
4275 case AArch64::STLURHi:
4281 case AArch64::LDURBi:
4282 case AArch64::LDURBBi:
4283 case AArch64::LDURSBXi:
4284 case AArch64::LDURSBWi:
4285 case AArch64::LDAPURBi:
4286 case AArch64::LDAPURSBWi:
4287 case AArch64::LDAPURSBXi:
4288 case AArch64::STURBi:
4289 case AArch64::STURBBi:
4290 case AArch64::STLURBi:
4297 case AArch64::LDPQi:
4298 case AArch64::LDNPQi:
4299 case AArch64::STPQi:
4300 case AArch64::STNPQi:
4301 case AArch64::LDPQpost:
4302 case AArch64::LDPQpre:
4303 case AArch64::STPQpost:
4304 case AArch64::STPQpre:
4310 case AArch64::LDPXi:
4311 case AArch64::LDPDi:
4312 case AArch64::LDNPXi:
4313 case AArch64::LDNPDi:
4314 case AArch64::STPXi:
4315 case AArch64::STPDi:
4316 case AArch64::STNPXi:
4317 case AArch64::STNPDi:
4318 case AArch64::LDPDpost:
4319 case AArch64::LDPDpre:
4320 case AArch64::LDPXpost:
4321 case AArch64::LDPXpre:
4322 case AArch64::STPDpost:
4323 case AArch64::STPDpre:
4324 case AArch64::STPXpost:
4325 case AArch64::STPXpre:
4331 case AArch64::LDPWi:
4332 case AArch64::LDPSi:
4333 case AArch64::LDNPWi:
4334 case AArch64::LDNPSi:
4335 case AArch64::STPWi:
4336 case AArch64::STPSi:
4337 case AArch64::STNPWi:
4338 case AArch64::STNPSi:
4339 case AArch64::LDPSpost:
4340 case AArch64::LDPSpre:
4341 case AArch64::LDPWpost:
4342 case AArch64::LDPWpre:
4343 case AArch64::STPSpost:
4344 case AArch64::STPSpre:
4345 case AArch64::STPWpost:
4346 case AArch64::STPWpre:
4352 case AArch64::StoreSwiftAsyncContext:
4365 case AArch64::TAGPstack:
4375 case AArch64::STGPreIndex:
4376 case AArch64::STGPostIndex:
4377 case AArch64::STZGi:
4378 case AArch64::STZGPreIndex:
4379 case AArch64::STZGPostIndex:
4386 case AArch64::STR_ZZZZXI:
4387 case AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS:
4388 case AArch64::LDR_ZZZZXI:
4389 case AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS:
4395 case AArch64::STR_ZZZXI:
4396 case AArch64::LDR_ZZZXI:
4402 case AArch64::STR_ZZXI:
4403 case AArch64::STR_ZZXI_STRIDED_CONTIGUOUS:
4404 case AArch64::LDR_ZZXI:
4405 case AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS:
4411 case AArch64::LDR_PXI:
4412 case AArch64::STR_PXI:
4418 case AArch64::LDR_PPXI:
4419 case AArch64::STR_PPXI:
4425 case AArch64::LDR_ZXI:
4426 case AArch64::STR_ZXI:
4432 case AArch64::LD1B_IMM:
4433 case AArch64::LD1H_IMM:
4434 case AArch64::LD1W_IMM:
4435 case AArch64::LD1D_IMM:
4436 case AArch64::LDNT1B_ZRI:
4437 case AArch64::LDNT1H_ZRI:
4438 case AArch64::LDNT1W_ZRI:
4439 case AArch64::LDNT1D_ZRI:
4440 case AArch64::ST1B_IMM:
4441 case AArch64::ST1H_IMM:
4442 case AArch64::ST1W_IMM:
4443 case AArch64::ST1D_IMM:
4444 case AArch64::STNT1B_ZRI:
4445 case AArch64::STNT1H_ZRI:
4446 case AArch64::STNT1W_ZRI:
4447 case AArch64::STNT1D_ZRI:
4448 case AArch64::LDNF1B_IMM:
4449 case AArch64::LDNF1H_IMM:
4450 case AArch64::LDNF1W_IMM:
4451 case AArch64::LDNF1D_IMM:
4459 case AArch64::LD2B_IMM:
4460 case AArch64::LD2H_IMM:
4461 case AArch64::LD2W_IMM:
4462 case AArch64::LD2D_IMM:
4463 case AArch64::ST2B_IMM:
4464 case AArch64::ST2H_IMM:
4465 case AArch64::ST2W_IMM:
4466 case AArch64::ST2D_IMM:
4472 case AArch64::LD3B_IMM:
4473 case AArch64::LD3H_IMM:
4474 case AArch64::LD3W_IMM:
4475 case AArch64::LD3D_IMM:
4476 case AArch64::ST3B_IMM:
4477 case AArch64::ST3H_IMM:
4478 case AArch64::ST3W_IMM:
4479 case AArch64::ST3D_IMM:
4485 case AArch64::LD4B_IMM:
4486 case AArch64::LD4H_IMM:
4487 case AArch64::LD4W_IMM:
4488 case AArch64::LD4D_IMM:
4489 case AArch64::ST4B_IMM:
4490 case AArch64::ST4H_IMM:
4491 case AArch64::ST4W_IMM:
4492 case AArch64::ST4D_IMM:
4498 case AArch64::LD1B_H_IMM:
4499 case AArch64::LD1SB_H_IMM:
4500 case AArch64::LD1H_S_IMM:
4501 case AArch64::LD1SH_S_IMM:
4502 case AArch64::LD1W_D_IMM:
4503 case AArch64::LD1SW_D_IMM:
4504 case AArch64::ST1B_H_IMM:
4505 case AArch64::ST1H_S_IMM:
4506 case AArch64::ST1W_D_IMM:
4507 case AArch64::LDNF1B_H_IMM:
4508 case AArch64::LDNF1SB_H_IMM:
4509 case AArch64::LDNF1H_S_IMM:
4510 case AArch64::LDNF1SH_S_IMM:
4511 case AArch64::LDNF1W_D_IMM:
4512 case AArch64::LDNF1SW_D_IMM:
4520 case AArch64::LD1B_S_IMM:
4521 case AArch64::LD1SB_S_IMM:
4522 case AArch64::LD1H_D_IMM:
4523 case AArch64::LD1SH_D_IMM:
4524 case AArch64::ST1B_S_IMM:
4525 case AArch64::ST1H_D_IMM:
4526 case AArch64::LDNF1B_S_IMM:
4527 case AArch64::LDNF1SB_S_IMM:
4528 case AArch64::LDNF1H_D_IMM:
4529 case AArch64::LDNF1SH_D_IMM:
4537 case AArch64::LD1B_D_IMM:
4538 case AArch64::LD1SB_D_IMM:
4539 case AArch64::ST1B_D_IMM:
4540 case AArch64::LDNF1B_D_IMM:
4541 case AArch64::LDNF1SB_D_IMM:
4549 case AArch64::ST2Gi:
4550 case AArch64::ST2GPreIndex:
4551 case AArch64::ST2GPostIndex:
4552 case AArch64::STZ2Gi:
4553 case AArch64::STZ2GPreIndex:
4554 case AArch64::STZ2GPostIndex:
4560 case AArch64::STGPi:
4561 case AArch64::STGPpost:
4562 case AArch64::STGPpre:
4568 case AArch64::LD1RB_IMM:
4569 case AArch64::LD1RB_H_IMM:
4570 case AArch64::LD1RB_S_IMM:
4571 case AArch64::LD1RB_D_IMM:
4572 case AArch64::LD1RSB_H_IMM:
4573 case AArch64::LD1RSB_S_IMM:
4574 case AArch64::LD1RSB_D_IMM:
4580 case AArch64::LD1RH_IMM:
4581 case AArch64::LD1RH_S_IMM:
4582 case AArch64::LD1RH_D_IMM:
4583 case AArch64::LD1RSH_S_IMM:
4584 case AArch64::LD1RSH_D_IMM:
4590 case AArch64::LD1RW_IMM:
4591 case AArch64::LD1RW_D_IMM:
4592 case AArch64::LD1RSW_IMM:
4598 case AArch64::LD1RD_IMM:
4614 case AArch64::LDRBBui:
4615 case AArch64::LDURBBi:
4616 case AArch64::LDRSBWui:
4617 case AArch64::LDURSBWi:
4618 case AArch64::STRBBui:
4619 case AArch64::STURBBi:
4621 case AArch64::LDRHHui:
4622 case AArch64::LDURHHi:
4623 case AArch64::LDRSHWui:
4624 case AArch64::LDURSHWi:
4625 case AArch64::STRHHui:
4626 case AArch64::STURHHi:
4628 case AArch64::LDRSui:
4629 case AArch64::LDURSi:
4630 case AArch64::LDRSpre:
4631 case AArch64::LDRSWui:
4632 case AArch64::LDURSWi:
4633 case AArch64::LDRSWpre:
4634 case AArch64::LDRWpre:
4635 case AArch64::LDRWui:
4636 case AArch64::LDURWi:
4637 case AArch64::STRSui:
4638 case AArch64::STURSi:
4639 case AArch64::STRSpre:
4640 case AArch64::STRWui:
4641 case AArch64::STURWi:
4642 case AArch64::STRWpre:
4643 case AArch64::LDPSi:
4644 case AArch64::LDPSWi:
4645 case AArch64::LDPWi:
4646 case AArch64::STPSi:
4647 case AArch64::STPWi:
4649 case AArch64::LDRDui:
4650 case AArch64::LDURDi:
4651 case AArch64::LDRDpre:
4652 case AArch64::LDRXui:
4653 case AArch64::LDURXi:
4654 case AArch64::LDRXpre:
4655 case AArch64::STRDui:
4656 case AArch64::STURDi:
4657 case AArch64::STRDpre:
4658 case AArch64::STRXui:
4659 case AArch64::STURXi:
4660 case AArch64::STRXpre:
4661 case AArch64::LDPDi:
4662 case AArch64::LDPXi:
4663 case AArch64::STPDi:
4664 case AArch64::STPXi:
4666 case AArch64::LDRQui:
4667 case AArch64::LDURQi:
4668 case AArch64::STRQui:
4669 case AArch64::STURQi:
4670 case AArch64::STRQpre:
4671 case AArch64::LDPQi:
4672 case AArch64::LDRQpre:
4673 case AArch64::STPQi:
4675 case AArch64::STZGi:
4676 case AArch64::ST2Gi:
4677 case AArch64::STZ2Gi:
4678 case AArch64::STGPi:
4684 switch (
MI.getOpcode()) {
4687 case AArch64::LDRWpre:
4688 case AArch64::LDRXpre:
4689 case AArch64::LDRSWpre:
4690 case AArch64::LDRSpre:
4691 case AArch64::LDRDpre:
4692 case AArch64::LDRQpre:
4698 switch (
MI.getOpcode()) {
4701 case AArch64::STRWpre:
4702 case AArch64::STRXpre:
4703 case AArch64::STRSpre:
4704 case AArch64::STRDpre:
4705 case AArch64::STRQpre:
4715 switch (
MI.getOpcode()) {
4718 case AArch64::LDPSi:
4719 case AArch64::LDPSWi:
4720 case AArch64::LDPDi:
4721 case AArch64::LDPQi:
4722 case AArch64::LDPWi:
4723 case AArch64::LDPXi:
4724 case AArch64::STPSi:
4725 case AArch64::STPDi:
4726 case AArch64::STPQi:
4727 case AArch64::STPWi:
4728 case AArch64::STPXi:
4729 case AArch64::STGPi:
4735 assert(
MI.mayLoadOrStore() &&
"Load or store instruction expected");
4739 return MI.getOperand(Idx);
4744 assert(
MI.mayLoadOrStore() &&
"Load or store instruction expected");
4748 return MI.getOperand(Idx);
4753 switch (
MI.getOpcode()) {
4756 case AArch64::LDRBroX:
4757 case AArch64::LDRBBroX:
4758 case AArch64::LDRSBXroX:
4759 case AArch64::LDRSBWroX:
4760 case AArch64::LDRHroX:
4761 case AArch64::LDRHHroX:
4762 case AArch64::LDRSHXroX:
4763 case AArch64::LDRSHWroX:
4764 case AArch64::LDRWroX:
4765 case AArch64::LDRSroX:
4766 case AArch64::LDRSWroX:
4767 case AArch64::LDRDroX:
4768 case AArch64::LDRXroX:
4769 case AArch64::LDRQroX:
4770 return MI.getOperand(4);
4776 if (
MI.getParent() ==
nullptr)
4786 auto Reg =
Op.getReg();
4787 if (Reg.isPhysical())
4788 return AArch64::FPR16RegClass.contains(Reg);
4790 return TRC == &AArch64::FPR16RegClass ||
4791 TRC == &AArch64::FPR16_loRegClass;
4800 auto Reg =
Op.getReg();
4801 if (Reg.isPhysical())
4802 return AArch64::FPR128RegClass.contains(Reg);
4804 return TRC == &AArch64::FPR128RegClass ||
4805 TRC == &AArch64::FPR128_loRegClass;
4811 switch (
MI.getOpcode()) {
4814 case AArch64::PACIASP:
4815 case AArch64::PACIBSP:
4818 case AArch64::PAUTH_PROLOGUE:
4821 case AArch64::HINT: {
4822 unsigned Imm =
MI.getOperand(0).getImm();
4824 if (Imm == 32 || Imm == 34 || Imm == 36 || Imm == 38)
4827 if (Imm == 25 || Imm == 27)
4839 assert(Reg.isPhysical() &&
"Expected physical register in isFpOrNEON");
4840 return AArch64::FPR128RegClass.contains(Reg) ||
4841 AArch64::FPR64RegClass.contains(Reg) ||
4842 AArch64::FPR32RegClass.contains(Reg) ||
4843 AArch64::FPR16RegClass.contains(Reg) ||
4844 AArch64::FPR8RegClass.contains(Reg);
4851 auto Reg =
Op.getReg();
4852 if (Reg.isPhysical())
4856 return TRC == &AArch64::FPR128RegClass ||
4857 TRC == &AArch64::FPR128_loRegClass ||
4858 TRC == &AArch64::FPR64RegClass ||
4859 TRC == &AArch64::FPR64_loRegClass ||
4860 TRC == &AArch64::FPR32RegClass || TRC == &AArch64::FPR16RegClass ||
4861 TRC == &AArch64::FPR8RegClass;
4883 if (FirstOpc == SecondOpc)
4889 case AArch64::STRSui:
4890 case AArch64::STURSi:
4891 return SecondOpc == AArch64::STRSui || SecondOpc == AArch64::STURSi;
4892 case AArch64::STRDui:
4893 case AArch64::STURDi:
4894 return SecondOpc == AArch64::STRDui || SecondOpc == AArch64::STURDi;
4895 case AArch64::STRQui:
4896 case AArch64::STURQi:
4897 return SecondOpc == AArch64::STRQui || SecondOpc == AArch64::STURQi;
4898 case AArch64::STRWui:
4899 case AArch64::STURWi:
4900 return SecondOpc == AArch64::STRWui || SecondOpc == AArch64::STURWi;
4901 case AArch64::STRXui:
4902 case AArch64::STURXi:
4903 return SecondOpc == AArch64::STRXui || SecondOpc == AArch64::STURXi;
4904 case AArch64::LDRSui:
4905 case AArch64::LDURSi:
4906 return SecondOpc == AArch64::LDRSui || SecondOpc == AArch64::LDURSi;
4907 case AArch64::LDRDui:
4908 case AArch64::LDURDi:
4909 return SecondOpc == AArch64::LDRDui || SecondOpc == AArch64::LDURDi;
4910 case AArch64::LDRQui:
4911 case AArch64::LDURQi:
4912 return SecondOpc == AArch64::LDRQui || SecondOpc == AArch64::LDURQi;
4913 case AArch64::LDRWui:
4914 case AArch64::LDURWi:
4915 return SecondOpc == AArch64::LDRSWui || SecondOpc == AArch64::LDURSWi;
4916 case AArch64::LDRSWui:
4917 case AArch64::LDURSWi:
4918 return SecondOpc == AArch64::LDRWui || SecondOpc == AArch64::LDURWi;
4919 case AArch64::LDRXui:
4920 case AArch64::LDURXi:
4921 return SecondOpc == AArch64::LDRXui || SecondOpc == AArch64::LDURXi;
4928 int64_t Offset1,
unsigned Opcode1,
int FI2,
4929 int64_t Offset2,
unsigned Opcode2) {
4935 assert(ObjectOffset1 <= ObjectOffset2 &&
"Object offsets are not ordered.");
4938 if (ObjectOffset1 % Scale1 != 0)
4940 ObjectOffset1 /= Scale1;
4942 if (ObjectOffset2 % Scale2 != 0)
4944 ObjectOffset2 /= Scale2;
4945 ObjectOffset1 += Offset1;
4946 ObjectOffset2 += Offset2;
4947 return ObjectOffset1 + 1 == ObjectOffset2;
4959 int64_t OpOffset2,
bool OffsetIsScalable2,
unsigned ClusterSize,
4960 unsigned NumBytes)
const {
4970 "Only base registers and frame indices are supported.");
4977 if (ClusterSize > 2)
4984 unsigned FirstOpc = FirstLdSt.
getOpcode();
4985 unsigned SecondOpc = SecondLdSt.
getOpcode();
5005 if (Offset1 > 63 || Offset1 < -64)
5010 if (BaseOp1.
isFI()) {
5012 "Caller should have ordered offsets.");
5017 BaseOp2.
getIndex(), Offset2, SecondOpc);
5020 assert(Offset1 <= Offset2 &&
"Caller should have ordered offsets.");
5022 return Offset1 + 1 == Offset2;
5032 if (
Reg.isPhysical())
5041 return ((DestReg - SrcReg) & 0x1f) < NumRegs;
5050 assert(Subtarget.hasNEON() &&
"Unexpected register copy without NEON");
5052 uint16_t DestEncoding =
TRI->getEncodingValue(DestReg);
5053 uint16_t SrcEncoding =
TRI->getEncodingValue(SrcReg);
5054 unsigned NumRegs = Indices.
size();
5056 int SubReg = 0, End = NumRegs, Incr = 1;
5075 unsigned Opcode,
unsigned ZeroReg,
5078 unsigned NumRegs = Indices.
size();
5081 uint16_t DestEncoding =
TRI->getEncodingValue(DestReg);
5082 uint16_t SrcEncoding =
TRI->getEncodingValue(SrcReg);
5083 assert(DestEncoding % NumRegs == 0 && SrcEncoding % NumRegs == 0 &&
5084 "GPR reg sequences should not be able to overlap");
5101 bool RenamableSrc)
const {
5102 if (AArch64::GPR32spRegClass.
contains(DestReg) &&
5103 AArch64::GPR32spRegClass.
contains(SrcReg)) {
5104 if (DestReg == AArch64::WSP || SrcReg == AArch64::WSP) {
5106 if (Subtarget.hasZeroCycleRegMoveGPR64() &&
5107 !Subtarget.hasZeroCycleRegMoveGPR32()) {
5109 MCRegister DestRegX = RI.getMatchingSuperReg(DestReg, AArch64::sub_32,
5110 &AArch64::GPR64spRegClass);
5111 MCRegister SrcRegX = RI.getMatchingSuperReg(SrcReg, AArch64::sub_32,
5112 &AArch64::GPR64spRegClass);
5128 }
else if (Subtarget.hasZeroCycleRegMoveGPR64() &&
5129 !Subtarget.hasZeroCycleRegMoveGPR32()) {
5131 MCRegister DestRegX = RI.getMatchingSuperReg(DestReg, AArch64::sub_32,
5132 &AArch64::GPR64spRegClass);
5133 assert(DestRegX.
isValid() &&
"Destination super-reg not valid");
5134 MCRegister SrcRegX = RI.getMatchingSuperReg(SrcReg, AArch64::sub_32,
5135 &AArch64::GPR64spRegClass);
5155 if (AArch64::GPR32spRegClass.
contains(DestReg) && SrcReg == AArch64::WZR) {
5156 if (Subtarget.hasZeroCycleZeroingGPR64() &&
5157 !Subtarget.hasZeroCycleZeroingGPR32()) {
5158 MCRegister DestRegX = RI.getMatchingSuperReg(DestReg, AArch64::sub_32,
5159 &AArch64::GPR64spRegClass);
5160 assert(DestRegX.
isValid() &&
"Destination super-reg not valid");
5164 }
else if (Subtarget.hasZeroCycleZeroingGPR32()) {
5176 if (AArch64::GPR64spRegClass.
contains(DestReg) &&
5177 AArch64::GPR64spRegClass.
contains(SrcReg)) {
5178 if (DestReg == AArch64::SP || SrcReg == AArch64::SP) {
5194 if (AArch64::GPR64spRegClass.
contains(DestReg) && SrcReg == AArch64::XZR) {
5195 if (Subtarget.hasZeroCycleZeroingGPR64()) {
5208 if (AArch64::PPRRegClass.
contains(DestReg) &&
5209 AArch64::PPRRegClass.
contains(SrcReg)) {
5210 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5211 "Unexpected SVE register.");
5221 bool DestIsPNR = AArch64::PNRRegClass.contains(DestReg);
5222 bool SrcIsPNR = AArch64::PNRRegClass.contains(SrcReg);
5223 if (DestIsPNR || SrcIsPNR) {
5225 return (R - AArch64::PN0) + AArch64::P0;
5230 if (PPRSrcReg != PPRDestReg) {
5242 if (AArch64::ZPRRegClass.
contains(DestReg) &&
5243 AArch64::ZPRRegClass.
contains(SrcReg)) {
5244 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5245 "Unexpected SVE register.");
5253 if ((AArch64::ZPR2RegClass.
contains(DestReg) ||
5254 AArch64::ZPR2StridedOrContiguousRegClass.
contains(DestReg)) &&
5255 (AArch64::ZPR2RegClass.
contains(SrcReg) ||
5256 AArch64::ZPR2StridedOrContiguousRegClass.
contains(SrcReg))) {
5257 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5258 "Unexpected SVE register.");
5259 static const unsigned Indices[] = {AArch64::zsub0, AArch64::zsub1};
5266 if (AArch64::ZPR3RegClass.
contains(DestReg) &&
5267 AArch64::ZPR3RegClass.
contains(SrcReg)) {
5268 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5269 "Unexpected SVE register.");
5270 static const unsigned Indices[] = {AArch64::zsub0, AArch64::zsub1,
5278 if ((AArch64::ZPR4RegClass.
contains(DestReg) ||
5279 AArch64::ZPR4StridedOrContiguousRegClass.
contains(DestReg)) &&
5280 (AArch64::ZPR4RegClass.
contains(SrcReg) ||
5281 AArch64::ZPR4StridedOrContiguousRegClass.
contains(SrcReg))) {
5282 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5283 "Unexpected SVE register.");
5284 static const unsigned Indices[] = {AArch64::zsub0, AArch64::zsub1,
5285 AArch64::zsub2, AArch64::zsub3};
5292 if (AArch64::DDDDRegClass.
contains(DestReg) &&
5293 AArch64::DDDDRegClass.
contains(SrcReg)) {
5294 static const unsigned Indices[] = {AArch64::dsub0, AArch64::dsub1,
5295 AArch64::dsub2, AArch64::dsub3};
5302 if (AArch64::DDDRegClass.
contains(DestReg) &&
5303 AArch64::DDDRegClass.
contains(SrcReg)) {
5304 static const unsigned Indices[] = {AArch64::dsub0, AArch64::dsub1,
5312 if (AArch64::DDRegClass.
contains(DestReg) &&
5313 AArch64::DDRegClass.
contains(SrcReg)) {
5314 static const unsigned Indices[] = {AArch64::dsub0, AArch64::dsub1};
5321 if (AArch64::QQQQRegClass.
contains(DestReg) &&
5322 AArch64::QQQQRegClass.
contains(SrcReg)) {
5323 static const unsigned Indices[] = {AArch64::qsub0, AArch64::qsub1,
5324 AArch64::qsub2, AArch64::qsub3};
5331 if (AArch64::QQQRegClass.
contains(DestReg) &&
5332 AArch64::QQQRegClass.
contains(SrcReg)) {
5333 static const unsigned Indices[] = {AArch64::qsub0, AArch64::qsub1,
5341 if (AArch64::QQRegClass.
contains(DestReg) &&
5342 AArch64::QQRegClass.
contains(SrcReg)) {
5343 static const unsigned Indices[] = {AArch64::qsub0, AArch64::qsub1};
5349 if (AArch64::XSeqPairsClassRegClass.
contains(DestReg) &&
5350 AArch64::XSeqPairsClassRegClass.
contains(SrcReg)) {
5351 static const unsigned Indices[] = {AArch64::sube64, AArch64::subo64};
5353 AArch64::XZR, Indices);
5357 if (AArch64::WSeqPairsClassRegClass.
contains(DestReg) &&
5358 AArch64::WSeqPairsClassRegClass.
contains(SrcReg)) {
5359 static const unsigned Indices[] = {AArch64::sube32, AArch64::subo32};
5361 AArch64::WZR, Indices);
5365 if (AArch64::FPR128RegClass.
contains(DestReg) &&
5366 AArch64::FPR128RegClass.
contains(SrcReg)) {
5367 if (Subtarget.isSVEorStreamingSVEAvailable() &&
5368 !Subtarget.isNeonAvailable())
5371 .
addReg(AArch64::Z0 + (SrcReg - AArch64::Q0))
5372 .
addReg(AArch64::Z0 + (SrcReg - AArch64::Q0));
5373 else if (Subtarget.isNeonAvailable())
5392 if (AArch64::FPR64RegClass.
contains(DestReg) &&
5393 AArch64::FPR64RegClass.
contains(SrcReg)) {
5394 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
5395 !Subtarget.hasZeroCycleRegMoveFPR64() &&
5396 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable()) {
5397 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::dsub,
5398 &AArch64::FPR128RegClass);
5399 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::dsub,
5400 &AArch64::FPR128RegClass);
5416 if (AArch64::FPR32RegClass.
contains(DestReg) &&
5417 AArch64::FPR32RegClass.
contains(SrcReg)) {
5418 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
5419 !Subtarget.hasZeroCycleRegMoveFPR64() &&
5420 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable()) {
5421 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::ssub,
5422 &AArch64::FPR128RegClass);
5423 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::ssub,
5424 &AArch64::FPR128RegClass);
5433 }
else if (Subtarget.hasZeroCycleRegMoveFPR64() &&
5434 !Subtarget.hasZeroCycleRegMoveFPR32()) {
5435 MCRegister DestRegD = RI.getMatchingSuperReg(DestReg, AArch64::ssub,
5436 &AArch64::FPR64RegClass);
5437 MCRegister SrcRegD = RI.getMatchingSuperReg(SrcReg, AArch64::ssub,
5438 &AArch64::FPR64RegClass);
5453 if (AArch64::FPR16RegClass.
contains(DestReg) &&
5454 AArch64::FPR16RegClass.
contains(SrcReg)) {
5455 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
5456 !Subtarget.hasZeroCycleRegMoveFPR64() &&
5457 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable()) {
5458 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
5459 &AArch64::FPR128RegClass);
5460 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
5461 &AArch64::FPR128RegClass);
5470 }
else if (Subtarget.hasZeroCycleRegMoveFPR64() &&
5471 !Subtarget.hasZeroCycleRegMoveFPR32()) {
5472 MCRegister DestRegD = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
5473 &AArch64::FPR64RegClass);
5474 MCRegister SrcRegD = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
5475 &AArch64::FPR64RegClass);
5484 DestReg = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
5485 &AArch64::FPR32RegClass);
5486 SrcReg = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
5487 &AArch64::FPR32RegClass);
5494 if (AArch64::FPR8RegClass.
contains(DestReg) &&
5495 AArch64::FPR8RegClass.
contains(SrcReg)) {
5496 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
5497 !Subtarget.hasZeroCycleRegMoveFPR64() &&
5498 !Subtarget.hasZeroCycleRegMoveFPR64() && Subtarget.isNeonAvailable()) {
5499 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
5500 &AArch64::FPR128RegClass);
5501 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
5502 &AArch64::FPR128RegClass);
5511 }
else if (Subtarget.hasZeroCycleRegMoveFPR64() &&
5512 !Subtarget.hasZeroCycleRegMoveFPR32()) {
5513 MCRegister DestRegD = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
5514 &AArch64::FPR64RegClass);
5515 MCRegister SrcRegD = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
5516 &AArch64::FPR64RegClass);
5525 DestReg = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
5526 &AArch64::FPR32RegClass);
5527 SrcReg = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
5528 &AArch64::FPR32RegClass);
5536 if (AArch64::FPR64RegClass.
contains(DestReg) &&
5537 AArch64::GPR64RegClass.
contains(SrcReg)) {
5538 if (AArch64::XZR == SrcReg) {
5546 if (AArch64::GPR64RegClass.
contains(DestReg) &&
5547 AArch64::FPR64RegClass.
contains(SrcReg)) {
5553 if (AArch64::FPR32RegClass.
contains(DestReg) &&
5554 AArch64::GPR32RegClass.
contains(SrcReg)) {
5555 if (AArch64::WZR == SrcReg) {
5563 if (AArch64::GPR32RegClass.
contains(DestReg) &&
5564 AArch64::FPR32RegClass.
contains(SrcReg)) {
5570 if (DestReg == AArch64::NZCV) {
5571 assert(AArch64::GPR64RegClass.
contains(SrcReg) &&
"Invalid NZCV copy");
5573 .
addImm(AArch64SysReg::NZCV)
5579 if (SrcReg == AArch64::NZCV) {
5580 assert(AArch64::GPR64RegClass.
contains(DestReg) &&
"Invalid NZCV copy");
5582 .
addImm(AArch64SysReg::NZCV)
5588 errs() << RI.getRegAsmName(DestReg) <<
" = COPY " << RI.getRegAsmName(SrcReg)
5599 unsigned SubIdx0,
unsigned SubIdx1,
int FI,
5604 SrcReg0 =
TRI.getSubReg(SrcReg, SubIdx0);
5606 SrcReg1 =
TRI.getSubReg(SrcReg, SubIdx1);
5619 Register SrcReg,
bool isKill,
int FI,
5635 switch (
TRI->getSpillSize(*RC)) {
5637 if (AArch64::FPR8RegClass.hasSubClassEq(RC))
5638 Opc = AArch64::STRBui;
5641 if (AArch64::FPR16RegClass.hasSubClassEq(RC))
5642 Opc = AArch64::STRHui;
5643 else if (AArch64::PNRRegClass.hasSubClassEq(RC) ||
5644 AArch64::PPRRegClass.hasSubClassEq(RC)) {
5645 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5646 "Unexpected register store without SVE store instructions");
5647 Opc = AArch64::STR_PXI;
5653 if (AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
5654 Opc = AArch64::STRWui;
5658 assert(SrcReg != AArch64::WSP);
5659 }
else if (AArch64::FPR32RegClass.hasSubClassEq(RC))
5660 Opc = AArch64::STRSui;
5661 else if (AArch64::PPR2RegClass.hasSubClassEq(RC)) {
5662 Opc = AArch64::STR_PPXI;
5667 if (AArch64::GPR64allRegClass.hasSubClassEq(RC)) {
5668 Opc = AArch64::STRXui;
5672 assert(SrcReg != AArch64::SP);
5673 }
else if (AArch64::FPR64RegClass.hasSubClassEq(RC)) {
5674 Opc = AArch64::STRDui;
5675 }
else if (AArch64::WSeqPairsClassRegClass.hasSubClassEq(RC)) {
5677 get(AArch64::STPWi), SrcReg, isKill,
5678 AArch64::sube32, AArch64::subo32, FI, MMO);
5683 if (AArch64::FPR128RegClass.hasSubClassEq(RC))
5684 Opc = AArch64::STRQui;
5685 else if (AArch64::DDRegClass.hasSubClassEq(RC)) {
5686 assert(Subtarget.hasNEON() &&
"Unexpected register store without NEON");
5687 Opc = AArch64::ST1Twov1d;
5689 }
else if (AArch64::XSeqPairsClassRegClass.hasSubClassEq(RC)) {
5691 get(AArch64::STPXi), SrcReg, isKill,
5692 AArch64::sube64, AArch64::subo64, FI, MMO);
5694 }
else if (AArch64::ZPRRegClass.hasSubClassEq(RC)) {
5695 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5696 "Unexpected register store without SVE store instructions");
5697 Opc = AArch64::STR_ZXI;
5702 if (AArch64::DDDRegClass.hasSubClassEq(RC)) {
5703 assert(Subtarget.hasNEON() &&
"Unexpected register store without NEON");
5704 Opc = AArch64::ST1Threev1d;
5709 if (AArch64::DDDDRegClass.hasSubClassEq(RC)) {
5710 assert(Subtarget.hasNEON() &&
"Unexpected register store without NEON");
5711 Opc = AArch64::ST1Fourv1d;
5713 }
else if (AArch64::QQRegClass.hasSubClassEq(RC)) {
5714 assert(Subtarget.hasNEON() &&
"Unexpected register store without NEON");
5715 Opc = AArch64::ST1Twov2d;
5717 }
else if (AArch64::ZPR2StridedOrContiguousRegClass.hasSubClassEq(RC)) {
5718 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5719 "Unexpected register store without SVE store instructions");
5720 Opc = AArch64::STR_ZZXI_STRIDED_CONTIGUOUS;
5722 }
else if (AArch64::ZPR2RegClass.hasSubClassEq(RC)) {
5723 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5724 "Unexpected register store without SVE store instructions");
5725 Opc = AArch64::STR_ZZXI;
5730 if (AArch64::QQQRegClass.hasSubClassEq(RC)) {
5731 assert(Subtarget.hasNEON() &&
"Unexpected register store without NEON");
5732 Opc = AArch64::ST1Threev2d;
5734 }
else if (AArch64::ZPR3RegClass.hasSubClassEq(RC)) {
5735 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5736 "Unexpected register store without SVE store instructions");
5737 Opc = AArch64::STR_ZZZXI;
5742 if (AArch64::QQQQRegClass.hasSubClassEq(RC)) {
5743 assert(Subtarget.hasNEON() &&
"Unexpected register store without NEON");
5744 Opc = AArch64::ST1Fourv2d;
5746 }
else if (AArch64::ZPR4StridedOrContiguousRegClass.hasSubClassEq(RC)) {
5747 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5748 "Unexpected register store without SVE store instructions");
5749 Opc = AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS;
5751 }
else if (AArch64::ZPR4RegClass.hasSubClassEq(RC)) {
5752 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5753 "Unexpected register store without SVE store instructions");
5754 Opc = AArch64::STR_ZZZZXI;
5759 assert(
Opc &&
"Unknown register class");
5770 MI.addMemOperand(MMO);
5777 Register DestReg,
unsigned SubIdx0,
5778 unsigned SubIdx1,
int FI,
5782 bool IsUndef =
true;
5784 DestReg0 =
TRI.getSubReg(DestReg, SubIdx0);
5786 DestReg1 =
TRI.getSubReg(DestReg, SubIdx1);
5813 switch (
TRI->getSpillSize(*RC)) {
5815 if (AArch64::FPR8RegClass.hasSubClassEq(RC))
5816 Opc = AArch64::LDRBui;
5819 bool IsPNR = AArch64::PNRRegClass.hasSubClassEq(RC);
5820 if (AArch64::FPR16RegClass.hasSubClassEq(RC))
5821 Opc = AArch64::LDRHui;
5822 else if (IsPNR || AArch64::PPRRegClass.hasSubClassEq(RC)) {
5823 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5824 "Unexpected register load without SVE load instructions");
5827 Opc = AArch64::LDR_PXI;
5833 if (AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
5834 Opc = AArch64::LDRWui;
5838 assert(DestReg != AArch64::WSP);
5839 }
else if (AArch64::FPR32RegClass.hasSubClassEq(RC))
5840 Opc = AArch64::LDRSui;
5841 else if (AArch64::PPR2RegClass.hasSubClassEq(RC)) {
5842 Opc = AArch64::LDR_PPXI;
5847 if (AArch64::GPR64allRegClass.hasSubClassEq(RC)) {
5848 Opc = AArch64::LDRXui;
5852 assert(DestReg != AArch64::SP);
5853 }
else if (AArch64::FPR64RegClass.hasSubClassEq(RC)) {
5854 Opc = AArch64::LDRDui;
5855 }
else if (AArch64::WSeqPairsClassRegClass.hasSubClassEq(RC)) {
5857 get(AArch64::LDPWi), DestReg, AArch64::sube32,
5858 AArch64::subo32, FI, MMO);
5863 if (AArch64::FPR128RegClass.hasSubClassEq(RC))
5864 Opc = AArch64::LDRQui;
5865 else if (AArch64::DDRegClass.hasSubClassEq(RC)) {
5866 assert(Subtarget.hasNEON() &&
"Unexpected register load without NEON");
5867 Opc = AArch64::LD1Twov1d;
5869 }
else if (AArch64::XSeqPairsClassRegClass.hasSubClassEq(RC)) {
5871 get(AArch64::LDPXi), DestReg, AArch64::sube64,
5872 AArch64::subo64, FI, MMO);
5874 }
else if (AArch64::ZPRRegClass.hasSubClassEq(RC)) {
5875 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5876 "Unexpected register load without SVE load instructions");
5877 Opc = AArch64::LDR_ZXI;
5882 if (AArch64::DDDRegClass.hasSubClassEq(RC)) {
5883 assert(Subtarget.hasNEON() &&
"Unexpected register load without NEON");
5884 Opc = AArch64::LD1Threev1d;
5889 if (AArch64::DDDDRegClass.hasSubClassEq(RC)) {
5890 assert(Subtarget.hasNEON() &&
"Unexpected register load without NEON");
5891 Opc = AArch64::LD1Fourv1d;
5893 }
else if (AArch64::QQRegClass.hasSubClassEq(RC)) {
5894 assert(Subtarget.hasNEON() &&
"Unexpected register load without NEON");
5895 Opc = AArch64::LD1Twov2d;
5897 }
else if (AArch64::ZPR2StridedOrContiguousRegClass.hasSubClassEq(RC)) {
5898 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5899 "Unexpected register load without SVE load instructions");
5900 Opc = AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS;
5902 }
else if (AArch64::ZPR2RegClass.hasSubClassEq(RC)) {
5903 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5904 "Unexpected register load without SVE load instructions");
5905 Opc = AArch64::LDR_ZZXI;
5910 if (AArch64::QQQRegClass.hasSubClassEq(RC)) {
5911 assert(Subtarget.hasNEON() &&
"Unexpected register load without NEON");
5912 Opc = AArch64::LD1Threev2d;
5914 }
else if (AArch64::ZPR3RegClass.hasSubClassEq(RC)) {
5915 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5916 "Unexpected register load without SVE load instructions");
5917 Opc = AArch64::LDR_ZZZXI;
5922 if (AArch64::QQQQRegClass.hasSubClassEq(RC)) {
5923 assert(Subtarget.hasNEON() &&
"Unexpected register load without NEON");
5924 Opc = AArch64::LD1Fourv2d;
5926 }
else if (AArch64::ZPR4StridedOrContiguousRegClass.hasSubClassEq(RC)) {
5927 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5928 "Unexpected register load without SVE load instructions");
5929 Opc = AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS;
5931 }
else if (AArch64::ZPR4RegClass.hasSubClassEq(RC)) {
5932 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
5933 "Unexpected register load without SVE load instructions");
5934 Opc = AArch64::LDR_ZZZZXI;
5940 assert(
Opc &&
"Unknown register class");
5950 MI.addMemOperand(MMO);
5957 UseMI.getIterator()),
5959 return I.modifiesRegister(AArch64::NZCV, TRI) ||
5960 I.readsRegister(AArch64::NZCV, TRI);
5964void AArch64InstrInfo::decomposeStackOffsetForDwarfOffsets(
5969 assert(
Offset.getScalable() % 2 == 0 &&
"Invalid frame offset");
5976 ByteSized =
Offset.getFixed();
5977 VGSized =
Offset.getScalable() / 2;
5983void AArch64InstrInfo::decomposeStackOffsetForFrameOffsets(
5985 int64_t &NumDataVectors) {
5989 assert(
Offset.getScalable() % 2 == 0 &&
"Invalid frame offset");
5991 NumBytes =
Offset.getFixed();
5993 NumPredicateVectors =
Offset.getScalable() / 2;
5998 if (NumPredicateVectors % 8 == 0 || NumPredicateVectors < -64 ||
5999 NumPredicateVectors > 62) {
6000 NumDataVectors = NumPredicateVectors / 8;
6001 NumPredicateVectors -= NumDataVectors * 8;
6027 Expr.
push_back((
char)dwarf::DW_OP_bregx);
6035 int64_t OffsetFromDefCFA) {
6049 Comment << (NumBytes < 0 ?
" - " :
" + ") << std::abs(NumBytes);
6050 if (!RegScale.empty())
6060 int64_t NumBytes, NumVGScaledBytes;
6061 AArch64InstrInfo::decomposeStackOffsetForDwarfOffsets(
Offset, NumBytes,
6063 std::string CommentBuffer;
6066 if (
Reg == AArch64::SP)
6068 else if (
Reg == AArch64::FP)
6075 unsigned DwarfReg =
TRI.getDwarfRegNum(
Reg,
true);
6076 assert(DwarfReg <= 31 &&
"DwarfReg out of bounds (0..31)");
6078 Expr.
push_back(dwarf::DW_OP_breg0 + DwarfReg);
6081 if (NumVGScaledBytes) {
6091 DefCfaExpr.
push_back(dwarf::DW_CFA_def_cfa_expression);
6099 unsigned FrameReg,
unsigned Reg,
6101 bool LastAdjustmentWasScalable) {
6102 if (
Offset.getScalable())
6105 if (FrameReg == Reg && !LastAdjustmentWasScalable)
6108 unsigned DwarfReg =
TRI.getDwarfRegNum(Reg,
true);
6115 std::optional<int64_t> IncomingVGOffsetFromDefCFA) {
6116 int64_t NumBytes, NumVGScaledBytes;
6117 AArch64InstrInfo::decomposeStackOffsetForDwarfOffsets(
6118 OffsetFromDefCFA, NumBytes, NumVGScaledBytes);
6120 unsigned DwarfReg =
TRI.getDwarfRegNum(Reg,
true);
6123 if (!NumVGScaledBytes)
6126 std::string CommentBuffer;
6131 assert(NumVGScaledBytes &&
"Expected scalable offset");
6135 if (IncomingVGOffsetFromDefCFA) {
6137 VGRegScale =
"* IncomingVG";
6140 VGRegScale =
"* VG";
6144 OffsetExpr.
push_back(dwarf::DW_OP_plus);
6153 CfaExpr.
push_back(dwarf::DW_CFA_expression);
6168 unsigned SrcReg, int64_t
Offset,
unsigned Opc,
6171 bool *HasWinCFI,
bool EmitCFAOffset,
6174 unsigned MaxEncoding, ShiftSize;
6176 case AArch64::ADDXri:
6177 case AArch64::ADDSXri:
6178 case AArch64::SUBXri:
6179 case AArch64::SUBSXri:
6180 MaxEncoding = 0xfff;
6183 case AArch64::ADDVL_XXI:
6184 case AArch64::ADDPL_XXI:
6185 case AArch64::ADDSVL_XXI:
6186 case AArch64::ADDSPL_XXI:
6201 if (
Opc == AArch64::ADDVL_XXI ||
Opc == AArch64::ADDSVL_XXI)
6203 else if (
Opc == AArch64::ADDPL_XXI ||
Opc == AArch64::ADDSPL_XXI)
6217 const unsigned MaxEncodableValue = MaxEncoding << ShiftSize;
6219 if (TmpReg == AArch64::XZR)
6220 TmpReg =
MBB.getParent()->getRegInfo().createVirtualRegister(
6221 &AArch64::GPR64RegClass);
6223 uint64_t ThisVal = std::min<uint64_t>(
Offset, MaxEncodableValue);
6224 unsigned LocalShiftSize = 0;
6225 if (ThisVal > MaxEncoding) {
6226 ThisVal = ThisVal >> ShiftSize;
6227 LocalShiftSize = ShiftSize;
6229 assert((ThisVal >> ShiftSize) <= MaxEncoding &&
6230 "Encoding cannot handle value that big");
6232 Offset -= ThisVal << LocalShiftSize;
6237 .
addImm(Sign * (
int)ThisVal);
6247 if (Sign == -1 ||
Opc == AArch64::SUBXri ||
Opc == AArch64::SUBSXri)
6248 CFAOffset += Change;
6250 CFAOffset -= Change;
6251 if (EmitCFAOffset && DestReg == TmpReg) {
6264 int Imm = (int)(ThisVal << LocalShiftSize);
6265 if (VScale != 1 && DestReg == AArch64::SP) {
6271 }
else if ((DestReg == AArch64::FP && SrcReg == AArch64::SP) ||
6272 (SrcReg == AArch64::FP && DestReg == AArch64::SP)) {
6273 assert(VScale == 1 &&
"Expected non-scalable operation");
6282 assert(
Offset == 0 &&
"Expected remaining offset to be zero to "
6283 "emit a single SEH directive");
6284 }
else if (DestReg == AArch64::SP) {
6285 assert(VScale == 1 &&
"Expected non-scalable operation");
6288 assert(SrcReg == AArch64::SP &&
"Unexpected SrcReg for SEH_StackAlloc");
6301 unsigned DestReg,
unsigned SrcReg,
6304 bool NeedsWinCFI,
bool *HasWinCFI,
6306 unsigned FrameReg) {
6313 bool UseSVL =
F.hasFnAttribute(
"aarch64_pstate_sm_body");
6315 int64_t Bytes, NumPredicateVectors, NumDataVectors;
6316 AArch64InstrInfo::decomposeStackOffsetForFrameOffsets(
6317 Offset, Bytes, NumPredicateVectors, NumDataVectors);
6320 bool NeedsFinalDefNZCV = SetNZCV && (NumPredicateVectors || NumDataVectors);
6321 if (NeedsFinalDefNZCV)
6325 if (Bytes || (!
Offset && SrcReg != DestReg)) {
6326 assert((DestReg != AArch64::SP || Bytes % 8 == 0) &&
6327 "SP increment/decrement not 8-byte aligned");
6328 unsigned Opc = SetNZCV ? AArch64::ADDSXri : AArch64::ADDXri;
6331 Opc = SetNZCV ? AArch64::SUBSXri : AArch64::SUBXri;
6334 NeedsWinCFI, HasWinCFI, EmitCFAOffset, CFAOffset,
6336 CFAOffset += (
Opc == AArch64::ADDXri ||
Opc == AArch64::ADDSXri)
6343 assert(!(NeedsWinCFI && NumPredicateVectors) &&
6344 "WinCFI can't allocate fractions of an SVE data vector");
6346 if (NumDataVectors) {
6348 UseSVL ? AArch64::ADDSVL_XXI : AArch64::ADDVL_XXI,
TII,
6349 Flag, NeedsWinCFI, HasWinCFI, EmitCFAOffset, CFAOffset,
6355 if (NumPredicateVectors) {
6356 assert(DestReg != AArch64::SP &&
"Unaligned access to SP");
6358 UseSVL ? AArch64::ADDSPL_XXI : AArch64::ADDPL_XXI,
TII,
6359 Flag, NeedsWinCFI, HasWinCFI, EmitCFAOffset, CFAOffset,
6363 if (NeedsFinalDefNZCV)
6384 if (
MI.isFullCopy()) {
6387 if (SrcReg == AArch64::SP && DstReg.
isVirtual()) {
6391 if (DstReg == AArch64::SP && SrcReg.
isVirtual()) {
6396 if (SrcReg == AArch64::NZCV || DstReg == AArch64::NZCV)
6424 if (
MI.isCopy() &&
Ops.size() == 1 &&
6426 (
Ops[0] == 0 ||
Ops[0] == 1)) {
6427 bool IsSpill =
Ops[0] == 0;
6428 bool IsFill = !IsSpill;
6440 :
TRI.getMinimalPhysRegClass(Reg);
6446 "Mismatched register size in non subreg COPY");
6453 return &*--InsertPt;
6465 if (IsSpill && DstMO.
isUndef() && SrcReg == AArch64::WZR &&
6468 "Unexpected subreg on physical register");
6470 FrameIndex, &AArch64::GPR64RegClass, &
TRI,
6472 return &*--InsertPt;
6489 case AArch64::sub_32:
6490 if (AArch64::GPR64RegClass.hasSubClassEq(
getRegClass(DstReg)))
6491 FillRC = &AArch64::GPR32RegClass;
6494 FillRC = &AArch64::FPR32RegClass;
6497 FillRC = &AArch64::FPR64RegClass;
6503 TRI.getRegSizeInBits(*FillRC) &&
6504 "Mismatched regclass size on folded subreg COPY");
6523 bool *OutUseUnscaledOp,
6524 unsigned *OutUnscaledOp,
6525 int64_t *EmittableOffset) {
6527 if (EmittableOffset)
6528 *EmittableOffset = 0;
6529 if (OutUseUnscaledOp)
6530 *OutUseUnscaledOp =
false;
6536 switch (
MI.getOpcode()) {
6539 case AArch64::LD1Rv1d:
6540 case AArch64::LD1Rv2s:
6541 case AArch64::LD1Rv2d:
6542 case AArch64::LD1Rv4h:
6543 case AArch64::LD1Rv4s:
6544 case AArch64::LD1Rv8b:
6545 case AArch64::LD1Rv8h:
6546 case AArch64::LD1Rv16b:
6547 case AArch64::LD1Twov2d:
6548 case AArch64::LD1Threev2d:
6549 case AArch64::LD1Fourv2d:
6550 case AArch64::LD1Twov1d:
6551 case AArch64::LD1Threev1d:
6552 case AArch64::LD1Fourv1d:
6553 case AArch64::ST1Twov2d:
6554 case AArch64::ST1Threev2d:
6555 case AArch64::ST1Fourv2d:
6556 case AArch64::ST1Twov1d:
6557 case AArch64::ST1Threev1d:
6558 case AArch64::ST1Fourv1d:
6559 case AArch64::ST1i8:
6560 case AArch64::ST1i16:
6561 case AArch64::ST1i32:
6562 case AArch64::ST1i64:
6564 case AArch64::IRGstack:
6565 case AArch64::STGloop:
6566 case AArch64::STZGloop:
6571 TypeSize ScaleValue(0U,
false), Width(0U,
false);
6572 int64_t MinOff, MaxOff;
6578 bool IsMulVL = ScaleValue.isScalable();
6579 unsigned Scale = ScaleValue.getKnownMinValue();
6589 std::optional<unsigned> UnscaledOp =
6591 bool useUnscaledOp = UnscaledOp && (
Offset % Scale ||
Offset < 0);
6592 if (useUnscaledOp &&
6597 Scale = ScaleValue.getKnownMinValue();
6598 assert(IsMulVL == ScaleValue.isScalable() &&
6599 "Unscaled opcode has different value for scalable");
6601 int64_t Remainder =
Offset % Scale;
6602 assert(!(Remainder && useUnscaledOp) &&
6603 "Cannot have remainder when using unscaled op");
6605 assert(MinOff < MaxOff &&
"Unexpected Min/Max offsets");
6606 int64_t NewOffset =
Offset / Scale;
6607 if (MinOff <= NewOffset && NewOffset <= MaxOff)
6610 NewOffset = NewOffset < 0 ? MinOff : MaxOff;
6614 if (EmittableOffset)
6615 *EmittableOffset = NewOffset;
6616 if (OutUseUnscaledOp)
6617 *OutUseUnscaledOp = useUnscaledOp;
6618 if (OutUnscaledOp && UnscaledOp)
6619 *OutUnscaledOp = *UnscaledOp;
6632 unsigned Opcode =
MI.getOpcode();
6633 unsigned ImmIdx = FrameRegIdx + 1;
6635 if (Opcode == AArch64::ADDSXri || Opcode == AArch64::ADDXri) {
6640 MI.eraseFromParent();
6646 unsigned UnscaledOp;
6649 &UnscaledOp, &NewOffset);
6653 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg,
false);
6655 MI.setDesc(
TII->get(UnscaledOp));
6657 MI.getOperand(ImmIdx).ChangeToImmediate(NewOffset);
6675bool AArch64InstrInfo::useMachineCombiner()
const {
return true; }
6680 case AArch64::ADDSWrr:
6681 case AArch64::ADDSWri:
6682 case AArch64::ADDSXrr:
6683 case AArch64::ADDSXri:
6684 case AArch64::SUBSWrr:
6685 case AArch64::SUBSXrr:
6687 case AArch64::SUBSWri:
6688 case AArch64::SUBSXri:
6699 case AArch64::ADDWrr:
6700 case AArch64::ADDWri:
6701 case AArch64::SUBWrr:
6702 case AArch64::ADDSWrr:
6703 case AArch64::ADDSWri:
6704 case AArch64::SUBSWrr:
6706 case AArch64::SUBWri:
6707 case AArch64::SUBSWri:
6718 case AArch64::ADDXrr:
6719 case AArch64::ADDXri:
6720 case AArch64::SUBXrr:
6721 case AArch64::ADDSXrr:
6722 case AArch64::ADDSXri:
6723 case AArch64::SUBSXrr:
6725 case AArch64::SUBXri:
6726 case AArch64::SUBSXri:
6727 case AArch64::ADDv8i8:
6728 case AArch64::ADDv16i8:
6729 case AArch64::ADDv4i16:
6730 case AArch64::ADDv8i16:
6731 case AArch64::ADDv2i32:
6732 case AArch64::ADDv4i32:
6733 case AArch64::SUBv8i8:
6734 case AArch64::SUBv16i8:
6735 case AArch64::SUBv4i16:
6736 case AArch64::SUBv8i16:
6737 case AArch64::SUBv2i32:
6738 case AArch64::SUBv4i32:
6751 case AArch64::FADDHrr:
6752 case AArch64::FADDSrr:
6753 case AArch64::FADDDrr:
6754 case AArch64::FADDv4f16:
6755 case AArch64::FADDv8f16:
6756 case AArch64::FADDv2f32:
6757 case AArch64::FADDv2f64:
6758 case AArch64::FADDv4f32:
6759 case AArch64::FSUBHrr:
6760 case AArch64::FSUBSrr:
6761 case AArch64::FSUBDrr:
6762 case AArch64::FSUBv4f16:
6763 case AArch64::FSUBv8f16:
6764 case AArch64::FSUBv2f32:
6765 case AArch64::FSUBv2f64:
6766 case AArch64::FSUBv4f32:
6785 unsigned CombineOpc,
unsigned ZeroReg = 0,
6786 bool CheckZeroReg =
false) {
6793 if (!
MI ||
MI->getParent() != &
MBB ||
MI->getOpcode() != CombineOpc)
6796 if (!
MRI.hasOneNonDBGUse(
MI->getOperand(0).getReg()))
6800 assert(
MI->getNumOperands() >= 4 &&
MI->getOperand(0).isReg() &&
6801 MI->getOperand(1).isReg() &&
MI->getOperand(2).isReg() &&
6802 MI->getOperand(3).isReg() &&
"MAdd/MSub must have a least 4 regs");
6804 if (
MI->getOperand(3).getReg() != ZeroReg)
6809 MI->findRegisterDefOperandIdx(AArch64::NZCV,
nullptr,
true) == -1)
6818 unsigned MulOpc,
unsigned ZeroReg) {
6833bool AArch64InstrInfo::isAssociativeAndCommutative(
const MachineInstr &Inst,
6834 bool Invert)
const {
6840 case AArch64::FADDHrr:
6841 case AArch64::FADDSrr:
6842 case AArch64::FADDDrr:
6843 case AArch64::FMULHrr:
6844 case AArch64::FMULSrr:
6845 case AArch64::FMULDrr:
6846 case AArch64::FMULX16:
6847 case AArch64::FMULX32:
6848 case AArch64::FMULX64:
6850 case AArch64::FADDv4f16:
6851 case AArch64::FADDv8f16:
6852 case AArch64::FADDv2f32:
6853 case AArch64::FADDv4f32:
6854 case AArch64::FADDv2f64:
6855 case AArch64::FMULv4f16:
6856 case AArch64::FMULv8f16:
6857 case AArch64::FMULv2f32:
6858 case AArch64::FMULv4f32:
6859 case AArch64::FMULv2f64:
6860 case AArch64::FMULXv4f16:
6861 case AArch64::FMULXv8f16:
6862 case AArch64::FMULXv2f32:
6863 case AArch64::FMULXv4f32:
6864 case AArch64::FMULXv2f64:
6868 case AArch64::FADD_ZZZ_H:
6869 case AArch64::FADD_ZZZ_S:
6870 case AArch64::FADD_ZZZ_D:
6871 case AArch64::FMUL_ZZZ_H:
6872 case AArch64::FMUL_ZZZ_S:
6873 case AArch64::FMUL_ZZZ_D:
6884 case AArch64::ADDWrr:
6885 case AArch64::ADDXrr:
6886 case AArch64::ANDWrr:
6887 case AArch64::ANDXrr:
6888 case AArch64::ORRWrr:
6889 case AArch64::ORRXrr:
6890 case AArch64::EORWrr:
6891 case AArch64::EORXrr:
6892 case AArch64::EONWrr:
6893 case AArch64::EONXrr:
6897 case AArch64::ADDv8i8:
6898 case AArch64::ADDv16i8:
6899 case AArch64::ADDv4i16:
6900 case AArch64::ADDv8i16:
6901 case AArch64::ADDv2i32:
6902 case AArch64::ADDv4i32:
6903 case AArch64::ADDv1i64:
6904 case AArch64::ADDv2i64:
6905 case AArch64::MULv8i8:
6906 case AArch64::MULv16i8:
6907 case AArch64::MULv4i16:
6908 case AArch64::MULv8i16:
6909 case AArch64::MULv2i32:
6910 case AArch64::MULv4i32:
6911 case AArch64::ANDv8i8:
6912 case AArch64::ANDv16i8:
6913 case AArch64::ORRv8i8:
6914 case AArch64::ORRv16i8:
6915 case AArch64::EORv8i8:
6916 case AArch64::EORv16i8:
6918 case AArch64::ADD_ZZZ_B:
6919 case AArch64::ADD_ZZZ_H:
6920 case AArch64::ADD_ZZZ_S:
6921 case AArch64::ADD_ZZZ_D:
6922 case AArch64::MUL_ZZZ_B:
6923 case AArch64::MUL_ZZZ_H:
6924 case AArch64::MUL_ZZZ_S:
6925 case AArch64::MUL_ZZZ_D:
6926 case AArch64::AND_ZZZ:
6927 case AArch64::ORR_ZZZ:
6928 case AArch64::EOR_ZZZ:
6959 auto setFound = [&](
int Opcode,
int Operand,
unsigned ZeroReg,
6967 auto setVFound = [&](
int Opcode,
int Operand,
unsigned Pattern) {
6979 case AArch64::ADDWrr:
6981 "ADDWrr does not have register operands");
6982 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULADDW_OP1);
6983 setFound(AArch64::MADDWrrr, 2, AArch64::WZR, MCP::MULADDW_OP2);
6985 case AArch64::ADDXrr:
6986 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULADDX_OP1);
6987 setFound(AArch64::MADDXrrr, 2, AArch64::XZR, MCP::MULADDX_OP2);
6989 case AArch64::SUBWrr:
6990 setFound(AArch64::MADDWrrr, 2, AArch64::WZR, MCP::MULSUBW_OP2);
6991 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULSUBW_OP1);
6993 case AArch64::SUBXrr:
6994 setFound(AArch64::MADDXrrr, 2, AArch64::XZR, MCP::MULSUBX_OP2);
6995 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULSUBX_OP1);
6997 case AArch64::ADDWri:
6998 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULADDWI_OP1);
7000 case AArch64::ADDXri:
7001 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULADDXI_OP1);
7003 case AArch64::SUBWri:
7004 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULSUBWI_OP1);
7006 case AArch64::SUBXri:
7007 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULSUBXI_OP1);
7009 case AArch64::ADDv8i8:
7010 setVFound(AArch64::MULv8i8, 1, MCP::MULADDv8i8_OP1);
7011 setVFound(AArch64::MULv8i8, 2, MCP::MULADDv8i8_OP2);
7013 case AArch64::ADDv16i8:
7014 setVFound(AArch64::MULv16i8, 1, MCP::MULADDv16i8_OP1);
7015 setVFound(AArch64::MULv16i8, 2, MCP::MULADDv16i8_OP2);
7017 case AArch64::ADDv4i16:
7018 setVFound(AArch64::MULv4i16, 1, MCP::MULADDv4i16_OP1);
7019 setVFound(AArch64::MULv4i16, 2, MCP::MULADDv4i16_OP2);
7020 setVFound(AArch64::MULv4i16_indexed, 1, MCP::MULADDv4i16_indexed_OP1);
7021 setVFound(AArch64::MULv4i16_indexed, 2, MCP::MULADDv4i16_indexed_OP2);
7023 case AArch64::ADDv8i16:
7024 setVFound(AArch64::MULv8i16, 1, MCP::MULADDv8i16_OP1);
7025 setVFound(AArch64::MULv8i16, 2, MCP::MULADDv8i16_OP2);
7026 setVFound(AArch64::MULv8i16_indexed, 1, MCP::MULADDv8i16_indexed_OP1);
7027 setVFound(AArch64::MULv8i16_indexed, 2, MCP::MULADDv8i16_indexed_OP2);
7029 case AArch64::ADDv2i32:
7030 setVFound(AArch64::MULv2i32, 1, MCP::MULADDv2i32_OP1);
7031 setVFound(AArch64::MULv2i32, 2, MCP::MULADDv2i32_OP2);
7032 setVFound(AArch64::MULv2i32_indexed, 1, MCP::MULADDv2i32_indexed_OP1);
7033 setVFound(AArch64::MULv2i32_indexed, 2, MCP::MULADDv2i32_indexed_OP2);
7035 case AArch64::ADDv4i32:
7036 setVFound(AArch64::MULv4i32, 1, MCP::MULADDv4i32_OP1);
7037 setVFound(AArch64::MULv4i32, 2, MCP::MULADDv4i32_OP2);
7038 setVFound(AArch64::MULv4i32_indexed, 1, MCP::MULADDv4i32_indexed_OP1);
7039 setVFound(AArch64::MULv4i32_indexed, 2, MCP::MULADDv4i32_indexed_OP2);
7041 case AArch64::SUBv8i8:
7042 setVFound(AArch64::MULv8i8, 1, MCP::MULSUBv8i8_OP1);
7043 setVFound(AArch64::MULv8i8, 2, MCP::MULSUBv8i8_OP2);
7045 case AArch64::SUBv16i8:
7046 setVFound(AArch64::MULv16i8, 1, MCP::MULSUBv16i8_OP1);
7047 setVFound(AArch64::MULv16i8, 2, MCP::MULSUBv16i8_OP2);
7049 case AArch64::SUBv4i16:
7050 setVFound(AArch64::MULv4i16, 1, MCP::MULSUBv4i16_OP1);
7051 setVFound(AArch64::MULv4i16, 2, MCP::MULSUBv4i16_OP2);
7052 setVFound(AArch64::MULv4i16_indexed, 1, MCP::MULSUBv4i16_indexed_OP1);
7053 setVFound(AArch64::MULv4i16_indexed, 2, MCP::MULSUBv4i16_indexed_OP2);
7055 case AArch64::SUBv8i16:
7056 setVFound(AArch64::MULv8i16, 1, MCP::MULSUBv8i16_OP1);
7057 setVFound(AArch64::MULv8i16, 2, MCP::MULSUBv8i16_OP2);
7058 setVFound(AArch64::MULv8i16_indexed, 1, MCP::MULSUBv8i16_indexed_OP1);
7059 setVFound(AArch64::MULv8i16_indexed, 2, MCP::MULSUBv8i16_indexed_OP2);
7061 case AArch64::SUBv2i32:
7062 setVFound(AArch64::MULv2i32, 1, MCP::MULSUBv2i32_OP1);
7063 setVFound(AArch64::MULv2i32, 2, MCP::MULSUBv2i32_OP2);
7064 setVFound(AArch64::MULv2i32_indexed, 1, MCP::MULSUBv2i32_indexed_OP1);
7065 setVFound(AArch64::MULv2i32_indexed, 2, MCP::MULSUBv2i32_indexed_OP2);
7067 case AArch64::SUBv4i32:
7068 setVFound(AArch64::MULv4i32, 1, MCP::MULSUBv4i32_OP1);
7069 setVFound(AArch64::MULv4i32, 2, MCP::MULSUBv4i32_OP2);
7070 setVFound(AArch64::MULv4i32_indexed, 1, MCP::MULSUBv4i32_indexed_OP1);
7071 setVFound(AArch64::MULv4i32_indexed, 2, MCP::MULSUBv4i32_indexed_OP2);
7077bool AArch64InstrInfo::isAccumulationOpcode(
unsigned Opcode)
const {
7081 case AArch64::UABALB_ZZZ_D:
7082 case AArch64::UABALB_ZZZ_H:
7083 case AArch64::UABALB_ZZZ_S:
7084 case AArch64::UABALT_ZZZ_D:
7085 case AArch64::UABALT_ZZZ_H:
7086 case AArch64::UABALT_ZZZ_S:
7087 case AArch64::SABALB_ZZZ_D:
7088 case AArch64::SABALB_ZZZ_S:
7089 case AArch64::SABALB_ZZZ_H:
7090 case AArch64::SABALT_ZZZ_D:
7091 case AArch64::SABALT_ZZZ_S:
7092 case AArch64::SABALT_ZZZ_H:
7093 case AArch64::UABALv16i8_v8i16:
7094 case AArch64::UABALv2i32_v2i64:
7095 case AArch64::UABALv4i16_v4i32:
7096 case AArch64::UABALv4i32_v2i64:
7097 case AArch64::UABALv8i16_v4i32:
7098 case AArch64::UABALv8i8_v8i16:
7099 case AArch64::UABAv16i8:
7100 case AArch64::UABAv2i32:
7101 case AArch64::UABAv4i16:
7102 case AArch64::UABAv4i32:
7103 case AArch64::UABAv8i16:
7104 case AArch64::UABAv8i8:
7105 case AArch64::SABALv16i8_v8i16:
7106 case AArch64::SABALv2i32_v2i64:
7107 case AArch64::SABALv4i16_v4i32:
7108 case AArch64::SABALv4i32_v2i64:
7109 case AArch64::SABALv8i16_v4i32:
7110 case AArch64::SABALv8i8_v8i16:
7111 case AArch64::SABAv16i8:
7112 case AArch64::SABAv2i32:
7113 case AArch64::SABAv4i16:
7114 case AArch64::SABAv4i32:
7115 case AArch64::SABAv8i16:
7116 case AArch64::SABAv8i8:
7123unsigned AArch64InstrInfo::getAccumulationStartOpcode(
7124 unsigned AccumulationOpcode)
const {
7125 switch (AccumulationOpcode) {
7128 case AArch64::UABALB_ZZZ_D:
7129 return AArch64::UABDLB_ZZZ_D;
7130 case AArch64::UABALB_ZZZ_H:
7131 return AArch64::UABDLB_ZZZ_H;
7132 case AArch64::UABALB_ZZZ_S:
7133 return AArch64::UABDLB_ZZZ_S;
7134 case AArch64::UABALT_ZZZ_D:
7135 return AArch64::UABDLT_ZZZ_D;
7136 case AArch64::UABALT_ZZZ_H:
7137 return AArch64::UABDLT_ZZZ_H;
7138 case AArch64::UABALT_ZZZ_S:
7139 return AArch64::UABDLT_ZZZ_S;
7140 case AArch64::UABALv16i8_v8i16:
7141 return AArch64::UABDLv16i8_v8i16;
7142 case AArch64::UABALv2i32_v2i64:
7143 return AArch64::UABDLv2i32_v2i64;
7144 case AArch64::UABALv4i16_v4i32:
7145 return AArch64::UABDLv4i16_v4i32;
7146 case AArch64::UABALv4i32_v2i64:
7147 return AArch64::UABDLv4i32_v2i64;
7148 case AArch64::UABALv8i16_v4i32:
7149 return AArch64::UABDLv8i16_v4i32;
7150 case AArch64::UABALv8i8_v8i16:
7151 return AArch64::UABDLv8i8_v8i16;
7152 case AArch64::UABAv16i8:
7153 return AArch64::UABDv16i8;
7154 case AArch64::UABAv2i32:
7155 return AArch64::UABDv2i32;
7156 case AArch64::UABAv4i16:
7157 return AArch64::UABDv4i16;
7158 case AArch64::UABAv4i32:
7159 return AArch64::UABDv4i32;
7160 case AArch64::UABAv8i16:
7161 return AArch64::UABDv8i16;
7162 case AArch64::UABAv8i8:
7163 return AArch64::UABDv8i8;
7164 case AArch64::SABALB_ZZZ_D:
7165 return AArch64::SABDLB_ZZZ_D;
7166 case AArch64::SABALB_ZZZ_S:
7167 return AArch64::SABDLB_ZZZ_S;
7168 case AArch64::SABALB_ZZZ_H:
7169 return AArch64::SABDLB_ZZZ_H;
7170 case AArch64::SABALT_ZZZ_D:
7171 return AArch64::SABDLT_ZZZ_D;
7172 case AArch64::SABALT_ZZZ_S:
7173 return AArch64::SABDLT_ZZZ_S;
7174 case AArch64::SABALT_ZZZ_H:
7175 return AArch64::SABDLT_ZZZ_H;
7176 case AArch64::SABALv16i8_v8i16:
7177 return AArch64::SABDLv16i8_v8i16;
7178 case AArch64::SABALv2i32_v2i64:
7179 return AArch64::SABDLv2i32_v2i64;
7180 case AArch64::SABALv4i16_v4i32:
7181 return AArch64::SABDLv4i16_v4i32;
7182 case AArch64::SABALv4i32_v2i64:
7183 return AArch64::SABDLv4i32_v2i64;
7184 case AArch64::SABALv8i16_v4i32:
7185 return AArch64::SABDLv8i16_v4i32;
7186 case AArch64::SABALv8i8_v8i16:
7187 return AArch64::SABDLv8i8_v8i16;
7188 case AArch64::SABAv16i8:
7189 return AArch64::SABDv16i8;
7190 case AArch64::SABAv2i32:
7191 return AArch64::SABAv2i32;
7192 case AArch64::SABAv4i16:
7193 return AArch64::SABDv4i16;
7194 case AArch64::SABAv4i32:
7195 return AArch64::SABDv4i32;
7196 case AArch64::SABAv8i16:
7197 return AArch64::SABDv8i16;
7198 case AArch64::SABAv8i8:
7199 return AArch64::SABDv8i8;
7215 auto Match = [&](
int Opcode,
int Operand,
unsigned Pattern) ->
bool {
7227 assert(
false &&
"Unsupported FP instruction in combiner\n");
7229 case AArch64::FADDHrr:
7231 "FADDHrr does not have register operands");
7233 Found = Match(AArch64::FMULHrr, 1, MCP::FMULADDH_OP1);
7234 Found |= Match(AArch64::FMULHrr, 2, MCP::FMULADDH_OP2);
7236 case AArch64::FADDSrr:
7238 "FADDSrr does not have register operands");
7240 Found |= Match(AArch64::FMULSrr, 1, MCP::FMULADDS_OP1) ||
7241 Match(AArch64::FMULv1i32_indexed, 1, MCP::FMLAv1i32_indexed_OP1);
7243 Found |= Match(AArch64::FMULSrr, 2, MCP::FMULADDS_OP2) ||
7244 Match(AArch64::FMULv1i32_indexed, 2, MCP::FMLAv1i32_indexed_OP2);
7246 case AArch64::FADDDrr:
7247 Found |= Match(AArch64::FMULDrr, 1, MCP::FMULADDD_OP1) ||
7248 Match(AArch64::FMULv1i64_indexed, 1, MCP::FMLAv1i64_indexed_OP1);
7250 Found |= Match(AArch64::FMULDrr, 2, MCP::FMULADDD_OP2) ||
7251 Match(AArch64::FMULv1i64_indexed, 2, MCP::FMLAv1i64_indexed_OP2);
7253 case AArch64::FADDv4f16:
7254 Found |= Match(AArch64::FMULv4i16_indexed, 1, MCP::FMLAv4i16_indexed_OP1) ||
7255 Match(AArch64::FMULv4f16, 1, MCP::FMLAv4f16_OP1);
7257 Found |= Match(AArch64::FMULv4i16_indexed, 2, MCP::FMLAv4i16_indexed_OP2) ||
7258 Match(AArch64::FMULv4f16, 2, MCP::FMLAv4f16_OP2);
7260 case AArch64::FADDv8f16:
7261 Found |= Match(AArch64::FMULv8i16_indexed, 1, MCP::FMLAv8i16_indexed_OP1) ||
7262 Match(AArch64::FMULv8f16, 1, MCP::FMLAv8f16_OP1);
7264 Found |= Match(AArch64::FMULv8i16_indexed, 2, MCP::FMLAv8i16_indexed_OP2) ||
7265 Match(AArch64::FMULv8f16, 2, MCP::FMLAv8f16_OP2);
7267 case AArch64::FADDv2f32:
7268 Found |= Match(AArch64::FMULv2i32_indexed, 1, MCP::FMLAv2i32_indexed_OP1) ||
7269 Match(AArch64::FMULv2f32, 1, MCP::FMLAv2f32_OP1);
7271 Found |= Match(AArch64::FMULv2i32_indexed, 2, MCP::FMLAv2i32_indexed_OP2) ||
7272 Match(AArch64::FMULv2f32, 2, MCP::FMLAv2f32_OP2);
7274 case AArch64::FADDv2f64:
7275 Found |= Match(AArch64::FMULv2i64_indexed, 1, MCP::FMLAv2i64_indexed_OP1) ||
7276 Match(AArch64::FMULv2f64, 1, MCP::FMLAv2f64_OP1);
7278 Found |= Match(AArch64::FMULv2i64_indexed, 2, MCP::FMLAv2i64_indexed_OP2) ||
7279 Match(AArch64::FMULv2f64, 2, MCP::FMLAv2f64_OP2);
7281 case AArch64::FADDv4f32:
7282 Found |= Match(AArch64::FMULv4i32_indexed, 1, MCP::FMLAv4i32_indexed_OP1) ||
7283 Match(AArch64::FMULv4f32, 1, MCP::FMLAv4f32_OP1);
7285 Found |= Match(AArch64::FMULv4i32_indexed, 2, MCP::FMLAv4i32_indexed_OP2) ||
7286 Match(AArch64::FMULv4f32, 2, MCP::FMLAv4f32_OP2);
7288 case AArch64::FSUBHrr:
7289 Found = Match(AArch64::FMULHrr, 1, MCP::FMULSUBH_OP1);
7290 Found |= Match(AArch64::FMULHrr, 2, MCP::FMULSUBH_OP2);
7291 Found |= Match(AArch64::FNMULHrr, 1, MCP::FNMULSUBH_OP1);
7293 case AArch64::FSUBSrr:
7294 Found = Match(AArch64::FMULSrr, 1, MCP::FMULSUBS_OP1);
7296 Found |= Match(AArch64::FMULSrr, 2, MCP::FMULSUBS_OP2) ||
7297 Match(AArch64::FMULv1i32_indexed, 2, MCP::FMLSv1i32_indexed_OP2);
7299 Found |= Match(AArch64::FNMULSrr, 1, MCP::FNMULSUBS_OP1);
7301 case AArch64::FSUBDrr:
7302 Found = Match(AArch64::FMULDrr, 1, MCP::FMULSUBD_OP1);
7304 Found |= Match(AArch64::FMULDrr, 2, MCP::FMULSUBD_OP2) ||
7305 Match(AArch64::FMULv1i64_indexed, 2, MCP::FMLSv1i64_indexed_OP2);
7307 Found |= Match(AArch64::FNMULDrr, 1, MCP::FNMULSUBD_OP1);
7309 case AArch64::FSUBv4f16:
7310 Found |= Match(AArch64::FMULv4i16_indexed, 2, MCP::FMLSv4i16_indexed_OP2) ||
7311 Match(AArch64::FMULv4f16, 2, MCP::FMLSv4f16_OP2);
7313 Found |= Match(AArch64::FMULv4i16_indexed, 1, MCP::FMLSv4i16_indexed_OP1) ||
7314 Match(AArch64::FMULv4f16, 1, MCP::FMLSv4f16_OP1);
7316 case AArch64::FSUBv8f16:
7317 Found |= Match(AArch64::FMULv8i16_indexed, 2, MCP::FMLSv8i16_indexed_OP2) ||
7318 Match(AArch64::FMULv8f16, 2, MCP::FMLSv8f16_OP2);
7320 Found |= Match(AArch64::FMULv8i16_indexed, 1, MCP::FMLSv8i16_indexed_OP1) ||
7321 Match(AArch64::FMULv8f16, 1, MCP::FMLSv8f16_OP1);
7323 case AArch64::FSUBv2f32:
7324 Found |= Match(AArch64::FMULv2i32_indexed, 2, MCP::FMLSv2i32_indexed_OP2) ||
7325 Match(AArch64::FMULv2f32, 2, MCP::FMLSv2f32_OP2);
7327 Found |= Match(AArch64::FMULv2i32_indexed, 1, MCP::FMLSv2i32_indexed_OP1) ||
7328 Match(AArch64::FMULv2f32, 1, MCP::FMLSv2f32_OP1);
7330 case AArch64::FSUBv2f64:
7331 Found |= Match(AArch64::FMULv2i64_indexed, 2, MCP::FMLSv2i64_indexed_OP2) ||
7332 Match(AArch64::FMULv2f64, 2, MCP::FMLSv2f64_OP2);
7334 Found |= Match(AArch64::FMULv2i64_indexed, 1, MCP::FMLSv2i64_indexed_OP1) ||
7335 Match(AArch64::FMULv2f64, 1, MCP::FMLSv2f64_OP1);
7337 case AArch64::FSUBv4f32:
7338 Found |= Match(AArch64::FMULv4i32_indexed, 2, MCP::FMLSv4i32_indexed_OP2) ||
7339 Match(AArch64::FMULv4f32, 2, MCP::FMLSv4f32_OP2);
7341 Found |= Match(AArch64::FMULv4i32_indexed, 1, MCP::FMLSv4i32_indexed_OP1) ||
7342 Match(AArch64::FMULv4f32, 1, MCP::FMLSv4f32_OP1);
7353 auto Match = [&](
unsigned Opcode,
int Operand,
unsigned Pattern) ->
bool {
7360 if (
MI &&
MI->getOpcode() == TargetOpcode::COPY &&
7361 MI->getOperand(1).getReg().isVirtual())
7362 MI =
MRI.getUniqueVRegDef(
MI->getOperand(1).getReg());
7363 if (
MI &&
MI->getOpcode() == Opcode) {
7375 case AArch64::FMULv2f32:
7376 Found = Match(AArch64::DUPv2i32lane, 1, MCP::FMULv2i32_indexed_OP1);
7377 Found |= Match(AArch64::DUPv2i32lane, 2, MCP::FMULv2i32_indexed_OP2);
7379 case AArch64::FMULv2f64:
7380 Found = Match(AArch64::DUPv2i64lane, 1, MCP::FMULv2i64_indexed_OP1);
7381 Found |= Match(AArch64::DUPv2i64lane, 2, MCP::FMULv2i64_indexed_OP2);
7383 case AArch64::FMULv4f16:
7384 Found = Match(AArch64::DUPv4i16lane, 1, MCP::FMULv4i16_indexed_OP1);
7385 Found |= Match(AArch64::DUPv4i16lane, 2, MCP::FMULv4i16_indexed_OP2);
7387 case AArch64::FMULv4f32:
7388 Found = Match(AArch64::DUPv4i32lane, 1, MCP::FMULv4i32_indexed_OP1);
7389 Found |= Match(AArch64::DUPv4i32lane, 2, MCP::FMULv4i32_indexed_OP2);
7391 case AArch64::FMULv8f16:
7392 Found = Match(AArch64::DUPv8i16lane, 1, MCP::FMULv8i16_indexed_OP1);
7393 Found |= Match(AArch64::DUPv8i16lane, 2, MCP::FMULv8i16_indexed_OP2);
7406 auto Match = [&](
unsigned Opcode,
unsigned Pattern) ->
bool {
7409 if (
MI !=
nullptr && (
MI->getOpcode() == Opcode) &&
7410 MRI.hasOneNonDBGUse(
MI->getOperand(0).getReg()) &&
7424 case AArch64::FNEGDr:
7426 case AArch64::FNEGSr:
7558 case AArch64::SUBWrr:
7559 case AArch64::SUBSWrr:
7560 case AArch64::SUBXrr:
7561 case AArch64::SUBSXrr:
7606 unsigned LoadLaneOpCode,
unsigned NumLanes) {
7629 while (!RemainingLanes.
empty() && CurrInstr &&
7630 CurrInstr->getOpcode() == LoadLaneOpCode &&
7631 MRI.hasOneNonDBGUse(CurrInstr->getOperand(0).getReg()) &&
7632 CurrInstr->getNumOperands() == 4) {
7633 RemainingLanes.
erase(CurrInstr->getOperand(2).getImm());
7635 CurrInstr =
MRI.getUniqueVRegDef(CurrInstr->getOperand(1).getReg());
7639 if (!RemainingLanes.
empty())
7643 if (CurrInstr->getOpcode() != TargetOpcode::SUBREG_TO_REG)
7647 auto Lane0LoadReg = CurrInstr->getOperand(2).getReg();
7648 unsigned SingleLaneSizeInBits = 128 / NumLanes;
7649 if (
TRI->getRegSizeInBits(Lane0LoadReg,
MRI) != SingleLaneSizeInBits)
7653 if (!
MRI.hasOneNonDBGUse(Lane0LoadReg))
7656 LoadInstrs.
push_back(
MRI.getUniqueVRegDef(Lane0LoadReg));
7665 RemainingLoadInstrs.
insert(LoadInstrs.
begin(), LoadInstrs.
end());
7668 for (; MBBItr !=
MBB->begin() && RemainingSteps > 0 &&
7669 !RemainingLoadInstrs.
empty();
7670 --MBBItr, --RemainingSteps) {
7674 RemainingLoadInstrs.
erase(&CurrInstr);
7684 if (RemainingSteps == 0 && !RemainingLoadInstrs.
empty())
7710 case AArch64::LD1i32:
7712 case AArch64::LD1i16:
7714 case AArch64::LD1i8:
7730 unsigned Pattern,
unsigned NumLanes) {
7738 for (
unsigned i = 0; i < NumLanes - 1; ++i) {
7746 return A->getOperand(2).getImm() >
B->getOperand(2).getImm();
7751 MRI.getUniqueVRegDef(SubregToReg->getOperand(2).getReg()));
7752 auto LoadToLaneInstrsAscending =
llvm::reverse(LoadToLaneInstrs);
7758 auto CreateLD1Instruction = [&](
MachineInstr *OriginalInstr,
7759 Register SrcRegister,
unsigned Lane,
7761 bool OffsetRegisterKillState) {
7762 auto NewRegister =
MRI.createVirtualRegister(FPR128RegClass);
7769 InstrIdxForVirtReg.
insert(std::make_pair(NewRegister, InsInstrs.
size()));
7770 InsInstrs.
push_back(LoadIndexIntoRegister);
7776 auto CreateLDRInstruction = [&](
unsigned NumLanes,
Register DestReg,
7782 Opcode = AArch64::LDRSui;
7785 Opcode = AArch64::LDRHui;
7788 Opcode = AArch64::LDRBui;
7792 "Got unsupported number of lanes in machine-combiner gather pattern");
7801 auto LanesToLoadToReg0 =
7803 LoadToLaneInstrsAscending.begin() + NumLanes / 2);
7804 Register PrevReg = SubregToReg->getOperand(0).getReg();
7806 const MachineOperand &OffsetRegOperand = LoadInstr->getOperand(3);
7807 PrevReg = CreateLD1Instruction(LoadInstr, PrevReg, Index + 1,
7808 OffsetRegOperand.
getReg(),
7809 OffsetRegOperand.
isKill());
7816 MachineInstr *Lane0Load = *LoadToLaneInstrsAscending.begin();
7818 *std::next(LoadToLaneInstrsAscending.begin(), NumLanes / 2);
7819 Register DestRegForMiddleIndex =
MRI.createVirtualRegister(
7825 CreateLDRInstruction(NumLanes, DestRegForMiddleIndex,
7826 OriginalSplitToLoadOffsetOperand.
getReg(),
7827 OriginalSplitToLoadOffsetOperand.
isKill());
7829 InstrIdxForVirtReg.
insert(
7830 std::make_pair(DestRegForMiddleIndex, InsInstrs.
size()));
7831 InsInstrs.
push_back(MiddleIndexLoadInstr);
7835 Register DestRegForSubregToReg =
MRI.createVirtualRegister(FPR128RegClass);
7836 unsigned SubregType;
7839 SubregType = AArch64::ssub;
7842 SubregType = AArch64::hsub;
7845 SubregType = AArch64::bsub;
7849 "Got invalid NumLanes for machine-combiner gather pattern");
7852 auto SubRegToRegInstr =
7854 DestRegForSubregToReg)
7858 InstrIdxForVirtReg.
insert(
7859 std::make_pair(DestRegForSubregToReg, InsInstrs.
size()));
7863 auto LanesToLoadToReg1 =
7865 LoadToLaneInstrsAscending.end());
7866 PrevReg = SubRegToRegInstr->getOperand(0).getReg();
7868 const MachineOperand &OffsetRegOperand = LoadInstr->getOperand(3);
7869 PrevReg = CreateLD1Instruction(LoadInstr, PrevReg, Index + 1,
7870 OffsetRegOperand.
getReg(),
7871 OffsetRegOperand.
isKill());
7874 if (Index == NumLanes / 2 - 2) {
7909bool AArch64InstrInfo::getMachineCombinerPatterns(
7911 bool DoRegPressureReduce)
const {
7932 DoRegPressureReduce);
7961 const Register *ReplacedAddend =
nullptr) {
7962 assert(IdxMulOpd == 1 || IdxMulOpd == 2);
7964 unsigned IdxOtherOpd = IdxMulOpd == 1 ? 2 : 1;
7967 Register SrcReg0 = MUL->getOperand(1).getReg();
7968 bool Src0IsKill = MUL->getOperand(1).isKill();
7969 Register SrcReg1 = MUL->getOperand(2).getReg();
7970 bool Src1IsKill = MUL->getOperand(2).isKill();
7974 if (ReplacedAddend) {
7976 SrcReg2 = *ReplacedAddend;
7984 MRI.constrainRegClass(ResultReg, RC);
7986 MRI.constrainRegClass(SrcReg0, RC);
7988 MRI.constrainRegClass(SrcReg1, RC);
7990 MRI.constrainRegClass(SrcReg2, RC);
8003 .
addImm(MUL->getOperand(3).getImm());
8010 assert(
false &&
"Invalid FMA instruction kind \n");
8024 if (AArch64::FPR32RegClass.hasSubClassEq(RC))
8025 Opc = AArch64::FNMADDSrrr;
8026 else if (AArch64::FPR64RegClass.hasSubClassEq(RC))
8027 Opc = AArch64::FNMADDDrrr;
8039 MRI.constrainRegClass(ResultReg, RC);
8041 MRI.constrainRegClass(SrcReg0, RC);
8043 MRI.constrainRegClass(SrcReg1, RC);
8045 MRI.constrainRegClass(SrcReg2, RC);
8061 unsigned IdxDupOp,
unsigned MulOpc,
8063 assert(((IdxDupOp == 1) || (IdxDupOp == 2)) &&
8064 "Invalid index of FMUL operand");
8072 if (Dup->
getOpcode() == TargetOpcode::COPY)
8076 MRI.clearKillFlags(DupSrcReg);
8077 MRI.constrainRegClass(DupSrcReg, RC);
8081 unsigned IdxMulOp = IdxDupOp == 1 ? 2 : 1;
8122 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
8137 genNeg(MF,
MRI,
TII, Root, InsInstrs, InstrIdxForVirtReg, MnegOpc, RC);
8164 genNeg(MF,
MRI,
TII, Root, InsInstrs, InstrIdxForVirtReg, MnegOpc, RC);
8192 unsigned IdxMulOpd,
unsigned MaddOpc,
unsigned VR,
8194 assert(IdxMulOpd == 1 || IdxMulOpd == 2);
8198 Register SrcReg0 = MUL->getOperand(1).getReg();
8199 bool Src0IsKill = MUL->getOperand(1).isKill();
8200 Register SrcReg1 = MUL->getOperand(2).getReg();
8201 bool Src1IsKill = MUL->getOperand(2).isKill();
8204 MRI.constrainRegClass(ResultReg, RC);
8206 MRI.constrainRegClass(SrcReg0, RC);
8208 MRI.constrainRegClass(SrcReg1, RC);
8210 MRI.constrainRegClass(VR, RC);
8231 assert(IdxOpd1 == 1 || IdxOpd1 == 2);
8232 unsigned IdxOtherOpd = IdxOpd1 == 1 ? 2 : 1;
8246 if (Opcode == AArch64::SUBSWrr)
8247 Opcode = AArch64::SUBWrr;
8248 else if (Opcode == AArch64::SUBSXrr)
8249 Opcode = AArch64::SUBXrr;
8251 assert((Opcode == AArch64::SUBWrr || Opcode == AArch64::SUBXrr) &&
8252 "Unexpected instruction opcode.");
8269 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
8276unsigned AArch64InstrInfo::getReduceOpcodeForAccumulator(
8277 unsigned int AccumulatorOpCode)
const {
8278 switch (AccumulatorOpCode) {
8279 case AArch64::UABALB_ZZZ_D:
8280 case AArch64::SABALB_ZZZ_D:
8281 case AArch64::UABALT_ZZZ_D:
8282 case AArch64::SABALT_ZZZ_D:
8283 return AArch64::ADD_ZZZ_D;
8284 case AArch64::UABALB_ZZZ_H:
8285 case AArch64::SABALB_ZZZ_H:
8286 case AArch64::UABALT_ZZZ_H:
8287 case AArch64::SABALT_ZZZ_H:
8288 return AArch64::ADD_ZZZ_H;
8289 case AArch64::UABALB_ZZZ_S:
8290 case AArch64::SABALB_ZZZ_S:
8291 case AArch64::UABALT_ZZZ_S:
8292 case AArch64::SABALT_ZZZ_S:
8293 return AArch64::ADD_ZZZ_S;
8294 case AArch64::UABALv16i8_v8i16:
8295 case AArch64::SABALv8i8_v8i16:
8296 case AArch64::SABAv8i16:
8297 case AArch64::UABAv8i16:
8298 return AArch64::ADDv8i16;
8299 case AArch64::SABALv2i32_v2i64:
8300 case AArch64::UABALv2i32_v2i64:
8301 case AArch64::SABALv4i32_v2i64:
8302 return AArch64::ADDv2i64;
8303 case AArch64::UABALv4i16_v4i32:
8304 case AArch64::SABALv4i16_v4i32:
8305 case AArch64::SABALv8i16_v4i32:
8306 case AArch64::SABAv4i32:
8307 case AArch64::UABAv4i32:
8308 return AArch64::ADDv4i32;
8309 case AArch64::UABALv4i32_v2i64:
8310 return AArch64::ADDv2i64;
8311 case AArch64::UABALv8i16_v4i32:
8312 return AArch64::ADDv4i32;
8313 case AArch64::UABALv8i8_v8i16:
8314 case AArch64::SABALv16i8_v8i16:
8315 return AArch64::ADDv8i16;
8316 case AArch64::UABAv16i8:
8317 case AArch64::SABAv16i8:
8318 return AArch64::ADDv16i8;
8319 case AArch64::UABAv4i16:
8320 case AArch64::SABAv4i16:
8321 return AArch64::ADDv4i16;
8322 case AArch64::UABAv2i32:
8323 case AArch64::SABAv2i32:
8324 return AArch64::ADDv2i32;
8325 case AArch64::UABAv8i8:
8326 case AArch64::SABAv8i8:
8327 return AArch64::ADDv8i8;
8336void AArch64InstrInfo::genAlternativeCodeSequence(
8346 MachineInstr *
MUL =
nullptr;
8347 const TargetRegisterClass *RC;
8353 DelInstrs, InstrIdxForVirtReg);
8359 InstrIdxForVirtReg);
8365 InstrIdxForVirtReg);
8374 Opc = AArch64::MADDWrrr;
8375 RC = &AArch64::GPR32RegClass;
8377 Opc = AArch64::MADDXrrr;
8378 RC = &AArch64::GPR64RegClass;
8389 Opc = AArch64::MADDWrrr;
8390 RC = &AArch64::GPR32RegClass;
8392 Opc = AArch64::MADDXrrr;
8393 RC = &AArch64::GPR64RegClass;
8406 const TargetRegisterClass *RC;
8407 unsigned BitSize, MovImm;
8410 MovImm = AArch64::MOVi32imm;
8411 RC = &AArch64::GPR32spRegClass;
8413 Opc = AArch64::MADDWrrr;
8414 RC = &AArch64::GPR32RegClass;
8416 MovImm = AArch64::MOVi64imm;
8417 RC = &AArch64::GPR64spRegClass;
8419 Opc = AArch64::MADDXrrr;
8420 RC = &AArch64::GPR64RegClass;
8431 uint64_t UImm =
SignExtend64(IsSub ? -Imm : Imm, BitSize);
8435 if (Insn.
size() != 1)
8437 MachineInstrBuilder MIB1 =
8438 BuildMI(MF, MIMetadata(Root),
TII->get(MovImm), NewVR)
8439 .
addImm(IsSub ? -Imm : Imm);
8441 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
8452 const TargetRegisterClass *SubRC;
8453 unsigned SubOpc, ZeroReg;
8455 SubOpc = AArch64::SUBWrr;
8456 SubRC = &AArch64::GPR32spRegClass;
8457 ZeroReg = AArch64::WZR;
8458 Opc = AArch64::MADDWrrr;
8459 RC = &AArch64::GPR32RegClass;
8461 SubOpc = AArch64::SUBXrr;
8462 SubRC = &AArch64::GPR64spRegClass;
8463 ZeroReg = AArch64::XZR;
8464 Opc = AArch64::MADDXrrr;
8465 RC = &AArch64::GPR64RegClass;
8467 Register NewVR =
MRI.createVirtualRegister(SubRC);
8469 MachineInstrBuilder MIB1 =
8470 BuildMI(MF, MIMetadata(Root),
TII->get(SubOpc), NewVR)
8474 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
8485 Opc = AArch64::MSUBWrrr;
8486 RC = &AArch64::GPR32RegClass;
8488 Opc = AArch64::MSUBXrrr;
8489 RC = &AArch64::GPR64RegClass;
8494 Opc = AArch64::MLAv8i8;
8495 RC = &AArch64::FPR64RegClass;
8499 Opc = AArch64::MLAv8i8;
8500 RC = &AArch64::FPR64RegClass;
8504 Opc = AArch64::MLAv16i8;
8505 RC = &AArch64::FPR128RegClass;
8509 Opc = AArch64::MLAv16i8;
8510 RC = &AArch64::FPR128RegClass;
8514 Opc = AArch64::MLAv4i16;
8515 RC = &AArch64::FPR64RegClass;
8519 Opc = AArch64::MLAv4i16;
8520 RC = &AArch64::FPR64RegClass;
8524 Opc = AArch64::MLAv8i16;
8525 RC = &AArch64::FPR128RegClass;
8529 Opc = AArch64::MLAv8i16;
8530 RC = &AArch64::FPR128RegClass;
8534 Opc = AArch64::MLAv2i32;
8535 RC = &AArch64::FPR64RegClass;
8539 Opc = AArch64::MLAv2i32;
8540 RC = &AArch64::FPR64RegClass;
8544 Opc = AArch64::MLAv4i32;
8545 RC = &AArch64::FPR128RegClass;
8549 Opc = AArch64::MLAv4i32;
8550 RC = &AArch64::FPR128RegClass;
8555 Opc = AArch64::MLAv8i8;
8556 RC = &AArch64::FPR64RegClass;
8558 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv8i8,
8562 Opc = AArch64::MLSv8i8;
8563 RC = &AArch64::FPR64RegClass;
8567 Opc = AArch64::MLAv16i8;
8568 RC = &AArch64::FPR128RegClass;
8570 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv16i8,
8574 Opc = AArch64::MLSv16i8;
8575 RC = &AArch64::FPR128RegClass;
8579 Opc = AArch64::MLAv4i16;
8580 RC = &AArch64::FPR64RegClass;
8582 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv4i16,
8586 Opc = AArch64::MLSv4i16;
8587 RC = &AArch64::FPR64RegClass;
8591 Opc = AArch64::MLAv8i16;
8592 RC = &AArch64::FPR128RegClass;
8594 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv8i16,
8598 Opc = AArch64::MLSv8i16;
8599 RC = &AArch64::FPR128RegClass;
8603 Opc = AArch64::MLAv2i32;
8604 RC = &AArch64::FPR64RegClass;
8606 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv2i32,
8610 Opc = AArch64::MLSv2i32;
8611 RC = &AArch64::FPR64RegClass;
8615 Opc = AArch64::MLAv4i32;
8616 RC = &AArch64::FPR128RegClass;
8618 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv4i32,
8622 Opc = AArch64::MLSv4i32;
8623 RC = &AArch64::FPR128RegClass;
8628 Opc = AArch64::MLAv4i16_indexed;
8629 RC = &AArch64::FPR64RegClass;
8633 Opc = AArch64::MLAv4i16_indexed;
8634 RC = &AArch64::FPR64RegClass;
8638 Opc = AArch64::MLAv8i16_indexed;
8639 RC = &AArch64::FPR128RegClass;
8643 Opc = AArch64::MLAv8i16_indexed;
8644 RC = &AArch64::FPR128RegClass;
8648 Opc = AArch64::MLAv2i32_indexed;
8649 RC = &AArch64::FPR64RegClass;
8653 Opc = AArch64::MLAv2i32_indexed;
8654 RC = &AArch64::FPR64RegClass;
8658 Opc = AArch64::MLAv4i32_indexed;
8659 RC = &AArch64::FPR128RegClass;
8663 Opc = AArch64::MLAv4i32_indexed;
8664 RC = &AArch64::FPR128RegClass;
8669 Opc = AArch64::MLAv4i16_indexed;
8670 RC = &AArch64::FPR64RegClass;
8672 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv4i16,
8676 Opc = AArch64::MLSv4i16_indexed;
8677 RC = &AArch64::FPR64RegClass;
8681 Opc = AArch64::MLAv8i16_indexed;
8682 RC = &AArch64::FPR128RegClass;
8684 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv8i16,
8688 Opc = AArch64::MLSv8i16_indexed;
8689 RC = &AArch64::FPR128RegClass;
8693 Opc = AArch64::MLAv2i32_indexed;
8694 RC = &AArch64::FPR64RegClass;
8696 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv2i32,
8700 Opc = AArch64::MLSv2i32_indexed;
8701 RC = &AArch64::FPR64RegClass;
8705 Opc = AArch64::MLAv4i32_indexed;
8706 RC = &AArch64::FPR128RegClass;
8708 InstrIdxForVirtReg, 1,
Opc, AArch64::NEGv4i32,
8712 Opc = AArch64::MLSv4i32_indexed;
8713 RC = &AArch64::FPR128RegClass;
8719 Opc = AArch64::FMADDHrrr;
8720 RC = &AArch64::FPR16RegClass;
8724 Opc = AArch64::FMADDSrrr;
8725 RC = &AArch64::FPR32RegClass;
8729 Opc = AArch64::FMADDDrrr;
8730 RC = &AArch64::FPR64RegClass;
8735 Opc = AArch64::FMADDHrrr;
8736 RC = &AArch64::FPR16RegClass;
8740 Opc = AArch64::FMADDSrrr;
8741 RC = &AArch64::FPR32RegClass;
8745 Opc = AArch64::FMADDDrrr;
8746 RC = &AArch64::FPR64RegClass;
8751 Opc = AArch64::FMLAv1i32_indexed;
8752 RC = &AArch64::FPR32RegClass;
8757 Opc = AArch64::FMLAv1i32_indexed;
8758 RC = &AArch64::FPR32RegClass;
8764 Opc = AArch64::FMLAv1i64_indexed;
8765 RC = &AArch64::FPR64RegClass;
8770 Opc = AArch64::FMLAv1i64_indexed;
8771 RC = &AArch64::FPR64RegClass;
8777 RC = &AArch64::FPR64RegClass;
8778 Opc = AArch64::FMLAv4i16_indexed;
8783 RC = &AArch64::FPR64RegClass;
8784 Opc = AArch64::FMLAv4f16;
8789 RC = &AArch64::FPR64RegClass;
8790 Opc = AArch64::FMLAv4i16_indexed;
8795 RC = &AArch64::FPR64RegClass;
8796 Opc = AArch64::FMLAv4f16;
8803 RC = &AArch64::FPR64RegClass;
8805 Opc = AArch64::FMLAv2i32_indexed;
8809 Opc = AArch64::FMLAv2f32;
8816 RC = &AArch64::FPR64RegClass;
8818 Opc = AArch64::FMLAv2i32_indexed;
8822 Opc = AArch64::FMLAv2f32;
8829 RC = &AArch64::FPR128RegClass;
8830 Opc = AArch64::FMLAv8i16_indexed;
8835 RC = &AArch64::FPR128RegClass;
8836 Opc = AArch64::FMLAv8f16;
8841 RC = &AArch64::FPR128RegClass;
8842 Opc = AArch64::FMLAv8i16_indexed;
8847 RC = &AArch64::FPR128RegClass;
8848 Opc = AArch64::FMLAv8f16;
8855 RC = &AArch64::FPR128RegClass;
8857 Opc = AArch64::FMLAv2i64_indexed;
8861 Opc = AArch64::FMLAv2f64;
8868 RC = &AArch64::FPR128RegClass;
8870 Opc = AArch64::FMLAv2i64_indexed;
8874 Opc = AArch64::FMLAv2f64;
8882 RC = &AArch64::FPR128RegClass;
8884 Opc = AArch64::FMLAv4i32_indexed;
8888 Opc = AArch64::FMLAv4f32;
8896 RC = &AArch64::FPR128RegClass;
8898 Opc = AArch64::FMLAv4i32_indexed;
8902 Opc = AArch64::FMLAv4f32;
8909 Opc = AArch64::FNMSUBHrrr;
8910 RC = &AArch64::FPR16RegClass;
8914 Opc = AArch64::FNMSUBSrrr;
8915 RC = &AArch64::FPR32RegClass;
8919 Opc = AArch64::FNMSUBDrrr;
8920 RC = &AArch64::FPR64RegClass;
8925 Opc = AArch64::FNMADDHrrr;
8926 RC = &AArch64::FPR16RegClass;
8930 Opc = AArch64::FNMADDSrrr;
8931 RC = &AArch64::FPR32RegClass;
8935 Opc = AArch64::FNMADDDrrr;
8936 RC = &AArch64::FPR64RegClass;
8941 Opc = AArch64::FMSUBHrrr;
8942 RC = &AArch64::FPR16RegClass;
8946 Opc = AArch64::FMSUBSrrr;
8947 RC = &AArch64::FPR32RegClass;
8951 Opc = AArch64::FMSUBDrrr;
8952 RC = &AArch64::FPR64RegClass;
8957 Opc = AArch64::FMLSv1i32_indexed;
8958 RC = &AArch64::FPR32RegClass;
8964 Opc = AArch64::FMLSv1i64_indexed;
8965 RC = &AArch64::FPR64RegClass;
8972 RC = &AArch64::FPR64RegClass;
8974 MachineInstrBuilder MIB1 =
8975 BuildMI(MF, MIMetadata(Root),
TII->get(AArch64::FNEGv4f16), NewVR)
8978 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
8980 Opc = AArch64::FMLAv4f16;
8984 Opc = AArch64::FMLAv4i16_indexed;
8991 RC = &AArch64::FPR64RegClass;
8992 Opc = AArch64::FMLSv4f16;
8997 RC = &AArch64::FPR64RegClass;
8998 Opc = AArch64::FMLSv4i16_indexed;
9005 RC = &AArch64::FPR64RegClass;
9007 Opc = AArch64::FMLSv2i32_indexed;
9011 Opc = AArch64::FMLSv2f32;
9019 RC = &AArch64::FPR128RegClass;
9021 MachineInstrBuilder MIB1 =
9022 BuildMI(MF, MIMetadata(Root),
TII->get(AArch64::FNEGv8f16), NewVR)
9025 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
9027 Opc = AArch64::FMLAv8f16;
9031 Opc = AArch64::FMLAv8i16_indexed;
9038 RC = &AArch64::FPR128RegClass;
9039 Opc = AArch64::FMLSv8f16;
9044 RC = &AArch64::FPR128RegClass;
9045 Opc = AArch64::FMLSv8i16_indexed;
9052 RC = &AArch64::FPR128RegClass;
9054 Opc = AArch64::FMLSv2i64_indexed;
9058 Opc = AArch64::FMLSv2f64;
9066 RC = &AArch64::FPR128RegClass;
9068 Opc = AArch64::FMLSv4i32_indexed;
9072 Opc = AArch64::FMLSv4f32;
9079 RC = &AArch64::FPR64RegClass;
9081 MachineInstrBuilder MIB1 =
9082 BuildMI(MF, MIMetadata(Root),
TII->get(AArch64::FNEGv2f32), NewVR)
9085 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
9087 Opc = AArch64::FMLAv2i32_indexed;
9091 Opc = AArch64::FMLAv2f32;
9099 RC = &AArch64::FPR128RegClass;
9101 MachineInstrBuilder MIB1 =
9102 BuildMI(MF, MIMetadata(Root),
TII->get(AArch64::FNEGv4f32), NewVR)
9105 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
9107 Opc = AArch64::FMLAv4i32_indexed;
9111 Opc = AArch64::FMLAv4f32;
9119 RC = &AArch64::FPR128RegClass;
9121 MachineInstrBuilder MIB1 =
9122 BuildMI(MF, MIMetadata(Root),
TII->get(AArch64::FNEGv2f64), NewVR)
9125 InstrIdxForVirtReg.
insert(std::make_pair(NewVR, 0));
9127 Opc = AArch64::FMLAv2i64_indexed;
9131 Opc = AArch64::FMLAv2f64;
9143 &AArch64::FPR128RegClass,
MRI);
9152 &AArch64::FPR128RegClass,
MRI);
9161 &AArch64::FPR128_loRegClass,
MRI);
9170 &AArch64::FPR128RegClass,
MRI);
9179 &AArch64::FPR128_loRegClass,
MRI);
9213 for (
auto *
MI : InsInstrs)
9214 MI->setFlags(Flags);
9255 bool IsNegativeBranch =
false;
9256 bool IsTestAndBranch =
false;
9257 unsigned TargetBBInMI = 0;
9258 switch (
MI.getOpcode()) {
9262 case AArch64::CBWPri:
9263 case AArch64::CBXPri:
9264 case AArch64::CBWPrr:
9265 case AArch64::CBXPrr:
9271 case AArch64::CBNZW:
9272 case AArch64::CBNZX:
9274 IsNegativeBranch =
true;
9279 IsTestAndBranch =
true;
9281 case AArch64::TBNZW:
9282 case AArch64::TBNZX:
9284 IsNegativeBranch =
true;
9285 IsTestAndBranch =
true;
9291 if (IsTestAndBranch &&
MI.getOperand(1).getImm())
9295 assert(
MI.getParent() &&
"Incomplete machine instruction\n");
9306 while (
DefMI->isCopy()) {
9308 if (!
MRI->hasOneNonDBGUse(CopyVReg))
9310 if (!
MRI->hasOneDef(CopyVReg))
9315 switch (
DefMI->getOpcode()) {
9319 case AArch64::ANDWri:
9320 case AArch64::ANDXri: {
9321 if (IsTestAndBranch)
9325 if (!
MRI->hasOneNonDBGUse(VReg))
9328 bool Is32Bit = (
DefMI->getOpcode() == AArch64::ANDWri);
9330 DefMI->getOperand(2).getImm(), Is32Bit ? 32 : 64);
9339 assert(!
MRI->def_empty(NewReg) &&
"Register must be defined.");
9345 unsigned Opc = (Imm < 32)
9346 ? (IsNegativeBranch ? AArch64::TBNZW : AArch64::TBZW)
9347 : (IsNegativeBranch ? AArch64::TBNZX : AArch64::TBZX);
9360 if (!Is32Bit && Imm < 32)
9362 MI.eraseFromParent();
9366 case AArch64::CSINCWr:
9367 case AArch64::CSINCXr: {
9368 if (!(
DefMI->getOperand(1).getReg() == AArch64::WZR &&
9369 DefMI->getOperand(2).getReg() == AArch64::WZR) &&
9370 !(
DefMI->getOperand(1).getReg() == AArch64::XZR &&
9371 DefMI->getOperand(2).getReg() == AArch64::XZR))
9374 if (
DefMI->findRegisterDefOperandIdx(AArch64::NZCV,
nullptr,
9387 if (IsNegativeBranch)
9390 MI.eraseFromParent();
9396std::pair<unsigned, unsigned>
9397AArch64InstrInfo::decomposeMachineOperandsTargetFlags(
unsigned TF)
const {
9399 return std::make_pair(TF & Mask, TF & ~Mask);
9403AArch64InstrInfo::getSerializableDirectMachineOperandTargetFlags()
const {
9406 static const std::pair<unsigned, const char *> TargetFlags[] = {
9407 {MO_PAGE,
"aarch64-page"}, {
MO_PAGEOFF,
"aarch64-pageoff"},
9408 {
MO_G3,
"aarch64-g3"}, {
MO_G2,
"aarch64-g2"},
9409 {
MO_G1,
"aarch64-g1"}, {
MO_G0,
"aarch64-g0"},
9415AArch64InstrInfo::getSerializableBitmaskMachineOperandTargetFlags()
const {
9416 using namespace AArch64II;
9418 static const std::pair<unsigned, const char *> TargetFlags[] = {
9421 {
MO_NC,
"aarch64-nc"},
9422 {
MO_S,
"aarch64-s"},
9433AArch64InstrInfo::getSerializableMachineMemOperandTargetFlags()
const {
9434 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
9536 MachineFunction *MF =
C.getMF();
9538 const AArch64RegisterInfo *ARI =
9539 static_cast<const AArch64RegisterInfo *
>(&
TRI);
9542 for (
unsigned Reg : AArch64::GPR64RegClass) {
9544 Reg != AArch64::LR &&
9545 Reg != AArch64::X16 &&
9546 Reg != AArch64::X17 &&
9547 C.isAvailableAcrossAndOutOfSeq(
Reg,
TRI) &&
9548 C.isAvailableInsideSeq(
Reg,
TRI))
9579 return SubtargetA.hasV8_3aOps() == SubtargetB.hasV8_3aOps();
9582std::optional<std::unique_ptr<outliner::OutlinedFunction>>
9583AArch64InstrInfo::getOutliningCandidateInfo(
9585 std::vector<outliner::Candidate> &RepeatedSequenceLocs,
9586 unsigned MinRepeats)
const {
9587 unsigned SequenceSize = 0;
9588 for (
auto &
MI : RepeatedSequenceLocs[0])
9591 unsigned NumBytesToCreateFrame = 0;
9601 if (std::adjacent_find(
9602 RepeatedSequenceLocs.begin(), RepeatedSequenceLocs.end(),
9603 [](
const outliner::Candidate &a,
const outliner::Candidate &b) {
9606 if (outliningCandidatesSigningScopeConsensus(a, b) &&
9607 outliningCandidatesSigningKeyConsensus(a, b) &&
9608 outliningCandidatesV8_3OpsConsensus(a, b)) {
9612 }) != RepeatedSequenceLocs.end()) {
9613 return std::nullopt;
9630 unsigned NumBytesToCheckLRInTCEpilogue = 0;
9631 if (RepeatedSequenceLocs[0]
9633 ->getInfo<AArch64FunctionInfo>()
9634 ->shouldSignReturnAddress(
true)) {
9636 NumBytesToCreateFrame += 8;
9639 auto LRCheckMethod = Subtarget.getAuthenticatedLRCheckMethod(
9640 *RepeatedSequenceLocs[0].getMF());
9641 NumBytesToCheckLRInTCEpilogue =
9645 if (isTailCallReturnInst(RepeatedSequenceLocs[0].
back()))
9646 SequenceSize += NumBytesToCheckLRInTCEpilogue;
9654 for (
auto &
MI :
C) {
9655 if (
MI.modifiesRegister(AArch64::SP, &
TRI)) {
9656 switch (
MI.getOpcode()) {
9657 case AArch64::ADDXri:
9658 case AArch64::ADDWri:
9659 assert(
MI.getNumOperands() == 4 &&
"Wrong number of operands");
9661 "Expected operand to be immediate");
9663 "Expected operand to be a register");
9667 if (
MI.getOperand(1).getReg() == AArch64::SP)
9668 SPValue +=
MI.getOperand(2).getImm();
9672 case AArch64::SUBXri:
9673 case AArch64::SUBWri:
9674 assert(
MI.getNumOperands() == 4 &&
"Wrong number of operands");
9676 "Expected operand to be immediate");
9678 "Expected operand to be a register");
9682 if (
MI.getOperand(1).getReg() == AArch64::SP)
9683 SPValue -=
MI.getOperand(2).getImm();
9700 if (RepeatedSequenceLocs.size() < MinRepeats)
9701 return std::nullopt;
9705 unsigned FlagsSetInAll = 0xF;
9709 FlagsSetInAll &=
C.Flags;
9711 unsigned LastInstrOpcode = RepeatedSequenceLocs[0].back().getOpcode();
9714 auto SetCandidateCallInfo =
9715 [&RepeatedSequenceLocs](
unsigned CallID,
unsigned NumBytesForCall) {
9717 C.setCallInfo(CallID, NumBytesForCall);
9721 NumBytesToCreateFrame += 4;
9729 unsigned CFICount = 0;
9730 for (
auto &
I : RepeatedSequenceLocs[0]) {
9731 if (
I.isCFIInstruction())
9741 std::vector<MCCFIInstruction> CFIInstructions =
9742 C.getMF()->getFrameInstructions();
9744 if (CFICount > 0 && CFICount != CFIInstructions.size())
9745 return std::nullopt;
9753 if (!
MI.modifiesRegister(AArch64::SP, &
TRI) &&
9754 !
MI.readsRegister(AArch64::SP, &
TRI))
9760 if (
MI.modifiesRegister(AArch64::SP, &
TRI))
9765 if (
MI.mayLoadOrStore()) {
9768 bool OffsetIsScalable;
9772 if (!getMemOperandWithOffset(
MI,
Base,
Offset, OffsetIsScalable, &
TRI) ||
9773 !
Base->isReg() ||
Base->getReg() != AArch64::SP)
9777 if (OffsetIsScalable)
9785 TypeSize Scale(0U,
false), DummyWidth(0U,
false);
9786 getMemOpInfo(
MI.getOpcode(), Scale, DummyWidth, MinOffset, MaxOffset);
9789 if (
Offset < MinOffset * (int64_t)Scale.getFixedValue() ||
9790 Offset > MaxOffset * (int64_t)Scale.getFixedValue())
9805 bool AllStackInstrsSafe =
9810 if (RepeatedSequenceLocs[0].
back().isTerminator()) {
9812 NumBytesToCreateFrame = 0;
9813 unsigned NumBytesForCall = 4 + NumBytesToCheckLRInTCEpilogue;
9817 else if (LastInstrOpcode == AArch64::BL ||
9818 ((LastInstrOpcode == AArch64::BLR ||
9819 LastInstrOpcode == AArch64::BLRNoIP) &&
9823 NumBytesToCreateFrame = NumBytesToCheckLRInTCEpilogue;
9831 unsigned NumBytesNoStackCalls = 0;
9832 std::vector<outliner::Candidate> CandidatesWithoutStackFixups;
9838 ?
C.isAvailableAcrossAndOutOfSeq(AArch64::LR,
TRI)
9847 C.getMF()->getFunction().hasFnAttribute(Attribute::NoReturn);
9850 if (LRAvailable && !IsNoReturn) {
9851 NumBytesNoStackCalls += 4;
9853 CandidatesWithoutStackFixups.push_back(
C);
9858 else if (findRegisterToSaveLRTo(
C)) {
9859 NumBytesNoStackCalls += 12;
9861 CandidatesWithoutStackFixups.push_back(
C);
9866 else if (
C.isAvailableInsideSeq(AArch64::SP,
TRI)) {
9867 NumBytesNoStackCalls += 12;
9869 CandidatesWithoutStackFixups.push_back(
C);
9875 NumBytesNoStackCalls += SequenceSize;
9882 if (!AllStackInstrsSafe ||
9883 NumBytesNoStackCalls <= RepeatedSequenceLocs.size() * 12) {
9884 RepeatedSequenceLocs = CandidatesWithoutStackFixups;
9886 if (RepeatedSequenceLocs.size() < MinRepeats)
9887 return std::nullopt;
9940 (!
C.isAvailableAcrossAndOutOfSeq(AArch64::LR,
TRI) ||
9941 !findRegisterToSaveLRTo(
C));
9947 if (RepeatedSequenceLocs.size() < MinRepeats)
9948 return std::nullopt;
9957 bool ModStackToSaveLR =
false;
9960 ModStackToSaveLR =
true;
9969 ModStackToSaveLR =
true;
9971 if (ModStackToSaveLR) {
9973 if (!AllStackInstrsSafe)
9974 return std::nullopt;
9977 NumBytesToCreateFrame += 8;
9984 return std::nullopt;
9986 return std::make_unique<outliner::OutlinedFunction>(
9987 RepeatedSequenceLocs, SequenceSize, NumBytesToCreateFrame, FrameID);
9990void AArch64InstrInfo::mergeOutliningCandidateAttributes(
9991 Function &
F, std::vector<outliner::Candidate> &Candidates)
const {
9995 const auto &CFn = Candidates.front().getMF()->getFunction();
9997 if (CFn.hasFnAttribute(
"ptrauth-returns"))
9998 F.addFnAttr(CFn.getFnAttribute(
"ptrauth-returns"));
9999 if (CFn.hasFnAttribute(
"ptrauth-auth-traps"))
10000 F.addFnAttr(CFn.getFnAttribute(
"ptrauth-auth-traps"));
10003 if (CFn.hasFnAttribute(
"sign-return-address"))
10004 F.addFnAttr(CFn.getFnAttribute(
"sign-return-address"));
10005 if (CFn.hasFnAttribute(
"sign-return-address-key"))
10006 F.addFnAttr(CFn.getFnAttribute(
"sign-return-address-key"));
10008 AArch64GenInstrInfo::mergeOutliningCandidateAttributes(
F, Candidates);
10011bool AArch64InstrInfo::isFunctionSafeToOutlineFrom(
10016 if (!OutlineFromLinkOnceODRs &&
F.hasLinkOnceODRLinkage())
10023 if (
F.hasSection())
10029 AArch64FunctionInfo *AFI = MF.
getInfo<AArch64FunctionInfo>();
10030 if (!AFI || AFI->
hasRedZone().value_or(
true))
10050 unsigned &Flags)
const {
10052 "Must track liveness!");
10054 std::pair<MachineBasicBlock::iterator, MachineBasicBlock::iterator>>
10069 auto AreAllUnsafeRegsDead = [&LRU]() {
10070 return LRU.available(AArch64::W16) && LRU.available(AArch64::W17) &&
10071 LRU.available(AArch64::NZCV);
10086 bool LRAvailableEverywhere =
true;
10088 LRU.addLiveOuts(
MBB);
10090 auto UpdateWholeMBBFlags = [&
Flags](
const MachineInstr &
MI) {
10091 if (
MI.isCall() && !
MI.isTerminator())
10097 auto CreateNewRangeStartingAt =
10098 [&RangeBegin, &RangeEnd,
10100 RangeBegin = NewBegin;
10101 RangeEnd = std::next(RangeBegin);
10104 auto SaveRangeIfNonEmpty = [&RangeLen, &
Ranges, &RangeBegin, &RangeEnd]() {
10110 if (!RangeBegin.isEnd() && RangeBegin->isBundledWithPred())
10112 if (!RangeEnd.isEnd() && RangeEnd->isBundledWithPred())
10114 Ranges.emplace_back(RangeBegin, RangeEnd);
10122 for (; FirstPossibleEndPt !=
MBB.
instr_rend(); ++FirstPossibleEndPt) {
10123 LRU.stepBackward(*FirstPossibleEndPt);
10126 UpdateWholeMBBFlags(*FirstPossibleEndPt);
10127 if (AreAllUnsafeRegsDead())
10134 CreateNewRangeStartingAt(FirstPossibleEndPt->getIterator());
10139 LRU.stepBackward(
MI);
10140 UpdateWholeMBBFlags(
MI);
10141 if (!AreAllUnsafeRegsDead()) {
10142 SaveRangeIfNonEmpty();
10143 CreateNewRangeStartingAt(
MI.getIterator());
10146 LRAvailableEverywhere &= LRU.available(AArch64::LR);
10147 RangeBegin =
MI.getIterator();
10152 if (AreAllUnsafeRegsDead())
10153 SaveRangeIfNonEmpty();
10161 if (!LRAvailableEverywhere)
10169 unsigned Flags)
const {
10170 MachineInstr &
MI = *MIT;
10174 switch (
MI.getOpcode()) {
10175 case AArch64::PACM:
10176 case AArch64::PACIASP:
10177 case AArch64::PACIBSP:
10178 case AArch64::PACIASPPC:
10179 case AArch64::PACIBSPPC:
10180 case AArch64::AUTIASP:
10181 case AArch64::AUTIBSP:
10182 case AArch64::AUTIASPPCi:
10183 case AArch64::AUTIASPPCr:
10184 case AArch64::AUTIBSPPCi:
10185 case AArch64::AUTIBSPPCr:
10186 case AArch64::RETAA:
10187 case AArch64::RETAB:
10188 case AArch64::RETAASPPCi:
10189 case AArch64::RETAASPPCr:
10190 case AArch64::RETABSPPCi:
10191 case AArch64::RETABSPPCr:
10192 case AArch64::EMITBKEY:
10193 case AArch64::PAUTH_PROLOGUE:
10194 case AArch64::PAUTH_EPILOGUE:
10204 if (
MI.isCFIInstruction())
10208 if (
MI.isTerminator())
10214 for (
const MachineOperand &MOP :
MI.operands()) {
10217 assert(!MOP.isCFIIndex());
10220 if (MOP.isReg() && !MOP.isImplicit() &&
10221 (MOP.getReg() == AArch64::LR || MOP.getReg() == AArch64::W30))
10228 if (
MI.getOpcode() == AArch64::ADRP)
10248 for (
const MachineOperand &MOP :
MI.operands()) {
10249 if (MOP.isGlobal()) {
10257 if (Callee &&
Callee->getName() ==
"\01_mcount")
10265 if (
MI.getOpcode() == AArch64::BLR ||
10266 MI.getOpcode() == AArch64::BLRNoIP ||
MI.getOpcode() == AArch64::BL)
10270 return UnknownCallOutlineType;
10278 return UnknownCallOutlineType;
10286 return UnknownCallOutlineType;
10307 for (MachineInstr &
MI :
MBB) {
10308 const MachineOperand *
Base;
10309 TypeSize Width(0,
false);
10311 bool OffsetIsScalable;
10314 if (!
MI.mayLoadOrStore() ||
10317 (
Base->isReg() &&
Base->getReg() != AArch64::SP))
10321 TypeSize Scale(0U,
false);
10322 int64_t Dummy1, Dummy2;
10325 assert(StackOffsetOperand.
isImm() &&
"Stack offset wasn't immediate!");
10327 assert(Scale != 0 &&
"Unexpected opcode!");
10328 assert(!OffsetIsScalable &&
"Expected offset to be a byte offset");
10333 int64_t NewImm = (
Offset + 16) / (int64_t)Scale.getFixedValue();
10334 StackOffsetOperand.
setImm(NewImm);
10340 bool ShouldSignReturnAddr) {
10341 if (!ShouldSignReturnAddr)
10347 TII->get(AArch64::PAUTH_EPILOGUE))
10351void AArch64InstrInfo::buildOutlinedFrame(
10355 AArch64FunctionInfo *FI = MF.
getInfo<AArch64FunctionInfo>();
10363 unsigned TailOpcode;
10365 TailOpcode = AArch64::TCRETURNdi;
10369 TailOpcode = AArch64::TCRETURNriALL;
10380 bool IsLeafFunction =
true;
10383 auto IsNonTailCall = [](
const MachineInstr &
MI) {
10384 return MI.isCall() && !
MI.isReturn();
10394 "Can only fix up stack references once");
10395 fixupPostOutline(
MBB);
10397 IsLeafFunction =
false;
10408 Et = std::prev(
MBB.
end());
10418 if (MF.
getInfo<AArch64FunctionInfo>()->needsDwarfUnwindInfo(MF)) {
10422 CFIBuilder.buildDefCFAOffset(16);
10426 CFIBuilder.buildOffset(AArch64::LR, -16);
10467 fixupPostOutline(
MBB);
10478 .addGlobalAddress(
M.getNamedValue(MF.
getName()))
10488 .addGlobalAddress(
M.getNamedValue(MF.
getName())));
10497 MachineInstr *Save;
10498 MachineInstr *Restore;
10504 assert(
Reg &&
"No callee-saved register available?");
10538 .addGlobalAddress(
M.getNamedValue(MF.
getName())));
10546bool AArch64InstrInfo::shouldOutlineFromFunctionByDefault(
10554 bool AllowSideEffects)
const {
10556 const AArch64Subtarget &STI = MF.
getSubtarget<AArch64Subtarget>();
10559 if (
TRI.isGeneralPurposeRegister(MF,
Reg)) {
10572 assert(STI.hasNEON() &&
"Expected to have NEON.");
10578std::optional<DestSourcePair>
10583 if (((
MI.getOpcode() == AArch64::ORRWrs &&
10584 MI.getOperand(1).getReg() == AArch64::WZR &&
10585 MI.getOperand(3).getImm() == 0x0) ||
10586 (
MI.getOpcode() == AArch64::ORRWrr &&
10587 MI.getOperand(1).getReg() == AArch64::WZR)) &&
10589 (!
MI.getOperand(0).getReg().isVirtual() ||
10590 MI.getOperand(0).getSubReg() == 0) &&
10591 (!
MI.getOperand(0).getReg().isPhysical() ||
10596 if (
MI.getOpcode() == AArch64::ORRXrs &&
10597 MI.getOperand(1).getReg() == AArch64::XZR &&
10598 MI.getOperand(3).getImm() == 0x0)
10601 return std::nullopt;
10604std::optional<DestSourcePair>
10606 if ((
MI.getOpcode() == AArch64::ORRWrs &&
10607 MI.getOperand(1).getReg() == AArch64::WZR &&
10608 MI.getOperand(3).getImm() == 0x0) ||
10609 (
MI.getOpcode() == AArch64::ORRWrr &&
10610 MI.getOperand(1).getReg() == AArch64::WZR))
10612 return std::nullopt;
10615std::optional<RegImmPair>
10624 return std::nullopt;
10626 switch (
MI.getOpcode()) {
10628 return std::nullopt;
10629 case AArch64::SUBWri:
10630 case AArch64::SUBXri:
10631 case AArch64::SUBSWri:
10632 case AArch64::SUBSXri:
10635 case AArch64::ADDSWri:
10636 case AArch64::ADDSXri:
10637 case AArch64::ADDWri:
10638 case AArch64::ADDXri: {
10640 if (!
MI.getOperand(0).isReg() || !
MI.getOperand(1).isReg() ||
10641 !
MI.getOperand(2).isImm())
10642 return std::nullopt;
10643 int Shift =
MI.getOperand(3).getImm();
10644 assert((Shift == 0 || Shift == 12) &&
"Shift can be either 0 or 12");
10648 return RegImmPair{
MI.getOperand(1).getReg(),
Offset};
10654static std::optional<ParamLoadedValue>
10658 auto DestSrc =
TII->isCopyLikeInstr(
MI);
10660 return std::nullopt;
10662 Register DestReg = DestSrc->Destination->getReg();
10663 Register SrcReg = DestSrc->Source->getReg();
10666 return std::nullopt;
10671 if (DestReg == DescribedReg)
10675 if (
MI.getOpcode() == AArch64::ORRWrs &&
10676 TRI->isSuperRegister(DestReg, DescribedReg))
10680 if (
MI.getOpcode() == AArch64::ORRXrs &&
10681 TRI->isSubRegister(DestReg, DescribedReg)) {
10682 Register SrcSubReg =
TRI->getSubReg(SrcReg, AArch64::sub_32);
10686 assert(!
TRI->isSuperOrSubRegisterEq(DestReg, DescribedReg) &&
10687 "Unhandled ORR[XW]rs copy case");
10689 return std::nullopt;
10692bool AArch64InstrInfo::isFunctionSafeToSplit(
const MachineFunction &MF)
const {
10697 if (MF.
getInfo<AArch64FunctionInfo>()->hasRedZone().value_or(
true))
10703bool AArch64InstrInfo::isMBBSafeToSplitToCold(
10707 auto isAsmGoto = [](
const MachineInstr &
MI) {
10708 return MI.getOpcode() == AArch64::INLINEASM_BR;
10718 auto containsMBB = [&
MBB](
const MachineJumpTableEntry &JTE) {
10725 for (
const MachineInstr &
MI :
MBB) {
10726 switch (
MI.getOpcode()) {
10727 case TargetOpcode::G_BRJT:
10728 case AArch64::JumpTableDest32:
10729 case AArch64::JumpTableDest16:
10730 case AArch64::JumpTableDest8:
10741std::optional<ParamLoadedValue>
10744 const MachineFunction *MF =
MI.getMF();
10746 switch (
MI.getOpcode()) {
10747 case AArch64::MOVZWi:
10748 case AArch64::MOVZXi: {
10751 if (!
TRI->isSuperRegisterEq(
MI.getOperand(0).getReg(),
Reg))
10752 return std::nullopt;
10754 if (!
MI.getOperand(1).isImm())
10755 return std::nullopt;
10756 int64_t Immediate =
MI.getOperand(1).getImm();
10757 int Shift =
MI.getOperand(2).getImm();
10761 case AArch64::ORRWrs:
10762 case AArch64::ORRXrs:
10769bool AArch64InstrInfo::isExtendLikelyToBeFolded(
10772 ExtMI.
getOpcode() == TargetOpcode::G_ZEXT ||
10773 ExtMI.
getOpcode() == TargetOpcode::G_ANYEXT);
10776 if (ExtMI.
getOpcode() == TargetOpcode::G_ANYEXT)
10780 if (!
MRI.hasOneNonDBGUse(DefReg))
10785 auto *UserMI = &*
MRI.use_instr_nodbg_begin(DefReg);
10786 return UserMI->getOpcode() == TargetOpcode::G_PTR_ADD;
10789uint64_t AArch64InstrInfo::getElementSizeForOpcode(
unsigned Opc)
const {
10793bool AArch64InstrInfo::isPTestLikeOpcode(
unsigned Opc)
const {
10797bool AArch64InstrInfo::isWhileOpcode(
unsigned Opc)
const {
10802AArch64InstrInfo::getTailDuplicateSize(
CodeGenOptLevel OptLevel)
const {
10806bool AArch64InstrInfo::isLegalAddressingMode(
unsigned NumBytes, int64_t
Offset,
10807 unsigned Scale)
const {
10818 unsigned Shift =
Log2_64(NumBytes);
10819 if (NumBytes &&
Offset > 0 && (
Offset / NumBytes) <= (1LL << 12) - 1 &&
10827 return Scale == 1 || (Scale > 0 && Scale == NumBytes);
10832 return AArch64::BLRNoIP;
10834 return AArch64::BLR;
10839 Register TargetReg,
bool FrameSetup)
const {
10840 assert(TargetReg != AArch64::SP &&
"New top of stack cannot already be in SP");
10852 MF.
insert(MBBInsertPoint, LoopTestMBB);
10855 MF.
insert(MBBInsertPoint, LoopBodyMBB);
10857 MF.
insert(MBBInsertPoint, ExitMBB);
10867 BuildMI(*LoopTestMBB, LoopTestMBB->
end(),
DL,
TII->get(AArch64::SUBSXrx64),
10875 BuildMI(*LoopTestMBB, LoopTestMBB->
end(),
DL,
TII->get(AArch64::Bcc))
10881 BuildMI(*LoopBodyMBB, LoopBodyMBB->
end(),
DL,
TII->get(AArch64::STRXui))
10894 BuildMI(*ExitMBB, ExitMBB->
end(),
DL,
TII->get(AArch64::ADDXri), AArch64::SP)
10913 MBB.addSuccessor(LoopTestMBB);
10919 return ExitMBB->
begin();
10936 unsigned CompCounterOprNum;
10940 unsigned UpdateCounterOprNum;
10944 bool IsUpdatePriorComp;
10956 TII(MF->getSubtarget().getInstrInfo()),
10957 TRI(MF->getSubtarget().getRegisterInfo()),
MRI(MF->getRegInfo()),
10958 LoopBB(LoopBB), CondBranch(CondBranch), Comp(Comp),
10959 CompCounterOprNum(CompCounterOprNum), Update(Update),
10960 UpdateCounterOprNum(UpdateCounterOprNum),
Init(
Init),
10961 IsUpdatePriorComp(IsUpdatePriorComp),
Cond(
Cond.begin(),
Cond.end()) {}
10963 bool shouldIgnoreForPipelining(
const MachineInstr *
MI)
const override {
10969 std::optional<bool> createTripCountGreaterCondition(
10970 int TC, MachineBasicBlock &
MBB,
10971 SmallVectorImpl<MachineOperand> &CondParam)
override {
10979 void createRemainingIterationsGreaterCondition(
10980 int TC, MachineBasicBlock &
MBB, SmallVectorImpl<MachineOperand> &
Cond,
10981 DenseMap<MachineInstr *, MachineInstr *> &LastStage0Insts)
override;
10983 void setPreheader(MachineBasicBlock *NewPreheader)
override {}
10985 void adjustTripCount(
int TripCountAdjust)
override {}
10987 bool isMVEExpanderSupported()
override {
return true; }
11000 MBB.getParent()->getSubtarget().getRegisterInfo();
11005 Result =
MRI.createVirtualRegister(
11008 }
else if (
I == ReplaceOprNum) {
11009 MRI.constrainRegClass(ReplaceReg,
11014 MBB.insert(InsertTo, NewMI);
11018void AArch64PipelinerLoopInfo::createRemainingIterationsGreaterCondition(
11034 assert(CondBranch->getOpcode() == AArch64::Bcc);
11038 if (CondBranch->getOperand(1).getMBB() == LoopBB)
11045 auto AccumulateCond = [&](
Register CurCond,
11047 Register NewCond =
MRI.createVirtualRegister(&AArch64::GPR64commonRegClass);
11056 if (!LastStage0Insts.
empty() && LastStage0Insts[Comp]->getParent() == &
MBB) {
11060 for (
int I = 0;
I <= TC; ++
I) {
11066 AccCond = AccumulateCond(AccCond, CC);
11070 if (Update != Comp && IsUpdatePriorComp) {
11072 LastStage0Insts[Comp]->getOperand(CompCounterOprNum).getReg();
11073 NextCounter =
cloneInstr(Update, UpdateCounterOprNum, Counter,
MBB,
11077 NextCounter = LastStage0Insts[Update]->getOperand(0).getReg();
11079 }
else if (Update != Comp) {
11084 Counter = NextCounter;
11088 if (LastStage0Insts.
empty()) {
11092 if (IsUpdatePriorComp)
11097 Counter = LastStage0Insts[Comp]->getOperand(CompCounterOprNum).getReg();
11100 for (
int I = 0;
I <= TC; ++
I) {
11104 AccCond = AccumulateCond(AccCond, CC);
11105 if (
I != TC && Update != Comp)
11108 Counter = NextCounter;
11124 assert(Phi.getNumOperands() == 5);
11125 if (Phi.getOperand(2).getMBB() ==
MBB) {
11126 RegMBB = Phi.getOperand(1).getReg();
11127 RegOther = Phi.getOperand(3).getReg();
11129 assert(Phi.getOperand(4).getMBB() ==
MBB);
11130 RegMBB = Phi.getOperand(3).getReg();
11131 RegOther = Phi.getOperand(1).getReg();
11136 if (!
Reg.isVirtual())
11139 return MRI.getVRegDef(
Reg)->getParent() != BB;
11145 unsigned &UpdateCounterOprNum,
Register &InitReg,
11146 bool &IsUpdatePriorComp) {
11160 if (!
Reg.isVirtual())
11163 UpdateInst =
nullptr;
11164 UpdateCounterOprNum = 0;
11166 IsUpdatePriorComp =
true;
11170 if (Def->getParent() != LoopBB)
11172 if (Def->isCopy()) {
11174 if (Def->getOperand(0).getSubReg() || Def->getOperand(1).getSubReg())
11176 CurReg = Def->getOperand(1).getReg();
11177 }
else if (Def->isPHI()) {
11181 IsUpdatePriorComp =
false;
11186 switch (Def->getOpcode()) {
11187 case AArch64::ADDSXri:
11188 case AArch64::ADDSWri:
11189 case AArch64::SUBSXri:
11190 case AArch64::SUBSWri:
11191 case AArch64::ADDXri:
11192 case AArch64::ADDWri:
11193 case AArch64::SUBXri:
11194 case AArch64::SUBWri:
11196 UpdateCounterOprNum = 1;
11198 case AArch64::ADDSXrr:
11199 case AArch64::ADDSWrr:
11200 case AArch64::SUBSXrr:
11201 case AArch64::SUBSWrr:
11202 case AArch64::ADDXrr:
11203 case AArch64::ADDWrr:
11204 case AArch64::SUBXrr:
11205 case AArch64::SUBWrr:
11208 UpdateCounterOprNum = 1;
11210 UpdateCounterOprNum = 2;
11217 CurReg = Def->getOperand(UpdateCounterOprNum).getReg();
11232std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
11243 if (
MI.isCall() ||
MI.hasUnmodeledSideEffects())
11254 if (
TBB == LoopBB && FBB == LoopBB)
11258 if (
TBB != LoopBB && FBB ==
nullptr)
11261 assert((
TBB == LoopBB || FBB == LoopBB) &&
11262 "The Loop must be a single-basic-block loop");
11267 if (CondBranch->
getOpcode() != AArch64::Bcc)
11275 unsigned CompCounterOprNum = 0;
11277 if (
MI.modifiesRegister(AArch64::NZCV, &
TRI)) {
11281 switch (
MI.getOpcode()) {
11282 case AArch64::SUBSXri:
11283 case AArch64::SUBSWri:
11284 case AArch64::ADDSXri:
11285 case AArch64::ADDSWri:
11287 CompCounterOprNum = 1;
11289 case AArch64::ADDSWrr:
11290 case AArch64::ADDSXrr:
11291 case AArch64::SUBSWrr:
11292 case AArch64::SUBSXrr:
11296 if (isWhileOpcode(
MI.getOpcode())) {
11303 if (CompCounterOprNum == 0) {
11305 CompCounterOprNum = 2;
11307 CompCounterOprNum = 1;
11319 bool IsUpdatePriorComp;
11320 unsigned UpdateCounterOprNum;
11322 Update, UpdateCounterOprNum,
Init, IsUpdatePriorComp))
11325 return std::make_unique<AArch64PipelinerLoopInfo>(
11326 LoopBB, CondBranch, Comp, CompCounterOprNum, Update, UpdateCounterOprNum,
11336 TypeSize Scale(0U,
false), Width(0U,
false);
11337 int64_t MinOffset, MaxOffset;
11338 if (
getMemOpInfo(
MI.getOpcode(), Scale, Width, MinOffset, MaxOffset)) {
11340 if (
MI.getOperand(ImmIdx).isImm() && !
MI.getOperand(ImmIdx - 1).isFI()) {
11341 int64_t Imm =
MI.getOperand(ImmIdx).getImm();
11342 if (Imm < MinOffset || Imm > MaxOffset) {
11343 ErrInfo =
"Unexpected immediate on load/store instruction";
11349 const MCInstrDesc &MCID =
MI.getDesc();
11351 const MachineOperand &MO =
MI.getOperand(
Op);
11355 ErrInfo =
"OPERAND_IMPLICIT_IMM_0 should be 0";
11364 ErrInfo =
"OPERAND_SHIFT_MSL should be msl shift of 8 or 16";
11375#define GET_INSTRINFO_HELPERS
11376#define GET_INSTRMAP_INFO
11377#include "AArch64GenInstrInfo.inc"
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
static bool forwardCopyWillClobberTuple(unsigned DestReg, unsigned SrcReg, unsigned NumRegs)
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 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 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 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 const MachineInstrBuilder & AddSubReg(const MachineInstrBuilder &MIB, MCRegister Reg, unsigned SubIdx, unsigned State, const TargetRegisterInfo *TRI)
static bool canPairLdStOpc(unsigned FirstOpc, unsigned SecondOpc)
static int findCondCodeUseOperandIdxForBranchOrSelect(const MachineInstr &Instr)
static bool isPostIndexLdStOpcode(unsigned Opcode)
Return true if the opcode is a post-index ld/st instruction, which really loads from base+0.
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 bool isSUBSRegImm(unsigned Opcode)
static bool UpdateOperandRegClass(MachineInstr &Instr)
static const TargetRegisterClass * getRegClass(const MachineInstr &MI, Register Reg)
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 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 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 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< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
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.
Machine Check Debug Module
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
MachineInstr unsigned OpIdx
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.
static bool canCombine(MachineBasicBlock &MBB, MachineOperand &MO, unsigned CombineOpc=0)
AArch64FunctionInfo - This class is derived from MachineFunctionInfo and contains private AArch64-spe...
bool hasStreamingModeChanges() const
bool shouldSignReturnAddress(const MachineFunction &MF) const
void setOutliningStyle(const std::string &Style)
std::optional< bool > hasRedZone() const
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.
bool areMemAccessesTriviallyDisjoint(const MachineInstr &MIa, const MachineInstr &MIb) const override
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.
bool isBranchOffsetInRange(unsigned BranchOpc, int64_t BrOffset) const override
bool canInsertSelect(const MachineBasicBlock &, ArrayRef< MachineOperand > Cond, Register, Register, Register, int &, int &, int &) const override
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
static bool isPairableLdStInst(const MachineInstr &MI)
Return true if pairing the given load or store may be paired with another.
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.
MachineInstr * foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, ArrayRef< unsigned > Ops, MachineBasicBlock::iterator InsertPt, int FrameIndex, LiveIntervals *LIS=nullptr, VirtRegMap *VRM=nullptr) const override
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.
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.
std::unique_ptr< TargetInstrInfo::PipelinerLoopInfo > analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const override
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
MachineBasicBlock::iterator probedStackAlloc(MachineBasicBlock::iterator MBBI, Register TargetReg, bool FrameSetup) const
Return true when there is potentially a faster code sequence for an instruction chain ending in Root.
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.
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
void copyPhysRegTuple(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, unsigned Opcode, llvm::ArrayRef< unsigned > Indices) const
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,...
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
const T & front() const
front - Get the first element.
size_t size() const
size - 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.
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.
MCInstBuilder & addImm(int64_t Val)
Add a new integer immediate operand.
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
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()
Instructions::const_iterator const_instr_iterator
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.
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.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
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...
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 & 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 & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
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 eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
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.
const std::vector< MachineJumpTableEntry > & getJumpTables() const
A description of a memory reference used in the backend.
@ 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.
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,...
bool tracksLiveness() const
tracksLiveness - Returns true when tracking register liveness accurately.
bool reservedRegsFrozen() const
reservedRegsFrozen - Returns true after freezeReservedRegs() was called to ensure the set of reserved...
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 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.
StringRef - 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 MCAsmInfo * getMCAsmInfo() const
Return target specific asm information.
bool contains(Register Reg) const
Return true if the specified register is included in this register class.
bool hasSubClassEq(const TargetRegisterClass *RC) const
Returns true if RC is a sub-class of or equal to this class.
bool hasSuperClassEq(const TargetRegisterClass *RC) const
Returns true if RC is a super-class of or equal to this class.
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.
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...
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 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 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.
@ C
The default llvm calling convention, compatible with C.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Renamable
Register that may be renamed.
@ Define
Register definition.
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
@ ScalablePredicateVector
initializer< Ty > init(const Ty &Val)
InstrType
Represents how an instruction should be mapped by the outliner.
LLVM_ABI Instruction & back() const
This is an optimization pass for GlobalISel generic memory operations.
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.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, 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 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
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.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
CombinerObjective
The combiner's goal may differ based on which pattern it is attempting to optimize.
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.
unsigned getUndefRegState(bool B)
static MCRegister getXRegFromWReg(MCRegister Reg)
unsigned getDefRegState(bool B)
MCCFIInstruction createCFAOffset(const TargetRegisterInfo &MRI, unsigned Reg, const StackOffset &OffsetFromDefCFA, std::optional< int64_t > IncomingVGOffsetFromDefCFA)
unsigned getKillRegState(bool B)
FunctionAddr VTableAddr Next
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.
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)
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 ...
auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
static const MachineMemOperand::Flags MOStridedAccess
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.
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 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.