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();
336 bool LittleEndian = STI.isLittleEndian();
337 MachineOperand &Dest0 = LittleEndian ? DestLo : DestHi;
338 MachineOperand &Dest1 = LittleEndian ? DestHi : DestLo;
339 Register New0Reg = LittleEndian ? NewLoReg : NewHiReg;
340 Register New1Reg = LittleEndian ? NewHiReg : NewLoReg;
342 unsigned LdxpOp, StxpOp;
344 switch (
MI.getOpcode()) {
345 case AArch64::CMP_SWAP_128_MONOTONIC:
346 LdxpOp = AArch64::LDXPX;
347 StxpOp = AArch64::STXPX;
349 case AArch64::CMP_SWAP_128_RELEASE:
350 LdxpOp = AArch64::LDXPX;
351 StxpOp = AArch64::STLXPX;
353 case AArch64::CMP_SWAP_128_ACQUIRE:
354 LdxpOp = AArch64::LDAXPX;
355 StxpOp = AArch64::STXPX;
357 case AArch64::CMP_SWAP_128:
358 LdxpOp = AArch64::LDAXPX;
359 StxpOp = AArch64::STLXPX;
372 MF->
insert(++LoadCmpBB->getIterator(), StoreBB);
373 MF->
insert(++StoreBB->getIterator(), FailBB);
374 MF->
insert(++FailBB->getIterator(), DoneBB);
385 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::SUBSXrs), AArch64::XZR)
389 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::CSINCWr), StatusReg)
393 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::SUBSXrs), AArch64::XZR)
397 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::CSINCWr), StatusReg)
398 .
addUse(StatusReg, RegState::Kill)
399 .
addUse(StatusReg, RegState::Kill)
401 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::CBNZW))
404 LoadCmpBB->addSuccessor(FailBB);
405 LoadCmpBB->addSuccessor(StoreBB);
410 BuildMI(StoreBB, MIMD,
TII->get(StxpOp), StatusReg)
414 BuildMI(StoreBB, MIMD,
TII->get(AArch64::CBNZW))
418 StoreBB->addSuccessor(LoadCmpBB);
419 StoreBB->addSuccessor(DoneBB);
424 BuildMI(FailBB, MIMD,
TII->get(StxpOp), StatusReg)
428 BuildMI(FailBB, MIMD,
TII->get(AArch64::CBNZW))
431 FailBB->addSuccessor(LoadCmpBB);
432 FailBB->addSuccessor(DoneBB);
434 DoneBB->splice(DoneBB->end(), &
MBB,
MI,
MBB.
end());
435 DoneBB->transferSuccessors(&
MBB);
440 MI.eraseFromParent();
443 LivePhysRegs LiveRegs;
450 FailBB->clearLiveIns();
452 StoreBB->clearLiveIns();
454 LoadCmpBB->clearLiveIns();
498bool AArch64ExpandPseudoImpl::expand_DestructiveOp(
499 MachineInstr &
MI, MachineBasicBlock &
MBB,
506 bool DstIsDead =
MI.getOperand(0).isDead();
508 unsigned PredIdx, DOPIdx, SrcIdx, Src2Idx;
513 if (DstReg ==
MI.getOperand(3).getReg()) {
515 std::tie(PredIdx, DOPIdx, SrcIdx) = std::make_tuple(1, 3, 2);
522 std::tie(PredIdx, DOPIdx, SrcIdx) = std::make_tuple(1, 2, 3);
525 std::tie(PredIdx, DOPIdx, SrcIdx) = std::make_tuple(2, 3, 3);
528 std::tie(PredIdx, DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 2, 3, 4);
529 if (DstReg ==
MI.getOperand(3).getReg()) {
531 std::tie(PredIdx, DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 3, 4, 2);
533 }
else if (DstReg ==
MI.getOperand(4).getReg()) {
535 std::tie(PredIdx, DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 4, 3, 2);
542 std::tie(DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 1, 2);
545 std::tie(DOPIdx, SrcIdx) = std::make_tuple(1, 2);
548 std::tie(DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 2, 3);
557 bool DOPRegIsUnique =
false;
560 DOPRegIsUnique = DstReg !=
MI.getOperand(SrcIdx).getReg();
565 DstReg !=
MI.getOperand(DOPIdx).getReg() ||
566 MI.getOperand(DOPIdx).getReg() !=
MI.getOperand(SrcIdx).getReg();
573 DOPRegIsUnique =
true;
577 DstReg !=
MI.getOperand(DOPIdx).getReg() ||
578 (
MI.getOperand(DOPIdx).
getReg() !=
MI.getOperand(SrcIdx).getReg() &&
579 MI.getOperand(DOPIdx).getReg() !=
MI.getOperand(Src2Idx).getReg());
595 uint64_t ElementSize =
TII->getElementSizeForOpcode(Opcode);
596 unsigned MovPrfx, LSLZero, MovPrfxZero;
597 switch (ElementSize) {
600 MovPrfx = AArch64::MOVPRFX_ZZ;
601 LSLZero = AArch64::LSL_ZPmI_B;
602 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_B;
605 MovPrfx = AArch64::MOVPRFX_ZZ;
606 LSLZero = AArch64::LSL_ZPmI_H;
607 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_H;
610 MovPrfx = AArch64::MOVPRFX_ZZ;
611 LSLZero = AArch64::LSL_ZPmI_S;
612 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_S;
615 MovPrfx = AArch64::MOVPRFX_ZZ;
616 LSLZero = AArch64::LSL_ZPmI_D;
617 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_D;
629 MachineInstrBuilder PRFX, DOP;
636 "The destructive operand should be unique");
638 "This instruction is unpredicated");
642 .
addReg(DstReg, RegState::Define)
643 .
addReg(
MI.getOperand(PredIdx).getReg())
644 .
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState);
658 .
addReg(DstReg, RegState::Define)
659 .
add(
MI.getOperand(PredIdx))
663 }
else if (DstReg !=
MI.getOperand(DOPIdx).getReg()) {
664 assert(DOPRegIsUnique &&
"The destructive operand should be unique");
666 .
addReg(DstReg, RegState::Define)
667 .
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState);
677 DOPRegState = DOPRegState | RegState::Kill;
681 DOP.
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState)
682 .
add(
MI.getOperand(PredIdx))
683 .
add(
MI.getOperand(SrcIdx));
689 DOP.
add(
MI.getOperand(PredIdx))
690 .
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState)
691 .
add(
MI.getOperand(SrcIdx));
694 DOP.
add(
MI.getOperand(PredIdx))
695 .
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState)
696 .
add(
MI.getOperand(SrcIdx))
697 .
add(
MI.getOperand(Src2Idx));
700 DOP.
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState)
701 .
add(
MI.getOperand(SrcIdx));
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;
1081AArch64ExpandPseudoImpl::ConditionalBlocks
1082AArch64ExpandPseudoImpl::expandConditionalPseudo(
1084 MachineInstrBuilder &Branch) {
1087 "Unexpected unreachable in block");
1093 MachineInstr &PrevMI = *std::prev(
MBBI);
1094 MachineBasicBlock *CondBB =
MBB.
splitAt(PrevMI,
true);
1095 MachineBasicBlock *EndBB =
1096 std::next(
MBBI) == CondBB->
end()
1109 return {*CondBB, *EndBB};
1113AArch64ExpandPseudoImpl::expandRestoreZASave(MachineBasicBlock &
MBB,
1115 MachineInstr &
MI = *
MBBI;
1119 MachineInstrBuilder
Branch =
1122 auto [CondBB, EndBB] = expandConditionalPseudo(
MBB,
MBBI,
DL, Branch);
1124 MachineInstrBuilder MIB =
1127 for (
unsigned I = 2;
I <
MI.getNumOperands(); ++
I)
1128 MIB.
add(
MI.getOperand(
I));
1130 MIB.
addReg(
MI.getOperand(1).getReg(), RegState::Implicit);
1132 MI.eraseFromParent();
1143 [[maybe_unused]]
auto *RI =
MBB.getParent()->getSubtarget().getRegisterInfo();
1149 auto [CondBB, EndBB] = expandConditionalPseudo(
MBB,
MBBI,
DL, Branch);
1154 for (
unsigned I = 3;
I <
MI.getNumOperands(); ++
I)
1155 MIB.
add(
MI.getOperand(
I));
1158 .
addImm(AArch64SysReg::TPIDR2_EL0)
1160 bool ZeroZA =
MI.getOperand(1).getImm() != 0;
1161 bool ZeroZT0 =
MI.getOperand(2).getImm() != 0;
1163 assert(
MI.definesRegister(AArch64::ZAB0, RI) &&
"should define ZA!");
1169 assert(
MI.definesRegister(AArch64::ZT0, RI) &&
"should define ZT0!");
1174 MI.eraseFromParent();
1179AArch64ExpandPseudoImpl::expandCondSMToggle(MachineBasicBlock &
MBB,
1181 MachineInstr &
MI = *
MBBI;
1188 MI.getParent()->successors().begin() ==
1189 MI.getParent()->successors().end()) {
1190 MI.eraseFromParent();
1233 switch (
MI.getOperand(2).getImm()) {
1237 Opc = AArch64::TBNZW;
1240 Opc = AArch64::TBZW;
1243 auto PStateSM =
MI.getOperand(3).getReg();
1245 unsigned SMReg32 =
TRI->getSubReg(PStateSM, AArch64::sub_32);
1246 MachineInstrBuilder Tbx =
1249 auto [CondBB, EndBB] = expandConditionalPseudo(
MBB,
MBBI,
DL, Tbx);
1251 MachineInstrBuilder MIB =
BuildMI(CondBB, CondBB.
back(),
MI.getDebugLoc(),
1252 TII->get(AArch64::MSRpstatesvcrImm1));
1256 MIB.
add(
MI.getOperand(0));
1257 MIB.
add(
MI.getOperand(1));
1258 for (
unsigned i = 4; i <
MI.getNumOperands(); ++i)
1259 MIB.
add(
MI.getOperand(i));
1261 MI.eraseFromParent();
1265bool AArch64ExpandPseudoImpl::expandMultiVecPseudo(
1269 unsigned StridedOpc) {
1270 MachineInstr &
MI = *
MBBI;
1284 .
add(
MI.getOperand(0))
1285 .
add(
MI.getOperand(1))
1286 .
add(
MI.getOperand(2))
1287 .
add(
MI.getOperand(3));
1288 transferImpOps(
MI, MIB, MIB);
1289 MI.eraseFromParent();
1293bool AArch64ExpandPseudoImpl::expandFormTuplePseudo(
1297 MachineInstr &
MI = *
MBBI;
1298 Register ReturnTuple =
MI.getOperand(0).getReg();
1300 const TargetRegisterInfo *
TRI =
1302 for (
unsigned I = 0;
I <
Size; ++
I) {
1303 Register FormTupleOpReg =
MI.getOperand(
I + 1).getReg();
1305 TRI->getSubReg(ReturnTuple, AArch64::zsub0 +
I);
1308 if (FormTupleOpReg != ReturnTupleSubReg)
1310 .
addReg(ReturnTupleSubReg, RegState::Define)
1315 MI.eraseFromParent();
1321bool AArch64ExpandPseudoImpl::expandMI(MachineBasicBlock &
MBB,
1324 MachineInstr &
MI = *
MBBI;
1325 unsigned Opcode =
MI.getOpcode();
1329 if (OrigInstr != -1) {
1330 auto &Orig =
TII->get(OrigInstr);
1333 return expand_DestructiveOp(
MI,
MBB,
MBBI);
1341 case AArch64::BSPv8i8:
1342 case AArch64::BSPv16i8: {
1344 if (DstReg ==
MI.getOperand(3).getReg()) {
1347 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BITv8i8
1348 : AArch64::BITv16i8))
1349 .
add(
MI.getOperand(0))
1350 .
add(
MI.getOperand(3))
1351 .
add(
MI.getOperand(2))
1352 .
add(
MI.getOperand(1));
1353 transferImpOps(
MI,
I,
I);
1354 }
else if (DstReg ==
MI.getOperand(2).getReg()) {
1357 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BIFv8i8
1358 : AArch64::BIFv16i8))
1359 .
add(
MI.getOperand(0))
1360 .
add(
MI.getOperand(2))
1361 .
add(
MI.getOperand(3))
1362 .
add(
MI.getOperand(1));
1363 transferImpOps(
MI,
I,
I);
1366 if (DstReg ==
MI.getOperand(1).getReg()) {
1369 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BSLv8i8
1370 : AArch64::BSLv16i8))
1371 .
add(
MI.getOperand(0))
1372 .
add(
MI.getOperand(1))
1373 .
add(
MI.getOperand(2))
1374 .
add(
MI.getOperand(3));
1375 transferImpOps(
MI,
I,
I);
1380 MI.getOperand(1).isKill() &&
1381 MI.getOperand(1).getReg() !=
MI.getOperand(2).getReg() &&
1382 MI.getOperand(1).getReg() !=
MI.getOperand(3).getReg());
1384 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::ORRv8i8
1385 : AArch64::ORRv16i8))
1393 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BSLv8i8
1394 : AArch64::BSLv16i8))
1395 .
add(
MI.getOperand(0))
1398 MI.getOperand(0).isRenamable()))
1399 .
add(
MI.getOperand(2))
1400 .
add(
MI.getOperand(3));
1401 transferImpOps(
MI, I2, I2);
1404 MI.eraseFromParent();
1408 case AArch64::ADDWrr:
1409 case AArch64::SUBWrr:
1410 case AArch64::ADDXrr:
1411 case AArch64::SUBXrr:
1412 case AArch64::ADDSWrr:
1413 case AArch64::SUBSWrr:
1414 case AArch64::ADDSXrr:
1415 case AArch64::SUBSXrr:
1416 case AArch64::ANDWrr:
1417 case AArch64::ANDXrr:
1418 case AArch64::BICWrr:
1419 case AArch64::BICXrr:
1420 case AArch64::ANDSWrr:
1421 case AArch64::ANDSXrr:
1422 case AArch64::BICSWrr:
1423 case AArch64::BICSXrr:
1424 case AArch64::EONWrr:
1425 case AArch64::EONXrr:
1426 case AArch64::EORWrr:
1427 case AArch64::EORXrr:
1428 case AArch64::ORNWrr:
1429 case AArch64::ORNXrr:
1430 case AArch64::ORRWrr:
1431 case AArch64::ORRXrr: {
1433 switch (
MI.getOpcode()) {
1436 case AArch64::ADDWrr: Opcode = AArch64::ADDWrs;
break;
1437 case AArch64::SUBWrr: Opcode = AArch64::SUBWrs;
break;
1438 case AArch64::ADDXrr: Opcode = AArch64::ADDXrs;
break;
1439 case AArch64::SUBXrr: Opcode = AArch64::SUBXrs;
break;
1440 case AArch64::ADDSWrr: Opcode = AArch64::ADDSWrs;
break;
1441 case AArch64::SUBSWrr: Opcode = AArch64::SUBSWrs;
break;
1442 case AArch64::ADDSXrr: Opcode = AArch64::ADDSXrs;
break;
1443 case AArch64::SUBSXrr: Opcode = AArch64::SUBSXrs;
break;
1444 case AArch64::ANDWrr: Opcode = AArch64::ANDWrs;
break;
1445 case AArch64::ANDXrr: Opcode = AArch64::ANDXrs;
break;
1446 case AArch64::BICWrr: Opcode = AArch64::BICWrs;
break;
1447 case AArch64::BICXrr: Opcode = AArch64::BICXrs;
break;
1448 case AArch64::ANDSWrr: Opcode = AArch64::ANDSWrs;
break;
1449 case AArch64::ANDSXrr: Opcode = AArch64::ANDSXrs;
break;
1450 case AArch64::BICSWrr: Opcode = AArch64::BICSWrs;
break;
1451 case AArch64::BICSXrr: Opcode = AArch64::BICSXrs;
break;
1452 case AArch64::EONWrr: Opcode = AArch64::EONWrs;
break;
1453 case AArch64::EONXrr: Opcode = AArch64::EONXrs;
break;
1454 case AArch64::EORWrr: Opcode = AArch64::EORWrs;
break;
1455 case AArch64::EORXrr: Opcode = AArch64::EORXrs;
break;
1456 case AArch64::ORNWrr: Opcode = AArch64::ORNWrs;
break;
1457 case AArch64::ORNXrr: Opcode = AArch64::ORNXrs;
break;
1458 case AArch64::ORRWrr: Opcode = AArch64::ORRWrs;
break;
1459 case AArch64::ORRXrr: Opcode = AArch64::ORRXrs;
break;
1463 MachineInstr *NewMI = MF.CreateMachineInstr(
1464 TII->get(Opcode),
MI.getDebugLoc(),
true);
1466 MachineInstrBuilder MIB1(MF, NewMI);
1467 MIB1->setPCSections(MF,
MI.getPCSections());
1468 MIB1.addReg(
MI.getOperand(0).getReg(), RegState::Define)
1469 .add(
MI.getOperand(1))
1470 .add(
MI.getOperand(2))
1472 transferImpOps(
MI, MIB1, MIB1);
1473 if (
auto DebugNumber =
MI.peekDebugInstrNum())
1475 MI.eraseFromParent();
1479 case AArch64::LOADgot: {
1482 const MachineOperand &MO1 =
MI.getOperand(1);
1488 TII->get(AArch64::LDRXl), DstReg);
1496 "Only expect globals, externalsymbols, or constant pools");
1501 MachineFunction &MF = *
MI.getParent()->getParent();
1503 MachineInstrBuilder MIB1 =
1506 MachineInstrBuilder MIB2;
1507 if (MF.
getSubtarget<AArch64Subtarget>().isTargetILP32()) {
1509 unsigned Reg32 =
TRI->getSubReg(DstReg, AArch64::sub_32);
1512 .
addReg(DstReg, RegState::Kill)
1513 .
addReg(DstReg, RegState::Implicit);
1517 .
add(
MI.getOperand(0))
1518 .
addUse(DstReg, RegState::Kill);
1532 "Only expect globals, externalsymbols, or constant pools");
1543 if (
MI.peekDebugInstrNum() != 0)
1545 transferImpOps(
MI, MIB1, MIB2);
1547 MI.eraseFromParent();
1550 case AArch64::MOVaddrBA:
1551 case AArch64::MOVaddr:
1552 case AArch64::MOVaddrJT:
1553 case AArch64::MOVaddrCP:
1554 case AArch64::MOVaddrTLS:
1555 case AArch64::MOVaddrEXT: {
1556 MachineFunction &MF = *
MI.getParent()->getParent();
1558 assert(DstReg != AArch64::XZR);
1560 bool IsTargetMachO = MF.
getSubtarget<AArch64Subtarget>().isTargetMachO();
1563 MI.getOpcode(),
MI.getOperand(1).getTargetFlags(), IsTargetMachO, Insn);
1566 std::optional<unsigned> CPIdx;
1567 if (Opcode == AArch64::MOVaddrBA && IsTargetMachO) {
1572 assert(
MI.getOperand(1).getOffset() == 0 &&
"unexpected offset");
1577 MachineInstrBuilder FirstMIB;
1578 MachineInstrBuilder LastMIB;
1579 for (
const auto &
I : Insn) {
1580 MachineInstrBuilder MIB;
1588 MIB.
add(
MI.getOperand(1));
1590 case AArch64::LDRXui:
1597 case AArch64::MOVKXi: {
1605 auto Tag =
MI.getOperand(1);
1607 Tag.setOffset(0x100000000);
1615 case AArch64::ADDXri:
1617 .
add(
MI.getOperand(0))
1619 .
add(
MI.getOperand(2))
1631 transferImpOps(
MI, FirstMIB, LastMIB);
1632 MI.eraseFromParent();
1635 case AArch64::ADDlowTLS:
1638 .
add(
MI.getOperand(0))
1639 .
add(
MI.getOperand(1))
1640 .
add(
MI.getOperand(2))
1642 MI.eraseFromParent();
1645 case AArch64::MOVbaseTLS: {
1647 auto SysReg = AArch64SysReg::TPIDR_EL0;
1649 if (MF->
getSubtarget<AArch64Subtarget>().useEL3ForTP())
1650 SysReg = AArch64SysReg::TPIDR_EL3;
1651 else if (MF->
getSubtarget<AArch64Subtarget>().useEL2ForTP())
1652 SysReg = AArch64SysReg::TPIDR_EL2;
1653 else if (MF->
getSubtarget<AArch64Subtarget>().useEL1ForTP())
1654 SysReg = AArch64SysReg::TPIDR_EL1;
1655 else if (MF->
getSubtarget<AArch64Subtarget>().useROEL0ForTP())
1656 SysReg = AArch64SysReg::TPIDRRO_EL0;
1659 MI.eraseFromParent();
1663 case AArch64::MOVi32imm:
1665 case AArch64::MOVi64imm:
1667 case AArch64::RET_ReallyLR: {
1673 MachineInstrBuilder MIB =
1675 .
addReg(AArch64::LR, RegState::Undef);
1676 transferImpOps(
MI, MIB, MIB);
1677 MI.eraseFromParent();
1680 case AArch64::CMP_SWAP_8:
1681 return expandCMP_SWAP(
MBB,
MBBI, AArch64::LDAXRB, AArch64::STLXRB,
1684 AArch64::WZR, NextMBBI);
1685 case AArch64::CMP_SWAP_16:
1686 return expandCMP_SWAP(
MBB,
MBBI, AArch64::LDAXRH, AArch64::STLXRH,
1689 AArch64::WZR, NextMBBI);
1690 case AArch64::CMP_SWAP_32:
1691 return expandCMP_SWAP(
MBB,
MBBI, AArch64::LDAXRW, AArch64::STLXRW,
1694 AArch64::WZR, NextMBBI);
1695 case AArch64::CMP_SWAP_64:
1696 return expandCMP_SWAP(
MBB,
MBBI,
1697 AArch64::LDAXRX, AArch64::STLXRX, AArch64::SUBSXrs,
1699 AArch64::XZR, NextMBBI);
1700 case AArch64::CMP_SWAP_128:
1701 case AArch64::CMP_SWAP_128_RELEASE:
1702 case AArch64::CMP_SWAP_128_ACQUIRE:
1703 case AArch64::CMP_SWAP_128_MONOTONIC:
1704 return expandCMP_SWAP_128(
MBB,
MBBI, NextMBBI);
1706 case AArch64::AESMCrrTied:
1707 case AArch64::AESIMCrrTied: {
1708 MachineInstrBuilder MIB =
1710 TII->get(Opcode == AArch64::AESMCrrTied ? AArch64::AESMCrr :
1712 .
add(
MI.getOperand(0))
1713 .
add(
MI.getOperand(1));
1714 transferImpOps(
MI, MIB, MIB);
1715 MI.eraseFromParent();
1718 case AArch64::IRGstack: {
1720 const AArch64FunctionInfo *AFI = MF.
getInfo<AArch64FunctionInfo>();
1721 const AArch64FrameLowering *TFI =
1722 MF.
getSubtarget<AArch64Subtarget>().getFrameLowering();
1729 StackOffset FrameRegOffset = TFI->resolveFrameOffsetReference(
1735 if (FrameRegOffset) {
1737 SrcReg =
MI.getOperand(0).getReg();
1739 FrameRegOffset,
TII);
1742 .
add(
MI.getOperand(0))
1744 .
add(
MI.getOperand(2));
1745 MI.eraseFromParent();
1748 case AArch64::TAGPstack: {
1749 int64_t
Offset =
MI.getOperand(2).getImm();
1751 TII->get(
Offset >= 0 ? AArch64::ADDG : AArch64::SUBG))
1752 .
add(
MI.getOperand(0))
1753 .
add(
MI.getOperand(1))
1755 .
add(
MI.getOperand(4));
1756 MI.eraseFromParent();
1759 case AArch64::STGloop_wback:
1760 case AArch64::STZGloop_wback:
1761 return expandSetTagLoop(
MBB,
MBBI, NextMBBI);
1762 case AArch64::STGloop:
1763 case AArch64::STZGloop:
1765 "Non-writeback variants of STGloop / STZGloop should not "
1766 "survive past PrologEpilogInserter.");
1767 case AArch64::STR_ZZZZXI:
1768 case AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS:
1769 return expandSVESpillFill(
MBB,
MBBI, AArch64::STR_ZXI, 4);
1770 case AArch64::STR_ZZZXI:
1771 return expandSVESpillFill(
MBB,
MBBI, AArch64::STR_ZXI, 3);
1772 case AArch64::STR_ZZXI:
1773 case AArch64::STR_ZZXI_STRIDED_CONTIGUOUS:
1774 return expandSVESpillFill(
MBB,
MBBI, AArch64::STR_ZXI, 2);
1775 case AArch64::STR_PPXI:
1776 return expandSVESpillFill(
MBB,
MBBI, AArch64::STR_PXI, 2);
1777 case AArch64::LDR_ZZZZXI:
1778 case AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS:
1779 return expandSVESpillFill(
MBB,
MBBI, AArch64::LDR_ZXI, 4);
1780 case AArch64::LDR_ZZZXI:
1781 return expandSVESpillFill(
MBB,
MBBI, AArch64::LDR_ZXI, 3);
1782 case AArch64::LDR_ZZXI:
1783 case AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS:
1784 return expandSVESpillFill(
MBB,
MBBI, AArch64::LDR_ZXI, 2);
1785 case AArch64::LDR_PPXI:
1786 return expandSVESpillFill(
MBB,
MBBI, AArch64::LDR_PXI, 2);
1787 case AArch64::BLR_RVMARKER:
1788 case AArch64::BLRA_RVMARKER:
1789 return expandCALL_RVMARKER(
MBB,
MBBI);
1790 case AArch64::BLR_BTI:
1791 return expandCALL_BTI(
MBB,
MBBI);
1792 case AArch64::StoreSwiftAsyncContext:
1793 return expandStoreSwiftAsyncContext(
MBB,
MBBI);
1794 case AArch64::RestoreZAPseudo:
1795 case AArch64::CommitZASavePseudo:
1796 case AArch64::MSRpstatePseudo: {
1797 auto *NewMBB = [&] {
1799 case AArch64::RestoreZAPseudo:
1800 return expandRestoreZASave(
MBB,
MBBI);
1801 case AArch64::CommitZASavePseudo:
1802 return expandCommitZASave(
MBB,
MBBI);
1803 case AArch64::MSRpstatePseudo:
1804 return expandCondSMToggle(
MBB,
MBBI);
1813 case AArch64::InOutZAUsePseudo:
1814 case AArch64::RequiresZASavePseudo:
1815 case AArch64::RequiresZT0SavePseudo:
1816 case AArch64::SMEStateAllocPseudo:
1817 case AArch64::COALESCER_BARRIER_FPR16:
1818 case AArch64::COALESCER_BARRIER_FPR32:
1819 case AArch64::COALESCER_BARRIER_FPR64:
1820 case AArch64::COALESCER_BARRIER_FPR128:
1821 MI.eraseFromParent();
1823 case AArch64::LD1B_2Z_IMM_PSEUDO:
1824 return expandMultiVecPseudo(
1825 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1826 AArch64::LD1B_2Z_IMM, AArch64::LD1B_2Z_STRIDED_IMM);
1827 case AArch64::LD1H_2Z_IMM_PSEUDO:
1828 return expandMultiVecPseudo(
1829 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1830 AArch64::LD1H_2Z_IMM, AArch64::LD1H_2Z_STRIDED_IMM);
1831 case AArch64::LD1W_2Z_IMM_PSEUDO:
1832 return expandMultiVecPseudo(
1833 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1834 AArch64::LD1W_2Z_IMM, AArch64::LD1W_2Z_STRIDED_IMM);
1835 case AArch64::LD1D_2Z_IMM_PSEUDO:
1836 return expandMultiVecPseudo(
1837 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1838 AArch64::LD1D_2Z_IMM, AArch64::LD1D_2Z_STRIDED_IMM);
1839 case AArch64::LDNT1B_2Z_IMM_PSEUDO:
1840 return expandMultiVecPseudo(
1841 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1842 AArch64::LDNT1B_2Z_IMM, AArch64::LDNT1B_2Z_STRIDED_IMM);
1843 case AArch64::LDNT1H_2Z_IMM_PSEUDO:
1844 return expandMultiVecPseudo(
1845 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1846 AArch64::LDNT1H_2Z_IMM, AArch64::LDNT1H_2Z_STRIDED_IMM);
1847 case AArch64::LDNT1W_2Z_IMM_PSEUDO:
1848 return expandMultiVecPseudo(
1849 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1850 AArch64::LDNT1W_2Z_IMM, AArch64::LDNT1W_2Z_STRIDED_IMM);
1851 case AArch64::LDNT1D_2Z_IMM_PSEUDO:
1852 return expandMultiVecPseudo(
1853 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1854 AArch64::LDNT1D_2Z_IMM, AArch64::LDNT1D_2Z_STRIDED_IMM);
1855 case AArch64::LD1B_2Z_PSEUDO:
1856 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1857 AArch64::ZPR2StridedRegClass, AArch64::LD1B_2Z,
1858 AArch64::LD1B_2Z_STRIDED);
1859 case AArch64::LD1H_2Z_PSEUDO:
1860 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1861 AArch64::ZPR2StridedRegClass, AArch64::LD1H_2Z,
1862 AArch64::LD1H_2Z_STRIDED);
1863 case AArch64::LD1W_2Z_PSEUDO:
1864 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1865 AArch64::ZPR2StridedRegClass, AArch64::LD1W_2Z,
1866 AArch64::LD1W_2Z_STRIDED);
1867 case AArch64::LD1D_2Z_PSEUDO:
1868 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1869 AArch64::ZPR2StridedRegClass, AArch64::LD1D_2Z,
1870 AArch64::LD1D_2Z_STRIDED);
1871 case AArch64::LDNT1B_2Z_PSEUDO:
1872 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1873 AArch64::ZPR2StridedRegClass,
1874 AArch64::LDNT1B_2Z, AArch64::LDNT1B_2Z_STRIDED);
1875 case AArch64::LDNT1H_2Z_PSEUDO:
1876 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1877 AArch64::ZPR2StridedRegClass,
1878 AArch64::LDNT1H_2Z, AArch64::LDNT1H_2Z_STRIDED);
1879 case AArch64::LDNT1W_2Z_PSEUDO:
1880 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1881 AArch64::ZPR2StridedRegClass,
1882 AArch64::LDNT1W_2Z, AArch64::LDNT1W_2Z_STRIDED);
1883 case AArch64::LDNT1D_2Z_PSEUDO:
1884 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1885 AArch64::ZPR2StridedRegClass,
1886 AArch64::LDNT1D_2Z, AArch64::LDNT1D_2Z_STRIDED);
1887 case AArch64::LD1B_4Z_IMM_PSEUDO:
1888 return expandMultiVecPseudo(
1889 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1890 AArch64::LD1B_4Z_IMM, AArch64::LD1B_4Z_STRIDED_IMM);
1891 case AArch64::LD1H_4Z_IMM_PSEUDO:
1892 return expandMultiVecPseudo(
1893 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1894 AArch64::LD1H_4Z_IMM, AArch64::LD1H_4Z_STRIDED_IMM);
1895 case AArch64::LD1W_4Z_IMM_PSEUDO:
1896 return expandMultiVecPseudo(
1897 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1898 AArch64::LD1W_4Z_IMM, AArch64::LD1W_4Z_STRIDED_IMM);
1899 case AArch64::LD1D_4Z_IMM_PSEUDO:
1900 return expandMultiVecPseudo(
1901 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1902 AArch64::LD1D_4Z_IMM, AArch64::LD1D_4Z_STRIDED_IMM);
1903 case AArch64::LDNT1B_4Z_IMM_PSEUDO:
1904 return expandMultiVecPseudo(
1905 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1906 AArch64::LDNT1B_4Z_IMM, AArch64::LDNT1B_4Z_STRIDED_IMM);
1907 case AArch64::LDNT1H_4Z_IMM_PSEUDO:
1908 return expandMultiVecPseudo(
1909 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1910 AArch64::LDNT1H_4Z_IMM, AArch64::LDNT1H_4Z_STRIDED_IMM);
1911 case AArch64::LDNT1W_4Z_IMM_PSEUDO:
1912 return expandMultiVecPseudo(
1913 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1914 AArch64::LDNT1W_4Z_IMM, AArch64::LDNT1W_4Z_STRIDED_IMM);
1915 case AArch64::LDNT1D_4Z_IMM_PSEUDO:
1916 return expandMultiVecPseudo(
1917 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1918 AArch64::LDNT1D_4Z_IMM, AArch64::LDNT1D_4Z_STRIDED_IMM);
1919 case AArch64::LD1B_4Z_PSEUDO:
1920 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1921 AArch64::ZPR4StridedRegClass, AArch64::LD1B_4Z,
1922 AArch64::LD1B_4Z_STRIDED);
1923 case AArch64::LD1H_4Z_PSEUDO:
1924 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1925 AArch64::ZPR4StridedRegClass, AArch64::LD1H_4Z,
1926 AArch64::LD1H_4Z_STRIDED);
1927 case AArch64::LD1W_4Z_PSEUDO:
1928 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1929 AArch64::ZPR4StridedRegClass, AArch64::LD1W_4Z,
1930 AArch64::LD1W_4Z_STRIDED);
1931 case AArch64::LD1D_4Z_PSEUDO:
1932 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1933 AArch64::ZPR4StridedRegClass, AArch64::LD1D_4Z,
1934 AArch64::LD1D_4Z_STRIDED);
1935 case AArch64::LDNT1B_4Z_PSEUDO:
1936 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1937 AArch64::ZPR4StridedRegClass,
1938 AArch64::LDNT1B_4Z, AArch64::LDNT1B_4Z_STRIDED);
1939 case AArch64::LDNT1H_4Z_PSEUDO:
1940 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1941 AArch64::ZPR4StridedRegClass,
1942 AArch64::LDNT1H_4Z, AArch64::LDNT1H_4Z_STRIDED);
1943 case AArch64::LDNT1W_4Z_PSEUDO:
1944 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1945 AArch64::ZPR4StridedRegClass,
1946 AArch64::LDNT1W_4Z, AArch64::LDNT1W_4Z_STRIDED);
1947 case AArch64::LDNT1D_4Z_PSEUDO:
1948 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1949 AArch64::ZPR4StridedRegClass,
1950 AArch64::LDNT1D_4Z, AArch64::LDNT1D_4Z_STRIDED);
1951 case AArch64::FORM_TRANSPOSED_REG_TUPLE_X2_PSEUDO:
1952 return expandFormTuplePseudo(
MBB,
MBBI, NextMBBI, 2);
1953 case AArch64::FORM_TRANSPOSED_REG_TUPLE_X4_PSEUDO:
1954 return expandFormTuplePseudo(
MBB,
MBBI, NextMBBI, 4);
1955 case AArch64::EON_ZZZ:
1956 case AArch64::NAND_ZZZ:
1957 case AArch64::NOR_ZZZ:
1958 return expandSVEBitwisePseudo(
MI,
MBB,
MBBI);
1965bool AArch64ExpandPseudoImpl::expandMBB(MachineBasicBlock &
MBB) {
1971 if (
MBBI->isPseudo())
1979bool AArch64ExpandPseudoImpl::run(MachineFunction &MF) {
1983 for (
auto &
MBB : MF)
1988bool AArch64ExpandPseudoLegacy::runOnMachineFunction(MachineFunction &MF) {
1989 return AArch64ExpandPseudoImpl().run(MF);
1994 return new AArch64ExpandPseudoLegacy();
2000 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.
ArrayRef< MCPhysReg > getRegisters() const
LLVM_ABI instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
LLVM_ABI MachineBasicBlock * splitAt(MachineInstr &SplitInst, bool UpdateLiveIns=true, LiveIntervals *LIS=nullptr)
Split a basic block into 2 pieces at SplitPoint.
LLVM_ABI void eraseFromParent()
This method unlinks 'this' from the containing function and deletes it.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
iterator_range< succ_iterator > successors()
MachineInstrBundleIterator< MachineInstr > iterator
LLVM_ABI unsigned getConstantPoolIndex(const Constant *C, Align Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void moveAdditionalCallInfo(const MachineInstr *Old, const MachineInstr *New)
Move the call site info from Old to \New call site info.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
Representation of each machine instruction.
void setDebugInstrNum(unsigned Num)
Set instruction number of this MachineInstr.
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.
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.
LLVM_ABI void computeAndAddLiveIns(LivePhysRegs &LiveRegs, MachineBasicBlock &MBB)
Convenience function combining computeLiveIns() and addLiveIns().
constexpr RegState getUndefRegState(bool B)
MCRegisterClass TargetRegisterClass
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.