44#define AARCH64_EXPAND_PSEUDO_NAME "AArch64 pseudo instruction expansion pass"
48class AArch64ExpandPseudoImpl {
62 unsigned ContiguousOpc,
unsigned StridedOpc);
75 unsigned LdarOp,
unsigned StlrOp,
unsigned CmpOp,
76 unsigned ExtendImm,
unsigned ZeroReg,
94 struct ConditionalBlocks {
123char AArch64ExpandPseudoLegacy::ID = 0;
135 assert(MO.isReg() && MO.getReg());
152 uint64_t
Imm =
MI.getOperand(1).getImm();
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();
214 .
addReg(DstReg, RegState::Define |
220 case AArch64::MOVKWi:
221 case AArch64::MOVKXi: {
223 bool DstIsDead =
MI.getOperand(0).isDead();
236 MI.eraseFromParent();
240bool AArch64ExpandPseudoImpl::expandCMP_SWAP(
242 unsigned StlrOp,
unsigned CmpOp,
unsigned ExtendImm,
unsigned ZeroReg,
246 const MachineOperand &Dest =
MI.getOperand(0);
247 Register StatusReg =
MI.getOperand(1).getReg();
248 bool StatusDead =
MI.getOperand(1).isDead();
251 assert(!
MI.getOperand(2).isUndef() &&
"cannot handle undef");
253 Register DesiredReg =
MI.getOperand(3).getReg();
262 MF->
insert(++LoadCmpBB->getIterator(), StoreBB);
263 MF->
insert(++StoreBB->getIterator(), DoneBB);
271 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::MOVZWi), StatusReg)
275 BuildMI(LoadCmpBB, MIMD,
TII->get(CmpOp), ZeroReg)
279 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::Bcc))
282 .
addReg(AArch64::NZCV, RegState::Implicit | RegState::Kill);
283 LoadCmpBB->addSuccessor(DoneBB);
284 LoadCmpBB->addSuccessor(StoreBB);
289 BuildMI(StoreBB, MIMD,
TII->get(StlrOp), StatusReg)
292 BuildMI(StoreBB, MIMD,
TII->get(AArch64::CBNZW))
295 StoreBB->addSuccessor(LoadCmpBB);
296 StoreBB->addSuccessor(DoneBB);
298 DoneBB->splice(DoneBB->end(), &
MBB,
MI,
MBB.
end());
299 DoneBB->transferSuccessors(&
MBB);
304 MI.eraseFromParent();
307 LivePhysRegs LiveRegs;
312 StoreBB->clearLiveIns();
314 LoadCmpBB->clearLiveIns();
320bool AArch64ExpandPseudoImpl::expandCMP_SWAP_128(
325 MachineOperand &DestLo =
MI.getOperand(0);
326 MachineOperand &DestHi =
MI.getOperand(1);
327 Register StatusReg =
MI.getOperand(2).getReg();
328 bool StatusDead =
MI.getOperand(2).isDead();
331 assert(!
MI.getOperand(3).isUndef() &&
"cannot handle undef");
333 Register DesiredLoReg =
MI.getOperand(4).getReg();
334 Register DesiredHiReg =
MI.getOperand(5).getReg();
335 Register NewLoReg =
MI.getOperand(6).getReg();
336 Register NewHiReg =
MI.getOperand(7).getReg();
338 unsigned LdxpOp, StxpOp;
340 switch (
MI.getOpcode()) {
341 case AArch64::CMP_SWAP_128_MONOTONIC:
342 LdxpOp = AArch64::LDXPX;
343 StxpOp = AArch64::STXPX;
345 case AArch64::CMP_SWAP_128_RELEASE:
346 LdxpOp = AArch64::LDXPX;
347 StxpOp = AArch64::STLXPX;
349 case AArch64::CMP_SWAP_128_ACQUIRE:
350 LdxpOp = AArch64::LDAXPX;
351 StxpOp = AArch64::STXPX;
353 case AArch64::CMP_SWAP_128:
354 LdxpOp = AArch64::LDAXPX;
355 StxpOp = AArch64::STLXPX;
368 MF->
insert(++LoadCmpBB->getIterator(), StoreBB);
369 MF->
insert(++StoreBB->getIterator(), FailBB);
370 MF->
insert(++FailBB->getIterator(), DoneBB);
381 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::SUBSXrs), AArch64::XZR)
385 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::CSINCWr), StatusReg)
389 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::SUBSXrs), AArch64::XZR)
393 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::CSINCWr), StatusReg)
394 .
addUse(StatusReg, RegState::Kill)
395 .
addUse(StatusReg, RegState::Kill)
397 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::CBNZW))
400 LoadCmpBB->addSuccessor(FailBB);
401 LoadCmpBB->addSuccessor(StoreBB);
406 BuildMI(StoreBB, MIMD,
TII->get(StxpOp), StatusReg)
410 BuildMI(StoreBB, MIMD,
TII->get(AArch64::CBNZW))
414 StoreBB->addSuccessor(LoadCmpBB);
415 StoreBB->addSuccessor(DoneBB);
420 BuildMI(FailBB, MIMD,
TII->get(StxpOp), StatusReg)
424 BuildMI(FailBB, MIMD,
TII->get(AArch64::CBNZW))
427 FailBB->addSuccessor(LoadCmpBB);
428 FailBB->addSuccessor(DoneBB);
430 DoneBB->splice(DoneBB->end(), &
MBB,
MI,
MBB.
end());
431 DoneBB->transferSuccessors(&
MBB);
436 MI.eraseFromParent();
439 LivePhysRegs LiveRegs;
446 FailBB->clearLiveIns();
448 StoreBB->clearLiveIns();
450 LoadCmpBB->clearLiveIns();
494bool AArch64ExpandPseudoImpl::expand_DestructiveOp(
495 MachineInstr &
MI, MachineBasicBlock &
MBB,
502 bool DstIsDead =
MI.getOperand(0).isDead();
504 unsigned PredIdx, DOPIdx, SrcIdx, Src2Idx;
509 if (DstReg ==
MI.getOperand(3).getReg()) {
511 std::tie(PredIdx, DOPIdx, SrcIdx) = std::make_tuple(1, 3, 2);
518 std::tie(PredIdx, DOPIdx, SrcIdx) = std::make_tuple(1, 2, 3);
521 std::tie(PredIdx, DOPIdx, SrcIdx) = std::make_tuple(2, 3, 3);
524 std::tie(PredIdx, DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 2, 3, 4);
525 if (DstReg ==
MI.getOperand(3).getReg()) {
527 std::tie(PredIdx, DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 3, 4, 2);
529 }
else if (DstReg ==
MI.getOperand(4).getReg()) {
531 std::tie(PredIdx, DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 4, 3, 2);
538 std::tie(DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 1, 2);
547 bool DOPRegIsUnique =
false;
550 DOPRegIsUnique = DstReg !=
MI.getOperand(SrcIdx).getReg();
555 DstReg !=
MI.getOperand(DOPIdx).getReg() ||
556 MI.getOperand(DOPIdx).getReg() !=
MI.getOperand(SrcIdx).getReg();
561 DOPRegIsUnique =
true;
565 DstReg !=
MI.getOperand(DOPIdx).getReg() ||
566 (
MI.getOperand(DOPIdx).
getReg() !=
MI.getOperand(SrcIdx).getReg() &&
567 MI.getOperand(DOPIdx).getReg() !=
MI.getOperand(Src2Idx).getReg());
583 uint64_t ElementSize =
TII->getElementSizeForOpcode(Opcode);
584 unsigned MovPrfx, LSLZero, MovPrfxZero;
585 switch (ElementSize) {
588 MovPrfx = AArch64::MOVPRFX_ZZ;
589 LSLZero = AArch64::LSL_ZPmI_B;
590 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_B;
593 MovPrfx = AArch64::MOVPRFX_ZZ;
594 LSLZero = AArch64::LSL_ZPmI_H;
595 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_H;
598 MovPrfx = AArch64::MOVPRFX_ZZ;
599 LSLZero = AArch64::LSL_ZPmI_S;
600 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_S;
603 MovPrfx = AArch64::MOVPRFX_ZZ;
604 LSLZero = AArch64::LSL_ZPmI_D;
605 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_D;
617 MachineInstrBuilder PRFX, DOP;
624 "The destructive operand should be unique");
626 "This instruction is unpredicated");
630 .
addReg(DstReg, RegState::Define)
631 .
addReg(
MI.getOperand(PredIdx).getReg())
632 .
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState);
646 .
addReg(DstReg, RegState::Define)
647 .
add(
MI.getOperand(PredIdx))
651 }
else if (DstReg !=
MI.getOperand(DOPIdx).getReg()) {
652 assert(DOPRegIsUnique &&
"The destructive operand should be unique");
654 .
addReg(DstReg, RegState::Define)
655 .
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState);
665 DOPRegState = DOPRegState | RegState::Kill;
669 DOP.
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState)
670 .
add(
MI.getOperand(PredIdx))
671 .
add(
MI.getOperand(SrcIdx));
677 DOP.
add(
MI.getOperand(PredIdx))
678 .
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState)
679 .
add(
MI.getOperand(SrcIdx));
682 DOP.
add(
MI.getOperand(PredIdx))
683 .
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState)
684 .
add(
MI.getOperand(SrcIdx))
685 .
add(
MI.getOperand(Src2Idx));
688 DOP.
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState)
689 .
add(
MI.getOperand(SrcIdx))
690 .
add(
MI.getOperand(Src2Idx));
695 transferImpOps(
MI, PRFX, DOP);
698 transferImpOps(
MI, DOP, DOP);
700 MI.eraseFromParent();
704bool AArch64ExpandPseudoImpl::expandSVEBitwisePseudo(
705 MachineInstr &
MI, MachineBasicBlock &
MBB,
707 MachineInstrBuilder PRFX, DOP;
708 const unsigned Opcode =
MI.getOpcode();
709 const MachineOperand &Op0 =
MI.getOperand(0);
710 const MachineOperand *Op1 = &
MI.getOperand(1);
711 const MachineOperand *Op2 = &
MI.getOperand(2);
714 if (DOPReg == Op2->
getReg()) {
717 }
else if (DOPReg != Op1->
getReg()) {
726 Opcode == AArch64::NAND_ZZZ));
729 assert((DOPReg == Op1->
getReg() || PRFX) &&
"invalid expansion");
738 case AArch64::EON_ZZZ:
741 .
addReg(DOPReg, DOPRegState)
745 case AArch64::NAND_ZZZ:
748 .
addReg(DOPReg, DOPRegState)
752 case AArch64::NOR_ZZZ:
755 .
addReg(DOPReg, DOPRegState)
762 transferImpOps(
MI, PRFX, DOP);
765 transferImpOps(
MI, DOP, DOP);
768 MI.eraseFromParent();
772bool AArch64ExpandPseudoImpl::expandSetTagLoop(
778 Register AddressReg =
MI.getOperand(1).getReg();
782 bool ZeroData =
MI.getOpcode() == AArch64::STZGloop_wback;
783 const unsigned OpCode1 =
784 ZeroData ? AArch64::STZGPostIndex : AArch64::STGPostIndex;
785 const unsigned OpCode2 =
786 ZeroData ? AArch64::STZ2GPostIndex : AArch64::ST2GPostIndex;
788 unsigned Size =
MI.getOperand(2).getImm();
790 if (
Size % (16 * 2) != 0) {
806 MF->
insert(++LoopBB->getIterator(), DoneBB);
823 .
addReg(AArch64::NZCV, RegState::Implicit | RegState::Kill);
825 LoopBB->addSuccessor(LoopBB);
826 LoopBB->addSuccessor(DoneBB);
828 DoneBB->splice(DoneBB->end(), &
MBB,
MI,
MBB.
end());
829 DoneBB->transferSuccessors(&
MBB);
834 MI.eraseFromParent();
836 LivePhysRegs LiveRegs;
841 LoopBB->clearLiveIns();
843 DoneBB->clearLiveIns();
849bool AArch64ExpandPseudoImpl::expandSVESpillFill(
852 assert((
Opc == AArch64::LDR_ZXI ||
Opc == AArch64::STR_ZXI ||
853 Opc == AArch64::LDR_PXI ||
Opc == AArch64::STR_PXI) &&
854 "Unexpected opcode");
857 unsigned sub0 = (
Opc == AArch64::LDR_ZXI ||
Opc == AArch64::STR_ZXI)
860 const TargetRegisterInfo *
TRI =
864 int ImmOffset =
MI.getOperand(2).getImm() +
Offset;
865 bool Kill = (
Offset + 1 ==
N) ?
MI.getOperand(1).isKill() :
false;
866 assert(ImmOffset >= -256 && ImmOffset < 256 &&
867 "Immediate spill offset out of range");
874 MI.eraseFromParent();
885 unsigned RegMaskStartIdx) {
894 while (!
MBBI->getOperand(RegMaskStartIdx).isRegMask()) {
896 assert(MOP.
isReg() &&
"can only add register operands");
898 MOP.
getReg(),
false,
true,
false,
904 Call->addOperand(MO);
915 unsigned RegMaskStartIdx) {
916 unsigned Opc = CallTarget.
isGlobal() ? AArch64::BL : AArch64::BLR;
919 "invalid operand for regular call");
923bool AArch64ExpandPseudoImpl::expandCALL_RVMARKER(
931 MachineOperand &RVTarget =
MI.getOperand(0);
932 bool DoEmitMarker =
MI.getOperand(1).getImm();
933 assert(RVTarget.
isGlobal() &&
"invalid operand for attached call");
935 MachineInstr *OriginalCall =
nullptr;
937 if (
MI.getOpcode() == AArch64::BLRA_RVMARKER) {
939 const MachineOperand &CallTarget =
MI.getOperand(2);
940 const MachineOperand &
Key =
MI.getOperand(3);
941 const MachineOperand &IntDisc =
MI.getOperand(4);
942 const MachineOperand &AddrDisc =
MI.getOperand(5);
946 "Invalid auth call key");
948 MachineOperand
Ops[] = {CallTarget,
Key, IntDisc, AddrDisc};
953 assert(
MI.getOpcode() == AArch64::BLR_RVMARKER &&
"unknown rvmarker MI");
961 .
addReg(AArch64::FP, RegState::Define)
970 if (
MI.shouldUpdateAdditionalCallInfo())
973 MI.eraseFromParent();
975 std::next(RVCall->getIterator()));
979bool AArch64ExpandPseudoImpl::expandCALL_BTI(MachineBasicBlock &
MBB,
999 if (
MI.shouldUpdateAdditionalCallInfo())
1002 MI.eraseFromParent();
1007bool AArch64ExpandPseudoImpl::expandStoreSwiftAsyncContext(
1015 if (STI.getTargetTriple().getArchName() !=
"arm64e") {
1032 unsigned Opc =
Offset >= 0 ? AArch64::ADDXri : AArch64::SUBXri;
1064bool AArch64ExpandPseudoImpl::expandSTSHHAtomicStore(
1066 MachineInstr &
MI = *
MBBI;
1069 unsigned Order =
MI.getOperand(2).getImm();
1070 unsigned Policy =
MI.getOperand(3).getImm();
1071 unsigned Size =
MI.getOperand(4).getImm();
1073 bool IsRelaxed = Order == 0;
1074 unsigned StoreOpc = 0;
1079 StoreOpc = IsRelaxed ? AArch64::STRBBui : AArch64::STLRB;
1082 StoreOpc = IsRelaxed ? AArch64::STRHHui : AArch64::STLRH;
1085 StoreOpc = IsRelaxed ? AArch64::STRWui : AArch64::STLRW;
1088 StoreOpc = IsRelaxed ? AArch64::STRXui : AArch64::STLRX;
1103 const TargetRegisterInfo *
TRI =
1105 Register SubReg =
TRI->getSubReg(ValReg, AArch64::sub_32);
1112 .
add(
MI.getOperand(1));
1120 transferImpOps(
MI, Store, Store);
1125 MI.eraseFromParent();
1129AArch64ExpandPseudoImpl::ConditionalBlocks
1130AArch64ExpandPseudoImpl::expandConditionalPseudo(
1132 MachineInstrBuilder &Branch) {
1135 "Unexpected unreachable in block");
1141 MachineInstr &PrevMI = *std::prev(
MBBI);
1142 MachineBasicBlock *CondBB =
MBB.
splitAt(PrevMI,
true);
1143 MachineBasicBlock *EndBB =
1144 std::next(
MBBI) == CondBB->
end()
1157 return {*CondBB, *EndBB};
1161AArch64ExpandPseudoImpl::expandRestoreZASave(MachineBasicBlock &
MBB,
1163 MachineInstr &
MI = *
MBBI;
1167 MachineInstrBuilder
Branch =
1170 auto [CondBB, EndBB] = expandConditionalPseudo(
MBB,
MBBI,
DL, Branch);
1172 MachineInstrBuilder MIB =
1175 for (
unsigned I = 2;
I <
MI.getNumOperands(); ++
I)
1176 MIB.
add(
MI.getOperand(
I));
1178 MIB.
addReg(
MI.getOperand(1).getReg(), RegState::Implicit);
1180 MI.eraseFromParent();
1191 [[maybe_unused]]
auto *RI =
MBB.getParent()->getSubtarget().getRegisterInfo();
1197 auto [CondBB, EndBB] = expandConditionalPseudo(
MBB,
MBBI,
DL, Branch);
1202 for (
unsigned I = 3;
I <
MI.getNumOperands(); ++
I)
1203 MIB.
add(
MI.getOperand(
I));
1206 .
addImm(AArch64SysReg::TPIDR2_EL0)
1208 bool ZeroZA =
MI.getOperand(1).getImm() != 0;
1209 bool ZeroZT0 =
MI.getOperand(2).getImm() != 0;
1211 assert(
MI.definesRegister(AArch64::ZAB0, RI) &&
"should define ZA!");
1217 assert(
MI.definesRegister(AArch64::ZT0, RI) &&
"should define ZT0!");
1222 MI.eraseFromParent();
1227AArch64ExpandPseudoImpl::expandCondSMToggle(MachineBasicBlock &
MBB,
1229 MachineInstr &
MI = *
MBBI;
1236 MI.getParent()->successors().begin() ==
1237 MI.getParent()->successors().end()) {
1238 MI.eraseFromParent();
1281 switch (
MI.getOperand(2).getImm()) {
1285 Opc = AArch64::TBNZW;
1288 Opc = AArch64::TBZW;
1291 auto PStateSM =
MI.getOperand(3).getReg();
1293 unsigned SMReg32 =
TRI->getSubReg(PStateSM, AArch64::sub_32);
1294 MachineInstrBuilder Tbx =
1297 auto [CondBB, EndBB] = expandConditionalPseudo(
MBB,
MBBI,
DL, Tbx);
1299 MachineInstrBuilder MIB =
BuildMI(CondBB, CondBB.
back(),
MI.getDebugLoc(),
1300 TII->get(AArch64::MSRpstatesvcrImm1));
1304 MIB.
add(
MI.getOperand(0));
1305 MIB.
add(
MI.getOperand(1));
1306 for (
unsigned i = 4; i <
MI.getNumOperands(); ++i)
1307 MIB.
add(
MI.getOperand(i));
1309 MI.eraseFromParent();
1313bool AArch64ExpandPseudoImpl::expandMultiVecPseudo(
1315 TargetRegisterClass ContiguousClass, TargetRegisterClass StridedClass,
1316 unsigned ContiguousOp,
unsigned StridedOpc) {
1317 MachineInstr &
MI = *
MBBI;
1331 .
add(
MI.getOperand(0))
1332 .
add(
MI.getOperand(1))
1333 .
add(
MI.getOperand(2))
1334 .
add(
MI.getOperand(3));
1335 transferImpOps(
MI, MIB, MIB);
1336 MI.eraseFromParent();
1340bool AArch64ExpandPseudoImpl::expandFormTuplePseudo(
1344 MachineInstr &
MI = *
MBBI;
1345 Register ReturnTuple =
MI.getOperand(0).getReg();
1347 const TargetRegisterInfo *
TRI =
1349 for (
unsigned I = 0;
I <
Size; ++
I) {
1350 Register FormTupleOpReg =
MI.getOperand(
I + 1).getReg();
1352 TRI->getSubReg(ReturnTuple, AArch64::zsub0 +
I);
1355 if (FormTupleOpReg != ReturnTupleSubReg)
1357 .
addReg(ReturnTupleSubReg, RegState::Define)
1362 MI.eraseFromParent();
1368bool AArch64ExpandPseudoImpl::expandMI(MachineBasicBlock &
MBB,
1371 MachineInstr &
MI = *
MBBI;
1372 unsigned Opcode =
MI.getOpcode();
1376 if (OrigInstr != -1) {
1377 auto &Orig =
TII->get(OrigInstr);
1380 return expand_DestructiveOp(
MI,
MBB,
MBBI);
1388 case AArch64::BSPv8i8:
1389 case AArch64::BSPv16i8: {
1391 if (DstReg ==
MI.getOperand(3).getReg()) {
1394 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BITv8i8
1395 : AArch64::BITv16i8))
1396 .
add(
MI.getOperand(0))
1397 .
add(
MI.getOperand(3))
1398 .
add(
MI.getOperand(2))
1399 .
add(
MI.getOperand(1));
1400 transferImpOps(
MI,
I,
I);
1401 }
else if (DstReg ==
MI.getOperand(2).getReg()) {
1404 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BIFv8i8
1405 : AArch64::BIFv16i8))
1406 .
add(
MI.getOperand(0))
1407 .
add(
MI.getOperand(2))
1408 .
add(
MI.getOperand(3))
1409 .
add(
MI.getOperand(1));
1410 transferImpOps(
MI,
I,
I);
1413 if (DstReg ==
MI.getOperand(1).getReg()) {
1416 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BSLv8i8
1417 : AArch64::BSLv16i8))
1418 .
add(
MI.getOperand(0))
1419 .
add(
MI.getOperand(1))
1420 .
add(
MI.getOperand(2))
1421 .
add(
MI.getOperand(3));
1422 transferImpOps(
MI,
I,
I);
1427 MI.getOperand(1).isKill() &&
1428 MI.getOperand(1).getReg() !=
MI.getOperand(2).getReg() &&
1429 MI.getOperand(1).getReg() !=
MI.getOperand(3).getReg());
1431 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::ORRv8i8
1432 : AArch64::ORRv16i8))
1440 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BSLv8i8
1441 : AArch64::BSLv16i8))
1442 .
add(
MI.getOperand(0))
1445 MI.getOperand(0).isRenamable()))
1446 .
add(
MI.getOperand(2))
1447 .
add(
MI.getOperand(3));
1448 transferImpOps(
MI, I2, I2);
1451 MI.eraseFromParent();
1455 case AArch64::ADDWrr:
1456 case AArch64::SUBWrr:
1457 case AArch64::ADDXrr:
1458 case AArch64::SUBXrr:
1459 case AArch64::ADDSWrr:
1460 case AArch64::SUBSWrr:
1461 case AArch64::ADDSXrr:
1462 case AArch64::SUBSXrr:
1463 case AArch64::ANDWrr:
1464 case AArch64::ANDXrr:
1465 case AArch64::BICWrr:
1466 case AArch64::BICXrr:
1467 case AArch64::ANDSWrr:
1468 case AArch64::ANDSXrr:
1469 case AArch64::BICSWrr:
1470 case AArch64::BICSXrr:
1471 case AArch64::EONWrr:
1472 case AArch64::EONXrr:
1473 case AArch64::EORWrr:
1474 case AArch64::EORXrr:
1475 case AArch64::ORNWrr:
1476 case AArch64::ORNXrr:
1477 case AArch64::ORRWrr:
1478 case AArch64::ORRXrr: {
1480 switch (
MI.getOpcode()) {
1483 case AArch64::ADDWrr: Opcode = AArch64::ADDWrs;
break;
1484 case AArch64::SUBWrr: Opcode = AArch64::SUBWrs;
break;
1485 case AArch64::ADDXrr: Opcode = AArch64::ADDXrs;
break;
1486 case AArch64::SUBXrr: Opcode = AArch64::SUBXrs;
break;
1487 case AArch64::ADDSWrr: Opcode = AArch64::ADDSWrs;
break;
1488 case AArch64::SUBSWrr: Opcode = AArch64::SUBSWrs;
break;
1489 case AArch64::ADDSXrr: Opcode = AArch64::ADDSXrs;
break;
1490 case AArch64::SUBSXrr: Opcode = AArch64::SUBSXrs;
break;
1491 case AArch64::ANDWrr: Opcode = AArch64::ANDWrs;
break;
1492 case AArch64::ANDXrr: Opcode = AArch64::ANDXrs;
break;
1493 case AArch64::BICWrr: Opcode = AArch64::BICWrs;
break;
1494 case AArch64::BICXrr: Opcode = AArch64::BICXrs;
break;
1495 case AArch64::ANDSWrr: Opcode = AArch64::ANDSWrs;
break;
1496 case AArch64::ANDSXrr: Opcode = AArch64::ANDSXrs;
break;
1497 case AArch64::BICSWrr: Opcode = AArch64::BICSWrs;
break;
1498 case AArch64::BICSXrr: Opcode = AArch64::BICSXrs;
break;
1499 case AArch64::EONWrr: Opcode = AArch64::EONWrs;
break;
1500 case AArch64::EONXrr: Opcode = AArch64::EONXrs;
break;
1501 case AArch64::EORWrr: Opcode = AArch64::EORWrs;
break;
1502 case AArch64::EORXrr: Opcode = AArch64::EORXrs;
break;
1503 case AArch64::ORNWrr: Opcode = AArch64::ORNWrs;
break;
1504 case AArch64::ORNXrr: Opcode = AArch64::ORNXrs;
break;
1505 case AArch64::ORRWrr: Opcode = AArch64::ORRWrs;
break;
1506 case AArch64::ORRXrr: Opcode = AArch64::ORRXrs;
break;
1510 MachineInstr *NewMI = MF.CreateMachineInstr(
1511 TII->get(Opcode),
MI.getDebugLoc(),
true);
1513 MachineInstrBuilder MIB1(MF, NewMI);
1514 MIB1->setPCSections(MF,
MI.getPCSections());
1515 MIB1.addReg(
MI.getOperand(0).getReg(), RegState::Define)
1516 .add(
MI.getOperand(1))
1517 .add(
MI.getOperand(2))
1519 transferImpOps(
MI, MIB1, MIB1);
1520 if (
auto DebugNumber =
MI.peekDebugInstrNum())
1522 MI.eraseFromParent();
1526 case AArch64::LOADgot: {
1529 const MachineOperand &MO1 =
MI.getOperand(1);
1535 TII->get(AArch64::LDRXl), DstReg);
1543 "Only expect globals, externalsymbols, or constant pools");
1548 MachineFunction &MF = *
MI.getParent()->getParent();
1550 MachineInstrBuilder MIB1 =
1553 MachineInstrBuilder MIB2;
1554 if (MF.
getSubtarget<AArch64Subtarget>().isTargetILP32()) {
1556 unsigned Reg32 =
TRI->getSubReg(DstReg, AArch64::sub_32);
1559 .
addReg(DstReg, RegState::Kill)
1560 .
addReg(DstReg, RegState::Implicit);
1564 .
add(
MI.getOperand(0))
1565 .
addUse(DstReg, RegState::Kill);
1579 "Only expect globals, externalsymbols, or constant pools");
1590 if (
MI.peekDebugInstrNum() != 0)
1592 transferImpOps(
MI, MIB1, MIB2);
1594 MI.eraseFromParent();
1597 case AArch64::MOVaddrBA: {
1598 MachineFunction &MF = *
MI.getParent()->getParent();
1599 if (MF.
getSubtarget<AArch64Subtarget>().isTargetMachO()) {
1604 assert(
MI.getOperand(1).getOffset() == 0 &&
"unexpected offset");
1614 TII->get(AArch64::LDRXui), DstReg)
1618 transferImpOps(
MI, MIB1, MIB2);
1619 MI.eraseFromParent();
1624 case AArch64::MOVaddr:
1625 case AArch64::MOVaddrJT:
1626 case AArch64::MOVaddrCP:
1627 case AArch64::MOVaddrTLS:
1628 case AArch64::MOVaddrEXT: {
1631 assert(DstReg != AArch64::XZR);
1632 MachineInstrBuilder MIB1 =
1634 .
add(
MI.getOperand(1));
1644 auto Tag =
MI.getOperand(1);
1646 Tag.setOffset(0x100000000);
1653 MachineInstrBuilder MIB2 =
1655 .
add(
MI.getOperand(0))
1657 .
add(
MI.getOperand(2))
1660 transferImpOps(
MI, MIB1, MIB2);
1661 MI.eraseFromParent();
1664 case AArch64::ADDlowTLS:
1667 .
add(
MI.getOperand(0))
1668 .
add(
MI.getOperand(1))
1669 .
add(
MI.getOperand(2))
1671 MI.eraseFromParent();
1674 case AArch64::MOVbaseTLS: {
1676 auto SysReg = AArch64SysReg::TPIDR_EL0;
1678 if (MF->
getSubtarget<AArch64Subtarget>().useEL3ForTP())
1679 SysReg = AArch64SysReg::TPIDR_EL3;
1680 else if (MF->
getSubtarget<AArch64Subtarget>().useEL2ForTP())
1681 SysReg = AArch64SysReg::TPIDR_EL2;
1682 else if (MF->
getSubtarget<AArch64Subtarget>().useEL1ForTP())
1683 SysReg = AArch64SysReg::TPIDR_EL1;
1684 else if (MF->
getSubtarget<AArch64Subtarget>().useROEL0ForTP())
1685 SysReg = AArch64SysReg::TPIDRRO_EL0;
1688 MI.eraseFromParent();
1692 case AArch64::MOVi32imm:
1694 case AArch64::MOVi64imm:
1696 case AArch64::RET_ReallyLR: {
1702 MachineInstrBuilder MIB =
1704 .
addReg(AArch64::LR, RegState::Undef);
1705 transferImpOps(
MI, MIB, MIB);
1706 MI.eraseFromParent();
1709 case AArch64::CMP_SWAP_8:
1710 return expandCMP_SWAP(
MBB,
MBBI, AArch64::LDAXRB, AArch64::STLXRB,
1713 AArch64::WZR, NextMBBI);
1714 case AArch64::CMP_SWAP_16:
1715 return expandCMP_SWAP(
MBB,
MBBI, AArch64::LDAXRH, AArch64::STLXRH,
1718 AArch64::WZR, NextMBBI);
1719 case AArch64::CMP_SWAP_32:
1720 return expandCMP_SWAP(
MBB,
MBBI, AArch64::LDAXRW, AArch64::STLXRW,
1723 AArch64::WZR, NextMBBI);
1724 case AArch64::CMP_SWAP_64:
1725 return expandCMP_SWAP(
MBB,
MBBI,
1726 AArch64::LDAXRX, AArch64::STLXRX, AArch64::SUBSXrs,
1728 AArch64::XZR, NextMBBI);
1729 case AArch64::CMP_SWAP_128:
1730 case AArch64::CMP_SWAP_128_RELEASE:
1731 case AArch64::CMP_SWAP_128_ACQUIRE:
1732 case AArch64::CMP_SWAP_128_MONOTONIC:
1733 return expandCMP_SWAP_128(
MBB,
MBBI, NextMBBI);
1735 case AArch64::AESMCrrTied:
1736 case AArch64::AESIMCrrTied: {
1737 MachineInstrBuilder MIB =
1739 TII->get(Opcode == AArch64::AESMCrrTied ? AArch64::AESMCrr :
1741 .
add(
MI.getOperand(0))
1742 .
add(
MI.getOperand(1));
1743 transferImpOps(
MI, MIB, MIB);
1744 MI.eraseFromParent();
1747 case AArch64::IRGstack: {
1749 const AArch64FunctionInfo *AFI = MF.
getInfo<AArch64FunctionInfo>();
1750 const AArch64FrameLowering *TFI =
1751 MF.
getSubtarget<AArch64Subtarget>().getFrameLowering();
1758 StackOffset FrameRegOffset = TFI->resolveFrameOffsetReference(
1764 if (FrameRegOffset) {
1766 SrcReg =
MI.getOperand(0).getReg();
1768 FrameRegOffset,
TII);
1771 .
add(
MI.getOperand(0))
1773 .
add(
MI.getOperand(2));
1774 MI.eraseFromParent();
1777 case AArch64::TAGPstack: {
1778 int64_t
Offset =
MI.getOperand(2).getImm();
1780 TII->get(
Offset >= 0 ? AArch64::ADDG : AArch64::SUBG))
1781 .
add(
MI.getOperand(0))
1782 .
add(
MI.getOperand(1))
1784 .
add(
MI.getOperand(4));
1785 MI.eraseFromParent();
1788 case AArch64::STGloop_wback:
1789 case AArch64::STZGloop_wback:
1790 return expandSetTagLoop(
MBB,
MBBI, NextMBBI);
1791 case AArch64::STGloop:
1792 case AArch64::STZGloop:
1794 "Non-writeback variants of STGloop / STZGloop should not "
1795 "survive past PrologEpilogInserter.");
1796 case AArch64::STR_ZZZZXI:
1797 case AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS:
1798 return expandSVESpillFill(
MBB,
MBBI, AArch64::STR_ZXI, 4);
1799 case AArch64::STR_ZZZXI:
1800 return expandSVESpillFill(
MBB,
MBBI, AArch64::STR_ZXI, 3);
1801 case AArch64::STR_ZZXI:
1802 case AArch64::STR_ZZXI_STRIDED_CONTIGUOUS:
1803 return expandSVESpillFill(
MBB,
MBBI, AArch64::STR_ZXI, 2);
1804 case AArch64::STR_PPXI:
1805 return expandSVESpillFill(
MBB,
MBBI, AArch64::STR_PXI, 2);
1806 case AArch64::LDR_ZZZZXI:
1807 case AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS:
1808 return expandSVESpillFill(
MBB,
MBBI, AArch64::LDR_ZXI, 4);
1809 case AArch64::LDR_ZZZXI:
1810 return expandSVESpillFill(
MBB,
MBBI, AArch64::LDR_ZXI, 3);
1811 case AArch64::LDR_ZZXI:
1812 case AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS:
1813 return expandSVESpillFill(
MBB,
MBBI, AArch64::LDR_ZXI, 2);
1814 case AArch64::LDR_PPXI:
1815 return expandSVESpillFill(
MBB,
MBBI, AArch64::LDR_PXI, 2);
1816 case AArch64::BLR_RVMARKER:
1817 case AArch64::BLRA_RVMARKER:
1818 return expandCALL_RVMARKER(
MBB,
MBBI);
1819 case AArch64::BLR_BTI:
1820 return expandCALL_BTI(
MBB,
MBBI);
1821 case AArch64::StoreSwiftAsyncContext:
1822 return expandStoreSwiftAsyncContext(
MBB,
MBBI);
1823 case AArch64::STSHH_ATOMIC_STORE_SZ:
1824 return expandSTSHHAtomicStore(
MBB,
MBBI);
1825 case AArch64::RestoreZAPseudo:
1826 case AArch64::CommitZASavePseudo:
1827 case AArch64::MSRpstatePseudo: {
1828 auto *NewMBB = [&] {
1830 case AArch64::RestoreZAPseudo:
1831 return expandRestoreZASave(
MBB,
MBBI);
1832 case AArch64::CommitZASavePseudo:
1833 return expandCommitZASave(
MBB,
MBBI);
1834 case AArch64::MSRpstatePseudo:
1835 return expandCondSMToggle(
MBB,
MBBI);
1844 case AArch64::InOutZAUsePseudo:
1845 case AArch64::RequiresZASavePseudo:
1846 case AArch64::RequiresZT0SavePseudo:
1847 case AArch64::SMEStateAllocPseudo:
1848 case AArch64::COALESCER_BARRIER_FPR16:
1849 case AArch64::COALESCER_BARRIER_FPR32:
1850 case AArch64::COALESCER_BARRIER_FPR64:
1851 case AArch64::COALESCER_BARRIER_FPR128:
1852 MI.eraseFromParent();
1854 case AArch64::LD1B_2Z_IMM_PSEUDO:
1855 return expandMultiVecPseudo(
1856 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1857 AArch64::LD1B_2Z_IMM, AArch64::LD1B_2Z_STRIDED_IMM);
1858 case AArch64::LD1H_2Z_IMM_PSEUDO:
1859 return expandMultiVecPseudo(
1860 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1861 AArch64::LD1H_2Z_IMM, AArch64::LD1H_2Z_STRIDED_IMM);
1862 case AArch64::LD1W_2Z_IMM_PSEUDO:
1863 return expandMultiVecPseudo(
1864 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1865 AArch64::LD1W_2Z_IMM, AArch64::LD1W_2Z_STRIDED_IMM);
1866 case AArch64::LD1D_2Z_IMM_PSEUDO:
1867 return expandMultiVecPseudo(
1868 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1869 AArch64::LD1D_2Z_IMM, AArch64::LD1D_2Z_STRIDED_IMM);
1870 case AArch64::LDNT1B_2Z_IMM_PSEUDO:
1871 return expandMultiVecPseudo(
1872 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1873 AArch64::LDNT1B_2Z_IMM, AArch64::LDNT1B_2Z_STRIDED_IMM);
1874 case AArch64::LDNT1H_2Z_IMM_PSEUDO:
1875 return expandMultiVecPseudo(
1876 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1877 AArch64::LDNT1H_2Z_IMM, AArch64::LDNT1H_2Z_STRIDED_IMM);
1878 case AArch64::LDNT1W_2Z_IMM_PSEUDO:
1879 return expandMultiVecPseudo(
1880 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1881 AArch64::LDNT1W_2Z_IMM, AArch64::LDNT1W_2Z_STRIDED_IMM);
1882 case AArch64::LDNT1D_2Z_IMM_PSEUDO:
1883 return expandMultiVecPseudo(
1884 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1885 AArch64::LDNT1D_2Z_IMM, AArch64::LDNT1D_2Z_STRIDED_IMM);
1886 case AArch64::LD1B_2Z_PSEUDO:
1887 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1888 AArch64::ZPR2StridedRegClass, AArch64::LD1B_2Z,
1889 AArch64::LD1B_2Z_STRIDED);
1890 case AArch64::LD1H_2Z_PSEUDO:
1891 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1892 AArch64::ZPR2StridedRegClass, AArch64::LD1H_2Z,
1893 AArch64::LD1H_2Z_STRIDED);
1894 case AArch64::LD1W_2Z_PSEUDO:
1895 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1896 AArch64::ZPR2StridedRegClass, AArch64::LD1W_2Z,
1897 AArch64::LD1W_2Z_STRIDED);
1898 case AArch64::LD1D_2Z_PSEUDO:
1899 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1900 AArch64::ZPR2StridedRegClass, AArch64::LD1D_2Z,
1901 AArch64::LD1D_2Z_STRIDED);
1902 case AArch64::LDNT1B_2Z_PSEUDO:
1903 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1904 AArch64::ZPR2StridedRegClass,
1905 AArch64::LDNT1B_2Z, AArch64::LDNT1B_2Z_STRIDED);
1906 case AArch64::LDNT1H_2Z_PSEUDO:
1907 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1908 AArch64::ZPR2StridedRegClass,
1909 AArch64::LDNT1H_2Z, AArch64::LDNT1H_2Z_STRIDED);
1910 case AArch64::LDNT1W_2Z_PSEUDO:
1911 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1912 AArch64::ZPR2StridedRegClass,
1913 AArch64::LDNT1W_2Z, AArch64::LDNT1W_2Z_STRIDED);
1914 case AArch64::LDNT1D_2Z_PSEUDO:
1915 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1916 AArch64::ZPR2StridedRegClass,
1917 AArch64::LDNT1D_2Z, AArch64::LDNT1D_2Z_STRIDED);
1918 case AArch64::LD1B_4Z_IMM_PSEUDO:
1919 return expandMultiVecPseudo(
1920 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1921 AArch64::LD1B_4Z_IMM, AArch64::LD1B_4Z_STRIDED_IMM);
1922 case AArch64::LD1H_4Z_IMM_PSEUDO:
1923 return expandMultiVecPseudo(
1924 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1925 AArch64::LD1H_4Z_IMM, AArch64::LD1H_4Z_STRIDED_IMM);
1926 case AArch64::LD1W_4Z_IMM_PSEUDO:
1927 return expandMultiVecPseudo(
1928 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1929 AArch64::LD1W_4Z_IMM, AArch64::LD1W_4Z_STRIDED_IMM);
1930 case AArch64::LD1D_4Z_IMM_PSEUDO:
1931 return expandMultiVecPseudo(
1932 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1933 AArch64::LD1D_4Z_IMM, AArch64::LD1D_4Z_STRIDED_IMM);
1934 case AArch64::LDNT1B_4Z_IMM_PSEUDO:
1935 return expandMultiVecPseudo(
1936 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1937 AArch64::LDNT1B_4Z_IMM, AArch64::LDNT1B_4Z_STRIDED_IMM);
1938 case AArch64::LDNT1H_4Z_IMM_PSEUDO:
1939 return expandMultiVecPseudo(
1940 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1941 AArch64::LDNT1H_4Z_IMM, AArch64::LDNT1H_4Z_STRIDED_IMM);
1942 case AArch64::LDNT1W_4Z_IMM_PSEUDO:
1943 return expandMultiVecPseudo(
1944 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1945 AArch64::LDNT1W_4Z_IMM, AArch64::LDNT1W_4Z_STRIDED_IMM);
1946 case AArch64::LDNT1D_4Z_IMM_PSEUDO:
1947 return expandMultiVecPseudo(
1948 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1949 AArch64::LDNT1D_4Z_IMM, AArch64::LDNT1D_4Z_STRIDED_IMM);
1950 case AArch64::LD1B_4Z_PSEUDO:
1951 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1952 AArch64::ZPR4StridedRegClass, AArch64::LD1B_4Z,
1953 AArch64::LD1B_4Z_STRIDED);
1954 case AArch64::LD1H_4Z_PSEUDO:
1955 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1956 AArch64::ZPR4StridedRegClass, AArch64::LD1H_4Z,
1957 AArch64::LD1H_4Z_STRIDED);
1958 case AArch64::LD1W_4Z_PSEUDO:
1959 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1960 AArch64::ZPR4StridedRegClass, AArch64::LD1W_4Z,
1961 AArch64::LD1W_4Z_STRIDED);
1962 case AArch64::LD1D_4Z_PSEUDO:
1963 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1964 AArch64::ZPR4StridedRegClass, AArch64::LD1D_4Z,
1965 AArch64::LD1D_4Z_STRIDED);
1966 case AArch64::LDNT1B_4Z_PSEUDO:
1967 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1968 AArch64::ZPR4StridedRegClass,
1969 AArch64::LDNT1B_4Z, AArch64::LDNT1B_4Z_STRIDED);
1970 case AArch64::LDNT1H_4Z_PSEUDO:
1971 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1972 AArch64::ZPR4StridedRegClass,
1973 AArch64::LDNT1H_4Z, AArch64::LDNT1H_4Z_STRIDED);
1974 case AArch64::LDNT1W_4Z_PSEUDO:
1975 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1976 AArch64::ZPR4StridedRegClass,
1977 AArch64::LDNT1W_4Z, AArch64::LDNT1W_4Z_STRIDED);
1978 case AArch64::LDNT1D_4Z_PSEUDO:
1979 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1980 AArch64::ZPR4StridedRegClass,
1981 AArch64::LDNT1D_4Z, AArch64::LDNT1D_4Z_STRIDED);
1982 case AArch64::FORM_TRANSPOSED_REG_TUPLE_X2_PSEUDO:
1983 return expandFormTuplePseudo(
MBB,
MBBI, NextMBBI, 2);
1984 case AArch64::FORM_TRANSPOSED_REG_TUPLE_X4_PSEUDO:
1985 return expandFormTuplePseudo(
MBB,
MBBI, NextMBBI, 4);
1986 case AArch64::EON_ZZZ:
1987 case AArch64::NAND_ZZZ:
1988 case AArch64::NOR_ZZZ:
1989 return expandSVEBitwisePseudo(
MI,
MBB,
MBBI);
1996bool AArch64ExpandPseudoImpl::expandMBB(MachineBasicBlock &
MBB) {
2009bool AArch64ExpandPseudoImpl::run(MachineFunction &MF) {
2013 for (
auto &
MBB : MF)
2018bool AArch64ExpandPseudoLegacy::runOnMachineFunction(MachineFunction &MF) {
2019 return AArch64ExpandPseudoImpl().run(MF);
2024 return new AArch64ExpandPseudoLegacy();
2030 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)
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
unsigned getTaggedBasePointerOffset() const
ArrayRef - 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.
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
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.
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.
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
void push_back(const T &Elt)
StringRef - Represent a constant reference to a string, i.e.
CodeModel::Model getCodeModel() const
Returns the code model.
ArrayRef< MCPhysReg > getRegisters() const
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_TAGGED
MO_TAGGED - With MO_PAGE, indicates that the page includes a memory tag in bits 56-63.
@ MO_G3
MO_G3 - A symbol operand with this flag (granule 3) represents the high 16-bits of a 64-bit address,...
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 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
@ DestructiveInstTypeMask
@ DestructiveUnaryPassthru
@ 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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
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.
void computeAndAddLiveIns(LivePhysRegs &LiveRegs, MachineBasicBlock &MBB)
Convenience function combining computeLiveIns() and addLiveIns().
constexpr RegState getUndefRegState(bool B)
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.