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:
176 .
add(
MI.getOperand(0))
177 .
addReg(BitSize == 32 ? AArch64::WZR : AArch64::XZR)
181 bool DstIsDead =
MI.getOperand(0).isDead();
184 .
addReg(DstReg, RegState::Define |
191 case AArch64::EONXrs:
192 case AArch64::EORXrs:
193 case AArch64::ORRWrs:
194 case AArch64::ORRXrs: {
196 bool DstIsDead =
MI.getOperand(0).isDead();
199 .
addReg(DstReg, RegState::Define |
206 case AArch64::ANDXri:
207 case AArch64::EORXri:
210 .
add(
MI.getOperand(0))
211 .
addReg(BitSize == 32 ? AArch64::WZR : AArch64::XZR)
215 bool DstIsDead =
MI.getOperand(0).isDead();
218 .
addReg(DstReg, RegState::Define |
225 case AArch64::MOVNWi:
226 case AArch64::MOVNXi:
227 case AArch64::MOVZWi:
228 case AArch64::MOVZXi: {
229 bool DstIsDead =
MI.getOperand(0).isDead();
231 .
addReg(DstReg, RegState::Define |
237 case AArch64::MOVKWi:
238 case AArch64::MOVKXi: {
240 bool DstIsDead =
MI.getOperand(0).isDead();
253 MI.eraseFromParent();
257bool AArch64ExpandPseudoImpl::expandCMP_SWAP(
259 unsigned StlrOp,
unsigned CmpOp,
unsigned ExtendImm,
unsigned ZeroReg,
263 const MachineOperand &Dest =
MI.getOperand(0);
264 Register StatusReg =
MI.getOperand(1).getReg();
265 bool StatusDead =
MI.getOperand(1).isDead();
268 assert(!
MI.getOperand(2).isUndef() &&
"cannot handle undef");
270 Register DesiredReg =
MI.getOperand(3).getReg();
279 MF->
insert(++LoadCmpBB->getIterator(), StoreBB);
280 MF->
insert(++StoreBB->getIterator(), DoneBB);
288 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::MOVZWi), StatusReg)
292 BuildMI(LoadCmpBB, MIMD,
TII->get(CmpOp), ZeroReg)
296 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::Bcc))
299 .
addReg(AArch64::NZCV, RegState::Implicit | RegState::Kill);
300 LoadCmpBB->addSuccessor(DoneBB);
301 LoadCmpBB->addSuccessor(StoreBB);
306 BuildMI(StoreBB, MIMD,
TII->get(StlrOp), StatusReg)
309 BuildMI(StoreBB, MIMD,
TII->get(AArch64::CBNZW))
312 StoreBB->addSuccessor(LoadCmpBB);
313 StoreBB->addSuccessor(DoneBB);
315 DoneBB->splice(DoneBB->end(), &
MBB,
MI,
MBB.
end());
316 DoneBB->transferSuccessors(&
MBB);
321 MI.eraseFromParent();
324 LivePhysRegs LiveRegs;
329 StoreBB->clearLiveIns();
331 LoadCmpBB->clearLiveIns();
337bool AArch64ExpandPseudoImpl::expandCMP_SWAP_128(
342 MachineOperand &DestLo =
MI.getOperand(0);
343 MachineOperand &DestHi =
MI.getOperand(1);
344 Register StatusReg =
MI.getOperand(2).getReg();
345 bool StatusDead =
MI.getOperand(2).isDead();
348 assert(!
MI.getOperand(3).isUndef() &&
"cannot handle undef");
350 Register DesiredLoReg =
MI.getOperand(4).getReg();
351 Register DesiredHiReg =
MI.getOperand(5).getReg();
352 Register NewLoReg =
MI.getOperand(6).getReg();
353 Register NewHiReg =
MI.getOperand(7).getReg();
355 unsigned LdxpOp, StxpOp;
357 switch (
MI.getOpcode()) {
358 case AArch64::CMP_SWAP_128_MONOTONIC:
359 LdxpOp = AArch64::LDXPX;
360 StxpOp = AArch64::STXPX;
362 case AArch64::CMP_SWAP_128_RELEASE:
363 LdxpOp = AArch64::LDXPX;
364 StxpOp = AArch64::STLXPX;
366 case AArch64::CMP_SWAP_128_ACQUIRE:
367 LdxpOp = AArch64::LDAXPX;
368 StxpOp = AArch64::STXPX;
370 case AArch64::CMP_SWAP_128:
371 LdxpOp = AArch64::LDAXPX;
372 StxpOp = AArch64::STLXPX;
385 MF->
insert(++LoadCmpBB->getIterator(), StoreBB);
386 MF->
insert(++StoreBB->getIterator(), FailBB);
387 MF->
insert(++FailBB->getIterator(), DoneBB);
398 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::SUBSXrs), AArch64::XZR)
402 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::CSINCWr), StatusReg)
406 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::SUBSXrs), AArch64::XZR)
410 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::CSINCWr), StatusReg)
411 .
addUse(StatusReg, RegState::Kill)
412 .
addUse(StatusReg, RegState::Kill)
414 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::CBNZW))
417 LoadCmpBB->addSuccessor(FailBB);
418 LoadCmpBB->addSuccessor(StoreBB);
423 BuildMI(StoreBB, MIMD,
TII->get(StxpOp), StatusReg)
427 BuildMI(StoreBB, MIMD,
TII->get(AArch64::CBNZW))
431 StoreBB->addSuccessor(LoadCmpBB);
432 StoreBB->addSuccessor(DoneBB);
437 BuildMI(FailBB, MIMD,
TII->get(StxpOp), StatusReg)
441 BuildMI(FailBB, MIMD,
TII->get(AArch64::CBNZW))
444 FailBB->addSuccessor(LoadCmpBB);
445 FailBB->addSuccessor(DoneBB);
447 DoneBB->splice(DoneBB->end(), &
MBB,
MI,
MBB.
end());
448 DoneBB->transferSuccessors(&
MBB);
453 MI.eraseFromParent();
456 LivePhysRegs LiveRegs;
463 FailBB->clearLiveIns();
465 StoreBB->clearLiveIns();
467 LoadCmpBB->clearLiveIns();
511bool AArch64ExpandPseudoImpl::expand_DestructiveOp(
512 MachineInstr &
MI, MachineBasicBlock &
MBB,
519 bool DstIsDead =
MI.getOperand(0).isDead();
521 unsigned PredIdx, DOPIdx, SrcIdx, Src2Idx;
526 if (DstReg ==
MI.getOperand(3).getReg()) {
528 std::tie(PredIdx, DOPIdx, SrcIdx) = std::make_tuple(1, 3, 2);
535 std::tie(PredIdx, DOPIdx, SrcIdx) = std::make_tuple(1, 2, 3);
538 std::tie(PredIdx, DOPIdx, SrcIdx) = std::make_tuple(2, 3, 3);
541 std::tie(PredIdx, DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 2, 3, 4);
542 if (DstReg ==
MI.getOperand(3).getReg()) {
544 std::tie(PredIdx, DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 3, 4, 2);
546 }
else if (DstReg ==
MI.getOperand(4).getReg()) {
548 std::tie(PredIdx, DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 4, 3, 2);
555 std::tie(DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 1, 2);
564 bool DOPRegIsUnique =
false;
567 DOPRegIsUnique = DstReg !=
MI.getOperand(SrcIdx).getReg();
572 DstReg !=
MI.getOperand(DOPIdx).getReg() ||
573 MI.getOperand(DOPIdx).getReg() !=
MI.getOperand(SrcIdx).getReg();
578 DOPRegIsUnique =
true;
582 DstReg !=
MI.getOperand(DOPIdx).getReg() ||
583 (
MI.getOperand(DOPIdx).
getReg() !=
MI.getOperand(SrcIdx).getReg() &&
584 MI.getOperand(DOPIdx).getReg() !=
MI.getOperand(Src2Idx).getReg());
600 uint64_t ElementSize =
TII->getElementSizeForOpcode(Opcode);
601 unsigned MovPrfx, LSLZero, MovPrfxZero;
602 switch (ElementSize) {
605 MovPrfx = AArch64::MOVPRFX_ZZ;
606 LSLZero = AArch64::LSL_ZPmI_B;
607 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_B;
610 MovPrfx = AArch64::MOVPRFX_ZZ;
611 LSLZero = AArch64::LSL_ZPmI_H;
612 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_H;
615 MovPrfx = AArch64::MOVPRFX_ZZ;
616 LSLZero = AArch64::LSL_ZPmI_S;
617 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_S;
620 MovPrfx = AArch64::MOVPRFX_ZZ;
621 LSLZero = AArch64::LSL_ZPmI_D;
622 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_D;
634 MachineInstrBuilder PRFX, DOP;
641 "The destructive operand should be unique");
643 "This instruction is unpredicated");
647 .
addReg(DstReg, RegState::Define)
648 .
addReg(
MI.getOperand(PredIdx).getReg())
649 .
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState);
663 .
addReg(DstReg, RegState::Define)
664 .
add(
MI.getOperand(PredIdx))
668 }
else if (DstReg !=
MI.getOperand(DOPIdx).getReg()) {
669 assert(DOPRegIsUnique &&
"The destructive operand should be unique");
671 .
addReg(DstReg, RegState::Define)
672 .
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState);
682 DOPRegState = DOPRegState | RegState::Kill;
686 DOP.
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState)
687 .
add(
MI.getOperand(PredIdx))
688 .
add(
MI.getOperand(SrcIdx));
694 DOP.
add(
MI.getOperand(PredIdx))
695 .
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState)
696 .
add(
MI.getOperand(SrcIdx));
699 DOP.
add(
MI.getOperand(PredIdx))
700 .
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState)
701 .
add(
MI.getOperand(SrcIdx))
702 .
add(
MI.getOperand(Src2Idx));
705 DOP.
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState)
706 .
add(
MI.getOperand(SrcIdx))
707 .
add(
MI.getOperand(Src2Idx));
712 transferImpOps(
MI, PRFX, DOP);
715 transferImpOps(
MI, DOP, DOP);
717 MI.eraseFromParent();
721bool AArch64ExpandPseudoImpl::expandSVEBitwisePseudo(
722 MachineInstr &
MI, MachineBasicBlock &
MBB,
724 MachineInstrBuilder PRFX, DOP;
725 const unsigned Opcode =
MI.getOpcode();
726 const MachineOperand &Op0 =
MI.getOperand(0);
727 const MachineOperand *Op1 = &
MI.getOperand(1);
728 const MachineOperand *Op2 = &
MI.getOperand(2);
731 if (DOPReg == Op2->
getReg()) {
734 }
else if (DOPReg != Op1->
getReg()) {
743 Opcode == AArch64::NAND_ZZZ));
746 assert((DOPReg == Op1->
getReg() || PRFX) &&
"invalid expansion");
755 case AArch64::EON_ZZZ:
758 .
addReg(DOPReg, DOPRegState)
762 case AArch64::NAND_ZZZ:
765 .
addReg(DOPReg, DOPRegState)
769 case AArch64::NOR_ZZZ:
772 .
addReg(DOPReg, DOPRegState)
779 transferImpOps(
MI, PRFX, DOP);
782 transferImpOps(
MI, DOP, DOP);
785 MI.eraseFromParent();
789bool AArch64ExpandPseudoImpl::expandSetTagLoop(
795 Register AddressReg =
MI.getOperand(1).getReg();
799 bool ZeroData =
MI.getOpcode() == AArch64::STZGloop_wback;
800 const unsigned OpCode1 =
801 ZeroData ? AArch64::STZGPostIndex : AArch64::STGPostIndex;
802 const unsigned OpCode2 =
803 ZeroData ? AArch64::STZ2GPostIndex : AArch64::ST2GPostIndex;
805 unsigned Size =
MI.getOperand(2).getImm();
807 if (
Size % (16 * 2) != 0) {
823 MF->
insert(++LoopBB->getIterator(), DoneBB);
840 .
addReg(AArch64::NZCV, RegState::Implicit | RegState::Kill);
842 LoopBB->addSuccessor(LoopBB);
843 LoopBB->addSuccessor(DoneBB);
845 DoneBB->splice(DoneBB->end(), &
MBB,
MI,
MBB.
end());
846 DoneBB->transferSuccessors(&
MBB);
851 MI.eraseFromParent();
853 LivePhysRegs LiveRegs;
858 LoopBB->clearLiveIns();
860 DoneBB->clearLiveIns();
866bool AArch64ExpandPseudoImpl::expandSVESpillFill(
869 assert((
Opc == AArch64::LDR_ZXI ||
Opc == AArch64::STR_ZXI ||
870 Opc == AArch64::LDR_PXI ||
Opc == AArch64::STR_PXI) &&
871 "Unexpected opcode");
874 unsigned sub0 = (
Opc == AArch64::LDR_ZXI ||
Opc == AArch64::STR_ZXI)
877 const TargetRegisterInfo *
TRI =
881 int ImmOffset =
MI.getOperand(2).getImm() +
Offset;
882 bool Kill = (
Offset + 1 ==
N) ?
MI.getOperand(1).isKill() :
false;
883 assert(ImmOffset >= -256 && ImmOffset < 256 &&
884 "Immediate spill offset out of range");
891 MI.eraseFromParent();
902 unsigned RegMaskStartIdx) {
911 while (!
MBBI->getOperand(RegMaskStartIdx).isRegMask()) {
913 assert(MOP.
isReg() &&
"can only add register operands");
915 MOP.
getReg(),
false,
true,
false,
921 Call->addOperand(MO);
932 unsigned RegMaskStartIdx) {
933 unsigned Opc = CallTarget.
isGlobal() ? AArch64::BL : AArch64::BLR;
936 "invalid operand for regular call");
940bool AArch64ExpandPseudoImpl::expandCALL_RVMARKER(
948 MachineOperand &RVTarget =
MI.getOperand(0);
949 bool DoEmitMarker =
MI.getOperand(1).getImm();
950 assert(RVTarget.
isGlobal() &&
"invalid operand for attached call");
952 MachineInstr *OriginalCall =
nullptr;
954 if (
MI.getOpcode() == AArch64::BLRA_RVMARKER) {
956 const MachineOperand &CallTarget =
MI.getOperand(2);
957 const MachineOperand &
Key =
MI.getOperand(3);
958 const MachineOperand &IntDisc =
MI.getOperand(4);
959 const MachineOperand &AddrDisc =
MI.getOperand(5);
963 "Invalid auth call key");
965 MachineOperand
Ops[] = {CallTarget,
Key, IntDisc, AddrDisc};
970 assert(
MI.getOpcode() == AArch64::BLR_RVMARKER &&
"unknown rvmarker MI");
978 .
addReg(AArch64::FP, RegState::Define)
987 if (
MI.shouldUpdateAdditionalCallInfo())
990 MI.eraseFromParent();
992 std::next(RVCall->getIterator()));
996bool AArch64ExpandPseudoImpl::expandCALL_BTI(MachineBasicBlock &
MBB,
1003 MachineInstr &
MI = *
MBBI;
1016 if (
MI.shouldUpdateAdditionalCallInfo())
1019 MI.eraseFromParent();
1024bool AArch64ExpandPseudoImpl::expandStoreSwiftAsyncContext(
1032 if (STI.getTargetTriple().getArchName() !=
"arm64e") {
1049 unsigned Opc =
Offset >= 0 ? AArch64::ADDXri : AArch64::SUBXri;
1081bool AArch64ExpandPseudoImpl::expandSTSHHAtomicStore(
1083 MachineInstr &
MI = *
MBBI;
1086 unsigned Order =
MI.getOperand(2).getImm();
1087 unsigned Policy =
MI.getOperand(3).getImm();
1088 unsigned Size =
MI.getOperand(4).getImm();
1090 bool IsRelaxed = Order == 0;
1091 unsigned StoreOpc = 0;
1096 StoreOpc = IsRelaxed ? AArch64::STRBBui : AArch64::STLRB;
1099 StoreOpc = IsRelaxed ? AArch64::STRHHui : AArch64::STLRH;
1102 StoreOpc = IsRelaxed ? AArch64::STRWui : AArch64::STLRW;
1105 StoreOpc = IsRelaxed ? AArch64::STRXui : AArch64::STLRX;
1120 const TargetRegisterInfo *
TRI =
1122 Register SubReg =
TRI->getSubReg(ValReg, AArch64::sub_32);
1129 .
add(
MI.getOperand(1));
1137 transferImpOps(
MI, Store, Store);
1142 MI.eraseFromParent();
1146AArch64ExpandPseudoImpl::ConditionalBlocks
1147AArch64ExpandPseudoImpl::expandConditionalPseudo(
1149 MachineInstrBuilder &Branch) {
1152 "Unexpected unreachable in block");
1158 MachineInstr &PrevMI = *std::prev(
MBBI);
1159 MachineBasicBlock *CondBB =
MBB.
splitAt(PrevMI,
true);
1160 MachineBasicBlock *EndBB =
1161 std::next(
MBBI) == CondBB->
end()
1174 return {*CondBB, *EndBB};
1178AArch64ExpandPseudoImpl::expandRestoreZASave(MachineBasicBlock &
MBB,
1180 MachineInstr &
MI = *
MBBI;
1184 MachineInstrBuilder
Branch =
1187 auto [CondBB, EndBB] = expandConditionalPseudo(
MBB,
MBBI,
DL, Branch);
1189 MachineInstrBuilder MIB =
1192 for (
unsigned I = 2;
I <
MI.getNumOperands(); ++
I)
1193 MIB.
add(
MI.getOperand(
I));
1195 MIB.
addReg(
MI.getOperand(1).getReg(), RegState::Implicit);
1197 MI.eraseFromParent();
1208 [[maybe_unused]]
auto *RI =
MBB.getParent()->getSubtarget().getRegisterInfo();
1214 auto [CondBB, EndBB] = expandConditionalPseudo(
MBB,
MBBI,
DL, Branch);
1219 for (
unsigned I = 3;
I <
MI.getNumOperands(); ++
I)
1220 MIB.
add(
MI.getOperand(
I));
1223 .
addImm(AArch64SysReg::TPIDR2_EL0)
1225 bool ZeroZA =
MI.getOperand(1).getImm() != 0;
1226 bool ZeroZT0 =
MI.getOperand(2).getImm() != 0;
1228 assert(
MI.definesRegister(AArch64::ZAB0, RI) &&
"should define ZA!");
1234 assert(
MI.definesRegister(AArch64::ZT0, RI) &&
"should define ZT0!");
1239 MI.eraseFromParent();
1244AArch64ExpandPseudoImpl::expandCondSMToggle(MachineBasicBlock &
MBB,
1246 MachineInstr &
MI = *
MBBI;
1253 MI.getParent()->successors().begin() ==
1254 MI.getParent()->successors().end()) {
1255 MI.eraseFromParent();
1298 switch (
MI.getOperand(2).getImm()) {
1302 Opc = AArch64::TBNZW;
1305 Opc = AArch64::TBZW;
1308 auto PStateSM =
MI.getOperand(3).getReg();
1310 unsigned SMReg32 =
TRI->getSubReg(PStateSM, AArch64::sub_32);
1311 MachineInstrBuilder Tbx =
1314 auto [CondBB, EndBB] = expandConditionalPseudo(
MBB,
MBBI,
DL, Tbx);
1316 MachineInstrBuilder MIB =
BuildMI(CondBB, CondBB.
back(),
MI.getDebugLoc(),
1317 TII->get(AArch64::MSRpstatesvcrImm1));
1321 MIB.
add(
MI.getOperand(0));
1322 MIB.
add(
MI.getOperand(1));
1323 for (
unsigned i = 4; i <
MI.getNumOperands(); ++i)
1324 MIB.
add(
MI.getOperand(i));
1326 MI.eraseFromParent();
1330bool AArch64ExpandPseudoImpl::expandMultiVecPseudo(
1332 TargetRegisterClass ContiguousClass, TargetRegisterClass StridedClass,
1333 unsigned ContiguousOp,
unsigned StridedOpc) {
1334 MachineInstr &
MI = *
MBBI;
1348 .
add(
MI.getOperand(0))
1349 .
add(
MI.getOperand(1))
1350 .
add(
MI.getOperand(2))
1351 .
add(
MI.getOperand(3));
1352 transferImpOps(
MI, MIB, MIB);
1353 MI.eraseFromParent();
1357bool AArch64ExpandPseudoImpl::expandFormTuplePseudo(
1361 MachineInstr &
MI = *
MBBI;
1362 Register ReturnTuple =
MI.getOperand(0).getReg();
1364 const TargetRegisterInfo *
TRI =
1366 for (
unsigned I = 0;
I <
Size; ++
I) {
1367 Register FormTupleOpReg =
MI.getOperand(
I + 1).getReg();
1369 TRI->getSubReg(ReturnTuple, AArch64::zsub0 +
I);
1372 if (FormTupleOpReg != ReturnTupleSubReg)
1374 .
addReg(ReturnTupleSubReg, RegState::Define)
1379 MI.eraseFromParent();
1385bool AArch64ExpandPseudoImpl::expandMI(MachineBasicBlock &
MBB,
1388 MachineInstr &
MI = *
MBBI;
1389 unsigned Opcode =
MI.getOpcode();
1393 if (OrigInstr != -1) {
1394 auto &Orig =
TII->get(OrigInstr);
1397 return expand_DestructiveOp(
MI,
MBB,
MBBI);
1405 case AArch64::BSPv8i8:
1406 case AArch64::BSPv16i8: {
1408 if (DstReg ==
MI.getOperand(3).getReg()) {
1411 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BITv8i8
1412 : AArch64::BITv16i8))
1413 .
add(
MI.getOperand(0))
1414 .
add(
MI.getOperand(3))
1415 .
add(
MI.getOperand(2))
1416 .
add(
MI.getOperand(1));
1417 transferImpOps(
MI,
I,
I);
1418 }
else if (DstReg ==
MI.getOperand(2).getReg()) {
1421 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BIFv8i8
1422 : AArch64::BIFv16i8))
1423 .
add(
MI.getOperand(0))
1424 .
add(
MI.getOperand(2))
1425 .
add(
MI.getOperand(3))
1426 .
add(
MI.getOperand(1));
1427 transferImpOps(
MI,
I,
I);
1430 if (DstReg ==
MI.getOperand(1).getReg()) {
1433 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BSLv8i8
1434 : AArch64::BSLv16i8))
1435 .
add(
MI.getOperand(0))
1436 .
add(
MI.getOperand(1))
1437 .
add(
MI.getOperand(2))
1438 .
add(
MI.getOperand(3));
1439 transferImpOps(
MI,
I,
I);
1444 MI.getOperand(1).isKill() &&
1445 MI.getOperand(1).getReg() !=
MI.getOperand(2).getReg() &&
1446 MI.getOperand(1).getReg() !=
MI.getOperand(3).getReg());
1448 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::ORRv8i8
1449 : AArch64::ORRv16i8))
1457 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BSLv8i8
1458 : AArch64::BSLv16i8))
1459 .
add(
MI.getOperand(0))
1462 MI.getOperand(0).isRenamable()))
1463 .
add(
MI.getOperand(2))
1464 .
add(
MI.getOperand(3));
1465 transferImpOps(
MI, I2, I2);
1468 MI.eraseFromParent();
1472 case AArch64::ADDWrr:
1473 case AArch64::SUBWrr:
1474 case AArch64::ADDXrr:
1475 case AArch64::SUBXrr:
1476 case AArch64::ADDSWrr:
1477 case AArch64::SUBSWrr:
1478 case AArch64::ADDSXrr:
1479 case AArch64::SUBSXrr:
1480 case AArch64::ANDWrr:
1481 case AArch64::ANDXrr:
1482 case AArch64::BICWrr:
1483 case AArch64::BICXrr:
1484 case AArch64::ANDSWrr:
1485 case AArch64::ANDSXrr:
1486 case AArch64::BICSWrr:
1487 case AArch64::BICSXrr:
1488 case AArch64::EONWrr:
1489 case AArch64::EONXrr:
1490 case AArch64::EORWrr:
1491 case AArch64::EORXrr:
1492 case AArch64::ORNWrr:
1493 case AArch64::ORNXrr:
1494 case AArch64::ORRWrr:
1495 case AArch64::ORRXrr: {
1497 switch (
MI.getOpcode()) {
1500 case AArch64::ADDWrr: Opcode = AArch64::ADDWrs;
break;
1501 case AArch64::SUBWrr: Opcode = AArch64::SUBWrs;
break;
1502 case AArch64::ADDXrr: Opcode = AArch64::ADDXrs;
break;
1503 case AArch64::SUBXrr: Opcode = AArch64::SUBXrs;
break;
1504 case AArch64::ADDSWrr: Opcode = AArch64::ADDSWrs;
break;
1505 case AArch64::SUBSWrr: Opcode = AArch64::SUBSWrs;
break;
1506 case AArch64::ADDSXrr: Opcode = AArch64::ADDSXrs;
break;
1507 case AArch64::SUBSXrr: Opcode = AArch64::SUBSXrs;
break;
1508 case AArch64::ANDWrr: Opcode = AArch64::ANDWrs;
break;
1509 case AArch64::ANDXrr: Opcode = AArch64::ANDXrs;
break;
1510 case AArch64::BICWrr: Opcode = AArch64::BICWrs;
break;
1511 case AArch64::BICXrr: Opcode = AArch64::BICXrs;
break;
1512 case AArch64::ANDSWrr: Opcode = AArch64::ANDSWrs;
break;
1513 case AArch64::ANDSXrr: Opcode = AArch64::ANDSXrs;
break;
1514 case AArch64::BICSWrr: Opcode = AArch64::BICSWrs;
break;
1515 case AArch64::BICSXrr: Opcode = AArch64::BICSXrs;
break;
1516 case AArch64::EONWrr: Opcode = AArch64::EONWrs;
break;
1517 case AArch64::EONXrr: Opcode = AArch64::EONXrs;
break;
1518 case AArch64::EORWrr: Opcode = AArch64::EORWrs;
break;
1519 case AArch64::EORXrr: Opcode = AArch64::EORXrs;
break;
1520 case AArch64::ORNWrr: Opcode = AArch64::ORNWrs;
break;
1521 case AArch64::ORNXrr: Opcode = AArch64::ORNXrs;
break;
1522 case AArch64::ORRWrr: Opcode = AArch64::ORRWrs;
break;
1523 case AArch64::ORRXrr: Opcode = AArch64::ORRXrs;
break;
1527 MachineInstr *NewMI = MF.CreateMachineInstr(
1528 TII->get(Opcode),
MI.getDebugLoc(),
true);
1530 MachineInstrBuilder MIB1(MF, NewMI);
1531 MIB1->setPCSections(MF,
MI.getPCSections());
1532 MIB1.addReg(
MI.getOperand(0).getReg(), RegState::Define)
1533 .add(
MI.getOperand(1))
1534 .add(
MI.getOperand(2))
1536 transferImpOps(
MI, MIB1, MIB1);
1537 if (
auto DebugNumber =
MI.peekDebugInstrNum())
1539 MI.eraseFromParent();
1543 case AArch64::LOADgot: {
1546 const MachineOperand &MO1 =
MI.getOperand(1);
1552 TII->get(AArch64::LDRXl), DstReg);
1560 "Only expect globals, externalsymbols, or constant pools");
1565 MachineFunction &MF = *
MI.getParent()->getParent();
1567 MachineInstrBuilder MIB1 =
1570 MachineInstrBuilder MIB2;
1571 if (MF.
getSubtarget<AArch64Subtarget>().isTargetILP32()) {
1573 unsigned Reg32 =
TRI->getSubReg(DstReg, AArch64::sub_32);
1576 .
addReg(DstReg, RegState::Kill)
1577 .
addReg(DstReg, RegState::Implicit);
1581 .
add(
MI.getOperand(0))
1582 .
addUse(DstReg, RegState::Kill);
1596 "Only expect globals, externalsymbols, or constant pools");
1607 if (
MI.peekDebugInstrNum() != 0)
1609 transferImpOps(
MI, MIB1, MIB2);
1611 MI.eraseFromParent();
1614 case AArch64::MOVaddrBA: {
1615 MachineFunction &MF = *
MI.getParent()->getParent();
1616 if (MF.
getSubtarget<AArch64Subtarget>().isTargetMachO()) {
1621 assert(
MI.getOperand(1).getOffset() == 0 &&
"unexpected offset");
1631 TII->get(AArch64::LDRXui), DstReg)
1635 transferImpOps(
MI, MIB1, MIB2);
1636 MI.eraseFromParent();
1641 case AArch64::MOVaddr:
1642 case AArch64::MOVaddrJT:
1643 case AArch64::MOVaddrCP:
1644 case AArch64::MOVaddrTLS:
1645 case AArch64::MOVaddrEXT: {
1648 assert(DstReg != AArch64::XZR);
1649 MachineInstrBuilder MIB1 =
1651 .
add(
MI.getOperand(1));
1661 auto Tag =
MI.getOperand(1);
1663 Tag.setOffset(0x100000000);
1670 MachineInstrBuilder MIB2 =
1672 .
add(
MI.getOperand(0))
1674 .
add(
MI.getOperand(2))
1677 transferImpOps(
MI, MIB1, MIB2);
1678 MI.eraseFromParent();
1681 case AArch64::ADDlowTLS:
1684 .
add(
MI.getOperand(0))
1685 .
add(
MI.getOperand(1))
1686 .
add(
MI.getOperand(2))
1688 MI.eraseFromParent();
1691 case AArch64::MOVbaseTLS: {
1693 auto SysReg = AArch64SysReg::TPIDR_EL0;
1695 if (MF->
getSubtarget<AArch64Subtarget>().useEL3ForTP())
1696 SysReg = AArch64SysReg::TPIDR_EL3;
1697 else if (MF->
getSubtarget<AArch64Subtarget>().useEL2ForTP())
1698 SysReg = AArch64SysReg::TPIDR_EL2;
1699 else if (MF->
getSubtarget<AArch64Subtarget>().useEL1ForTP())
1700 SysReg = AArch64SysReg::TPIDR_EL1;
1701 else if (MF->
getSubtarget<AArch64Subtarget>().useROEL0ForTP())
1702 SysReg = AArch64SysReg::TPIDRRO_EL0;
1705 MI.eraseFromParent();
1709 case AArch64::MOVi32imm:
1711 case AArch64::MOVi64imm:
1713 case AArch64::RET_ReallyLR: {
1719 MachineInstrBuilder MIB =
1721 .
addReg(AArch64::LR, RegState::Undef);
1722 transferImpOps(
MI, MIB, MIB);
1723 MI.eraseFromParent();
1726 case AArch64::CMP_SWAP_8:
1727 return expandCMP_SWAP(
MBB,
MBBI, AArch64::LDAXRB, AArch64::STLXRB,
1730 AArch64::WZR, NextMBBI);
1731 case AArch64::CMP_SWAP_16:
1732 return expandCMP_SWAP(
MBB,
MBBI, AArch64::LDAXRH, AArch64::STLXRH,
1735 AArch64::WZR, NextMBBI);
1736 case AArch64::CMP_SWAP_32:
1737 return expandCMP_SWAP(
MBB,
MBBI, AArch64::LDAXRW, AArch64::STLXRW,
1740 AArch64::WZR, NextMBBI);
1741 case AArch64::CMP_SWAP_64:
1742 return expandCMP_SWAP(
MBB,
MBBI,
1743 AArch64::LDAXRX, AArch64::STLXRX, AArch64::SUBSXrs,
1745 AArch64::XZR, NextMBBI);
1746 case AArch64::CMP_SWAP_128:
1747 case AArch64::CMP_SWAP_128_RELEASE:
1748 case AArch64::CMP_SWAP_128_ACQUIRE:
1749 case AArch64::CMP_SWAP_128_MONOTONIC:
1750 return expandCMP_SWAP_128(
MBB,
MBBI, NextMBBI);
1752 case AArch64::AESMCrrTied:
1753 case AArch64::AESIMCrrTied: {
1754 MachineInstrBuilder MIB =
1756 TII->get(Opcode == AArch64::AESMCrrTied ? AArch64::AESMCrr :
1758 .
add(
MI.getOperand(0))
1759 .
add(
MI.getOperand(1));
1760 transferImpOps(
MI, MIB, MIB);
1761 MI.eraseFromParent();
1764 case AArch64::IRGstack: {
1766 const AArch64FunctionInfo *AFI = MF.
getInfo<AArch64FunctionInfo>();
1767 const AArch64FrameLowering *TFI =
1768 MF.
getSubtarget<AArch64Subtarget>().getFrameLowering();
1775 StackOffset FrameRegOffset = TFI->resolveFrameOffsetReference(
1781 if (FrameRegOffset) {
1783 SrcReg =
MI.getOperand(0).getReg();
1785 FrameRegOffset,
TII);
1788 .
add(
MI.getOperand(0))
1790 .
add(
MI.getOperand(2));
1791 MI.eraseFromParent();
1794 case AArch64::TAGPstack: {
1795 int64_t
Offset =
MI.getOperand(2).getImm();
1797 TII->get(
Offset >= 0 ? AArch64::ADDG : AArch64::SUBG))
1798 .
add(
MI.getOperand(0))
1799 .
add(
MI.getOperand(1))
1801 .
add(
MI.getOperand(4));
1802 MI.eraseFromParent();
1805 case AArch64::STGloop_wback:
1806 case AArch64::STZGloop_wback:
1807 return expandSetTagLoop(
MBB,
MBBI, NextMBBI);
1808 case AArch64::STGloop:
1809 case AArch64::STZGloop:
1811 "Non-writeback variants of STGloop / STZGloop should not "
1812 "survive past PrologEpilogInserter.");
1813 case AArch64::STR_ZZZZXI:
1814 case AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS:
1815 return expandSVESpillFill(
MBB,
MBBI, AArch64::STR_ZXI, 4);
1816 case AArch64::STR_ZZZXI:
1817 return expandSVESpillFill(
MBB,
MBBI, AArch64::STR_ZXI, 3);
1818 case AArch64::STR_ZZXI:
1819 case AArch64::STR_ZZXI_STRIDED_CONTIGUOUS:
1820 return expandSVESpillFill(
MBB,
MBBI, AArch64::STR_ZXI, 2);
1821 case AArch64::STR_PPXI:
1822 return expandSVESpillFill(
MBB,
MBBI, AArch64::STR_PXI, 2);
1823 case AArch64::LDR_ZZZZXI:
1824 case AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS:
1825 return expandSVESpillFill(
MBB,
MBBI, AArch64::LDR_ZXI, 4);
1826 case AArch64::LDR_ZZZXI:
1827 return expandSVESpillFill(
MBB,
MBBI, AArch64::LDR_ZXI, 3);
1828 case AArch64::LDR_ZZXI:
1829 case AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS:
1830 return expandSVESpillFill(
MBB,
MBBI, AArch64::LDR_ZXI, 2);
1831 case AArch64::LDR_PPXI:
1832 return expandSVESpillFill(
MBB,
MBBI, AArch64::LDR_PXI, 2);
1833 case AArch64::BLR_RVMARKER:
1834 case AArch64::BLRA_RVMARKER:
1835 return expandCALL_RVMARKER(
MBB,
MBBI);
1836 case AArch64::BLR_BTI:
1837 return expandCALL_BTI(
MBB,
MBBI);
1838 case AArch64::StoreSwiftAsyncContext:
1839 return expandStoreSwiftAsyncContext(
MBB,
MBBI);
1840 case AArch64::STSHH_ATOMIC_STORE_SZ:
1841 return expandSTSHHAtomicStore(
MBB,
MBBI);
1842 case AArch64::RestoreZAPseudo:
1843 case AArch64::CommitZASavePseudo:
1844 case AArch64::MSRpstatePseudo: {
1845 auto *NewMBB = [&] {
1847 case AArch64::RestoreZAPseudo:
1848 return expandRestoreZASave(
MBB,
MBBI);
1849 case AArch64::CommitZASavePseudo:
1850 return expandCommitZASave(
MBB,
MBBI);
1851 case AArch64::MSRpstatePseudo:
1852 return expandCondSMToggle(
MBB,
MBBI);
1861 case AArch64::InOutZAUsePseudo:
1862 case AArch64::RequiresZASavePseudo:
1863 case AArch64::RequiresZT0SavePseudo:
1864 case AArch64::SMEStateAllocPseudo:
1865 case AArch64::COALESCER_BARRIER_FPR16:
1866 case AArch64::COALESCER_BARRIER_FPR32:
1867 case AArch64::COALESCER_BARRIER_FPR64:
1868 case AArch64::COALESCER_BARRIER_FPR128:
1869 MI.eraseFromParent();
1871 case AArch64::LD1B_2Z_IMM_PSEUDO:
1872 return expandMultiVecPseudo(
1873 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1874 AArch64::LD1B_2Z_IMM, AArch64::LD1B_2Z_STRIDED_IMM);
1875 case AArch64::LD1H_2Z_IMM_PSEUDO:
1876 return expandMultiVecPseudo(
1877 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1878 AArch64::LD1H_2Z_IMM, AArch64::LD1H_2Z_STRIDED_IMM);
1879 case AArch64::LD1W_2Z_IMM_PSEUDO:
1880 return expandMultiVecPseudo(
1881 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1882 AArch64::LD1W_2Z_IMM, AArch64::LD1W_2Z_STRIDED_IMM);
1883 case AArch64::LD1D_2Z_IMM_PSEUDO:
1884 return expandMultiVecPseudo(
1885 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1886 AArch64::LD1D_2Z_IMM, AArch64::LD1D_2Z_STRIDED_IMM);
1887 case AArch64::LDNT1B_2Z_IMM_PSEUDO:
1888 return expandMultiVecPseudo(
1889 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1890 AArch64::LDNT1B_2Z_IMM, AArch64::LDNT1B_2Z_STRIDED_IMM);
1891 case AArch64::LDNT1H_2Z_IMM_PSEUDO:
1892 return expandMultiVecPseudo(
1893 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1894 AArch64::LDNT1H_2Z_IMM, AArch64::LDNT1H_2Z_STRIDED_IMM);
1895 case AArch64::LDNT1W_2Z_IMM_PSEUDO:
1896 return expandMultiVecPseudo(
1897 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1898 AArch64::LDNT1W_2Z_IMM, AArch64::LDNT1W_2Z_STRIDED_IMM);
1899 case AArch64::LDNT1D_2Z_IMM_PSEUDO:
1900 return expandMultiVecPseudo(
1901 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1902 AArch64::LDNT1D_2Z_IMM, AArch64::LDNT1D_2Z_STRIDED_IMM);
1903 case AArch64::LD1B_2Z_PSEUDO:
1904 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1905 AArch64::ZPR2StridedRegClass, AArch64::LD1B_2Z,
1906 AArch64::LD1B_2Z_STRIDED);
1907 case AArch64::LD1H_2Z_PSEUDO:
1908 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1909 AArch64::ZPR2StridedRegClass, AArch64::LD1H_2Z,
1910 AArch64::LD1H_2Z_STRIDED);
1911 case AArch64::LD1W_2Z_PSEUDO:
1912 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1913 AArch64::ZPR2StridedRegClass, AArch64::LD1W_2Z,
1914 AArch64::LD1W_2Z_STRIDED);
1915 case AArch64::LD1D_2Z_PSEUDO:
1916 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1917 AArch64::ZPR2StridedRegClass, AArch64::LD1D_2Z,
1918 AArch64::LD1D_2Z_STRIDED);
1919 case AArch64::LDNT1B_2Z_PSEUDO:
1920 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1921 AArch64::ZPR2StridedRegClass,
1922 AArch64::LDNT1B_2Z, AArch64::LDNT1B_2Z_STRIDED);
1923 case AArch64::LDNT1H_2Z_PSEUDO:
1924 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1925 AArch64::ZPR2StridedRegClass,
1926 AArch64::LDNT1H_2Z, AArch64::LDNT1H_2Z_STRIDED);
1927 case AArch64::LDNT1W_2Z_PSEUDO:
1928 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1929 AArch64::ZPR2StridedRegClass,
1930 AArch64::LDNT1W_2Z, AArch64::LDNT1W_2Z_STRIDED);
1931 case AArch64::LDNT1D_2Z_PSEUDO:
1932 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1933 AArch64::ZPR2StridedRegClass,
1934 AArch64::LDNT1D_2Z, AArch64::LDNT1D_2Z_STRIDED);
1935 case AArch64::LD1B_4Z_IMM_PSEUDO:
1936 return expandMultiVecPseudo(
1937 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1938 AArch64::LD1B_4Z_IMM, AArch64::LD1B_4Z_STRIDED_IMM);
1939 case AArch64::LD1H_4Z_IMM_PSEUDO:
1940 return expandMultiVecPseudo(
1941 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1942 AArch64::LD1H_4Z_IMM, AArch64::LD1H_4Z_STRIDED_IMM);
1943 case AArch64::LD1W_4Z_IMM_PSEUDO:
1944 return expandMultiVecPseudo(
1945 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1946 AArch64::LD1W_4Z_IMM, AArch64::LD1W_4Z_STRIDED_IMM);
1947 case AArch64::LD1D_4Z_IMM_PSEUDO:
1948 return expandMultiVecPseudo(
1949 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1950 AArch64::LD1D_4Z_IMM, AArch64::LD1D_4Z_STRIDED_IMM);
1951 case AArch64::LDNT1B_4Z_IMM_PSEUDO:
1952 return expandMultiVecPseudo(
1953 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1954 AArch64::LDNT1B_4Z_IMM, AArch64::LDNT1B_4Z_STRIDED_IMM);
1955 case AArch64::LDNT1H_4Z_IMM_PSEUDO:
1956 return expandMultiVecPseudo(
1957 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1958 AArch64::LDNT1H_4Z_IMM, AArch64::LDNT1H_4Z_STRIDED_IMM);
1959 case AArch64::LDNT1W_4Z_IMM_PSEUDO:
1960 return expandMultiVecPseudo(
1961 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1962 AArch64::LDNT1W_4Z_IMM, AArch64::LDNT1W_4Z_STRIDED_IMM);
1963 case AArch64::LDNT1D_4Z_IMM_PSEUDO:
1964 return expandMultiVecPseudo(
1965 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1966 AArch64::LDNT1D_4Z_IMM, AArch64::LDNT1D_4Z_STRIDED_IMM);
1967 case AArch64::LD1B_4Z_PSEUDO:
1968 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1969 AArch64::ZPR4StridedRegClass, AArch64::LD1B_4Z,
1970 AArch64::LD1B_4Z_STRIDED);
1971 case AArch64::LD1H_4Z_PSEUDO:
1972 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1973 AArch64::ZPR4StridedRegClass, AArch64::LD1H_4Z,
1974 AArch64::LD1H_4Z_STRIDED);
1975 case AArch64::LD1W_4Z_PSEUDO:
1976 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1977 AArch64::ZPR4StridedRegClass, AArch64::LD1W_4Z,
1978 AArch64::LD1W_4Z_STRIDED);
1979 case AArch64::LD1D_4Z_PSEUDO:
1980 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1981 AArch64::ZPR4StridedRegClass, AArch64::LD1D_4Z,
1982 AArch64::LD1D_4Z_STRIDED);
1983 case AArch64::LDNT1B_4Z_PSEUDO:
1984 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1985 AArch64::ZPR4StridedRegClass,
1986 AArch64::LDNT1B_4Z, AArch64::LDNT1B_4Z_STRIDED);
1987 case AArch64::LDNT1H_4Z_PSEUDO:
1988 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1989 AArch64::ZPR4StridedRegClass,
1990 AArch64::LDNT1H_4Z, AArch64::LDNT1H_4Z_STRIDED);
1991 case AArch64::LDNT1W_4Z_PSEUDO:
1992 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1993 AArch64::ZPR4StridedRegClass,
1994 AArch64::LDNT1W_4Z, AArch64::LDNT1W_4Z_STRIDED);
1995 case AArch64::LDNT1D_4Z_PSEUDO:
1996 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1997 AArch64::ZPR4StridedRegClass,
1998 AArch64::LDNT1D_4Z, AArch64::LDNT1D_4Z_STRIDED);
1999 case AArch64::FORM_TRANSPOSED_REG_TUPLE_X2_PSEUDO:
2000 return expandFormTuplePseudo(
MBB,
MBBI, NextMBBI, 2);
2001 case AArch64::FORM_TRANSPOSED_REG_TUPLE_X4_PSEUDO:
2002 return expandFormTuplePseudo(
MBB,
MBBI, NextMBBI, 4);
2003 case AArch64::EON_ZZZ:
2004 case AArch64::NAND_ZZZ:
2005 case AArch64::NOR_ZZZ:
2006 return expandSVEBitwisePseudo(
MI,
MBB,
MBBI);
2013bool AArch64ExpandPseudoImpl::expandMBB(MachineBasicBlock &
MBB) {
2026bool AArch64ExpandPseudoImpl::run(MachineFunction &MF) {
2030 for (
auto &
MBB : MF)
2035bool AArch64ExpandPseudoLegacy::runOnMachineFunction(MachineFunction &MF) {
2036 return AArch64ExpandPseudoImpl().run(MF);
2041 return new AArch64ExpandPseudoLegacy();
2047 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.