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 {
123char AArch64ExpandPseudoLegacy::ID = 0;
135 assert(MO.isReg() && MO.getReg());
154 if (DstReg == AArch64::XZR || DstReg == AArch64::WZR) {
157 MI.eraseFromParent();
165 SmallVector<MachineInstrBuilder, 4> MIBS;
167 bool LastItem = std::next(
I) ==
E;
172 case AArch64::ORRWri:
173 case AArch64::ORRXri:
174 case AArch64::ANDXri:
175 case AArch64::EORXri:
178 .
add(
MI.getOperand(0))
179 .
addReg(BitSize == 32 ? AArch64::WZR : AArch64::XZR)
183 bool DstIsDead =
MI.getOperand(0).isDead();
186 .
addReg(DstReg, RegState::Define |
193 case AArch64::EONXrs:
194 case AArch64::EORXrs:
195 case AArch64::ORRWrs:
196 case AArch64::ORRXrs: {
198 bool DstIsDead =
MI.getOperand(0).isDead();
201 .
addReg(DstReg, RegState::Define |
208 case AArch64::MOVNWi:
209 case AArch64::MOVNXi:
210 case AArch64::MOVZWi:
211 case AArch64::MOVZXi: {
212 bool DstIsDead =
MI.getOperand(0).isDead();
215 .
addReg(DstReg, RegState::Define |
221 case AArch64::MOVKWi:
222 case AArch64::MOVKXi: {
224 bool DstIsDead =
MI.getOperand(0).isDead();
227 .
addReg(DstReg, RegState::Define |
237 MI.eraseFromParent();
241bool AArch64ExpandPseudoImpl::expandCMP_SWAP(
243 unsigned StlrOp,
unsigned CmpOp,
unsigned ExtendImm,
unsigned ZeroReg,
247 const MachineOperand &Dest =
MI.getOperand(0);
248 Register StatusReg =
MI.getOperand(1).getReg();
249 bool StatusDead =
MI.getOperand(1).isDead();
252 assert(!
MI.getOperand(2).isUndef() &&
"cannot handle undef");
254 Register DesiredReg =
MI.getOperand(3).getReg();
263 MF->
insert(++LoadCmpBB->getIterator(), StoreBB);
264 MF->
insert(++StoreBB->getIterator(), DoneBB);
272 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::MOVZWi), StatusReg)
276 BuildMI(LoadCmpBB, MIMD,
TII->get(CmpOp), ZeroReg)
280 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::Bcc))
283 .
addReg(AArch64::NZCV, RegState::Implicit | RegState::Kill);
284 LoadCmpBB->addSuccessor(DoneBB);
285 LoadCmpBB->addSuccessor(StoreBB);
290 BuildMI(StoreBB, MIMD,
TII->get(StlrOp), StatusReg)
293 BuildMI(StoreBB, MIMD,
TII->get(AArch64::CBNZW))
296 StoreBB->addSuccessor(LoadCmpBB);
297 StoreBB->addSuccessor(DoneBB);
299 DoneBB->splice(DoneBB->end(), &
MBB,
MI,
MBB.
end());
300 DoneBB->transferSuccessors(&
MBB);
305 MI.eraseFromParent();
308 LivePhysRegs LiveRegs;
313 StoreBB->clearLiveIns();
315 LoadCmpBB->clearLiveIns();
321bool AArch64ExpandPseudoImpl::expandCMP_SWAP_128(
326 MachineOperand &DestLo =
MI.getOperand(0);
327 MachineOperand &DestHi =
MI.getOperand(1);
328 Register StatusReg =
MI.getOperand(2).getReg();
329 bool StatusDead =
MI.getOperand(2).isDead();
332 assert(!
MI.getOperand(3).isUndef() &&
"cannot handle undef");
334 Register DesiredLoReg =
MI.getOperand(4).getReg();
335 Register DesiredHiReg =
MI.getOperand(5).getReg();
336 Register NewLoReg =
MI.getOperand(6).getReg();
337 Register NewHiReg =
MI.getOperand(7).getReg();
340 bool LittleEndian = STI.isLittleEndian();
341 MachineOperand &Dest0 = LittleEndian ? DestLo : DestHi;
342 MachineOperand &Dest1 = LittleEndian ? DestHi : DestLo;
343 Register New0Reg = LittleEndian ? NewLoReg : NewHiReg;
344 Register New1Reg = LittleEndian ? NewHiReg : NewLoReg;
346 unsigned LdxpOp, StxpOp;
348 switch (
MI.getOpcode()) {
349 case AArch64::CMP_SWAP_128_MONOTONIC:
350 LdxpOp = AArch64::LDXPX;
351 StxpOp = AArch64::STXPX;
353 case AArch64::CMP_SWAP_128_RELEASE:
354 LdxpOp = AArch64::LDXPX;
355 StxpOp = AArch64::STLXPX;
357 case AArch64::CMP_SWAP_128_ACQUIRE:
358 LdxpOp = AArch64::LDAXPX;
359 StxpOp = AArch64::STXPX;
361 case AArch64::CMP_SWAP_128:
362 LdxpOp = AArch64::LDAXPX;
363 StxpOp = AArch64::STLXPX;
376 MF->
insert(++LoadCmpBB->getIterator(), StoreBB);
377 MF->
insert(++StoreBB->getIterator(), FailBB);
378 MF->
insert(++FailBB->getIterator(), DoneBB);
389 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::SUBSXrs), AArch64::XZR)
393 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::CSINCWr), StatusReg)
397 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::SUBSXrs), AArch64::XZR)
401 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::CSINCWr), StatusReg)
402 .
addUse(StatusReg, RegState::Kill)
403 .
addUse(StatusReg, RegState::Kill)
405 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::CBNZW))
408 LoadCmpBB->addSuccessor(FailBB);
409 LoadCmpBB->addSuccessor(StoreBB);
414 BuildMI(StoreBB, MIMD,
TII->get(StxpOp), StatusReg)
418 BuildMI(StoreBB, MIMD,
TII->get(AArch64::CBNZW))
422 StoreBB->addSuccessor(LoadCmpBB);
423 StoreBB->addSuccessor(DoneBB);
428 BuildMI(FailBB, MIMD,
TII->get(StxpOp), StatusReg)
432 BuildMI(FailBB, MIMD,
TII->get(AArch64::CBNZW))
435 FailBB->addSuccessor(LoadCmpBB);
436 FailBB->addSuccessor(DoneBB);
438 DoneBB->splice(DoneBB->end(), &
MBB,
MI,
MBB.
end());
439 DoneBB->transferSuccessors(&
MBB);
444 MI.eraseFromParent();
447 LivePhysRegs LiveRegs;
454 FailBB->clearLiveIns();
456 StoreBB->clearLiveIns();
458 LoadCmpBB->clearLiveIns();
502bool AArch64ExpandPseudoImpl::expand_DestructiveOp(
503 MachineInstr &
MI, MachineBasicBlock &
MBB,
510 bool DstIsDead =
MI.getOperand(0).isDead();
512 unsigned PredIdx, DOPIdx, SrcIdx, Src2Idx;
517 if (DstReg ==
MI.getOperand(3).getReg()) {
519 std::tie(PredIdx, DOPIdx, SrcIdx) = std::make_tuple(1, 3, 2);
526 std::tie(PredIdx, DOPIdx, SrcIdx) = std::make_tuple(1, 2, 3);
529 std::tie(PredIdx, DOPIdx, SrcIdx) = std::make_tuple(2, 3, 3);
532 std::tie(PredIdx, DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 2, 3, 4);
533 if (DstReg ==
MI.getOperand(3).getReg()) {
535 std::tie(PredIdx, DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 3, 4, 2);
537 }
else if (DstReg ==
MI.getOperand(4).getReg()) {
539 std::tie(PredIdx, DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 4, 3, 2);
546 std::tie(DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 1, 2);
549 std::tie(DOPIdx, SrcIdx) = std::make_tuple(1, 2);
552 std::tie(DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 2, 3);
561 bool DOPRegIsUnique =
false;
564 DOPRegIsUnique = DstReg !=
MI.getOperand(SrcIdx).getReg();
569 DstReg !=
MI.getOperand(DOPIdx).getReg() ||
570 MI.getOperand(DOPIdx).getReg() !=
MI.getOperand(SrcIdx).getReg();
577 DOPRegIsUnique =
true;
581 DstReg !=
MI.getOperand(DOPIdx).getReg() ||
582 (
MI.getOperand(DOPIdx).
getReg() !=
MI.getOperand(SrcIdx).getReg() &&
583 MI.getOperand(DOPIdx).getReg() !=
MI.getOperand(Src2Idx).getReg());
599 uint64_t ElementSize =
TII->getElementSizeForOpcode(Opcode);
600 unsigned MovPrfx, LSLZero, MovPrfxZero;
601 switch (ElementSize) {
604 MovPrfx = AArch64::MOVPRFX_ZZ;
605 LSLZero = AArch64::LSL_ZPmI_B;
606 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_B;
609 MovPrfx = AArch64::MOVPRFX_ZZ;
610 LSLZero = AArch64::LSL_ZPmI_H;
611 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_H;
614 MovPrfx = AArch64::MOVPRFX_ZZ;
615 LSLZero = AArch64::LSL_ZPmI_S;
616 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_S;
619 MovPrfx = AArch64::MOVPRFX_ZZ;
620 LSLZero = AArch64::LSL_ZPmI_D;
621 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_D;
633 MachineInstrBuilder PRFX, DOP;
640 "The destructive operand should be unique");
642 "This instruction is unpredicated");
646 .
addReg(DstReg, RegState::Define)
647 .
addReg(
MI.getOperand(PredIdx).getReg())
648 .
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState);
662 .
addReg(DstReg, RegState::Define)
663 .
add(
MI.getOperand(PredIdx))
667 }
else if (DstReg !=
MI.getOperand(DOPIdx).getReg()) {
668 assert(DOPRegIsUnique &&
"The destructive operand should be unique");
670 .
addReg(DstReg, RegState::Define)
671 .
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState);
681 DOPRegState = DOPRegState | RegState::Kill;
685 DOP.
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState)
686 .
add(
MI.getOperand(PredIdx))
687 .
add(
MI.getOperand(SrcIdx));
693 DOP.
add(
MI.getOperand(PredIdx))
694 .
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState)
695 .
add(
MI.getOperand(SrcIdx));
698 DOP.
add(
MI.getOperand(PredIdx))
699 .
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState)
700 .
add(
MI.getOperand(SrcIdx))
701 .
add(
MI.getOperand(Src2Idx));
704 DOP.
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState)
705 .
add(
MI.getOperand(SrcIdx));
709 DOP.
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState)
710 .
add(
MI.getOperand(SrcIdx))
711 .
add(
MI.getOperand(Src2Idx));
721 MI.eraseFromParent();
725bool AArch64ExpandPseudoImpl::expandSVEBitwisePseudo(
726 MachineInstr &
MI, MachineBasicBlock &
MBB,
728 MachineInstrBuilder PRFX, DOP;
729 const unsigned Opcode =
MI.getOpcode();
730 const MachineOperand &Op0 =
MI.getOperand(0);
731 const MachineOperand *Op1 = &
MI.getOperand(1);
732 const MachineOperand *Op2 = &
MI.getOperand(2);
735 if (DOPReg == Op2->
getReg()) {
738 }
else if (DOPReg != Op1->
getReg()) {
747 Opcode == AArch64::NAND_ZZZ));
750 assert((DOPReg == Op1->
getReg() || PRFX) &&
"invalid expansion");
759 case AArch64::EON_ZZZ:
762 .
addReg(DOPReg, DOPRegState)
766 case AArch64::NAND_ZZZ:
769 .
addReg(DOPReg, DOPRegState)
773 case AArch64::NOR_ZZZ:
776 .
addReg(DOPReg, DOPRegState)
789 MI.eraseFromParent();
793bool AArch64ExpandPseudoImpl::expandSetTagLoop(
799 Register AddressReg =
MI.getOperand(1).getReg();
803 bool ZeroData =
MI.getOpcode() == AArch64::STZGloop_wback;
804 const unsigned OpCode1 =
805 ZeroData ? AArch64::STZGPostIndex : AArch64::STGPostIndex;
806 const unsigned OpCode2 =
807 ZeroData ? AArch64::STZ2GPostIndex : AArch64::ST2GPostIndex;
809 unsigned Size =
MI.getOperand(2).getImm();
811 if (
Size % (16 * 2) != 0) {
827 MF->
insert(++LoopBB->getIterator(), DoneBB);
844 .
addReg(AArch64::NZCV, RegState::Implicit | RegState::Kill);
846 LoopBB->addSuccessor(LoopBB);
847 LoopBB->addSuccessor(DoneBB);
849 DoneBB->splice(DoneBB->end(), &
MBB,
MI,
MBB.
end());
850 DoneBB->transferSuccessors(&
MBB);
855 MI.eraseFromParent();
857 LivePhysRegs LiveRegs;
862 LoopBB->clearLiveIns();
864 DoneBB->clearLiveIns();
870bool AArch64ExpandPseudoImpl::expandSVESpillFill(
873 assert((
Opc == AArch64::LDR_ZXI ||
Opc == AArch64::STR_ZXI ||
874 Opc == AArch64::LDR_PXI ||
Opc == AArch64::STR_PXI) &&
875 "Unexpected opcode");
878 unsigned sub0 = (
Opc == AArch64::LDR_ZXI ||
Opc == AArch64::STR_ZXI)
881 const TargetRegisterInfo *
TRI =
885 int ImmOffset =
MI.getOperand(2).getImm() +
Offset;
886 bool Kill = (
Offset + 1 ==
N) ?
MI.getOperand(1).isKill() :
false;
887 assert(ImmOffset >= -256 && ImmOffset < 256 &&
888 "Immediate spill offset out of range");
906 unsigned RegMaskStartIdx) {
911 MF.CreateMachineInstr(
TII->get(Opcode),
MBBI->getDebugLoc(),
919 while (!
MBBI->getOperand(RegMaskStartIdx).isRegMask()) {
921 assert(MOP.
isReg() &&
"can only add register operands");
923 MOP.
getReg(),
false,
true,
false,
929 Call->addOperand(MO);
940 unsigned RegMaskStartIdx) {
941 unsigned Opc = CallTarget.
isGlobal() ? AArch64::BL : AArch64::BLR;
944 "invalid operand for regular call");
948bool AArch64ExpandPseudoImpl::expandCALL_RVMARKER(
956 MachineOperand &RVTarget =
MI.getOperand(0);
957 bool DoEmitMarker =
MI.getOperand(1).getImm();
958 assert(RVTarget.
isGlobal() &&
"invalid operand for attached call");
960 MachineInstr *OriginalCall =
nullptr;
962 if (
MI.getOpcode() == AArch64::BLRA_RVMARKER) {
964 const MachineOperand &CallTarget =
MI.getOperand(2);
965 const MachineOperand &
Key =
MI.getOperand(3);
966 const MachineOperand &IntDisc =
MI.getOperand(4);
967 const MachineOperand &AddrDisc =
MI.getOperand(5);
971 "Invalid auth call key");
973 MachineOperand
Ops[] = {CallTarget,
Key, IntDisc, AddrDisc};
978 assert(
MI.getOpcode() == AArch64::BLR_RVMARKER &&
"unknown rvmarker MI");
986 .
addReg(AArch64::FP, RegState::Define)
995 if (
MI.shouldUpdateAdditionalCallInfo())
998 MI.eraseFromParent();
1000 std::next(RVCall->getIterator()));
1004bool AArch64ExpandPseudoImpl::expandCALL_BTI(MachineBasicBlock &
MBB,
1011 MachineInstr &
MI = *
MBBI;
1024 if (
MI.shouldUpdateAdditionalCallInfo())
1027 MI.eraseFromParent();
1032bool AArch64ExpandPseudoImpl::expandStoreSwiftAsyncContext(
1040 if (STI.getTargetTriple().getArchName() !=
"arm64e") {
1057 unsigned Opc =
Offset >= 0 ? AArch64::ADDXri : AArch64::SUBXri;
1089AArch64ExpandPseudoImpl::ConditionalBlocks
1090AArch64ExpandPseudoImpl::expandConditionalPseudo(
1092 MachineInstrBuilder &Branch) {
1095 "Unexpected unreachable in block");
1101 MachineInstr &PrevMI = *std::prev(
MBBI);
1102 MachineBasicBlock *CondBB =
MBB.
splitAt(PrevMI,
true);
1103 MachineBasicBlock *EndBB =
1104 std::next(
MBBI) == CondBB->
end()
1117 return {*CondBB, *EndBB};
1121AArch64ExpandPseudoImpl::expandRestoreZASave(MachineBasicBlock &
MBB,
1123 MachineInstr &
MI = *
MBBI;
1127 MachineInstrBuilder
Branch =
1130 auto [CondBB, EndBB] = expandConditionalPseudo(
MBB,
MBBI,
DL, Branch);
1132 MachineInstrBuilder MIB =
1135 for (
unsigned I = 2;
I <
MI.getNumOperands(); ++
I)
1136 MIB.
add(
MI.getOperand(
I));
1138 MIB.
addReg(
MI.getOperand(1).getReg(), RegState::Implicit);
1140 MI.eraseFromParent();
1151 [[maybe_unused]]
auto *RI =
MBB.getParent()->getSubtarget().getRegisterInfo();
1157 auto [CondBB, EndBB] = expandConditionalPseudo(
MBB,
MBBI,
DL, Branch);
1162 for (
unsigned I = 3;
I <
MI.getNumOperands(); ++
I)
1163 MIB.
add(
MI.getOperand(
I));
1166 .
addImm(AArch64SysReg::TPIDR2_EL0)
1168 bool ZeroZA =
MI.getOperand(1).getImm() != 0;
1169 bool ZeroZT0 =
MI.getOperand(2).getImm() != 0;
1171 assert(
MI.definesRegister(AArch64::ZAB0, RI) &&
"should define ZA!");
1177 assert(
MI.definesRegister(AArch64::ZT0, RI) &&
"should define ZT0!");
1182 MI.eraseFromParent();
1187AArch64ExpandPseudoImpl::expandCondSMToggle(MachineBasicBlock &
MBB,
1189 MachineInstr &
MI = *
MBBI;
1196 MI.getParent()->successors().begin() ==
1197 MI.getParent()->successors().end()) {
1198 MI.eraseFromParent();
1241 switch (
MI.getOperand(2).getImm()) {
1245 Opc = AArch64::TBNZW;
1248 Opc = AArch64::TBZW;
1251 auto PStateSM =
MI.getOperand(3).getReg();
1253 unsigned SMReg32 =
TRI->getSubReg(PStateSM, AArch64::sub_32);
1254 MachineInstrBuilder Tbx =
1257 auto [CondBB, EndBB] = expandConditionalPseudo(
MBB,
MBBI,
DL, Tbx);
1260 TII->get(AArch64::MSRpstatesvcrImm1));
1264 MIB.
add(
MI.getOperand(0));
1265 MIB.
add(
MI.getOperand(1));
1266 for (
unsigned i = 4; i <
MI.getNumOperands(); ++i)
1267 MIB.
add(
MI.getOperand(i));
1269 MI.eraseFromParent();
1273bool AArch64ExpandPseudoImpl::expandMultiVecPseudo(
1277 unsigned StridedOpc) {
1278 MachineInstr &
MI = *
MBBI;
1292 .
add(
MI.getOperand(0))
1293 .
add(
MI.getOperand(1))
1294 .
add(
MI.getOperand(2))
1295 .
add(
MI.getOperand(3));
1297 MI.eraseFromParent();
1301bool AArch64ExpandPseudoImpl::expandCopyIntoTuplePseudo(
1302 MachineInstr &
MI, MachineBasicBlock &
MBB,
1309 .
addReg(Dest, RegState::Define)
1313 MI.eraseFromParent();
1319bool AArch64ExpandPseudoImpl::expandMI(MachineBasicBlock &
MBB,
1322 MachineInstr &
MI = *
MBBI;
1323 unsigned Opcode =
MI.getOpcode();
1327 if (OrigInstr != -1) {
1328 auto &Orig =
TII->get(OrigInstr);
1331 return expand_DestructiveOp(
MI,
MBB,
MBBI);
1339 case AArch64::BSPv8i8:
1340 case AArch64::BSPv16i8: {
1342 if (DstReg ==
MI.getOperand(3).getReg()) {
1345 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BITv8i8
1346 : AArch64::BITv16i8))
1347 .
add(
MI.getOperand(0))
1348 .
add(
MI.getOperand(3))
1349 .
add(
MI.getOperand(2))
1350 .
add(
MI.getOperand(1));
1352 }
else if (DstReg ==
MI.getOperand(2).getReg()) {
1355 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BIFv8i8
1356 : AArch64::BIFv16i8))
1357 .
add(
MI.getOperand(0))
1358 .
add(
MI.getOperand(2))
1359 .
add(
MI.getOperand(3))
1360 .
add(
MI.getOperand(1));
1365 if (DstReg ==
MI.getOperand(1).getReg()) {
1368 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BSLv8i8
1369 : AArch64::BSLv16i8))
1370 .
add(
MI.getOperand(0))
1371 .
add(
MI.getOperand(1))
1372 .
add(
MI.getOperand(2))
1373 .
add(
MI.getOperand(3));
1375 }
else if (Opcode == AArch64::BSPv16i8 &&
1376 ST.isSVEorStreamingSVEAvailable() &&
1377 (
ST.hasSVE2() ||
ST.hasSME())) {
1381 auto getZReg = [&
TRI](
const MachineOperand &MO) ->
Register {
1382 return TRI.getMatchingSuperReg(MO.getReg(), AArch64::zsub,
1383 &AArch64::ZPRRegClass);
1385 const MachineOperand &Dst =
MI.getOperand(0);
1386 const MachineOperand &
Mask =
MI.getOperand(1);
1387 const MachineOperand &TVal =
MI.getOperand(2);
1388 const MachineOperand &FVal =
MI.getOperand(3);
1403 .
addReg(DOPReg, RegState::Kill |
1420 MI.getOperand(1).isKill() &&
1421 MI.getOperand(1).getReg() !=
MI.getOperand(2).getReg() &&
1422 MI.getOperand(1).getReg() !=
MI.getOperand(3).getReg());
1424 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::ORRv8i8
1425 : AArch64::ORRv16i8))
1433 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BSLv8i8
1434 : AArch64::BSLv16i8))
1435 .
add(
MI.getOperand(0))
1438 MI.getOperand(0).isRenamable()))
1439 .
add(
MI.getOperand(2))
1440 .
add(
MI.getOperand(3));
1444 MI.eraseFromParent();
1448 case AArch64::ADDWrr:
1449 case AArch64::SUBWrr:
1450 case AArch64::ADDXrr:
1451 case AArch64::SUBXrr:
1452 case AArch64::ADDSWrr:
1453 case AArch64::SUBSWrr:
1454 case AArch64::ADDSXrr:
1455 case AArch64::SUBSXrr:
1456 case AArch64::ANDWrr:
1457 case AArch64::ANDXrr:
1458 case AArch64::BICWrr:
1459 case AArch64::BICXrr:
1460 case AArch64::ANDSWrr:
1461 case AArch64::ANDSXrr:
1462 case AArch64::BICSWrr:
1463 case AArch64::BICSXrr:
1464 case AArch64::EONWrr:
1465 case AArch64::EONXrr:
1466 case AArch64::EORWrr:
1467 case AArch64::EORXrr:
1468 case AArch64::ORNWrr:
1469 case AArch64::ORNXrr:
1470 case AArch64::ORRWrr:
1471 case AArch64::ORRXrr: {
1473 switch (
MI.getOpcode()) {
1476 case AArch64::ADDWrr: Opcode = AArch64::ADDWrs;
break;
1477 case AArch64::SUBWrr: Opcode = AArch64::SUBWrs;
break;
1478 case AArch64::ADDXrr: Opcode = AArch64::ADDXrs;
break;
1479 case AArch64::SUBXrr: Opcode = AArch64::SUBXrs;
break;
1480 case AArch64::ADDSWrr: Opcode = AArch64::ADDSWrs;
break;
1481 case AArch64::SUBSWrr: Opcode = AArch64::SUBSWrs;
break;
1482 case AArch64::ADDSXrr: Opcode = AArch64::ADDSXrs;
break;
1483 case AArch64::SUBSXrr: Opcode = AArch64::SUBSXrs;
break;
1484 case AArch64::ANDWrr: Opcode = AArch64::ANDWrs;
break;
1485 case AArch64::ANDXrr: Opcode = AArch64::ANDXrs;
break;
1486 case AArch64::BICWrr: Opcode = AArch64::BICWrs;
break;
1487 case AArch64::BICXrr: Opcode = AArch64::BICXrs;
break;
1488 case AArch64::ANDSWrr: Opcode = AArch64::ANDSWrs;
break;
1489 case AArch64::ANDSXrr: Opcode = AArch64::ANDSXrs;
break;
1490 case AArch64::BICSWrr: Opcode = AArch64::BICSWrs;
break;
1491 case AArch64::BICSXrr: Opcode = AArch64::BICSXrs;
break;
1492 case AArch64::EONWrr: Opcode = AArch64::EONWrs;
break;
1493 case AArch64::EONXrr: Opcode = AArch64::EONXrs;
break;
1494 case AArch64::EORWrr: Opcode = AArch64::EORWrs;
break;
1495 case AArch64::EORXrr: Opcode = AArch64::EORXrs;
break;
1496 case AArch64::ORNWrr: Opcode = AArch64::ORNWrs;
break;
1497 case AArch64::ORNXrr: Opcode = AArch64::ORNXrs;
break;
1498 case AArch64::ORRWrr: Opcode = AArch64::ORRWrs;
break;
1499 case AArch64::ORRXrr: Opcode = AArch64::ORRXrs;
break;
1503 MachineInstr *NewMI = MF.CreateMachineInstr(
1504 TII->get(Opcode),
MI.getDebugLoc(),
true);
1506 MachineInstrBuilder MIB1(MF, NewMI);
1507 MIB1->setPCSections(MF,
MI.getPCSections());
1508 MIB1.addReg(
MI.getOperand(0).getReg(), RegState::Define)
1509 .add(
MI.getOperand(1))
1510 .add(
MI.getOperand(2))
1513 if (
auto DebugNumber =
MI.peekDebugInstrNum())
1515 MI.eraseFromParent();
1519 case AArch64::LOADgot: {
1522 const MachineOperand &MO1 =
MI.getOperand(1);
1528 TII->get(AArch64::LDRXl), DstReg);
1536 "Only expect globals, externalsymbols, or constant pools");
1543 MachineInstrBuilder MIB1 =
1546 MachineInstrBuilder MIB2;
1547 if (MF.
getSubtarget<AArch64Subtarget>().isTargetILP32()) {
1549 unsigned Reg32 =
TRI->getSubReg(DstReg, AArch64::sub_32);
1552 .
addReg(DstReg, RegState::Kill)
1553 .
addReg(DstReg, RegState::Implicit);
1557 .
add(
MI.getOperand(0))
1558 .
addUse(DstReg, RegState::Kill);
1572 "Only expect globals, externalsymbols, or constant pools");
1583 if (
MI.peekDebugInstrNum() != 0)
1587 MI.eraseFromParent();
1590 case AArch64::MOVaddrBA:
1591 case AArch64::MOVaddr:
1592 case AArch64::MOVaddrJT:
1593 case AArch64::MOVaddrCP:
1594 case AArch64::MOVaddrTLS:
1595 case AArch64::MOVaddrEXT: {
1598 assert(DstReg != AArch64::XZR);
1600 bool IsTargetMachO = MF.
getSubtarget<AArch64Subtarget>().isTargetMachO();
1603 MI.getOpcode(),
MI.getOperand(1).getTargetFlags(), IsTargetMachO, Insn);
1606 std::optional<unsigned> CPIdx;
1607 if (Opcode == AArch64::MOVaddrBA && IsTargetMachO) {
1612 assert(
MI.getOperand(1).getOffset() == 0 &&
"unexpected offset");
1617 MachineInstrBuilder FirstMIB;
1618 MachineInstrBuilder LastMIB;
1619 for (
const auto &
I : Insn) {
1620 MachineInstrBuilder MIB;
1628 MIB.
add(
MI.getOperand(1));
1630 case AArch64::LDRXui:
1637 case AArch64::MOVKXi: {
1645 auto Tag =
MI.getOperand(1);
1647 Tag.setOffset(0x100000000);
1655 case AArch64::ADDXri:
1657 .
add(
MI.getOperand(0))
1659 .
add(
MI.getOperand(2))
1672 MI.eraseFromParent();
1675 case AArch64::ADDlowTLS:
1678 .
add(
MI.getOperand(0))
1679 .
add(
MI.getOperand(1))
1680 .
add(
MI.getOperand(2))
1682 MI.eraseFromParent();
1685 case AArch64::MOVbaseTLS: {
1687 auto SysReg = AArch64SysReg::TPIDR_EL0;
1689 if (MF->
getSubtarget<AArch64Subtarget>().useEL3ForTP())
1690 SysReg = AArch64SysReg::TPIDR_EL3;
1691 else if (MF->
getSubtarget<AArch64Subtarget>().useEL2ForTP())
1692 SysReg = AArch64SysReg::TPIDR_EL2;
1693 else if (MF->
getSubtarget<AArch64Subtarget>().useEL1ForTP())
1694 SysReg = AArch64SysReg::TPIDR_EL1;
1695 else if (MF->
getSubtarget<AArch64Subtarget>().useROEL0ForTP())
1696 SysReg = AArch64SysReg::TPIDRRO_EL0;
1699 MI.eraseFromParent();
1703 case AArch64::MOVi32imm:
1705 case AArch64::MOVi64imm:
1707 case AArch64::RET_ReallyLR: {
1713 MachineInstrBuilder MIB =
1715 .
addReg(AArch64::LR, RegState::Undef);
1717 MI.eraseFromParent();
1720 case AArch64::CMP_SWAP_8:
1721 return expandCMP_SWAP(
MBB,
MBBI, AArch64::LDAXRB, AArch64::STLXRB,
1724 AArch64::WZR, NextMBBI);
1725 case AArch64::CMP_SWAP_16:
1726 return expandCMP_SWAP(
MBB,
MBBI, AArch64::LDAXRH, AArch64::STLXRH,
1729 AArch64::WZR, NextMBBI);
1730 case AArch64::CMP_SWAP_32:
1731 return expandCMP_SWAP(
MBB,
MBBI, AArch64::LDAXRW, AArch64::STLXRW,
1734 AArch64::WZR, NextMBBI);
1735 case AArch64::CMP_SWAP_64:
1736 return expandCMP_SWAP(
MBB,
MBBI,
1737 AArch64::LDAXRX, AArch64::STLXRX, AArch64::SUBSXrs,
1739 AArch64::XZR, NextMBBI);
1740 case AArch64::CMP_SWAP_128:
1741 case AArch64::CMP_SWAP_128_RELEASE:
1742 case AArch64::CMP_SWAP_128_ACQUIRE:
1743 case AArch64::CMP_SWAP_128_MONOTONIC:
1744 return expandCMP_SWAP_128(
MBB,
MBBI, NextMBBI);
1746 case AArch64::AESMCrrTied:
1747 case AArch64::AESIMCrrTied: {
1748 MachineInstrBuilder MIB =
1750 TII->get(Opcode == AArch64::AESMCrrTied ? AArch64::AESMCrr :
1752 .
add(
MI.getOperand(0))
1753 .
add(
MI.getOperand(1));
1755 MI.eraseFromParent();
1758 case AArch64::IRGstack: {
1760 const AArch64FunctionInfo *AFI = MF.
getInfo<AArch64FunctionInfo>();
1761 const AArch64FrameLowering *TFI =
1762 MF.
getSubtarget<AArch64Subtarget>().getFrameLowering();
1769 StackOffset FrameRegOffset = TFI->resolveFrameOffsetReference(
1775 if (FrameRegOffset) {
1777 SrcReg =
MI.getOperand(0).getReg();
1779 FrameRegOffset,
TII);
1782 .
add(
MI.getOperand(0))
1784 .
add(
MI.getOperand(2));
1785 MI.eraseFromParent();
1788 case AArch64::TAGPstack: {
1789 int64_t
Offset =
MI.getOperand(2).getImm();
1791 TII->get(
Offset >= 0 ? AArch64::ADDG : AArch64::SUBG))
1792 .
add(
MI.getOperand(0))
1793 .
add(
MI.getOperand(1))
1795 .
add(
MI.getOperand(4));
1796 MI.eraseFromParent();
1799 case AArch64::STGloop_wback:
1800 case AArch64::STZGloop_wback:
1801 return expandSetTagLoop(
MBB,
MBBI, NextMBBI);
1802 case AArch64::STGloop:
1803 case AArch64::STZGloop:
1805 "Non-writeback variants of STGloop / STZGloop should not "
1806 "survive past PrologEpilogInserter.");
1807 case AArch64::STR_ZZZZXI:
1808 case AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS:
1809 return expandSVESpillFill(
MBB,
MBBI, AArch64::STR_ZXI, 4);
1810 case AArch64::STR_ZZZXI:
1811 return expandSVESpillFill(
MBB,
MBBI, AArch64::STR_ZXI, 3);
1812 case AArch64::STR_ZZXI:
1813 case AArch64::STR_ZZXI_STRIDED_CONTIGUOUS:
1814 return expandSVESpillFill(
MBB,
MBBI, AArch64::STR_ZXI, 2);
1815 case AArch64::STR_PPXI:
1816 return expandSVESpillFill(
MBB,
MBBI, AArch64::STR_PXI, 2);
1817 case AArch64::LDR_ZZZZXI:
1818 case AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS:
1819 return expandSVESpillFill(
MBB,
MBBI, AArch64::LDR_ZXI, 4);
1820 case AArch64::LDR_ZZZXI:
1821 return expandSVESpillFill(
MBB,
MBBI, AArch64::LDR_ZXI, 3);
1822 case AArch64::LDR_ZZXI:
1823 case AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS:
1824 return expandSVESpillFill(
MBB,
MBBI, AArch64::LDR_ZXI, 2);
1825 case AArch64::LDR_PPXI:
1826 return expandSVESpillFill(
MBB,
MBBI, AArch64::LDR_PXI, 2);
1827 case AArch64::BLR_RVMARKER:
1828 case AArch64::BLRA_RVMARKER:
1829 return expandCALL_RVMARKER(
MBB,
MBBI);
1830 case AArch64::BLR_BTI:
1831 return expandCALL_BTI(
MBB,
MBBI);
1832 case AArch64::StoreSwiftAsyncContext:
1833 return expandStoreSwiftAsyncContext(
MBB,
MBBI);
1834 case AArch64::RestoreZAPseudo:
1835 case AArch64::CommitZASavePseudo:
1836 case AArch64::MSRpstatePseudo: {
1837 auto *NewMBB = [&] {
1839 case AArch64::RestoreZAPseudo:
1840 return expandRestoreZASave(
MBB,
MBBI);
1841 case AArch64::CommitZASavePseudo:
1842 return expandCommitZASave(
MBB,
MBBI);
1843 case AArch64::MSRpstatePseudo:
1844 return expandCondSMToggle(
MBB,
MBBI);
1853 case AArch64::InOutZAUsePseudo:
1854 case AArch64::RequiresZASavePseudo:
1855 case AArch64::RequiresZT0SavePseudo:
1856 case AArch64::SMEStateAllocPseudo:
1857 case AArch64::COALESCER_BARRIER_FPR16:
1858 case AArch64::COALESCER_BARRIER_FPR32:
1859 case AArch64::COALESCER_BARRIER_FPR64:
1860 case AArch64::COALESCER_BARRIER_FPR128:
1861 MI.eraseFromParent();
1863 case AArch64::LD1B_2Z_IMM_PSEUDO:
1864 return expandMultiVecPseudo(
1865 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1866 AArch64::LD1B_2Z_IMM, AArch64::LD1B_2Z_STRIDED_IMM);
1867 case AArch64::LD1H_2Z_IMM_PSEUDO:
1868 return expandMultiVecPseudo(
1869 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1870 AArch64::LD1H_2Z_IMM, AArch64::LD1H_2Z_STRIDED_IMM);
1871 case AArch64::LD1W_2Z_IMM_PSEUDO:
1872 return expandMultiVecPseudo(
1873 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1874 AArch64::LD1W_2Z_IMM, AArch64::LD1W_2Z_STRIDED_IMM);
1875 case AArch64::LD1D_2Z_IMM_PSEUDO:
1876 return expandMultiVecPseudo(
1877 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1878 AArch64::LD1D_2Z_IMM, AArch64::LD1D_2Z_STRIDED_IMM);
1879 case AArch64::LDNT1B_2Z_IMM_PSEUDO:
1880 return expandMultiVecPseudo(
1881 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1882 AArch64::LDNT1B_2Z_IMM, AArch64::LDNT1B_2Z_STRIDED_IMM);
1883 case AArch64::LDNT1H_2Z_IMM_PSEUDO:
1884 return expandMultiVecPseudo(
1885 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1886 AArch64::LDNT1H_2Z_IMM, AArch64::LDNT1H_2Z_STRIDED_IMM);
1887 case AArch64::LDNT1W_2Z_IMM_PSEUDO:
1888 return expandMultiVecPseudo(
1889 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1890 AArch64::LDNT1W_2Z_IMM, AArch64::LDNT1W_2Z_STRIDED_IMM);
1891 case AArch64::LDNT1D_2Z_IMM_PSEUDO:
1892 return expandMultiVecPseudo(
1893 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1894 AArch64::LDNT1D_2Z_IMM, AArch64::LDNT1D_2Z_STRIDED_IMM);
1895 case AArch64::ST1B_2Z_IMM_PSEUDO:
1896 return expandMultiVecPseudo(
1897 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1898 AArch64::ST1B_2Z_IMM, AArch64::ST1B_2Z_STRIDED_IMM);
1899 case AArch64::ST1H_2Z_IMM_PSEUDO:
1900 return expandMultiVecPseudo(
1901 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1902 AArch64::ST1H_2Z_IMM, AArch64::ST1H_2Z_STRIDED_IMM);
1903 case AArch64::ST1W_2Z_IMM_PSEUDO:
1904 return expandMultiVecPseudo(
1905 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1906 AArch64::ST1W_2Z_IMM, AArch64::ST1W_2Z_STRIDED_IMM);
1907 case AArch64::ST1D_2Z_IMM_PSEUDO:
1908 return expandMultiVecPseudo(
1909 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1910 AArch64::ST1D_2Z_IMM, AArch64::ST1D_2Z_STRIDED_IMM);
1911 case AArch64::STNT1B_2Z_IMM_PSEUDO:
1912 return expandMultiVecPseudo(
1913 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1914 AArch64::STNT1B_2Z_IMM, AArch64::STNT1B_2Z_STRIDED_IMM);
1915 case AArch64::STNT1H_2Z_IMM_PSEUDO:
1916 return expandMultiVecPseudo(
1917 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1918 AArch64::STNT1H_2Z_IMM, AArch64::STNT1H_2Z_STRIDED_IMM);
1919 case AArch64::STNT1W_2Z_IMM_PSEUDO:
1920 return expandMultiVecPseudo(
1921 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1922 AArch64::STNT1W_2Z_IMM, AArch64::STNT1W_2Z_STRIDED_IMM);
1923 case AArch64::STNT1D_2Z_IMM_PSEUDO:
1924 return expandMultiVecPseudo(
1925 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1926 AArch64::STNT1D_2Z_IMM, AArch64::STNT1D_2Z_STRIDED_IMM);
1927 case AArch64::LD1B_2Z_PSEUDO:
1928 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1929 AArch64::ZPR2StridedRegClass, AArch64::LD1B_2Z,
1930 AArch64::LD1B_2Z_STRIDED);
1931 case AArch64::LD1H_2Z_PSEUDO:
1932 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1933 AArch64::ZPR2StridedRegClass, AArch64::LD1H_2Z,
1934 AArch64::LD1H_2Z_STRIDED);
1935 case AArch64::LD1W_2Z_PSEUDO:
1936 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1937 AArch64::ZPR2StridedRegClass, AArch64::LD1W_2Z,
1938 AArch64::LD1W_2Z_STRIDED);
1939 case AArch64::LD1D_2Z_PSEUDO:
1940 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1941 AArch64::ZPR2StridedRegClass, AArch64::LD1D_2Z,
1942 AArch64::LD1D_2Z_STRIDED);
1943 case AArch64::LDNT1B_2Z_PSEUDO:
1944 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1945 AArch64::ZPR2StridedRegClass,
1946 AArch64::LDNT1B_2Z, AArch64::LDNT1B_2Z_STRIDED);
1947 case AArch64::LDNT1H_2Z_PSEUDO:
1948 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1949 AArch64::ZPR2StridedRegClass,
1950 AArch64::LDNT1H_2Z, AArch64::LDNT1H_2Z_STRIDED);
1951 case AArch64::LDNT1W_2Z_PSEUDO:
1952 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1953 AArch64::ZPR2StridedRegClass,
1954 AArch64::LDNT1W_2Z, AArch64::LDNT1W_2Z_STRIDED);
1955 case AArch64::LDNT1D_2Z_PSEUDO:
1956 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1957 AArch64::ZPR2StridedRegClass,
1958 AArch64::LDNT1D_2Z, AArch64::LDNT1D_2Z_STRIDED);
1959 case AArch64::LD1B_4Z_IMM_PSEUDO:
1960 return expandMultiVecPseudo(
1961 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1962 AArch64::LD1B_4Z_IMM, AArch64::LD1B_4Z_STRIDED_IMM);
1963 case AArch64::LD1H_4Z_IMM_PSEUDO:
1964 return expandMultiVecPseudo(
1965 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1966 AArch64::LD1H_4Z_IMM, AArch64::LD1H_4Z_STRIDED_IMM);
1967 case AArch64::LD1W_4Z_IMM_PSEUDO:
1968 return expandMultiVecPseudo(
1969 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1970 AArch64::LD1W_4Z_IMM, AArch64::LD1W_4Z_STRIDED_IMM);
1971 case AArch64::LD1D_4Z_IMM_PSEUDO:
1972 return expandMultiVecPseudo(
1973 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1974 AArch64::LD1D_4Z_IMM, AArch64::LD1D_4Z_STRIDED_IMM);
1975 case AArch64::LDNT1B_4Z_IMM_PSEUDO:
1976 return expandMultiVecPseudo(
1977 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1978 AArch64::LDNT1B_4Z_IMM, AArch64::LDNT1B_4Z_STRIDED_IMM);
1979 case AArch64::LDNT1H_4Z_IMM_PSEUDO:
1980 return expandMultiVecPseudo(
1981 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1982 AArch64::LDNT1H_4Z_IMM, AArch64::LDNT1H_4Z_STRIDED_IMM);
1983 case AArch64::LDNT1W_4Z_IMM_PSEUDO:
1984 return expandMultiVecPseudo(
1985 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1986 AArch64::LDNT1W_4Z_IMM, AArch64::LDNT1W_4Z_STRIDED_IMM);
1987 case AArch64::LDNT1D_4Z_IMM_PSEUDO:
1988 return expandMultiVecPseudo(
1989 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1990 AArch64::LDNT1D_4Z_IMM, AArch64::LDNT1D_4Z_STRIDED_IMM);
1991 case AArch64::ST1B_4Z_IMM_PSEUDO:
1992 return expandMultiVecPseudo(
1993 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1994 AArch64::ST1B_4Z_IMM, AArch64::ST1B_4Z_STRIDED_IMM);
1995 case AArch64::ST1H_4Z_IMM_PSEUDO:
1996 return expandMultiVecPseudo(
1997 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1998 AArch64::ST1H_4Z_IMM, AArch64::ST1H_4Z_STRIDED_IMM);
1999 case AArch64::ST1W_4Z_IMM_PSEUDO:
2000 return expandMultiVecPseudo(
2001 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
2002 AArch64::ST1W_4Z_IMM, AArch64::ST1W_4Z_STRIDED_IMM);
2003 case AArch64::ST1D_4Z_IMM_PSEUDO:
2004 return expandMultiVecPseudo(
2005 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
2006 AArch64::ST1D_4Z_IMM, AArch64::ST1D_4Z_STRIDED_IMM);
2007 case AArch64::STNT1B_4Z_IMM_PSEUDO:
2008 return expandMultiVecPseudo(
2009 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
2010 AArch64::STNT1B_4Z_IMM, AArch64::STNT1B_4Z_STRIDED_IMM);
2011 case AArch64::STNT1H_4Z_IMM_PSEUDO:
2012 return expandMultiVecPseudo(
2013 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
2014 AArch64::STNT1H_4Z_IMM, AArch64::STNT1H_4Z_STRIDED_IMM);
2015 case AArch64::STNT1W_4Z_IMM_PSEUDO:
2016 return expandMultiVecPseudo(
2017 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
2018 AArch64::STNT1W_4Z_IMM, AArch64::STNT1W_4Z_STRIDED_IMM);
2019 case AArch64::STNT1D_4Z_IMM_PSEUDO:
2020 return expandMultiVecPseudo(
2021 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
2022 AArch64::STNT1D_4Z_IMM, AArch64::STNT1D_4Z_STRIDED_IMM);
2023 case AArch64::LD1B_4Z_PSEUDO:
2024 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
2025 AArch64::ZPR4StridedRegClass, AArch64::LD1B_4Z,
2026 AArch64::LD1B_4Z_STRIDED);
2027 case AArch64::LD1H_4Z_PSEUDO:
2028 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
2029 AArch64::ZPR4StridedRegClass, AArch64::LD1H_4Z,
2030 AArch64::LD1H_4Z_STRIDED);
2031 case AArch64::LD1W_4Z_PSEUDO:
2032 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
2033 AArch64::ZPR4StridedRegClass, AArch64::LD1W_4Z,
2034 AArch64::LD1W_4Z_STRIDED);
2035 case AArch64::LD1D_4Z_PSEUDO:
2036 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
2037 AArch64::ZPR4StridedRegClass, AArch64::LD1D_4Z,
2038 AArch64::LD1D_4Z_STRIDED);
2039 case AArch64::LDNT1B_4Z_PSEUDO:
2040 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
2041 AArch64::ZPR4StridedRegClass,
2042 AArch64::LDNT1B_4Z, AArch64::LDNT1B_4Z_STRIDED);
2043 case AArch64::LDNT1H_4Z_PSEUDO:
2044 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
2045 AArch64::ZPR4StridedRegClass,
2046 AArch64::LDNT1H_4Z, AArch64::LDNT1H_4Z_STRIDED);
2047 case AArch64::LDNT1W_4Z_PSEUDO:
2048 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
2049 AArch64::ZPR4StridedRegClass,
2050 AArch64::LDNT1W_4Z, AArch64::LDNT1W_4Z_STRIDED);
2051 case AArch64::LDNT1D_4Z_PSEUDO:
2052 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
2053 AArch64::ZPR4StridedRegClass,
2054 AArch64::LDNT1D_4Z, AArch64::LDNT1D_4Z_STRIDED);
2055 case AArch64::COPY_INTO_TRANSPOSED_TUPLE:
2056 return expandCopyIntoTuplePseudo(
MI,
MBB,
MBBI);
2057 case AArch64::EON_ZZZ:
2058 case AArch64::NAND_ZZZ:
2059 case AArch64::NOR_ZZZ:
2060 return expandSVEBitwisePseudo(
MI,
MBB,
MBBI);
2067bool AArch64ExpandPseudoImpl::expandMBB(MachineBasicBlock &
MBB) {
2073 if (
MBBI->isPseudo())
2085 for (
auto &
MBB : MF)
2090bool AArch64ExpandPseudoLegacy::runOnMachineFunction(
MachineFunction &MF) {
2091 return AArch64ExpandPseudoImpl().run(MF);
2096 return new AArch64ExpandPseudoLegacy();
2102 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 the analysis usage information of a pass.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
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.
const HexagonRegisterInfo & getRegisterInfo() const
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 getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
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.
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.
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.