43#define AARCH64_EXPAND_PSEUDO_NAME "AArch64 pseudo instruction expansion pass"
47class AArch64ExpandPseudoImpl {
61 unsigned ContiguousOpc,
unsigned StridedOpc);
72 unsigned LdarOp,
unsigned StlrOp,
unsigned CmpOp,
73 unsigned ExtendImm,
unsigned ZeroReg,
89 struct ConditionalBlocks {
118char AArch64ExpandPseudoLegacy::ID = 0;
130 assert(MO.isReg() && MO.getReg());
149 if (DstReg == AArch64::XZR || DstReg == AArch64::WZR) {
152 MI.eraseFromParent();
160 SmallVector<MachineInstrBuilder, 4> MIBS;
162 bool LastItem = std::next(
I) ==
E;
167 case AArch64::ORRWri:
168 case AArch64::ORRXri:
169 case AArch64::ANDXri:
170 case AArch64::EORXri:
173 .
add(
MI.getOperand(0))
174 .
addReg(BitSize == 32 ? AArch64::WZR : AArch64::XZR)
178 bool DstIsDead =
MI.getOperand(0).isDead();
181 .
addReg(DstReg, RegState::Define |
188 case AArch64::EONXrs:
189 case AArch64::EORXrs:
190 case AArch64::ORRWrs:
191 case AArch64::ORRXrs: {
193 bool DstIsDead =
MI.getOperand(0).isDead();
196 .
addReg(DstReg, RegState::Define |
203 case AArch64::MOVNWi:
204 case AArch64::MOVNXi:
205 case AArch64::MOVZWi:
206 case AArch64::MOVZXi: {
207 bool DstIsDead =
MI.getOperand(0).isDead();
210 .
addReg(DstReg, RegState::Define |
216 case AArch64::MOVKWi:
217 case AArch64::MOVKXi: {
219 bool DstIsDead =
MI.getOperand(0).isDead();
222 .
addReg(DstReg, RegState::Define |
232 MI.eraseFromParent();
236bool AArch64ExpandPseudoImpl::expandCMP_SWAP(
238 unsigned StlrOp,
unsigned CmpOp,
unsigned ExtendImm,
unsigned ZeroReg,
242 const MachineOperand &Dest =
MI.getOperand(0);
243 Register StatusReg =
MI.getOperand(1).getReg();
244 bool StatusDead =
MI.getOperand(1).isDead();
247 assert(!
MI.getOperand(2).isUndef() &&
"cannot handle undef");
249 Register DesiredReg =
MI.getOperand(3).getReg();
258 MF->
insert(++LoadCmpBB->getIterator(), StoreBB);
259 MF->
insert(++StoreBB->getIterator(), DoneBB);
267 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::MOVZWi), StatusReg)
271 BuildMI(LoadCmpBB, MIMD,
TII->get(CmpOp), ZeroReg)
275 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::Bcc))
278 .
addReg(AArch64::NZCV, RegState::Implicit | RegState::Kill);
279 LoadCmpBB->addSuccessor(DoneBB);
280 LoadCmpBB->addSuccessor(StoreBB);
285 BuildMI(StoreBB, MIMD,
TII->get(StlrOp), StatusReg)
288 BuildMI(StoreBB, MIMD,
TII->get(AArch64::CBNZW))
291 StoreBB->addSuccessor(LoadCmpBB);
292 StoreBB->addSuccessor(DoneBB);
294 DoneBB->splice(DoneBB->end(), &
MBB,
MI,
MBB.
end());
295 DoneBB->transferSuccessors(&
MBB);
300 MI.eraseFromParent();
303 LivePhysRegs LiveRegs;
308 StoreBB->clearLiveIns();
310 LoadCmpBB->clearLiveIns();
316bool AArch64ExpandPseudoImpl::expandCMP_SWAP_128(
321 MachineOperand &DestLo =
MI.getOperand(0);
322 MachineOperand &DestHi =
MI.getOperand(1);
323 Register StatusReg =
MI.getOperand(2).getReg();
324 bool StatusDead =
MI.getOperand(2).isDead();
327 assert(!
MI.getOperand(3).isUndef() &&
"cannot handle undef");
329 Register DesiredLoReg =
MI.getOperand(4).getReg();
330 Register DesiredHiReg =
MI.getOperand(5).getReg();
331 Register NewLoReg =
MI.getOperand(6).getReg();
332 Register NewHiReg =
MI.getOperand(7).getReg();
335 bool LittleEndian = STI.isLittleEndian();
336 MachineOperand &Dest0 = LittleEndian ? DestLo : DestHi;
337 MachineOperand &Dest1 = LittleEndian ? DestHi : DestLo;
338 Register New0Reg = LittleEndian ? NewLoReg : NewHiReg;
339 Register New1Reg = LittleEndian ? NewHiReg : NewLoReg;
341 unsigned LdxpOp, StxpOp;
343 switch (
MI.getOpcode()) {
344 case AArch64::CMP_SWAP_128_MONOTONIC:
345 LdxpOp = AArch64::LDXPX;
346 StxpOp = AArch64::STXPX;
348 case AArch64::CMP_SWAP_128_RELEASE:
349 LdxpOp = AArch64::LDXPX;
350 StxpOp = AArch64::STLXPX;
352 case AArch64::CMP_SWAP_128_ACQUIRE:
353 LdxpOp = AArch64::LDAXPX;
354 StxpOp = AArch64::STXPX;
356 case AArch64::CMP_SWAP_128:
357 LdxpOp = AArch64::LDAXPX;
358 StxpOp = AArch64::STLXPX;
371 MF->
insert(++LoadCmpBB->getIterator(), StoreBB);
372 MF->
insert(++StoreBB->getIterator(), FailBB);
373 MF->
insert(++FailBB->getIterator(), DoneBB);
384 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::SUBSXrs), AArch64::XZR)
388 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::CSINCWr), StatusReg)
392 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::SUBSXrs), AArch64::XZR)
396 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::CSINCWr), StatusReg)
397 .
addUse(StatusReg, RegState::Kill)
398 .
addUse(StatusReg, RegState::Kill)
400 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::CBNZW))
403 LoadCmpBB->addSuccessor(FailBB);
404 LoadCmpBB->addSuccessor(StoreBB);
409 BuildMI(StoreBB, MIMD,
TII->get(StxpOp), StatusReg)
413 BuildMI(StoreBB, MIMD,
TII->get(AArch64::CBNZW))
417 StoreBB->addSuccessor(LoadCmpBB);
418 StoreBB->addSuccessor(DoneBB);
423 BuildMI(FailBB, MIMD,
TII->get(StxpOp), StatusReg)
427 BuildMI(FailBB, MIMD,
TII->get(AArch64::CBNZW))
430 FailBB->addSuccessor(LoadCmpBB);
431 FailBB->addSuccessor(DoneBB);
433 DoneBB->splice(DoneBB->end(), &
MBB,
MI,
MBB.
end());
434 DoneBB->transferSuccessors(&
MBB);
439 MI.eraseFromParent();
442 LivePhysRegs LiveRegs;
449 FailBB->clearLiveIns();
451 StoreBB->clearLiveIns();
453 LoadCmpBB->clearLiveIns();
497bool AArch64ExpandPseudoImpl::expand_DestructiveOp(
498 MachineInstr &
MI, MachineBasicBlock &
MBB,
505 bool DstIsDead =
MI.getOperand(0).isDead();
507 unsigned PredIdx, DOPIdx, SrcIdx, Src2Idx;
512 if (DstReg ==
MI.getOperand(3).getReg()) {
514 std::tie(PredIdx, DOPIdx, SrcIdx) = std::make_tuple(1, 3, 2);
521 std::tie(PredIdx, DOPIdx, SrcIdx) = std::make_tuple(1, 2, 3);
524 std::tie(PredIdx, DOPIdx, SrcIdx) = std::make_tuple(2, 3, 3);
527 std::tie(PredIdx, DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 2, 3, 4);
528 if (DstReg ==
MI.getOperand(3).getReg()) {
530 std::tie(PredIdx, DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 3, 4, 2);
532 }
else if (DstReg ==
MI.getOperand(4).getReg()) {
534 std::tie(PredIdx, DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 4, 3, 2);
541 std::tie(DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 1, 2);
544 std::tie(DOPIdx, SrcIdx) = std::make_tuple(1, 2);
547 std::tie(DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 2, 3);
556 bool DOPRegIsUnique =
false;
559 DOPRegIsUnique = DstReg !=
MI.getOperand(SrcIdx).getReg();
564 DstReg !=
MI.getOperand(DOPIdx).getReg() ||
565 MI.getOperand(DOPIdx).getReg() !=
MI.getOperand(SrcIdx).getReg();
572 DOPRegIsUnique =
true;
576 DstReg !=
MI.getOperand(DOPIdx).getReg() ||
577 (
MI.getOperand(DOPIdx).
getReg() !=
MI.getOperand(SrcIdx).getReg() &&
578 MI.getOperand(DOPIdx).getReg() !=
MI.getOperand(Src2Idx).getReg());
594 uint64_t ElementSize =
TII->getElementSizeForOpcode(Opcode);
595 unsigned MovPrfx, LSLZero, MovPrfxZero;
596 switch (ElementSize) {
599 MovPrfx = AArch64::MOVPRFX_ZZ;
600 LSLZero = AArch64::LSL_ZPmI_B;
601 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_B;
604 MovPrfx = AArch64::MOVPRFX_ZZ;
605 LSLZero = AArch64::LSL_ZPmI_H;
606 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_H;
609 MovPrfx = AArch64::MOVPRFX_ZZ;
610 LSLZero = AArch64::LSL_ZPmI_S;
611 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_S;
614 MovPrfx = AArch64::MOVPRFX_ZZ;
615 LSLZero = AArch64::LSL_ZPmI_D;
616 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_D;
628 MachineInstrBuilder PRFX, DOP;
635 "The destructive operand should be unique");
637 "This instruction is unpredicated");
641 .
addReg(DstReg, RegState::Define)
642 .
addReg(
MI.getOperand(PredIdx).getReg())
643 .
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState);
657 .
addReg(DstReg, RegState::Define)
658 .
add(
MI.getOperand(PredIdx))
662 }
else if (DstReg !=
MI.getOperand(DOPIdx).getReg()) {
663 assert(DOPRegIsUnique &&
"The destructive operand should be unique");
665 .
addReg(DstReg, RegState::Define)
666 .
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState);
676 DOPRegState = DOPRegState | RegState::Kill;
680 DOP.
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState)
681 .
add(
MI.getOperand(PredIdx))
682 .
add(
MI.getOperand(SrcIdx));
688 DOP.
add(
MI.getOperand(PredIdx))
689 .
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState)
690 .
add(
MI.getOperand(SrcIdx));
693 DOP.
add(
MI.getOperand(PredIdx))
694 .
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState)
695 .
add(
MI.getOperand(SrcIdx))
696 .
add(
MI.getOperand(Src2Idx));
699 DOP.
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState)
700 .
add(
MI.getOperand(SrcIdx));
704 DOP.
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState)
705 .
add(
MI.getOperand(SrcIdx))
706 .
add(
MI.getOperand(Src2Idx));
716 MI.eraseFromParent();
720bool AArch64ExpandPseudoImpl::expandSVEBitwisePseudo(
721 MachineInstr &
MI, MachineBasicBlock &
MBB,
723 MachineInstrBuilder PRFX, DOP;
724 const unsigned Opcode =
MI.getOpcode();
725 const MachineOperand &Op0 =
MI.getOperand(0);
726 const MachineOperand *Op1 = &
MI.getOperand(1);
727 const MachineOperand *Op2 = &
MI.getOperand(2);
730 if (DOPReg == Op2->
getReg()) {
733 }
else if (DOPReg != Op1->
getReg()) {
742 Opcode == AArch64::NAND_ZZZ));
745 assert((DOPReg == Op1->
getReg() || PRFX) &&
"invalid expansion");
754 case AArch64::EON_ZZZ:
757 .
addReg(DOPReg, DOPRegState)
761 case AArch64::NAND_ZZZ:
764 .
addReg(DOPReg, DOPRegState)
768 case AArch64::NOR_ZZZ:
771 .
addReg(DOPReg, DOPRegState)
784 MI.eraseFromParent();
788bool AArch64ExpandPseudoImpl::expandSetTagLoop(
794 Register AddressReg =
MI.getOperand(1).getReg();
798 bool ZeroData =
MI.getOpcode() == AArch64::STZGloop_wback;
799 const unsigned OpCode1 =
800 ZeroData ? AArch64::STZGPostIndex : AArch64::STGPostIndex;
801 const unsigned OpCode2 =
802 ZeroData ? AArch64::STZ2GPostIndex : AArch64::ST2GPostIndex;
804 unsigned Size =
MI.getOperand(2).getImm();
806 if (
Size % (16 * 2) != 0) {
822 MF->
insert(++LoopBB->getIterator(), DoneBB);
839 .
addReg(AArch64::NZCV, RegState::Implicit | RegState::Kill);
841 LoopBB->addSuccessor(LoopBB);
842 LoopBB->addSuccessor(DoneBB);
844 DoneBB->splice(DoneBB->end(), &
MBB,
MI,
MBB.
end());
845 DoneBB->transferSuccessors(&
MBB);
850 MI.eraseFromParent();
852 LivePhysRegs LiveRegs;
857 LoopBB->clearLiveIns();
859 DoneBB->clearLiveIns();
865bool AArch64ExpandPseudoImpl::expandSVESpillFill(
868 assert((
Opc == AArch64::LDR_ZXI ||
Opc == AArch64::STR_ZXI ||
869 Opc == AArch64::LDR_PXI ||
Opc == AArch64::STR_PXI) &&
870 "Unexpected opcode");
873 unsigned sub0 = (
Opc == AArch64::LDR_ZXI ||
Opc == AArch64::STR_ZXI)
876 const TargetRegisterInfo *
TRI =
880 int ImmOffset =
MI.getOperand(2).getImm() +
Offset;
881 bool Kill = (
Offset + 1 ==
N) ?
MI.getOperand(1).isKill() :
false;
882 assert(ImmOffset >= -256 && ImmOffset < 256 &&
883 "Immediate spill offset out of range");
901 unsigned RegMaskStartIdx) {
906 MF.CreateMachineInstr(
TII->get(Opcode),
MBBI->getDebugLoc(),
914 while (!
MBBI->getOperand(RegMaskStartIdx).isRegMask()) {
916 assert(MOP.
isReg() &&
"can only add register operands");
918 MOP.
getReg(),
false,
true,
false,
924 Call->addOperand(MO);
935 unsigned RegMaskStartIdx) {
936 unsigned Opc = CallTarget.
isGlobal() ? AArch64::BL : AArch64::BLR;
939 "invalid operand for regular call");
943bool AArch64ExpandPseudoImpl::expandCALL_RVMARKER(
951 MachineOperand &RVTarget =
MI.getOperand(0);
952 bool DoEmitMarker =
MI.getOperand(1).getImm();
953 assert(RVTarget.
isGlobal() &&
"invalid operand for attached call");
955 MachineInstr *OriginalCall =
nullptr;
957 if (
MI.getOpcode() == AArch64::BLRA_RVMARKER) {
959 const MachineOperand &CallTarget =
MI.getOperand(2);
960 const MachineOperand &
Key =
MI.getOperand(3);
961 const MachineOperand &IntDisc =
MI.getOperand(4);
962 const MachineOperand &AddrDisc =
MI.getOperand(5);
966 "Invalid auth call key");
968 MachineOperand
Ops[] = {CallTarget,
Key, IntDisc, AddrDisc};
973 assert(
MI.getOpcode() == AArch64::BLR_RVMARKER &&
"unknown rvmarker MI");
981 .
addReg(AArch64::FP, RegState::Define)
990 if (
MI.shouldUpdateAdditionalCallInfo())
993 MI.eraseFromParent();
995 std::next(RVCall->getIterator()));
999bool AArch64ExpandPseudoImpl::expandCALL_BTI(MachineBasicBlock &
MBB,
1006 MachineInstr &
MI = *
MBBI;
1019 if (
MI.shouldUpdateAdditionalCallInfo())
1022 MI.eraseFromParent();
1027bool AArch64ExpandPseudoImpl::expandStoreSwiftAsyncContext(
1035 if (STI.getTargetTriple().getArchName() !=
"arm64e") {
1052 unsigned Opc =
Offset >= 0 ? AArch64::ADDXri : AArch64::SUBXri;
1084AArch64ExpandPseudoImpl::ConditionalBlocks
1085AArch64ExpandPseudoImpl::expandConditionalPseudo(
1087 MachineInstrBuilder &Branch) {
1090 "Unexpected unreachable in block");
1096 MachineInstr &PrevMI = *std::prev(
MBBI);
1097 MachineBasicBlock *CondBB =
MBB.
splitAt(PrevMI,
true);
1098 MachineBasicBlock *EndBB =
1099 std::next(
MBBI) == CondBB->
end()
1112 return {*CondBB, *EndBB};
1116AArch64ExpandPseudoImpl::expandRestoreZASave(MachineBasicBlock &
MBB,
1118 MachineInstr &
MI = *
MBBI;
1122 MachineInstrBuilder
Branch =
1125 auto [CondBB, EndBB] = expandConditionalPseudo(
MBB,
MBBI,
DL, Branch);
1127 MachineInstrBuilder MIB =
1130 for (
unsigned I = 2;
I <
MI.getNumOperands(); ++
I)
1131 MIB.
add(
MI.getOperand(
I));
1133 MIB.
addReg(
MI.getOperand(1).getReg(), RegState::Implicit);
1135 MI.eraseFromParent();
1146 [[maybe_unused]]
auto *RI =
MBB.getParent()->getSubtarget().getRegisterInfo();
1152 auto [CondBB, EndBB] = expandConditionalPseudo(
MBB,
MBBI,
DL, Branch);
1157 for (
unsigned I = 3;
I <
MI.getNumOperands(); ++
I)
1158 MIB.
add(
MI.getOperand(
I));
1161 .
addImm(AArch64SysReg::TPIDR2_EL0)
1163 bool ZeroZA =
MI.getOperand(1).getImm() != 0;
1164 bool ZeroZT0 =
MI.getOperand(2).getImm() != 0;
1166 assert(
MI.definesRegister(AArch64::ZAB0, RI) &&
"should define ZA!");
1172 assert(
MI.definesRegister(AArch64::ZT0, RI) &&
"should define ZT0!");
1177 MI.eraseFromParent();
1182AArch64ExpandPseudoImpl::expandCondSMToggle(MachineBasicBlock &
MBB,
1184 MachineInstr &
MI = *
MBBI;
1191 MI.getParent()->successors().begin() ==
1192 MI.getParent()->successors().end()) {
1193 MI.eraseFromParent();
1236 switch (
MI.getOperand(2).getImm()) {
1240 Opc = AArch64::TBNZW;
1243 Opc = AArch64::TBZW;
1246 auto PStateSM =
MI.getOperand(3).getReg();
1248 unsigned SMReg32 =
TRI->getSubReg(PStateSM, AArch64::sub_32);
1249 MachineInstrBuilder Tbx =
1252 auto [CondBB, EndBB] = expandConditionalPseudo(
MBB,
MBBI,
DL, Tbx);
1255 TII->get(AArch64::MSRpstatesvcrImm1));
1259 MIB.
add(
MI.getOperand(0));
1260 MIB.
add(
MI.getOperand(1));
1261 for (
unsigned i = 4; i <
MI.getNumOperands(); ++i)
1262 MIB.
add(
MI.getOperand(i));
1264 MI.eraseFromParent();
1268bool AArch64ExpandPseudoImpl::expandMultiVecPseudo(
1272 unsigned StridedOpc) {
1273 MachineInstr &
MI = *
MBBI;
1287 .
add(
MI.getOperand(0))
1288 .
add(
MI.getOperand(1))
1289 .
add(
MI.getOperand(2))
1290 .
add(
MI.getOperand(3));
1292 MI.eraseFromParent();
1296bool AArch64ExpandPseudoImpl::expandCopyIntoTuplePseudo(
1297 MachineInstr &
MI, MachineBasicBlock &
MBB,
1304 .
addReg(Dest, RegState::Define)
1308 MI.eraseFromParent();
1314bool AArch64ExpandPseudoImpl::expandMI(MachineBasicBlock &
MBB,
1317 MachineInstr &
MI = *
MBBI;
1318 unsigned Opcode =
MI.getOpcode();
1322 if (OrigInstr != -1) {
1323 auto &Orig =
TII->get(OrigInstr);
1326 return expand_DestructiveOp(
MI,
MBB,
MBBI);
1334 case AArch64::BSPv8i8:
1335 case AArch64::BSPv16i8: {
1337 if (DstReg ==
MI.getOperand(3).getReg()) {
1340 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BITv8i8
1341 : AArch64::BITv16i8))
1342 .
add(
MI.getOperand(0))
1343 .
add(
MI.getOperand(3))
1344 .
add(
MI.getOperand(2))
1345 .
add(
MI.getOperand(1));
1347 }
else if (DstReg ==
MI.getOperand(2).getReg()) {
1350 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BIFv8i8
1351 : AArch64::BIFv16i8))
1352 .
add(
MI.getOperand(0))
1353 .
add(
MI.getOperand(2))
1354 .
add(
MI.getOperand(3))
1355 .
add(
MI.getOperand(1));
1359 if (DstReg ==
MI.getOperand(1).getReg()) {
1362 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BSLv8i8
1363 : AArch64::BSLv16i8))
1364 .
add(
MI.getOperand(0))
1365 .
add(
MI.getOperand(1))
1366 .
add(
MI.getOperand(2))
1367 .
add(
MI.getOperand(3));
1373 MI.getOperand(1).isKill() &&
1374 MI.getOperand(1).getReg() !=
MI.getOperand(2).getReg() &&
1375 MI.getOperand(1).getReg() !=
MI.getOperand(3).getReg());
1377 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::ORRv8i8
1378 : AArch64::ORRv16i8))
1386 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BSLv8i8
1387 : AArch64::BSLv16i8))
1388 .
add(
MI.getOperand(0))
1391 MI.getOperand(0).isRenamable()))
1392 .
add(
MI.getOperand(2))
1393 .
add(
MI.getOperand(3));
1397 MI.eraseFromParent();
1401 case AArch64::ADDWrr:
1402 case AArch64::SUBWrr:
1403 case AArch64::ADDXrr:
1404 case AArch64::SUBXrr:
1405 case AArch64::ADDSWrr:
1406 case AArch64::SUBSWrr:
1407 case AArch64::ADDSXrr:
1408 case AArch64::SUBSXrr:
1409 case AArch64::ANDWrr:
1410 case AArch64::ANDXrr:
1411 case AArch64::BICWrr:
1412 case AArch64::BICXrr:
1413 case AArch64::ANDSWrr:
1414 case AArch64::ANDSXrr:
1415 case AArch64::BICSWrr:
1416 case AArch64::BICSXrr:
1417 case AArch64::EONWrr:
1418 case AArch64::EONXrr:
1419 case AArch64::EORWrr:
1420 case AArch64::EORXrr:
1421 case AArch64::ORNWrr:
1422 case AArch64::ORNXrr:
1423 case AArch64::ORRWrr:
1424 case AArch64::ORRXrr: {
1426 switch (
MI.getOpcode()) {
1429 case AArch64::ADDWrr: Opcode = AArch64::ADDWrs;
break;
1430 case AArch64::SUBWrr: Opcode = AArch64::SUBWrs;
break;
1431 case AArch64::ADDXrr: Opcode = AArch64::ADDXrs;
break;
1432 case AArch64::SUBXrr: Opcode = AArch64::SUBXrs;
break;
1433 case AArch64::ADDSWrr: Opcode = AArch64::ADDSWrs;
break;
1434 case AArch64::SUBSWrr: Opcode = AArch64::SUBSWrs;
break;
1435 case AArch64::ADDSXrr: Opcode = AArch64::ADDSXrs;
break;
1436 case AArch64::SUBSXrr: Opcode = AArch64::SUBSXrs;
break;
1437 case AArch64::ANDWrr: Opcode = AArch64::ANDWrs;
break;
1438 case AArch64::ANDXrr: Opcode = AArch64::ANDXrs;
break;
1439 case AArch64::BICWrr: Opcode = AArch64::BICWrs;
break;
1440 case AArch64::BICXrr: Opcode = AArch64::BICXrs;
break;
1441 case AArch64::ANDSWrr: Opcode = AArch64::ANDSWrs;
break;
1442 case AArch64::ANDSXrr: Opcode = AArch64::ANDSXrs;
break;
1443 case AArch64::BICSWrr: Opcode = AArch64::BICSWrs;
break;
1444 case AArch64::BICSXrr: Opcode = AArch64::BICSXrs;
break;
1445 case AArch64::EONWrr: Opcode = AArch64::EONWrs;
break;
1446 case AArch64::EONXrr: Opcode = AArch64::EONXrs;
break;
1447 case AArch64::EORWrr: Opcode = AArch64::EORWrs;
break;
1448 case AArch64::EORXrr: Opcode = AArch64::EORXrs;
break;
1449 case AArch64::ORNWrr: Opcode = AArch64::ORNWrs;
break;
1450 case AArch64::ORNXrr: Opcode = AArch64::ORNXrs;
break;
1451 case AArch64::ORRWrr: Opcode = AArch64::ORRWrs;
break;
1452 case AArch64::ORRXrr: Opcode = AArch64::ORRXrs;
break;
1456 MachineInstr *NewMI = MF.CreateMachineInstr(
1457 TII->get(Opcode),
MI.getDebugLoc(),
true);
1459 MachineInstrBuilder MIB1(MF, NewMI);
1460 MIB1->setPCSections(MF,
MI.getPCSections());
1461 MIB1.addReg(
MI.getOperand(0).getReg(), RegState::Define)
1462 .add(
MI.getOperand(1))
1463 .add(
MI.getOperand(2))
1466 if (
auto DebugNumber =
MI.peekDebugInstrNum())
1468 MI.eraseFromParent();
1472 case AArch64::LOADgot: {
1475 const MachineOperand &MO1 =
MI.getOperand(1);
1481 TII->get(AArch64::LDRXl), DstReg);
1489 "Only expect globals, externalsymbols, or constant pools");
1496 MachineInstrBuilder MIB1 =
1499 MachineInstrBuilder MIB2;
1500 if (MF.
getSubtarget<AArch64Subtarget>().isTargetILP32()) {
1502 unsigned Reg32 =
TRI->getSubReg(DstReg, AArch64::sub_32);
1505 .
addReg(DstReg, RegState::Kill)
1506 .
addReg(DstReg, RegState::Implicit);
1510 .
add(
MI.getOperand(0))
1511 .
addUse(DstReg, RegState::Kill);
1525 "Only expect globals, externalsymbols, or constant pools");
1536 if (
MI.peekDebugInstrNum() != 0)
1540 MI.eraseFromParent();
1543 case AArch64::MOVaddrBA:
1544 case AArch64::MOVaddr:
1545 case AArch64::MOVaddrJT:
1546 case AArch64::MOVaddrCP:
1547 case AArch64::MOVaddrTLS:
1548 case AArch64::MOVaddrEXT: {
1551 assert(DstReg != AArch64::XZR);
1553 bool IsTargetMachO = MF.
getSubtarget<AArch64Subtarget>().isTargetMachO();
1556 MI.getOpcode(),
MI.getOperand(1).getTargetFlags(), IsTargetMachO, Insn);
1559 std::optional<unsigned> CPIdx;
1560 if (Opcode == AArch64::MOVaddrBA && IsTargetMachO) {
1565 assert(
MI.getOperand(1).getOffset() == 0 &&
"unexpected offset");
1570 MachineInstrBuilder FirstMIB;
1571 MachineInstrBuilder LastMIB;
1572 for (
const auto &
I : Insn) {
1573 MachineInstrBuilder MIB;
1581 MIB.
add(
MI.getOperand(1));
1583 case AArch64::LDRXui:
1590 case AArch64::MOVKXi: {
1598 auto Tag =
MI.getOperand(1);
1600 Tag.setOffset(0x100000000);
1608 case AArch64::ADDXri:
1610 .
add(
MI.getOperand(0))
1612 .
add(
MI.getOperand(2))
1625 MI.eraseFromParent();
1628 case AArch64::ADDlowTLS:
1631 .
add(
MI.getOperand(0))
1632 .
add(
MI.getOperand(1))
1633 .
add(
MI.getOperand(2))
1635 MI.eraseFromParent();
1638 case AArch64::MOVbaseTLS: {
1640 auto SysReg = AArch64SysReg::TPIDR_EL0;
1642 if (MF->
getSubtarget<AArch64Subtarget>().useEL3ForTP())
1643 SysReg = AArch64SysReg::TPIDR_EL3;
1644 else if (MF->
getSubtarget<AArch64Subtarget>().useEL2ForTP())
1645 SysReg = AArch64SysReg::TPIDR_EL2;
1646 else if (MF->
getSubtarget<AArch64Subtarget>().useEL1ForTP())
1647 SysReg = AArch64SysReg::TPIDR_EL1;
1648 else if (MF->
getSubtarget<AArch64Subtarget>().useROEL0ForTP())
1649 SysReg = AArch64SysReg::TPIDRRO_EL0;
1652 MI.eraseFromParent();
1656 case AArch64::MOVi32imm:
1658 case AArch64::MOVi64imm:
1660 case AArch64::RET_ReallyLR: {
1666 MachineInstrBuilder MIB =
1668 .
addReg(AArch64::LR, RegState::Undef);
1670 MI.eraseFromParent();
1673 case AArch64::CMP_SWAP_8:
1674 return expandCMP_SWAP(
MBB,
MBBI, AArch64::LDAXRB, AArch64::STLXRB,
1677 AArch64::WZR, NextMBBI);
1678 case AArch64::CMP_SWAP_16:
1679 return expandCMP_SWAP(
MBB,
MBBI, AArch64::LDAXRH, AArch64::STLXRH,
1682 AArch64::WZR, NextMBBI);
1683 case AArch64::CMP_SWAP_32:
1684 return expandCMP_SWAP(
MBB,
MBBI, AArch64::LDAXRW, AArch64::STLXRW,
1687 AArch64::WZR, NextMBBI);
1688 case AArch64::CMP_SWAP_64:
1689 return expandCMP_SWAP(
MBB,
MBBI,
1690 AArch64::LDAXRX, AArch64::STLXRX, AArch64::SUBSXrs,
1692 AArch64::XZR, NextMBBI);
1693 case AArch64::CMP_SWAP_128:
1694 case AArch64::CMP_SWAP_128_RELEASE:
1695 case AArch64::CMP_SWAP_128_ACQUIRE:
1696 case AArch64::CMP_SWAP_128_MONOTONIC:
1697 return expandCMP_SWAP_128(
MBB,
MBBI, NextMBBI);
1699 case AArch64::AESMCrrTied:
1700 case AArch64::AESIMCrrTied: {
1701 MachineInstrBuilder MIB =
1703 TII->get(Opcode == AArch64::AESMCrrTied ? AArch64::AESMCrr :
1705 .
add(
MI.getOperand(0))
1706 .
add(
MI.getOperand(1));
1708 MI.eraseFromParent();
1711 case AArch64::IRGstack: {
1713 const AArch64FunctionInfo *AFI = MF.
getInfo<AArch64FunctionInfo>();
1714 const AArch64FrameLowering *TFI =
1715 MF.
getSubtarget<AArch64Subtarget>().getFrameLowering();
1722 StackOffset FrameRegOffset = TFI->resolveFrameOffsetReference(
1728 if (FrameRegOffset) {
1730 SrcReg =
MI.getOperand(0).getReg();
1732 FrameRegOffset,
TII);
1735 .
add(
MI.getOperand(0))
1737 .
add(
MI.getOperand(2));
1738 MI.eraseFromParent();
1741 case AArch64::TAGPstack: {
1742 int64_t
Offset =
MI.getOperand(2).getImm();
1744 TII->get(
Offset >= 0 ? AArch64::ADDG : AArch64::SUBG))
1745 .
add(
MI.getOperand(0))
1746 .
add(
MI.getOperand(1))
1748 .
add(
MI.getOperand(4));
1749 MI.eraseFromParent();
1752 case AArch64::STGloop_wback:
1753 case AArch64::STZGloop_wback:
1754 return expandSetTagLoop(
MBB,
MBBI, NextMBBI);
1755 case AArch64::STGloop:
1756 case AArch64::STZGloop:
1758 "Non-writeback variants of STGloop / STZGloop should not "
1759 "survive past PrologEpilogInserter.");
1760 case AArch64::STR_ZZZZXI:
1761 case AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS:
1762 return expandSVESpillFill(
MBB,
MBBI, AArch64::STR_ZXI, 4);
1763 case AArch64::STR_ZZZXI:
1764 return expandSVESpillFill(
MBB,
MBBI, AArch64::STR_ZXI, 3);
1765 case AArch64::STR_ZZXI:
1766 case AArch64::STR_ZZXI_STRIDED_CONTIGUOUS:
1767 return expandSVESpillFill(
MBB,
MBBI, AArch64::STR_ZXI, 2);
1768 case AArch64::STR_PPXI:
1769 return expandSVESpillFill(
MBB,
MBBI, AArch64::STR_PXI, 2);
1770 case AArch64::LDR_ZZZZXI:
1771 case AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS:
1772 return expandSVESpillFill(
MBB,
MBBI, AArch64::LDR_ZXI, 4);
1773 case AArch64::LDR_ZZZXI:
1774 return expandSVESpillFill(
MBB,
MBBI, AArch64::LDR_ZXI, 3);
1775 case AArch64::LDR_ZZXI:
1776 case AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS:
1777 return expandSVESpillFill(
MBB,
MBBI, AArch64::LDR_ZXI, 2);
1778 case AArch64::LDR_PPXI:
1779 return expandSVESpillFill(
MBB,
MBBI, AArch64::LDR_PXI, 2);
1780 case AArch64::BLR_RVMARKER:
1781 case AArch64::BLRA_RVMARKER:
1782 return expandCALL_RVMARKER(
MBB,
MBBI);
1783 case AArch64::BLR_BTI:
1784 return expandCALL_BTI(
MBB,
MBBI);
1785 case AArch64::StoreSwiftAsyncContext:
1786 return expandStoreSwiftAsyncContext(
MBB,
MBBI);
1787 case AArch64::RestoreZAPseudo:
1788 case AArch64::CommitZASavePseudo:
1789 case AArch64::MSRpstatePseudo: {
1790 auto *NewMBB = [&] {
1792 case AArch64::RestoreZAPseudo:
1793 return expandRestoreZASave(
MBB,
MBBI);
1794 case AArch64::CommitZASavePseudo:
1795 return expandCommitZASave(
MBB,
MBBI);
1796 case AArch64::MSRpstatePseudo:
1797 return expandCondSMToggle(
MBB,
MBBI);
1806 case AArch64::InOutZAUsePseudo:
1807 case AArch64::RequiresZASavePseudo:
1808 case AArch64::RequiresZT0SavePseudo:
1809 case AArch64::SMEStateAllocPseudo:
1810 case AArch64::COALESCER_BARRIER_FPR16:
1811 case AArch64::COALESCER_BARRIER_FPR32:
1812 case AArch64::COALESCER_BARRIER_FPR64:
1813 case AArch64::COALESCER_BARRIER_FPR128:
1814 MI.eraseFromParent();
1816 case AArch64::LD1B_2Z_IMM_PSEUDO:
1817 return expandMultiVecPseudo(
1818 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1819 AArch64::LD1B_2Z_IMM, AArch64::LD1B_2Z_STRIDED_IMM);
1820 case AArch64::LD1H_2Z_IMM_PSEUDO:
1821 return expandMultiVecPseudo(
1822 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1823 AArch64::LD1H_2Z_IMM, AArch64::LD1H_2Z_STRIDED_IMM);
1824 case AArch64::LD1W_2Z_IMM_PSEUDO:
1825 return expandMultiVecPseudo(
1826 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1827 AArch64::LD1W_2Z_IMM, AArch64::LD1W_2Z_STRIDED_IMM);
1828 case AArch64::LD1D_2Z_IMM_PSEUDO:
1829 return expandMultiVecPseudo(
1830 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1831 AArch64::LD1D_2Z_IMM, AArch64::LD1D_2Z_STRIDED_IMM);
1832 case AArch64::LDNT1B_2Z_IMM_PSEUDO:
1833 return expandMultiVecPseudo(
1834 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1835 AArch64::LDNT1B_2Z_IMM, AArch64::LDNT1B_2Z_STRIDED_IMM);
1836 case AArch64::LDNT1H_2Z_IMM_PSEUDO:
1837 return expandMultiVecPseudo(
1838 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1839 AArch64::LDNT1H_2Z_IMM, AArch64::LDNT1H_2Z_STRIDED_IMM);
1840 case AArch64::LDNT1W_2Z_IMM_PSEUDO:
1841 return expandMultiVecPseudo(
1842 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1843 AArch64::LDNT1W_2Z_IMM, AArch64::LDNT1W_2Z_STRIDED_IMM);
1844 case AArch64::LDNT1D_2Z_IMM_PSEUDO:
1845 return expandMultiVecPseudo(
1846 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1847 AArch64::LDNT1D_2Z_IMM, AArch64::LDNT1D_2Z_STRIDED_IMM);
1848 case AArch64::ST1B_2Z_IMM_PSEUDO:
1849 return expandMultiVecPseudo(
1850 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1851 AArch64::ST1B_2Z_IMM, AArch64::ST1B_2Z_STRIDED_IMM);
1852 case AArch64::ST1H_2Z_IMM_PSEUDO:
1853 return expandMultiVecPseudo(
1854 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1855 AArch64::ST1H_2Z_IMM, AArch64::ST1H_2Z_STRIDED_IMM);
1856 case AArch64::ST1W_2Z_IMM_PSEUDO:
1857 return expandMultiVecPseudo(
1858 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1859 AArch64::ST1W_2Z_IMM, AArch64::ST1W_2Z_STRIDED_IMM);
1860 case AArch64::ST1D_2Z_IMM_PSEUDO:
1861 return expandMultiVecPseudo(
1862 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1863 AArch64::ST1D_2Z_IMM, AArch64::ST1D_2Z_STRIDED_IMM);
1864 case AArch64::STNT1B_2Z_IMM_PSEUDO:
1865 return expandMultiVecPseudo(
1866 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1867 AArch64::STNT1B_2Z_IMM, AArch64::STNT1B_2Z_STRIDED_IMM);
1868 case AArch64::STNT1H_2Z_IMM_PSEUDO:
1869 return expandMultiVecPseudo(
1870 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1871 AArch64::STNT1H_2Z_IMM, AArch64::STNT1H_2Z_STRIDED_IMM);
1872 case AArch64::STNT1W_2Z_IMM_PSEUDO:
1873 return expandMultiVecPseudo(
1874 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1875 AArch64::STNT1W_2Z_IMM, AArch64::STNT1W_2Z_STRIDED_IMM);
1876 case AArch64::STNT1D_2Z_IMM_PSEUDO:
1877 return expandMultiVecPseudo(
1878 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1879 AArch64::STNT1D_2Z_IMM, AArch64::STNT1D_2Z_STRIDED_IMM);
1880 case AArch64::LD1B_2Z_PSEUDO:
1881 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1882 AArch64::ZPR2StridedRegClass, AArch64::LD1B_2Z,
1883 AArch64::LD1B_2Z_STRIDED);
1884 case AArch64::LD1H_2Z_PSEUDO:
1885 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1886 AArch64::ZPR2StridedRegClass, AArch64::LD1H_2Z,
1887 AArch64::LD1H_2Z_STRIDED);
1888 case AArch64::LD1W_2Z_PSEUDO:
1889 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1890 AArch64::ZPR2StridedRegClass, AArch64::LD1W_2Z,
1891 AArch64::LD1W_2Z_STRIDED);
1892 case AArch64::LD1D_2Z_PSEUDO:
1893 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1894 AArch64::ZPR2StridedRegClass, AArch64::LD1D_2Z,
1895 AArch64::LD1D_2Z_STRIDED);
1896 case AArch64::LDNT1B_2Z_PSEUDO:
1897 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1898 AArch64::ZPR2StridedRegClass,
1899 AArch64::LDNT1B_2Z, AArch64::LDNT1B_2Z_STRIDED);
1900 case AArch64::LDNT1H_2Z_PSEUDO:
1901 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1902 AArch64::ZPR2StridedRegClass,
1903 AArch64::LDNT1H_2Z, AArch64::LDNT1H_2Z_STRIDED);
1904 case AArch64::LDNT1W_2Z_PSEUDO:
1905 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1906 AArch64::ZPR2StridedRegClass,
1907 AArch64::LDNT1W_2Z, AArch64::LDNT1W_2Z_STRIDED);
1908 case AArch64::LDNT1D_2Z_PSEUDO:
1909 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1910 AArch64::ZPR2StridedRegClass,
1911 AArch64::LDNT1D_2Z, AArch64::LDNT1D_2Z_STRIDED);
1912 case AArch64::LD1B_4Z_IMM_PSEUDO:
1913 return expandMultiVecPseudo(
1914 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1915 AArch64::LD1B_4Z_IMM, AArch64::LD1B_4Z_STRIDED_IMM);
1916 case AArch64::LD1H_4Z_IMM_PSEUDO:
1917 return expandMultiVecPseudo(
1918 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1919 AArch64::LD1H_4Z_IMM, AArch64::LD1H_4Z_STRIDED_IMM);
1920 case AArch64::LD1W_4Z_IMM_PSEUDO:
1921 return expandMultiVecPseudo(
1922 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1923 AArch64::LD1W_4Z_IMM, AArch64::LD1W_4Z_STRIDED_IMM);
1924 case AArch64::LD1D_4Z_IMM_PSEUDO:
1925 return expandMultiVecPseudo(
1926 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1927 AArch64::LD1D_4Z_IMM, AArch64::LD1D_4Z_STRIDED_IMM);
1928 case AArch64::LDNT1B_4Z_IMM_PSEUDO:
1929 return expandMultiVecPseudo(
1930 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1931 AArch64::LDNT1B_4Z_IMM, AArch64::LDNT1B_4Z_STRIDED_IMM);
1932 case AArch64::LDNT1H_4Z_IMM_PSEUDO:
1933 return expandMultiVecPseudo(
1934 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1935 AArch64::LDNT1H_4Z_IMM, AArch64::LDNT1H_4Z_STRIDED_IMM);
1936 case AArch64::LDNT1W_4Z_IMM_PSEUDO:
1937 return expandMultiVecPseudo(
1938 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1939 AArch64::LDNT1W_4Z_IMM, AArch64::LDNT1W_4Z_STRIDED_IMM);
1940 case AArch64::LDNT1D_4Z_IMM_PSEUDO:
1941 return expandMultiVecPseudo(
1942 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1943 AArch64::LDNT1D_4Z_IMM, AArch64::LDNT1D_4Z_STRIDED_IMM);
1944 case AArch64::ST1B_4Z_IMM_PSEUDO:
1945 return expandMultiVecPseudo(
1946 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1947 AArch64::ST1B_4Z_IMM, AArch64::ST1B_4Z_STRIDED_IMM);
1948 case AArch64::ST1H_4Z_IMM_PSEUDO:
1949 return expandMultiVecPseudo(
1950 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1951 AArch64::ST1H_4Z_IMM, AArch64::ST1H_4Z_STRIDED_IMM);
1952 case AArch64::ST1W_4Z_IMM_PSEUDO:
1953 return expandMultiVecPseudo(
1954 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1955 AArch64::ST1W_4Z_IMM, AArch64::ST1W_4Z_STRIDED_IMM);
1956 case AArch64::ST1D_4Z_IMM_PSEUDO:
1957 return expandMultiVecPseudo(
1958 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1959 AArch64::ST1D_4Z_IMM, AArch64::ST1D_4Z_STRIDED_IMM);
1960 case AArch64::STNT1B_4Z_IMM_PSEUDO:
1961 return expandMultiVecPseudo(
1962 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1963 AArch64::STNT1B_4Z_IMM, AArch64::STNT1B_4Z_STRIDED_IMM);
1964 case AArch64::STNT1H_4Z_IMM_PSEUDO:
1965 return expandMultiVecPseudo(
1966 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1967 AArch64::STNT1H_4Z_IMM, AArch64::STNT1H_4Z_STRIDED_IMM);
1968 case AArch64::STNT1W_4Z_IMM_PSEUDO:
1969 return expandMultiVecPseudo(
1970 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1971 AArch64::STNT1W_4Z_IMM, AArch64::STNT1W_4Z_STRIDED_IMM);
1972 case AArch64::STNT1D_4Z_IMM_PSEUDO:
1973 return expandMultiVecPseudo(
1974 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1975 AArch64::STNT1D_4Z_IMM, AArch64::STNT1D_4Z_STRIDED_IMM);
1976 case AArch64::LD1B_4Z_PSEUDO:
1977 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1978 AArch64::ZPR4StridedRegClass, AArch64::LD1B_4Z,
1979 AArch64::LD1B_4Z_STRIDED);
1980 case AArch64::LD1H_4Z_PSEUDO:
1981 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1982 AArch64::ZPR4StridedRegClass, AArch64::LD1H_4Z,
1983 AArch64::LD1H_4Z_STRIDED);
1984 case AArch64::LD1W_4Z_PSEUDO:
1985 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1986 AArch64::ZPR4StridedRegClass, AArch64::LD1W_4Z,
1987 AArch64::LD1W_4Z_STRIDED);
1988 case AArch64::LD1D_4Z_PSEUDO:
1989 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1990 AArch64::ZPR4StridedRegClass, AArch64::LD1D_4Z,
1991 AArch64::LD1D_4Z_STRIDED);
1992 case AArch64::LDNT1B_4Z_PSEUDO:
1993 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1994 AArch64::ZPR4StridedRegClass,
1995 AArch64::LDNT1B_4Z, AArch64::LDNT1B_4Z_STRIDED);
1996 case AArch64::LDNT1H_4Z_PSEUDO:
1997 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1998 AArch64::ZPR4StridedRegClass,
1999 AArch64::LDNT1H_4Z, AArch64::LDNT1H_4Z_STRIDED);
2000 case AArch64::LDNT1W_4Z_PSEUDO:
2001 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
2002 AArch64::ZPR4StridedRegClass,
2003 AArch64::LDNT1W_4Z, AArch64::LDNT1W_4Z_STRIDED);
2004 case AArch64::LDNT1D_4Z_PSEUDO:
2005 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
2006 AArch64::ZPR4StridedRegClass,
2007 AArch64::LDNT1D_4Z, AArch64::LDNT1D_4Z_STRIDED);
2008 case AArch64::COPY_INTO_TRANSPOSED_TUPLE:
2009 return expandCopyIntoTuplePseudo(
MI,
MBB,
MBBI);
2010 case AArch64::EON_ZZZ:
2011 case AArch64::NAND_ZZZ:
2012 case AArch64::NOR_ZZZ:
2013 return expandSVEBitwisePseudo(
MI,
MBB,
MBBI);
2020bool AArch64ExpandPseudoImpl::expandMBB(MachineBasicBlock &
MBB) {
2026 if (
MBBI->isPseudo())
2038 for (
auto &
MBB : MF)
2043bool AArch64ExpandPseudoLegacy::runOnMachineFunction(
MachineFunction &MF) {
2044 return AArch64ExpandPseudoImpl().run(MF);
2049 return new AArch64ExpandPseudoLegacy();
2055 const bool Changed = AArch64ExpandPseudoImpl().run(MF);
#define AARCH64_EXPAND_PSEUDO_NAME
MachineInstrBuilder & UseMI
static MachineInstr * createCallWithOps(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const AArch64InstrInfo *TII, unsigned Opcode, ArrayRef< MachineOperand > ExplicitOps, unsigned RegMaskStartIdx)
static constexpr unsigned ZERO_ALL_ZA_MASK
static MachineInstr * createCall(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const AArch64InstrInfo *TII, MachineOperand &CallTarget, unsigned RegMaskStartIdx)
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const HexagonInstrInfo * TII
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static void transferImpOps(const MachineInstr &OldMI, MachineInstrBuilder &MI)
Transfer implicit operands on the pseudo instruction to the instructions created from the expansion.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
unsigned getTaggedBasePointerOffset() const
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Represents analyses that only rely on functions' control flow.
FunctionPass class - This class is used to implement most global optimizations.
Describe properties that are true of each instruction in the target description file.
ArrayRef< MCPhysReg > getRegisters() const
LLVM_ABI instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
LLVM_ABI MachineBasicBlock * splitAt(MachineInstr &SplitInst, bool UpdateLiveIns=true, LiveIntervals *LIS=nullptr)
Split a basic block into 2 pieces at SplitPoint.
LLVM_ABI void eraseFromParent()
This method unlinks 'this' from the containing function and deletes it.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
iterator_range< succ_iterator > successors()
MachineInstrBundleIterator< MachineInstr > iterator
LLVM_ABI unsigned getConstantPoolIndex(const Constant *C, Align Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void moveAdditionalCallInfo(const MachineInstr *Old, const MachineInstr *New)
Move the call site info from Old to \New call site info.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool 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 & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
void setDebugInstrNum(unsigned Num)
Set instruction number of this MachineInstr.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isCPI() const
isCPI - Tests if this is a MO_ConstantPoolIndex operand.
bool isSymbol() const
isSymbol - Tests if this is a MO_ExternalSymbol operand.
LLVM_ABI bool isRenamable() const
isRenamable - Returns true if this register may be renamed, i.e.
unsigned getTargetFlags() const
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
const char * getSymbolName() const
Register getReg() const
getReg - Returns the register number.
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)
int64_t getOffset() const
Return the offset from the symbol in this operand.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
void push_back(const T &Elt)
Represent a constant reference to a string, i.e.
CodeModel::Model getCodeModel() const
Returns the code model.
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ MO_NC
MO_NC - Indicates whether the linker is expected to check the symbol reference for overflow.
@ MO_PAGEOFF
MO_PAGEOFF - A symbol operand with this flag represents the offset of that symbol within a 4K page.
@ MO_PREL
MO_PREL - Indicates that the bits of the symbol operand represented by MO_G0 etc are PC relative.
@ MO_PAGE
MO_PAGE - A symbol operand with this flag represents the pc-relative offset of the 4K page containing...
@ MO_G3
MO_G3 - A symbol operand with this flag (granule 3) represents the high 16-bits of a 64-bit address,...
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 getShifterImm(AArch64_AM::ShiftExtendType ST, unsigned Imm)
getShifterImm - Encode the shift type and amount: imm: 6-bit shift amount shifter: 000 ==> lsl 001 ==...
void expandMOVAddr(unsigned Opcode, unsigned TargetFlags, bool IsTargetMachO, SmallVectorImpl< AddrInsnModel > &Insn)
void expandMOVImm(uint64_t Imm, unsigned BitSize, SmallVectorImpl< ImmInsnModel > &Insn)
Expand a MOVi32imm or MOVi64imm pseudo instruction to one or more real move-immediate instructions to...
@ Destructive2xRegImmUnpred
@ DestructiveBinaryShImmUnpred
@ DestructiveInstTypeMask
@ DestructiveUnaryPassthru
@ DestructiveBinaryImmUnpred
@ DestructiveTernaryCommWithRev
@ DestructiveBinaryCommWithRev
int32_t getSVERevInstr(uint32_t Opcode)
int32_t getSVENonRevInstr(uint32_t Opcode)
int32_t getSVEPseudoMap(uint32_t Opcode)
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
LLVM_ABI void finalizeBundle(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
finalizeBundle - Finalize a machine instruction bundle which includes a sequence of instructions star...
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
RegState
Flags to represent properties of register accesses.
@ Kill
The last use of a register.
constexpr RegState getKillRegState(bool B)
APFloat abs(APFloat X)
Returns the absolute value of the argument.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
constexpr RegState getDeadRegState(bool B)
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
FunctionPass * createAArch64ExpandPseudoLegacyPass()
Returns an instance of the pseudo instruction expansion pass.
constexpr RegState getRenamableRegState(bool B)
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)
constexpr RegState getDefRegState(bool B)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
LLVM_ABI void computeAndAddLiveIns(LivePhysRegs &LiveRegs, MachineBasicBlock &MBB)
Convenience function combining computeLiveIns() and addLiveIns().
constexpr RegState getUndefRegState(bool B)
MCRegisterClass TargetRegisterClass
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.