43#define AARCH64_EXPAND_PSEUDO_NAME "AArch64 pseudo instruction expansion pass"
47class AArch64ExpandPseudoImpl {
61 unsigned ContiguousOpc,
unsigned StridedOpc);
74 unsigned LdarOp,
unsigned StlrOp,
unsigned CmpOp,
75 unsigned ExtendImm,
unsigned ZeroReg,
91 struct ConditionalBlocks {
120char AArch64ExpandPseudoLegacy::ID = 0;
132 assert(MO.isReg() && MO.getReg());
149 uint64_t
Imm =
MI.getOperand(1).getImm();
151 if (DstReg == AArch64::XZR || DstReg == AArch64::WZR) {
154 MI.eraseFromParent();
162 SmallVector<MachineInstrBuilder, 4> MIBS;
164 bool LastItem = std::next(
I) ==
E;
169 case AArch64::ORRWri:
170 case AArch64::ORRXri:
171 case AArch64::ANDXri:
172 case AArch64::EORXri:
175 .
add(
MI.getOperand(0))
176 .
addReg(BitSize == 32 ? AArch64::WZR : AArch64::XZR)
180 bool DstIsDead =
MI.getOperand(0).isDead();
183 .
addReg(DstReg, RegState::Define |
190 case AArch64::EONXrs:
191 case AArch64::EORXrs:
192 case AArch64::ORRWrs:
193 case AArch64::ORRXrs: {
195 bool DstIsDead =
MI.getOperand(0).isDead();
198 .
addReg(DstReg, RegState::Define |
205 case AArch64::MOVNWi:
206 case AArch64::MOVNXi:
207 case AArch64::MOVZWi:
208 case AArch64::MOVZXi: {
209 bool DstIsDead =
MI.getOperand(0).isDead();
211 .
addReg(DstReg, RegState::Define |
217 case AArch64::MOVKWi:
218 case AArch64::MOVKXi: {
220 bool DstIsDead =
MI.getOperand(0).isDead();
233 MI.eraseFromParent();
237bool AArch64ExpandPseudoImpl::expandCMP_SWAP(
239 unsigned StlrOp,
unsigned CmpOp,
unsigned ExtendImm,
unsigned ZeroReg,
243 const MachineOperand &Dest =
MI.getOperand(0);
244 Register StatusReg =
MI.getOperand(1).getReg();
245 bool StatusDead =
MI.getOperand(1).isDead();
248 assert(!
MI.getOperand(2).isUndef() &&
"cannot handle undef");
250 Register DesiredReg =
MI.getOperand(3).getReg();
259 MF->
insert(++LoadCmpBB->getIterator(), StoreBB);
260 MF->
insert(++StoreBB->getIterator(), DoneBB);
268 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::MOVZWi), StatusReg)
272 BuildMI(LoadCmpBB, MIMD,
TII->get(CmpOp), ZeroReg)
276 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::Bcc))
279 .
addReg(AArch64::NZCV, RegState::Implicit | RegState::Kill);
280 LoadCmpBB->addSuccessor(DoneBB);
281 LoadCmpBB->addSuccessor(StoreBB);
286 BuildMI(StoreBB, MIMD,
TII->get(StlrOp), StatusReg)
289 BuildMI(StoreBB, MIMD,
TII->get(AArch64::CBNZW))
292 StoreBB->addSuccessor(LoadCmpBB);
293 StoreBB->addSuccessor(DoneBB);
295 DoneBB->splice(DoneBB->end(), &
MBB,
MI,
MBB.
end());
296 DoneBB->transferSuccessors(&
MBB);
301 MI.eraseFromParent();
304 LivePhysRegs LiveRegs;
309 StoreBB->clearLiveIns();
311 LoadCmpBB->clearLiveIns();
317bool AArch64ExpandPseudoImpl::expandCMP_SWAP_128(
322 MachineOperand &DestLo =
MI.getOperand(0);
323 MachineOperand &DestHi =
MI.getOperand(1);
324 Register StatusReg =
MI.getOperand(2).getReg();
325 bool StatusDead =
MI.getOperand(2).isDead();
328 assert(!
MI.getOperand(3).isUndef() &&
"cannot handle undef");
330 Register DesiredLoReg =
MI.getOperand(4).getReg();
331 Register DesiredHiReg =
MI.getOperand(5).getReg();
332 Register NewLoReg =
MI.getOperand(6).getReg();
333 Register NewHiReg =
MI.getOperand(7).getReg();
335 unsigned LdxpOp, StxpOp;
337 switch (
MI.getOpcode()) {
338 case AArch64::CMP_SWAP_128_MONOTONIC:
339 LdxpOp = AArch64::LDXPX;
340 StxpOp = AArch64::STXPX;
342 case AArch64::CMP_SWAP_128_RELEASE:
343 LdxpOp = AArch64::LDXPX;
344 StxpOp = AArch64::STLXPX;
346 case AArch64::CMP_SWAP_128_ACQUIRE:
347 LdxpOp = AArch64::LDAXPX;
348 StxpOp = AArch64::STXPX;
350 case AArch64::CMP_SWAP_128:
351 LdxpOp = AArch64::LDAXPX;
352 StxpOp = AArch64::STLXPX;
365 MF->
insert(++LoadCmpBB->getIterator(), StoreBB);
366 MF->
insert(++StoreBB->getIterator(), FailBB);
367 MF->
insert(++FailBB->getIterator(), DoneBB);
378 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::SUBSXrs), AArch64::XZR)
382 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::CSINCWr), StatusReg)
386 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::SUBSXrs), AArch64::XZR)
390 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::CSINCWr), StatusReg)
391 .
addUse(StatusReg, RegState::Kill)
392 .
addUse(StatusReg, RegState::Kill)
394 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::CBNZW))
397 LoadCmpBB->addSuccessor(FailBB);
398 LoadCmpBB->addSuccessor(StoreBB);
403 BuildMI(StoreBB, MIMD,
TII->get(StxpOp), StatusReg)
407 BuildMI(StoreBB, MIMD,
TII->get(AArch64::CBNZW))
411 StoreBB->addSuccessor(LoadCmpBB);
412 StoreBB->addSuccessor(DoneBB);
417 BuildMI(FailBB, MIMD,
TII->get(StxpOp), StatusReg)
421 BuildMI(FailBB, MIMD,
TII->get(AArch64::CBNZW))
424 FailBB->addSuccessor(LoadCmpBB);
425 FailBB->addSuccessor(DoneBB);
427 DoneBB->splice(DoneBB->end(), &
MBB,
MI,
MBB.
end());
428 DoneBB->transferSuccessors(&
MBB);
433 MI.eraseFromParent();
436 LivePhysRegs LiveRegs;
443 FailBB->clearLiveIns();
445 StoreBB->clearLiveIns();
447 LoadCmpBB->clearLiveIns();
491bool AArch64ExpandPseudoImpl::expand_DestructiveOp(
492 MachineInstr &
MI, MachineBasicBlock &
MBB,
499 bool DstIsDead =
MI.getOperand(0).isDead();
501 unsigned PredIdx, DOPIdx, SrcIdx, Src2Idx;
506 if (DstReg ==
MI.getOperand(3).getReg()) {
508 std::tie(PredIdx, DOPIdx, SrcIdx) = std::make_tuple(1, 3, 2);
515 std::tie(PredIdx, DOPIdx, SrcIdx) = std::make_tuple(1, 2, 3);
518 std::tie(PredIdx, DOPIdx, SrcIdx) = std::make_tuple(2, 3, 3);
521 std::tie(PredIdx, DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 2, 3, 4);
522 if (DstReg ==
MI.getOperand(3).getReg()) {
524 std::tie(PredIdx, DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 3, 4, 2);
526 }
else if (DstReg ==
MI.getOperand(4).getReg()) {
528 std::tie(PredIdx, DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 4, 3, 2);
535 std::tie(DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 1, 2);
538 std::tie(DOPIdx, SrcIdx) = std::make_tuple(1, 2);
541 std::tie(DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 2, 3);
550 bool DOPRegIsUnique =
false;
553 DOPRegIsUnique = DstReg !=
MI.getOperand(SrcIdx).getReg();
558 DstReg !=
MI.getOperand(DOPIdx).getReg() ||
559 MI.getOperand(DOPIdx).getReg() !=
MI.getOperand(SrcIdx).getReg();
566 DOPRegIsUnique =
true;
570 DstReg !=
MI.getOperand(DOPIdx).getReg() ||
571 (
MI.getOperand(DOPIdx).
getReg() !=
MI.getOperand(SrcIdx).getReg() &&
572 MI.getOperand(DOPIdx).getReg() !=
MI.getOperand(Src2Idx).getReg());
588 uint64_t ElementSize =
TII->getElementSizeForOpcode(Opcode);
589 unsigned MovPrfx, LSLZero, MovPrfxZero;
590 switch (ElementSize) {
593 MovPrfx = AArch64::MOVPRFX_ZZ;
594 LSLZero = AArch64::LSL_ZPmI_B;
595 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_B;
598 MovPrfx = AArch64::MOVPRFX_ZZ;
599 LSLZero = AArch64::LSL_ZPmI_H;
600 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_H;
603 MovPrfx = AArch64::MOVPRFX_ZZ;
604 LSLZero = AArch64::LSL_ZPmI_S;
605 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_S;
608 MovPrfx = AArch64::MOVPRFX_ZZ;
609 LSLZero = AArch64::LSL_ZPmI_D;
610 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_D;
622 MachineInstrBuilder PRFX, DOP;
629 "The destructive operand should be unique");
631 "This instruction is unpredicated");
635 .
addReg(DstReg, RegState::Define)
636 .
addReg(
MI.getOperand(PredIdx).getReg())
637 .
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState);
651 .
addReg(DstReg, RegState::Define)
652 .
add(
MI.getOperand(PredIdx))
656 }
else if (DstReg !=
MI.getOperand(DOPIdx).getReg()) {
657 assert(DOPRegIsUnique &&
"The destructive operand should be unique");
659 .
addReg(DstReg, RegState::Define)
660 .
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState);
670 DOPRegState = DOPRegState | RegState::Kill;
674 DOP.
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState)
675 .
add(
MI.getOperand(PredIdx))
676 .
add(
MI.getOperand(SrcIdx));
682 DOP.
add(
MI.getOperand(PredIdx))
683 .
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState)
684 .
add(
MI.getOperand(SrcIdx));
687 DOP.
add(
MI.getOperand(PredIdx))
688 .
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState)
689 .
add(
MI.getOperand(SrcIdx))
690 .
add(
MI.getOperand(Src2Idx));
693 DOP.
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState)
694 .
add(
MI.getOperand(SrcIdx));
698 DOP.
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState)
699 .
add(
MI.getOperand(SrcIdx))
700 .
add(
MI.getOperand(Src2Idx));
705 transferImpOps(
MI, PRFX, DOP);
708 transferImpOps(
MI, DOP, DOP);
710 MI.eraseFromParent();
714bool AArch64ExpandPseudoImpl::expandSVEBitwisePseudo(
715 MachineInstr &
MI, MachineBasicBlock &
MBB,
717 MachineInstrBuilder PRFX, DOP;
718 const unsigned Opcode =
MI.getOpcode();
719 const MachineOperand &Op0 =
MI.getOperand(0);
720 const MachineOperand *Op1 = &
MI.getOperand(1);
721 const MachineOperand *Op2 = &
MI.getOperand(2);
724 if (DOPReg == Op2->
getReg()) {
727 }
else if (DOPReg != Op1->
getReg()) {
736 Opcode == AArch64::NAND_ZZZ));
739 assert((DOPReg == Op1->
getReg() || PRFX) &&
"invalid expansion");
748 case AArch64::EON_ZZZ:
751 .
addReg(DOPReg, DOPRegState)
755 case AArch64::NAND_ZZZ:
758 .
addReg(DOPReg, DOPRegState)
762 case AArch64::NOR_ZZZ:
765 .
addReg(DOPReg, DOPRegState)
772 transferImpOps(
MI, PRFX, DOP);
775 transferImpOps(
MI, DOP, DOP);
778 MI.eraseFromParent();
782bool AArch64ExpandPseudoImpl::expandSetTagLoop(
788 Register AddressReg =
MI.getOperand(1).getReg();
792 bool ZeroData =
MI.getOpcode() == AArch64::STZGloop_wback;
793 const unsigned OpCode1 =
794 ZeroData ? AArch64::STZGPostIndex : AArch64::STGPostIndex;
795 const unsigned OpCode2 =
796 ZeroData ? AArch64::STZ2GPostIndex : AArch64::ST2GPostIndex;
798 unsigned Size =
MI.getOperand(2).getImm();
800 if (
Size % (16 * 2) != 0) {
816 MF->
insert(++LoopBB->getIterator(), DoneBB);
833 .
addReg(AArch64::NZCV, RegState::Implicit | RegState::Kill);
835 LoopBB->addSuccessor(LoopBB);
836 LoopBB->addSuccessor(DoneBB);
838 DoneBB->splice(DoneBB->end(), &
MBB,
MI,
MBB.
end());
839 DoneBB->transferSuccessors(&
MBB);
844 MI.eraseFromParent();
846 LivePhysRegs LiveRegs;
851 LoopBB->clearLiveIns();
853 DoneBB->clearLiveIns();
859bool AArch64ExpandPseudoImpl::expandSVESpillFill(
862 assert((
Opc == AArch64::LDR_ZXI ||
Opc == AArch64::STR_ZXI ||
863 Opc == AArch64::LDR_PXI ||
Opc == AArch64::STR_PXI) &&
864 "Unexpected opcode");
867 unsigned sub0 = (
Opc == AArch64::LDR_ZXI ||
Opc == AArch64::STR_ZXI)
870 const TargetRegisterInfo *
TRI =
874 int ImmOffset =
MI.getOperand(2).getImm() +
Offset;
875 bool Kill = (
Offset + 1 ==
N) ?
MI.getOperand(1).isKill() :
false;
876 assert(ImmOffset >= -256 && ImmOffset < 256 &&
877 "Immediate spill offset out of range");
884 MI.eraseFromParent();
895 unsigned RegMaskStartIdx) {
904 while (!
MBBI->getOperand(RegMaskStartIdx).isRegMask()) {
906 assert(MOP.
isReg() &&
"can only add register operands");
908 MOP.
getReg(),
false,
true,
false,
914 Call->addOperand(MO);
925 unsigned RegMaskStartIdx) {
926 unsigned Opc = CallTarget.
isGlobal() ? AArch64::BL : AArch64::BLR;
929 "invalid operand for regular call");
933bool AArch64ExpandPseudoImpl::expandCALL_RVMARKER(
941 MachineOperand &RVTarget =
MI.getOperand(0);
942 bool DoEmitMarker =
MI.getOperand(1).getImm();
943 assert(RVTarget.
isGlobal() &&
"invalid operand for attached call");
945 MachineInstr *OriginalCall =
nullptr;
947 if (
MI.getOpcode() == AArch64::BLRA_RVMARKER) {
949 const MachineOperand &CallTarget =
MI.getOperand(2);
950 const MachineOperand &
Key =
MI.getOperand(3);
951 const MachineOperand &IntDisc =
MI.getOperand(4);
952 const MachineOperand &AddrDisc =
MI.getOperand(5);
956 "Invalid auth call key");
958 MachineOperand
Ops[] = {CallTarget,
Key, IntDisc, AddrDisc};
963 assert(
MI.getOpcode() == AArch64::BLR_RVMARKER &&
"unknown rvmarker MI");
971 .
addReg(AArch64::FP, RegState::Define)
980 if (
MI.shouldUpdateAdditionalCallInfo())
983 MI.eraseFromParent();
985 std::next(RVCall->getIterator()));
989bool AArch64ExpandPseudoImpl::expandCALL_BTI(MachineBasicBlock &
MBB,
1009 if (
MI.shouldUpdateAdditionalCallInfo())
1012 MI.eraseFromParent();
1017bool AArch64ExpandPseudoImpl::expandStoreSwiftAsyncContext(
1025 if (STI.getTargetTriple().getArchName() !=
"arm64e") {
1042 unsigned Opc =
Offset >= 0 ? AArch64::ADDXri : AArch64::SUBXri;
1074AArch64ExpandPseudoImpl::ConditionalBlocks
1075AArch64ExpandPseudoImpl::expandConditionalPseudo(
1077 MachineInstrBuilder &Branch) {
1080 "Unexpected unreachable in block");
1086 MachineInstr &PrevMI = *std::prev(
MBBI);
1087 MachineBasicBlock *CondBB =
MBB.
splitAt(PrevMI,
true);
1088 MachineBasicBlock *EndBB =
1089 std::next(
MBBI) == CondBB->
end()
1102 return {*CondBB, *EndBB};
1106AArch64ExpandPseudoImpl::expandRestoreZASave(MachineBasicBlock &
MBB,
1108 MachineInstr &
MI = *
MBBI;
1112 MachineInstrBuilder
Branch =
1115 auto [CondBB, EndBB] = expandConditionalPseudo(
MBB,
MBBI,
DL, Branch);
1117 MachineInstrBuilder MIB =
1120 for (
unsigned I = 2;
I <
MI.getNumOperands(); ++
I)
1121 MIB.
add(
MI.getOperand(
I));
1123 MIB.
addReg(
MI.getOperand(1).getReg(), RegState::Implicit);
1125 MI.eraseFromParent();
1136 [[maybe_unused]]
auto *RI =
MBB.getParent()->getSubtarget().getRegisterInfo();
1142 auto [CondBB, EndBB] = expandConditionalPseudo(
MBB,
MBBI,
DL, Branch);
1147 for (
unsigned I = 3;
I <
MI.getNumOperands(); ++
I)
1148 MIB.
add(
MI.getOperand(
I));
1151 .
addImm(AArch64SysReg::TPIDR2_EL0)
1153 bool ZeroZA =
MI.getOperand(1).getImm() != 0;
1154 bool ZeroZT0 =
MI.getOperand(2).getImm() != 0;
1156 assert(
MI.definesRegister(AArch64::ZAB0, RI) &&
"should define ZA!");
1162 assert(
MI.definesRegister(AArch64::ZT0, RI) &&
"should define ZT0!");
1167 MI.eraseFromParent();
1172AArch64ExpandPseudoImpl::expandCondSMToggle(MachineBasicBlock &
MBB,
1174 MachineInstr &
MI = *
MBBI;
1181 MI.getParent()->successors().begin() ==
1182 MI.getParent()->successors().end()) {
1183 MI.eraseFromParent();
1226 switch (
MI.getOperand(2).getImm()) {
1230 Opc = AArch64::TBNZW;
1233 Opc = AArch64::TBZW;
1236 auto PStateSM =
MI.getOperand(3).getReg();
1238 unsigned SMReg32 =
TRI->getSubReg(PStateSM, AArch64::sub_32);
1239 MachineInstrBuilder Tbx =
1242 auto [CondBB, EndBB] = expandConditionalPseudo(
MBB,
MBBI,
DL, Tbx);
1244 MachineInstrBuilder MIB =
BuildMI(CondBB, CondBB.
back(),
MI.getDebugLoc(),
1245 TII->get(AArch64::MSRpstatesvcrImm1));
1249 MIB.
add(
MI.getOperand(0));
1250 MIB.
add(
MI.getOperand(1));
1251 for (
unsigned i = 4; i <
MI.getNumOperands(); ++i)
1252 MIB.
add(
MI.getOperand(i));
1254 MI.eraseFromParent();
1258bool AArch64ExpandPseudoImpl::expandMultiVecPseudo(
1260 TargetRegisterClass ContiguousClass, TargetRegisterClass StridedClass,
1261 unsigned ContiguousOp,
unsigned StridedOpc) {
1262 MachineInstr &
MI = *
MBBI;
1276 .
add(
MI.getOperand(0))
1277 .
add(
MI.getOperand(1))
1278 .
add(
MI.getOperand(2))
1279 .
add(
MI.getOperand(3));
1280 transferImpOps(
MI, MIB, MIB);
1281 MI.eraseFromParent();
1285bool AArch64ExpandPseudoImpl::expandFormTuplePseudo(
1289 MachineInstr &
MI = *
MBBI;
1290 Register ReturnTuple =
MI.getOperand(0).getReg();
1292 const TargetRegisterInfo *
TRI =
1294 for (
unsigned I = 0;
I <
Size; ++
I) {
1295 Register FormTupleOpReg =
MI.getOperand(
I + 1).getReg();
1297 TRI->getSubReg(ReturnTuple, AArch64::zsub0 +
I);
1300 if (FormTupleOpReg != ReturnTupleSubReg)
1302 .
addReg(ReturnTupleSubReg, RegState::Define)
1307 MI.eraseFromParent();
1313bool AArch64ExpandPseudoImpl::expandMI(MachineBasicBlock &
MBB,
1316 MachineInstr &
MI = *
MBBI;
1317 unsigned Opcode =
MI.getOpcode();
1321 if (OrigInstr != -1) {
1322 auto &Orig =
TII->get(OrigInstr);
1325 return expand_DestructiveOp(
MI,
MBB,
MBBI);
1333 case AArch64::BSPv8i8:
1334 case AArch64::BSPv16i8: {
1336 if (DstReg ==
MI.getOperand(3).getReg()) {
1339 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BITv8i8
1340 : AArch64::BITv16i8))
1341 .
add(
MI.getOperand(0))
1342 .
add(
MI.getOperand(3))
1343 .
add(
MI.getOperand(2))
1344 .
add(
MI.getOperand(1));
1345 transferImpOps(
MI,
I,
I);
1346 }
else if (DstReg ==
MI.getOperand(2).getReg()) {
1349 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BIFv8i8
1350 : AArch64::BIFv16i8))
1351 .
add(
MI.getOperand(0))
1352 .
add(
MI.getOperand(2))
1353 .
add(
MI.getOperand(3))
1354 .
add(
MI.getOperand(1));
1355 transferImpOps(
MI,
I,
I);
1358 if (DstReg ==
MI.getOperand(1).getReg()) {
1361 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BSLv8i8
1362 : AArch64::BSLv16i8))
1363 .
add(
MI.getOperand(0))
1364 .
add(
MI.getOperand(1))
1365 .
add(
MI.getOperand(2))
1366 .
add(
MI.getOperand(3));
1367 transferImpOps(
MI,
I,
I);
1372 MI.getOperand(1).isKill() &&
1373 MI.getOperand(1).getReg() !=
MI.getOperand(2).getReg() &&
1374 MI.getOperand(1).getReg() !=
MI.getOperand(3).getReg());
1376 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::ORRv8i8
1377 : AArch64::ORRv16i8))
1385 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BSLv8i8
1386 : AArch64::BSLv16i8))
1387 .
add(
MI.getOperand(0))
1390 MI.getOperand(0).isRenamable()))
1391 .
add(
MI.getOperand(2))
1392 .
add(
MI.getOperand(3));
1393 transferImpOps(
MI, I2, I2);
1396 MI.eraseFromParent();
1400 case AArch64::ADDWrr:
1401 case AArch64::SUBWrr:
1402 case AArch64::ADDXrr:
1403 case AArch64::SUBXrr:
1404 case AArch64::ADDSWrr:
1405 case AArch64::SUBSWrr:
1406 case AArch64::ADDSXrr:
1407 case AArch64::SUBSXrr:
1408 case AArch64::ANDWrr:
1409 case AArch64::ANDXrr:
1410 case AArch64::BICWrr:
1411 case AArch64::BICXrr:
1412 case AArch64::ANDSWrr:
1413 case AArch64::ANDSXrr:
1414 case AArch64::BICSWrr:
1415 case AArch64::BICSXrr:
1416 case AArch64::EONWrr:
1417 case AArch64::EONXrr:
1418 case AArch64::EORWrr:
1419 case AArch64::EORXrr:
1420 case AArch64::ORNWrr:
1421 case AArch64::ORNXrr:
1422 case AArch64::ORRWrr:
1423 case AArch64::ORRXrr: {
1425 switch (
MI.getOpcode()) {
1428 case AArch64::ADDWrr: Opcode = AArch64::ADDWrs;
break;
1429 case AArch64::SUBWrr: Opcode = AArch64::SUBWrs;
break;
1430 case AArch64::ADDXrr: Opcode = AArch64::ADDXrs;
break;
1431 case AArch64::SUBXrr: Opcode = AArch64::SUBXrs;
break;
1432 case AArch64::ADDSWrr: Opcode = AArch64::ADDSWrs;
break;
1433 case AArch64::SUBSWrr: Opcode = AArch64::SUBSWrs;
break;
1434 case AArch64::ADDSXrr: Opcode = AArch64::ADDSXrs;
break;
1435 case AArch64::SUBSXrr: Opcode = AArch64::SUBSXrs;
break;
1436 case AArch64::ANDWrr: Opcode = AArch64::ANDWrs;
break;
1437 case AArch64::ANDXrr: Opcode = AArch64::ANDXrs;
break;
1438 case AArch64::BICWrr: Opcode = AArch64::BICWrs;
break;
1439 case AArch64::BICXrr: Opcode = AArch64::BICXrs;
break;
1440 case AArch64::ANDSWrr: Opcode = AArch64::ANDSWrs;
break;
1441 case AArch64::ANDSXrr: Opcode = AArch64::ANDSXrs;
break;
1442 case AArch64::BICSWrr: Opcode = AArch64::BICSWrs;
break;
1443 case AArch64::BICSXrr: Opcode = AArch64::BICSXrs;
break;
1444 case AArch64::EONWrr: Opcode = AArch64::EONWrs;
break;
1445 case AArch64::EONXrr: Opcode = AArch64::EONXrs;
break;
1446 case AArch64::EORWrr: Opcode = AArch64::EORWrs;
break;
1447 case AArch64::EORXrr: Opcode = AArch64::EORXrs;
break;
1448 case AArch64::ORNWrr: Opcode = AArch64::ORNWrs;
break;
1449 case AArch64::ORNXrr: Opcode = AArch64::ORNXrs;
break;
1450 case AArch64::ORRWrr: Opcode = AArch64::ORRWrs;
break;
1451 case AArch64::ORRXrr: Opcode = AArch64::ORRXrs;
break;
1455 MachineInstr *NewMI = MF.CreateMachineInstr(
1456 TII->get(Opcode),
MI.getDebugLoc(),
true);
1458 MachineInstrBuilder MIB1(MF, NewMI);
1459 MIB1->setPCSections(MF,
MI.getPCSections());
1460 MIB1.addReg(
MI.getOperand(0).getReg(), RegState::Define)
1461 .add(
MI.getOperand(1))
1462 .add(
MI.getOperand(2))
1464 transferImpOps(
MI, MIB1, MIB1);
1465 if (
auto DebugNumber =
MI.peekDebugInstrNum())
1467 MI.eraseFromParent();
1471 case AArch64::LOADgot: {
1474 const MachineOperand &MO1 =
MI.getOperand(1);
1480 TII->get(AArch64::LDRXl), DstReg);
1488 "Only expect globals, externalsymbols, or constant pools");
1493 MachineFunction &MF = *
MI.getParent()->getParent();
1495 MachineInstrBuilder MIB1 =
1498 MachineInstrBuilder MIB2;
1499 if (MF.
getSubtarget<AArch64Subtarget>().isTargetILP32()) {
1501 unsigned Reg32 =
TRI->getSubReg(DstReg, AArch64::sub_32);
1504 .
addReg(DstReg, RegState::Kill)
1505 .
addReg(DstReg, RegState::Implicit);
1509 .
add(
MI.getOperand(0))
1510 .
addUse(DstReg, RegState::Kill);
1524 "Only expect globals, externalsymbols, or constant pools");
1535 if (
MI.peekDebugInstrNum() != 0)
1537 transferImpOps(
MI, MIB1, MIB2);
1539 MI.eraseFromParent();
1542 case AArch64::MOVaddrBA:
1543 case AArch64::MOVaddr:
1544 case AArch64::MOVaddrJT:
1545 case AArch64::MOVaddrCP:
1546 case AArch64::MOVaddrTLS:
1547 case AArch64::MOVaddrEXT: {
1548 MachineFunction &MF = *
MI.getParent()->getParent();
1550 assert(DstReg != AArch64::XZR);
1552 bool IsTargetMachO = MF.
getSubtarget<AArch64Subtarget>().isTargetMachO();
1555 MI.getOpcode(),
MI.getOperand(1).getTargetFlags(), IsTargetMachO, Insn);
1558 std::optional<unsigned> CPIdx;
1559 if (Opcode == AArch64::MOVaddrBA && IsTargetMachO) {
1564 assert(
MI.getOperand(1).getOffset() == 0 &&
"unexpected offset");
1569 MachineInstrBuilder FirstMIB;
1570 MachineInstrBuilder LastMIB;
1571 for (
const auto &
I : Insn) {
1572 MachineInstrBuilder MIB;
1580 MIB.
add(
MI.getOperand(1));
1582 case AArch64::LDRXui:
1589 case AArch64::MOVKXi: {
1597 auto Tag =
MI.getOperand(1);
1599 Tag.setOffset(0x100000000);
1607 case AArch64::ADDXri:
1609 .
add(
MI.getOperand(0))
1611 .
add(
MI.getOperand(2))
1623 transferImpOps(
MI, FirstMIB, LastMIB);
1624 MI.eraseFromParent();
1627 case AArch64::ADDlowTLS:
1630 .
add(
MI.getOperand(0))
1631 .
add(
MI.getOperand(1))
1632 .
add(
MI.getOperand(2))
1634 MI.eraseFromParent();
1637 case AArch64::MOVbaseTLS: {
1639 auto SysReg = AArch64SysReg::TPIDR_EL0;
1641 if (MF->
getSubtarget<AArch64Subtarget>().useEL3ForTP())
1642 SysReg = AArch64SysReg::TPIDR_EL3;
1643 else if (MF->
getSubtarget<AArch64Subtarget>().useEL2ForTP())
1644 SysReg = AArch64SysReg::TPIDR_EL2;
1645 else if (MF->
getSubtarget<AArch64Subtarget>().useEL1ForTP())
1646 SysReg = AArch64SysReg::TPIDR_EL1;
1647 else if (MF->
getSubtarget<AArch64Subtarget>().useROEL0ForTP())
1648 SysReg = AArch64SysReg::TPIDRRO_EL0;
1651 MI.eraseFromParent();
1655 case AArch64::MOVi32imm:
1657 case AArch64::MOVi64imm:
1659 case AArch64::RET_ReallyLR: {
1665 MachineInstrBuilder MIB =
1667 .
addReg(AArch64::LR, RegState::Undef);
1668 transferImpOps(
MI, MIB, MIB);
1669 MI.eraseFromParent();
1672 case AArch64::CMP_SWAP_8:
1673 return expandCMP_SWAP(
MBB,
MBBI, AArch64::LDAXRB, AArch64::STLXRB,
1676 AArch64::WZR, NextMBBI);
1677 case AArch64::CMP_SWAP_16:
1678 return expandCMP_SWAP(
MBB,
MBBI, AArch64::LDAXRH, AArch64::STLXRH,
1681 AArch64::WZR, NextMBBI);
1682 case AArch64::CMP_SWAP_32:
1683 return expandCMP_SWAP(
MBB,
MBBI, AArch64::LDAXRW, AArch64::STLXRW,
1686 AArch64::WZR, NextMBBI);
1687 case AArch64::CMP_SWAP_64:
1688 return expandCMP_SWAP(
MBB,
MBBI,
1689 AArch64::LDAXRX, AArch64::STLXRX, AArch64::SUBSXrs,
1691 AArch64::XZR, NextMBBI);
1692 case AArch64::CMP_SWAP_128:
1693 case AArch64::CMP_SWAP_128_RELEASE:
1694 case AArch64::CMP_SWAP_128_ACQUIRE:
1695 case AArch64::CMP_SWAP_128_MONOTONIC:
1696 return expandCMP_SWAP_128(
MBB,
MBBI, NextMBBI);
1698 case AArch64::AESMCrrTied:
1699 case AArch64::AESIMCrrTied: {
1700 MachineInstrBuilder MIB =
1702 TII->get(Opcode == AArch64::AESMCrrTied ? AArch64::AESMCrr :
1704 .
add(
MI.getOperand(0))
1705 .
add(
MI.getOperand(1));
1706 transferImpOps(
MI, MIB, MIB);
1707 MI.eraseFromParent();
1710 case AArch64::IRGstack: {
1712 const AArch64FunctionInfo *AFI = MF.
getInfo<AArch64FunctionInfo>();
1713 const AArch64FrameLowering *TFI =
1714 MF.
getSubtarget<AArch64Subtarget>().getFrameLowering();
1721 StackOffset FrameRegOffset = TFI->resolveFrameOffsetReference(
1727 if (FrameRegOffset) {
1729 SrcReg =
MI.getOperand(0).getReg();
1731 FrameRegOffset,
TII);
1734 .
add(
MI.getOperand(0))
1736 .
add(
MI.getOperand(2));
1737 MI.eraseFromParent();
1740 case AArch64::TAGPstack: {
1741 int64_t
Offset =
MI.getOperand(2).getImm();
1743 TII->get(
Offset >= 0 ? AArch64::ADDG : AArch64::SUBG))
1744 .
add(
MI.getOperand(0))
1745 .
add(
MI.getOperand(1))
1747 .
add(
MI.getOperand(4));
1748 MI.eraseFromParent();
1751 case AArch64::STGloop_wback:
1752 case AArch64::STZGloop_wback:
1753 return expandSetTagLoop(
MBB,
MBBI, NextMBBI);
1754 case AArch64::STGloop:
1755 case AArch64::STZGloop:
1757 "Non-writeback variants of STGloop / STZGloop should not "
1758 "survive past PrologEpilogInserter.");
1759 case AArch64::STR_ZZZZXI:
1760 case AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS:
1761 return expandSVESpillFill(
MBB,
MBBI, AArch64::STR_ZXI, 4);
1762 case AArch64::STR_ZZZXI:
1763 return expandSVESpillFill(
MBB,
MBBI, AArch64::STR_ZXI, 3);
1764 case AArch64::STR_ZZXI:
1765 case AArch64::STR_ZZXI_STRIDED_CONTIGUOUS:
1766 return expandSVESpillFill(
MBB,
MBBI, AArch64::STR_ZXI, 2);
1767 case AArch64::STR_PPXI:
1768 return expandSVESpillFill(
MBB,
MBBI, AArch64::STR_PXI, 2);
1769 case AArch64::LDR_ZZZZXI:
1770 case AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS:
1771 return expandSVESpillFill(
MBB,
MBBI, AArch64::LDR_ZXI, 4);
1772 case AArch64::LDR_ZZZXI:
1773 return expandSVESpillFill(
MBB,
MBBI, AArch64::LDR_ZXI, 3);
1774 case AArch64::LDR_ZZXI:
1775 case AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS:
1776 return expandSVESpillFill(
MBB,
MBBI, AArch64::LDR_ZXI, 2);
1777 case AArch64::LDR_PPXI:
1778 return expandSVESpillFill(
MBB,
MBBI, AArch64::LDR_PXI, 2);
1779 case AArch64::BLR_RVMARKER:
1780 case AArch64::BLRA_RVMARKER:
1781 return expandCALL_RVMARKER(
MBB,
MBBI);
1782 case AArch64::BLR_BTI:
1783 return expandCALL_BTI(
MBB,
MBBI);
1784 case AArch64::StoreSwiftAsyncContext:
1785 return expandStoreSwiftAsyncContext(
MBB,
MBBI);
1786 case AArch64::RestoreZAPseudo:
1787 case AArch64::CommitZASavePseudo:
1788 case AArch64::MSRpstatePseudo: {
1789 auto *NewMBB = [&] {
1791 case AArch64::RestoreZAPseudo:
1792 return expandRestoreZASave(
MBB,
MBBI);
1793 case AArch64::CommitZASavePseudo:
1794 return expandCommitZASave(
MBB,
MBBI);
1795 case AArch64::MSRpstatePseudo:
1796 return expandCondSMToggle(
MBB,
MBBI);
1805 case AArch64::InOutZAUsePseudo:
1806 case AArch64::RequiresZASavePseudo:
1807 case AArch64::RequiresZT0SavePseudo:
1808 case AArch64::SMEStateAllocPseudo:
1809 case AArch64::COALESCER_BARRIER_FPR16:
1810 case AArch64::COALESCER_BARRIER_FPR32:
1811 case AArch64::COALESCER_BARRIER_FPR64:
1812 case AArch64::COALESCER_BARRIER_FPR128:
1813 MI.eraseFromParent();
1815 case AArch64::LD1B_2Z_IMM_PSEUDO:
1816 return expandMultiVecPseudo(
1817 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1818 AArch64::LD1B_2Z_IMM, AArch64::LD1B_2Z_STRIDED_IMM);
1819 case AArch64::LD1H_2Z_IMM_PSEUDO:
1820 return expandMultiVecPseudo(
1821 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1822 AArch64::LD1H_2Z_IMM, AArch64::LD1H_2Z_STRIDED_IMM);
1823 case AArch64::LD1W_2Z_IMM_PSEUDO:
1824 return expandMultiVecPseudo(
1825 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1826 AArch64::LD1W_2Z_IMM, AArch64::LD1W_2Z_STRIDED_IMM);
1827 case AArch64::LD1D_2Z_IMM_PSEUDO:
1828 return expandMultiVecPseudo(
1829 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1830 AArch64::LD1D_2Z_IMM, AArch64::LD1D_2Z_STRIDED_IMM);
1831 case AArch64::LDNT1B_2Z_IMM_PSEUDO:
1832 return expandMultiVecPseudo(
1833 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1834 AArch64::LDNT1B_2Z_IMM, AArch64::LDNT1B_2Z_STRIDED_IMM);
1835 case AArch64::LDNT1H_2Z_IMM_PSEUDO:
1836 return expandMultiVecPseudo(
1837 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1838 AArch64::LDNT1H_2Z_IMM, AArch64::LDNT1H_2Z_STRIDED_IMM);
1839 case AArch64::LDNT1W_2Z_IMM_PSEUDO:
1840 return expandMultiVecPseudo(
1841 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1842 AArch64::LDNT1W_2Z_IMM, AArch64::LDNT1W_2Z_STRIDED_IMM);
1843 case AArch64::LDNT1D_2Z_IMM_PSEUDO:
1844 return expandMultiVecPseudo(
1845 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1846 AArch64::LDNT1D_2Z_IMM, AArch64::LDNT1D_2Z_STRIDED_IMM);
1847 case AArch64::LD1B_2Z_PSEUDO:
1848 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1849 AArch64::ZPR2StridedRegClass, AArch64::LD1B_2Z,
1850 AArch64::LD1B_2Z_STRIDED);
1851 case AArch64::LD1H_2Z_PSEUDO:
1852 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1853 AArch64::ZPR2StridedRegClass, AArch64::LD1H_2Z,
1854 AArch64::LD1H_2Z_STRIDED);
1855 case AArch64::LD1W_2Z_PSEUDO:
1856 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1857 AArch64::ZPR2StridedRegClass, AArch64::LD1W_2Z,
1858 AArch64::LD1W_2Z_STRIDED);
1859 case AArch64::LD1D_2Z_PSEUDO:
1860 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1861 AArch64::ZPR2StridedRegClass, AArch64::LD1D_2Z,
1862 AArch64::LD1D_2Z_STRIDED);
1863 case AArch64::LDNT1B_2Z_PSEUDO:
1864 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1865 AArch64::ZPR2StridedRegClass,
1866 AArch64::LDNT1B_2Z, AArch64::LDNT1B_2Z_STRIDED);
1867 case AArch64::LDNT1H_2Z_PSEUDO:
1868 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1869 AArch64::ZPR2StridedRegClass,
1870 AArch64::LDNT1H_2Z, AArch64::LDNT1H_2Z_STRIDED);
1871 case AArch64::LDNT1W_2Z_PSEUDO:
1872 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1873 AArch64::ZPR2StridedRegClass,
1874 AArch64::LDNT1W_2Z, AArch64::LDNT1W_2Z_STRIDED);
1875 case AArch64::LDNT1D_2Z_PSEUDO:
1876 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1877 AArch64::ZPR2StridedRegClass,
1878 AArch64::LDNT1D_2Z, AArch64::LDNT1D_2Z_STRIDED);
1879 case AArch64::LD1B_4Z_IMM_PSEUDO:
1880 return expandMultiVecPseudo(
1881 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1882 AArch64::LD1B_4Z_IMM, AArch64::LD1B_4Z_STRIDED_IMM);
1883 case AArch64::LD1H_4Z_IMM_PSEUDO:
1884 return expandMultiVecPseudo(
1885 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1886 AArch64::LD1H_4Z_IMM, AArch64::LD1H_4Z_STRIDED_IMM);
1887 case AArch64::LD1W_4Z_IMM_PSEUDO:
1888 return expandMultiVecPseudo(
1889 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1890 AArch64::LD1W_4Z_IMM, AArch64::LD1W_4Z_STRIDED_IMM);
1891 case AArch64::LD1D_4Z_IMM_PSEUDO:
1892 return expandMultiVecPseudo(
1893 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1894 AArch64::LD1D_4Z_IMM, AArch64::LD1D_4Z_STRIDED_IMM);
1895 case AArch64::LDNT1B_4Z_IMM_PSEUDO:
1896 return expandMultiVecPseudo(
1897 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1898 AArch64::LDNT1B_4Z_IMM, AArch64::LDNT1B_4Z_STRIDED_IMM);
1899 case AArch64::LDNT1H_4Z_IMM_PSEUDO:
1900 return expandMultiVecPseudo(
1901 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1902 AArch64::LDNT1H_4Z_IMM, AArch64::LDNT1H_4Z_STRIDED_IMM);
1903 case AArch64::LDNT1W_4Z_IMM_PSEUDO:
1904 return expandMultiVecPseudo(
1905 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1906 AArch64::LDNT1W_4Z_IMM, AArch64::LDNT1W_4Z_STRIDED_IMM);
1907 case AArch64::LDNT1D_4Z_IMM_PSEUDO:
1908 return expandMultiVecPseudo(
1909 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1910 AArch64::LDNT1D_4Z_IMM, AArch64::LDNT1D_4Z_STRIDED_IMM);
1911 case AArch64::LD1B_4Z_PSEUDO:
1912 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1913 AArch64::ZPR4StridedRegClass, AArch64::LD1B_4Z,
1914 AArch64::LD1B_4Z_STRIDED);
1915 case AArch64::LD1H_4Z_PSEUDO:
1916 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1917 AArch64::ZPR4StridedRegClass, AArch64::LD1H_4Z,
1918 AArch64::LD1H_4Z_STRIDED);
1919 case AArch64::LD1W_4Z_PSEUDO:
1920 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1921 AArch64::ZPR4StridedRegClass, AArch64::LD1W_4Z,
1922 AArch64::LD1W_4Z_STRIDED);
1923 case AArch64::LD1D_4Z_PSEUDO:
1924 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1925 AArch64::ZPR4StridedRegClass, AArch64::LD1D_4Z,
1926 AArch64::LD1D_4Z_STRIDED);
1927 case AArch64::LDNT1B_4Z_PSEUDO:
1928 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1929 AArch64::ZPR4StridedRegClass,
1930 AArch64::LDNT1B_4Z, AArch64::LDNT1B_4Z_STRIDED);
1931 case AArch64::LDNT1H_4Z_PSEUDO:
1932 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1933 AArch64::ZPR4StridedRegClass,
1934 AArch64::LDNT1H_4Z, AArch64::LDNT1H_4Z_STRIDED);
1935 case AArch64::LDNT1W_4Z_PSEUDO:
1936 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1937 AArch64::ZPR4StridedRegClass,
1938 AArch64::LDNT1W_4Z, AArch64::LDNT1W_4Z_STRIDED);
1939 case AArch64::LDNT1D_4Z_PSEUDO:
1940 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1941 AArch64::ZPR4StridedRegClass,
1942 AArch64::LDNT1D_4Z, AArch64::LDNT1D_4Z_STRIDED);
1943 case AArch64::FORM_TRANSPOSED_REG_TUPLE_X2_PSEUDO:
1944 return expandFormTuplePseudo(
MBB,
MBBI, NextMBBI, 2);
1945 case AArch64::FORM_TRANSPOSED_REG_TUPLE_X4_PSEUDO:
1946 return expandFormTuplePseudo(
MBB,
MBBI, NextMBBI, 4);
1947 case AArch64::EON_ZZZ:
1948 case AArch64::NAND_ZZZ:
1949 case AArch64::NOR_ZZZ:
1950 return expandSVEBitwisePseudo(
MI,
MBB,
MBBI);
1957bool AArch64ExpandPseudoImpl::expandMBB(MachineBasicBlock &
MBB) {
1963 if (
MBBI->isPseudo())
1971bool AArch64ExpandPseudoImpl::run(MachineFunction &MF) {
1975 for (
auto &
MBB : MF)
1980bool AArch64ExpandPseudoLegacy::runOnMachineFunction(MachineFunction &MF) {
1981 return AArch64ExpandPseudoImpl().run(MF);
1986 return new AArch64ExpandPseudoLegacy();
1992 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
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)
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_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.
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.