43#define AARCH64_EXPAND_PSEUDO_NAME "AArch64 pseudo instruction expansion pass"
47class AArch64ExpandPseudoImpl {
61 unsigned ContiguousOpc,
unsigned StridedOpc);
72 unsigned LdarOp,
unsigned StlrOp,
unsigned CmpOp,
73 unsigned ExtendImm,
unsigned ZeroReg,
89 struct ConditionalBlocks {
118char AArch64ExpandPseudoLegacy::ID = 0;
130 assert(MO.isReg() && MO.getReg());
147 uint64_t
Imm =
MI.getOperand(1).getImm();
149 if (DstReg == AArch64::XZR || DstReg == AArch64::WZR) {
152 MI.eraseFromParent();
160 SmallVector<MachineInstrBuilder, 4> MIBS;
162 bool LastItem = std::next(
I) ==
E;
167 case AArch64::ORRWri:
168 case AArch64::ORRXri:
169 case AArch64::ANDXri:
170 case AArch64::EORXri:
173 .
add(
MI.getOperand(0))
174 .
addReg(BitSize == 32 ? AArch64::WZR : AArch64::XZR)
178 bool DstIsDead =
MI.getOperand(0).isDead();
181 .
addReg(DstReg, RegState::Define |
188 case AArch64::EONXrs:
189 case AArch64::EORXrs:
190 case AArch64::ORRWrs:
191 case AArch64::ORRXrs: {
193 bool DstIsDead =
MI.getOperand(0).isDead();
196 .
addReg(DstReg, RegState::Define |
203 case AArch64::MOVNWi:
204 case AArch64::MOVNXi:
205 case AArch64::MOVZWi:
206 case AArch64::MOVZXi: {
207 bool DstIsDead =
MI.getOperand(0).isDead();
209 .
addReg(DstReg, RegState::Define |
215 case AArch64::MOVKWi:
216 case AArch64::MOVKXi: {
218 bool DstIsDead =
MI.getOperand(0).isDead();
231 MI.eraseFromParent();
235bool AArch64ExpandPseudoImpl::expandCMP_SWAP(
237 unsigned StlrOp,
unsigned CmpOp,
unsigned ExtendImm,
unsigned ZeroReg,
241 const MachineOperand &Dest =
MI.getOperand(0);
242 Register StatusReg =
MI.getOperand(1).getReg();
243 bool StatusDead =
MI.getOperand(1).isDead();
246 assert(!
MI.getOperand(2).isUndef() &&
"cannot handle undef");
248 Register DesiredReg =
MI.getOperand(3).getReg();
257 MF->
insert(++LoadCmpBB->getIterator(), StoreBB);
258 MF->
insert(++StoreBB->getIterator(), DoneBB);
266 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::MOVZWi), StatusReg)
270 BuildMI(LoadCmpBB, MIMD,
TII->get(CmpOp), ZeroReg)
274 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::Bcc))
277 .
addReg(AArch64::NZCV, RegState::Implicit | RegState::Kill);
278 LoadCmpBB->addSuccessor(DoneBB);
279 LoadCmpBB->addSuccessor(StoreBB);
284 BuildMI(StoreBB, MIMD,
TII->get(StlrOp), StatusReg)
287 BuildMI(StoreBB, MIMD,
TII->get(AArch64::CBNZW))
290 StoreBB->addSuccessor(LoadCmpBB);
291 StoreBB->addSuccessor(DoneBB);
293 DoneBB->splice(DoneBB->end(), &
MBB,
MI,
MBB.
end());
294 DoneBB->transferSuccessors(&
MBB);
299 MI.eraseFromParent();
302 LivePhysRegs LiveRegs;
307 StoreBB->clearLiveIns();
309 LoadCmpBB->clearLiveIns();
315bool AArch64ExpandPseudoImpl::expandCMP_SWAP_128(
320 MachineOperand &DestLo =
MI.getOperand(0);
321 MachineOperand &DestHi =
MI.getOperand(1);
322 Register StatusReg =
MI.getOperand(2).getReg();
323 bool StatusDead =
MI.getOperand(2).isDead();
326 assert(!
MI.getOperand(3).isUndef() &&
"cannot handle undef");
328 Register DesiredLoReg =
MI.getOperand(4).getReg();
329 Register DesiredHiReg =
MI.getOperand(5).getReg();
330 Register NewLoReg =
MI.getOperand(6).getReg();
331 Register NewHiReg =
MI.getOperand(7).getReg();
334 bool LittleEndian = STI.isLittleEndian();
335 MachineOperand &Dest0 = LittleEndian ? DestLo : DestHi;
336 MachineOperand &Dest1 = LittleEndian ? DestHi : DestLo;
337 Register New0Reg = LittleEndian ? NewLoReg : NewHiReg;
338 Register New1Reg = LittleEndian ? NewHiReg : NewLoReg;
340 unsigned LdxpOp, StxpOp;
342 switch (
MI.getOpcode()) {
343 case AArch64::CMP_SWAP_128_MONOTONIC:
344 LdxpOp = AArch64::LDXPX;
345 StxpOp = AArch64::STXPX;
347 case AArch64::CMP_SWAP_128_RELEASE:
348 LdxpOp = AArch64::LDXPX;
349 StxpOp = AArch64::STLXPX;
351 case AArch64::CMP_SWAP_128_ACQUIRE:
352 LdxpOp = AArch64::LDAXPX;
353 StxpOp = AArch64::STXPX;
355 case AArch64::CMP_SWAP_128:
356 LdxpOp = AArch64::LDAXPX;
357 StxpOp = AArch64::STLXPX;
370 MF->
insert(++LoadCmpBB->getIterator(), StoreBB);
371 MF->
insert(++StoreBB->getIterator(), FailBB);
372 MF->
insert(++FailBB->getIterator(), DoneBB);
383 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::SUBSXrs), AArch64::XZR)
387 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::CSINCWr), StatusReg)
391 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::SUBSXrs), AArch64::XZR)
395 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::CSINCWr), StatusReg)
396 .
addUse(StatusReg, RegState::Kill)
397 .
addUse(StatusReg, RegState::Kill)
399 BuildMI(LoadCmpBB, MIMD,
TII->get(AArch64::CBNZW))
402 LoadCmpBB->addSuccessor(FailBB);
403 LoadCmpBB->addSuccessor(StoreBB);
408 BuildMI(StoreBB, MIMD,
TII->get(StxpOp), StatusReg)
412 BuildMI(StoreBB, MIMD,
TII->get(AArch64::CBNZW))
416 StoreBB->addSuccessor(LoadCmpBB);
417 StoreBB->addSuccessor(DoneBB);
422 BuildMI(FailBB, MIMD,
TII->get(StxpOp), StatusReg)
426 BuildMI(FailBB, MIMD,
TII->get(AArch64::CBNZW))
429 FailBB->addSuccessor(LoadCmpBB);
430 FailBB->addSuccessor(DoneBB);
432 DoneBB->splice(DoneBB->end(), &
MBB,
MI,
MBB.
end());
433 DoneBB->transferSuccessors(&
MBB);
438 MI.eraseFromParent();
441 LivePhysRegs LiveRegs;
448 FailBB->clearLiveIns();
450 StoreBB->clearLiveIns();
452 LoadCmpBB->clearLiveIns();
496bool AArch64ExpandPseudoImpl::expand_DestructiveOp(
497 MachineInstr &
MI, MachineBasicBlock &
MBB,
504 bool DstIsDead =
MI.getOperand(0).isDead();
506 unsigned PredIdx, DOPIdx, SrcIdx, Src2Idx;
511 if (DstReg ==
MI.getOperand(3).getReg()) {
513 std::tie(PredIdx, DOPIdx, SrcIdx) = std::make_tuple(1, 3, 2);
520 std::tie(PredIdx, DOPIdx, SrcIdx) = std::make_tuple(1, 2, 3);
523 std::tie(PredIdx, DOPIdx, SrcIdx) = std::make_tuple(2, 3, 3);
526 std::tie(PredIdx, DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 2, 3, 4);
527 if (DstReg ==
MI.getOperand(3).getReg()) {
529 std::tie(PredIdx, DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 3, 4, 2);
531 }
else if (DstReg ==
MI.getOperand(4).getReg()) {
533 std::tie(PredIdx, DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 4, 3, 2);
540 std::tie(DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 1, 2);
543 std::tie(DOPIdx, SrcIdx) = std::make_tuple(1, 2);
546 std::tie(DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 2, 3);
555 bool DOPRegIsUnique =
false;
558 DOPRegIsUnique = DstReg !=
MI.getOperand(SrcIdx).getReg();
563 DstReg !=
MI.getOperand(DOPIdx).getReg() ||
564 MI.getOperand(DOPIdx).getReg() !=
MI.getOperand(SrcIdx).getReg();
571 DOPRegIsUnique =
true;
575 DstReg !=
MI.getOperand(DOPIdx).getReg() ||
576 (
MI.getOperand(DOPIdx).
getReg() !=
MI.getOperand(SrcIdx).getReg() &&
577 MI.getOperand(DOPIdx).getReg() !=
MI.getOperand(Src2Idx).getReg());
593 uint64_t ElementSize =
TII->getElementSizeForOpcode(Opcode);
594 unsigned MovPrfx, LSLZero, MovPrfxZero;
595 switch (ElementSize) {
598 MovPrfx = AArch64::MOVPRFX_ZZ;
599 LSLZero = AArch64::LSL_ZPmI_B;
600 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_B;
603 MovPrfx = AArch64::MOVPRFX_ZZ;
604 LSLZero = AArch64::LSL_ZPmI_H;
605 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_H;
608 MovPrfx = AArch64::MOVPRFX_ZZ;
609 LSLZero = AArch64::LSL_ZPmI_S;
610 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_S;
613 MovPrfx = AArch64::MOVPRFX_ZZ;
614 LSLZero = AArch64::LSL_ZPmI_D;
615 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_D;
627 MachineInstrBuilder PRFX, DOP;
634 "The destructive operand should be unique");
636 "This instruction is unpredicated");
640 .
addReg(DstReg, RegState::Define)
641 .
addReg(
MI.getOperand(PredIdx).getReg())
642 .
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState);
656 .
addReg(DstReg, RegState::Define)
657 .
add(
MI.getOperand(PredIdx))
661 }
else if (DstReg !=
MI.getOperand(DOPIdx).getReg()) {
662 assert(DOPRegIsUnique &&
"The destructive operand should be unique");
664 .
addReg(DstReg, RegState::Define)
665 .
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState);
675 DOPRegState = DOPRegState | RegState::Kill;
679 DOP.
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState)
680 .
add(
MI.getOperand(PredIdx))
681 .
add(
MI.getOperand(SrcIdx));
687 DOP.
add(
MI.getOperand(PredIdx))
688 .
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState)
689 .
add(
MI.getOperand(SrcIdx));
692 DOP.
add(
MI.getOperand(PredIdx))
693 .
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState)
694 .
add(
MI.getOperand(SrcIdx))
695 .
add(
MI.getOperand(Src2Idx));
698 DOP.
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState)
699 .
add(
MI.getOperand(SrcIdx));
703 DOP.
addReg(
MI.getOperand(DOPIdx).getReg(), DOPRegState)
704 .
add(
MI.getOperand(SrcIdx))
705 .
add(
MI.getOperand(Src2Idx));
710 transferImpOps(
MI, PRFX, DOP);
713 transferImpOps(
MI, DOP, DOP);
715 MI.eraseFromParent();
719bool AArch64ExpandPseudoImpl::expandSVEBitwisePseudo(
720 MachineInstr &
MI, MachineBasicBlock &
MBB,
722 MachineInstrBuilder PRFX, DOP;
723 const unsigned Opcode =
MI.getOpcode();
724 const MachineOperand &Op0 =
MI.getOperand(0);
725 const MachineOperand *Op1 = &
MI.getOperand(1);
726 const MachineOperand *Op2 = &
MI.getOperand(2);
729 if (DOPReg == Op2->
getReg()) {
732 }
else if (DOPReg != Op1->
getReg()) {
741 Opcode == AArch64::NAND_ZZZ));
744 assert((DOPReg == Op1->
getReg() || PRFX) &&
"invalid expansion");
753 case AArch64::EON_ZZZ:
756 .
addReg(DOPReg, DOPRegState)
760 case AArch64::NAND_ZZZ:
763 .
addReg(DOPReg, DOPRegState)
767 case AArch64::NOR_ZZZ:
770 .
addReg(DOPReg, DOPRegState)
777 transferImpOps(
MI, PRFX, DOP);
780 transferImpOps(
MI, DOP, DOP);
783 MI.eraseFromParent();
787bool AArch64ExpandPseudoImpl::expandSetTagLoop(
793 Register AddressReg =
MI.getOperand(1).getReg();
797 bool ZeroData =
MI.getOpcode() == AArch64::STZGloop_wback;
798 const unsigned OpCode1 =
799 ZeroData ? AArch64::STZGPostIndex : AArch64::STGPostIndex;
800 const unsigned OpCode2 =
801 ZeroData ? AArch64::STZ2GPostIndex : AArch64::ST2GPostIndex;
803 unsigned Size =
MI.getOperand(2).getImm();
805 if (
Size % (16 * 2) != 0) {
821 MF->
insert(++LoopBB->getIterator(), DoneBB);
838 .
addReg(AArch64::NZCV, RegState::Implicit | RegState::Kill);
840 LoopBB->addSuccessor(LoopBB);
841 LoopBB->addSuccessor(DoneBB);
843 DoneBB->splice(DoneBB->end(), &
MBB,
MI,
MBB.
end());
844 DoneBB->transferSuccessors(&
MBB);
849 MI.eraseFromParent();
851 LivePhysRegs LiveRegs;
856 LoopBB->clearLiveIns();
858 DoneBB->clearLiveIns();
864bool AArch64ExpandPseudoImpl::expandSVESpillFill(
867 assert((
Opc == AArch64::LDR_ZXI ||
Opc == AArch64::STR_ZXI ||
868 Opc == AArch64::LDR_PXI ||
Opc == AArch64::STR_PXI) &&
869 "Unexpected opcode");
872 unsigned sub0 = (
Opc == AArch64::LDR_ZXI ||
Opc == AArch64::STR_ZXI)
875 const TargetRegisterInfo *
TRI =
879 int ImmOffset =
MI.getOperand(2).getImm() +
Offset;
880 bool Kill = (
Offset + 1 ==
N) ?
MI.getOperand(1).isKill() :
false;
881 assert(ImmOffset >= -256 && ImmOffset < 256 &&
882 "Immediate spill offset out of range");
889 MI.eraseFromParent();
900 unsigned RegMaskStartIdx) {
909 while (!
MBBI->getOperand(RegMaskStartIdx).isRegMask()) {
911 assert(MOP.
isReg() &&
"can only add register operands");
913 MOP.
getReg(),
false,
true,
false,
919 Call->addOperand(MO);
930 unsigned RegMaskStartIdx) {
931 unsigned Opc = CallTarget.
isGlobal() ? AArch64::BL : AArch64::BLR;
934 "invalid operand for regular call");
938bool AArch64ExpandPseudoImpl::expandCALL_RVMARKER(
946 MachineOperand &RVTarget =
MI.getOperand(0);
947 bool DoEmitMarker =
MI.getOperand(1).getImm();
948 assert(RVTarget.
isGlobal() &&
"invalid operand for attached call");
950 MachineInstr *OriginalCall =
nullptr;
952 if (
MI.getOpcode() == AArch64::BLRA_RVMARKER) {
954 const MachineOperand &CallTarget =
MI.getOperand(2);
955 const MachineOperand &
Key =
MI.getOperand(3);
956 const MachineOperand &IntDisc =
MI.getOperand(4);
957 const MachineOperand &AddrDisc =
MI.getOperand(5);
961 "Invalid auth call key");
963 MachineOperand
Ops[] = {CallTarget,
Key, IntDisc, AddrDisc};
968 assert(
MI.getOpcode() == AArch64::BLR_RVMARKER &&
"unknown rvmarker MI");
976 .
addReg(AArch64::FP, RegState::Define)
985 if (
MI.shouldUpdateAdditionalCallInfo())
988 MI.eraseFromParent();
990 std::next(RVCall->getIterator()));
994bool AArch64ExpandPseudoImpl::expandCALL_BTI(MachineBasicBlock &
MBB,
1001 MachineInstr &
MI = *
MBBI;
1014 if (
MI.shouldUpdateAdditionalCallInfo())
1017 MI.eraseFromParent();
1022bool AArch64ExpandPseudoImpl::expandStoreSwiftAsyncContext(
1030 if (STI.getTargetTriple().getArchName() !=
"arm64e") {
1047 unsigned Opc =
Offset >= 0 ? AArch64::ADDXri : AArch64::SUBXri;
1079AArch64ExpandPseudoImpl::ConditionalBlocks
1080AArch64ExpandPseudoImpl::expandConditionalPseudo(
1082 MachineInstrBuilder &Branch) {
1085 "Unexpected unreachable in block");
1091 MachineInstr &PrevMI = *std::prev(
MBBI);
1092 MachineBasicBlock *CondBB =
MBB.
splitAt(PrevMI,
true);
1093 MachineBasicBlock *EndBB =
1094 std::next(
MBBI) == CondBB->
end()
1107 return {*CondBB, *EndBB};
1111AArch64ExpandPseudoImpl::expandRestoreZASave(MachineBasicBlock &
MBB,
1113 MachineInstr &
MI = *
MBBI;
1117 MachineInstrBuilder
Branch =
1120 auto [CondBB, EndBB] = expandConditionalPseudo(
MBB,
MBBI,
DL, Branch);
1122 MachineInstrBuilder MIB =
1125 for (
unsigned I = 2;
I <
MI.getNumOperands(); ++
I)
1126 MIB.
add(
MI.getOperand(
I));
1128 MIB.
addReg(
MI.getOperand(1).getReg(), RegState::Implicit);
1130 MI.eraseFromParent();
1141 [[maybe_unused]]
auto *RI =
MBB.getParent()->getSubtarget().getRegisterInfo();
1147 auto [CondBB, EndBB] = expandConditionalPseudo(
MBB,
MBBI,
DL, Branch);
1152 for (
unsigned I = 3;
I <
MI.getNumOperands(); ++
I)
1153 MIB.
add(
MI.getOperand(
I));
1156 .
addImm(AArch64SysReg::TPIDR2_EL0)
1158 bool ZeroZA =
MI.getOperand(1).getImm() != 0;
1159 bool ZeroZT0 =
MI.getOperand(2).getImm() != 0;
1161 assert(
MI.definesRegister(AArch64::ZAB0, RI) &&
"should define ZA!");
1167 assert(
MI.definesRegister(AArch64::ZT0, RI) &&
"should define ZT0!");
1172 MI.eraseFromParent();
1177AArch64ExpandPseudoImpl::expandCondSMToggle(MachineBasicBlock &
MBB,
1179 MachineInstr &
MI = *
MBBI;
1186 MI.getParent()->successors().begin() ==
1187 MI.getParent()->successors().end()) {
1188 MI.eraseFromParent();
1231 switch (
MI.getOperand(2).getImm()) {
1235 Opc = AArch64::TBNZW;
1238 Opc = AArch64::TBZW;
1241 auto PStateSM =
MI.getOperand(3).getReg();
1243 unsigned SMReg32 =
TRI->getSubReg(PStateSM, AArch64::sub_32);
1244 MachineInstrBuilder Tbx =
1247 auto [CondBB, EndBB] = expandConditionalPseudo(
MBB,
MBBI,
DL, Tbx);
1249 MachineInstrBuilder MIB =
BuildMI(CondBB, CondBB.
back(),
MI.getDebugLoc(),
1250 TII->get(AArch64::MSRpstatesvcrImm1));
1254 MIB.
add(
MI.getOperand(0));
1255 MIB.
add(
MI.getOperand(1));
1256 for (
unsigned i = 4; i <
MI.getNumOperands(); ++i)
1257 MIB.
add(
MI.getOperand(i));
1259 MI.eraseFromParent();
1263bool AArch64ExpandPseudoImpl::expandMultiVecPseudo(
1267 unsigned StridedOpc) {
1268 MachineInstr &
MI = *
MBBI;
1282 .
add(
MI.getOperand(0))
1283 .
add(
MI.getOperand(1))
1284 .
add(
MI.getOperand(2))
1285 .
add(
MI.getOperand(3));
1286 transferImpOps(
MI, MIB, MIB);
1287 MI.eraseFromParent();
1291bool AArch64ExpandPseudoImpl::expandCopyIntoTuplePseudo(
1292 MachineInstr &
MI, MachineBasicBlock &
MBB,
1299 .
addReg(Dest, RegState::Define)
1303 MI.eraseFromParent();
1309bool AArch64ExpandPseudoImpl::expandMI(MachineBasicBlock &
MBB,
1312 MachineInstr &
MI = *
MBBI;
1313 unsigned Opcode =
MI.getOpcode();
1317 if (OrigInstr != -1) {
1318 auto &Orig =
TII->get(OrigInstr);
1321 return expand_DestructiveOp(
MI,
MBB,
MBBI);
1329 case AArch64::BSPv8i8:
1330 case AArch64::BSPv16i8: {
1332 if (DstReg ==
MI.getOperand(3).getReg()) {
1335 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BITv8i8
1336 : AArch64::BITv16i8))
1337 .
add(
MI.getOperand(0))
1338 .
add(
MI.getOperand(3))
1339 .
add(
MI.getOperand(2))
1340 .
add(
MI.getOperand(1));
1341 transferImpOps(
MI,
I,
I);
1342 }
else if (DstReg ==
MI.getOperand(2).getReg()) {
1345 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BIFv8i8
1346 : AArch64::BIFv16i8))
1347 .
add(
MI.getOperand(0))
1348 .
add(
MI.getOperand(2))
1349 .
add(
MI.getOperand(3))
1350 .
add(
MI.getOperand(1));
1351 transferImpOps(
MI,
I,
I);
1354 if (DstReg ==
MI.getOperand(1).getReg()) {
1357 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BSLv8i8
1358 : AArch64::BSLv16i8))
1359 .
add(
MI.getOperand(0))
1360 .
add(
MI.getOperand(1))
1361 .
add(
MI.getOperand(2))
1362 .
add(
MI.getOperand(3));
1363 transferImpOps(
MI,
I,
I);
1368 MI.getOperand(1).isKill() &&
1369 MI.getOperand(1).getReg() !=
MI.getOperand(2).getReg() &&
1370 MI.getOperand(1).getReg() !=
MI.getOperand(3).getReg());
1372 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::ORRv8i8
1373 : AArch64::ORRv16i8))
1381 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BSLv8i8
1382 : AArch64::BSLv16i8))
1383 .
add(
MI.getOperand(0))
1386 MI.getOperand(0).isRenamable()))
1387 .
add(
MI.getOperand(2))
1388 .
add(
MI.getOperand(3));
1389 transferImpOps(
MI, I2, I2);
1392 MI.eraseFromParent();
1396 case AArch64::ADDWrr:
1397 case AArch64::SUBWrr:
1398 case AArch64::ADDXrr:
1399 case AArch64::SUBXrr:
1400 case AArch64::ADDSWrr:
1401 case AArch64::SUBSWrr:
1402 case AArch64::ADDSXrr:
1403 case AArch64::SUBSXrr:
1404 case AArch64::ANDWrr:
1405 case AArch64::ANDXrr:
1406 case AArch64::BICWrr:
1407 case AArch64::BICXrr:
1408 case AArch64::ANDSWrr:
1409 case AArch64::ANDSXrr:
1410 case AArch64::BICSWrr:
1411 case AArch64::BICSXrr:
1412 case AArch64::EONWrr:
1413 case AArch64::EONXrr:
1414 case AArch64::EORWrr:
1415 case AArch64::EORXrr:
1416 case AArch64::ORNWrr:
1417 case AArch64::ORNXrr:
1418 case AArch64::ORRWrr:
1419 case AArch64::ORRXrr: {
1421 switch (
MI.getOpcode()) {
1424 case AArch64::ADDWrr: Opcode = AArch64::ADDWrs;
break;
1425 case AArch64::SUBWrr: Opcode = AArch64::SUBWrs;
break;
1426 case AArch64::ADDXrr: Opcode = AArch64::ADDXrs;
break;
1427 case AArch64::SUBXrr: Opcode = AArch64::SUBXrs;
break;
1428 case AArch64::ADDSWrr: Opcode = AArch64::ADDSWrs;
break;
1429 case AArch64::SUBSWrr: Opcode = AArch64::SUBSWrs;
break;
1430 case AArch64::ADDSXrr: Opcode = AArch64::ADDSXrs;
break;
1431 case AArch64::SUBSXrr: Opcode = AArch64::SUBSXrs;
break;
1432 case AArch64::ANDWrr: Opcode = AArch64::ANDWrs;
break;
1433 case AArch64::ANDXrr: Opcode = AArch64::ANDXrs;
break;
1434 case AArch64::BICWrr: Opcode = AArch64::BICWrs;
break;
1435 case AArch64::BICXrr: Opcode = AArch64::BICXrs;
break;
1436 case AArch64::ANDSWrr: Opcode = AArch64::ANDSWrs;
break;
1437 case AArch64::ANDSXrr: Opcode = AArch64::ANDSXrs;
break;
1438 case AArch64::BICSWrr: Opcode = AArch64::BICSWrs;
break;
1439 case AArch64::BICSXrr: Opcode = AArch64::BICSXrs;
break;
1440 case AArch64::EONWrr: Opcode = AArch64::EONWrs;
break;
1441 case AArch64::EONXrr: Opcode = AArch64::EONXrs;
break;
1442 case AArch64::EORWrr: Opcode = AArch64::EORWrs;
break;
1443 case AArch64::EORXrr: Opcode = AArch64::EORXrs;
break;
1444 case AArch64::ORNWrr: Opcode = AArch64::ORNWrs;
break;
1445 case AArch64::ORNXrr: Opcode = AArch64::ORNXrs;
break;
1446 case AArch64::ORRWrr: Opcode = AArch64::ORRWrs;
break;
1447 case AArch64::ORRXrr: Opcode = AArch64::ORRXrs;
break;
1451 MachineInstr *NewMI = MF.CreateMachineInstr(
1452 TII->get(Opcode),
MI.getDebugLoc(),
true);
1454 MachineInstrBuilder MIB1(MF, NewMI);
1455 MIB1->setPCSections(MF,
MI.getPCSections());
1456 MIB1.addReg(
MI.getOperand(0).getReg(), RegState::Define)
1457 .add(
MI.getOperand(1))
1458 .add(
MI.getOperand(2))
1460 transferImpOps(
MI, MIB1, MIB1);
1461 if (
auto DebugNumber =
MI.peekDebugInstrNum())
1463 MI.eraseFromParent();
1467 case AArch64::LOADgot: {
1470 const MachineOperand &MO1 =
MI.getOperand(1);
1476 TII->get(AArch64::LDRXl), DstReg);
1484 "Only expect globals, externalsymbols, or constant pools");
1489 MachineFunction &MF = *
MI.getParent()->getParent();
1491 MachineInstrBuilder MIB1 =
1494 MachineInstrBuilder MIB2;
1495 if (MF.
getSubtarget<AArch64Subtarget>().isTargetILP32()) {
1497 unsigned Reg32 =
TRI->getSubReg(DstReg, AArch64::sub_32);
1500 .
addReg(DstReg, RegState::Kill)
1501 .
addReg(DstReg, RegState::Implicit);
1505 .
add(
MI.getOperand(0))
1506 .
addUse(DstReg, RegState::Kill);
1520 "Only expect globals, externalsymbols, or constant pools");
1531 if (
MI.peekDebugInstrNum() != 0)
1533 transferImpOps(
MI, MIB1, MIB2);
1535 MI.eraseFromParent();
1538 case AArch64::MOVaddrBA:
1539 case AArch64::MOVaddr:
1540 case AArch64::MOVaddrJT:
1541 case AArch64::MOVaddrCP:
1542 case AArch64::MOVaddrTLS:
1543 case AArch64::MOVaddrEXT: {
1544 MachineFunction &MF = *
MI.getParent()->getParent();
1546 assert(DstReg != AArch64::XZR);
1548 bool IsTargetMachO = MF.
getSubtarget<AArch64Subtarget>().isTargetMachO();
1551 MI.getOpcode(),
MI.getOperand(1).getTargetFlags(), IsTargetMachO, Insn);
1554 std::optional<unsigned> CPIdx;
1555 if (Opcode == AArch64::MOVaddrBA && IsTargetMachO) {
1560 assert(
MI.getOperand(1).getOffset() == 0 &&
"unexpected offset");
1565 MachineInstrBuilder FirstMIB;
1566 MachineInstrBuilder LastMIB;
1567 for (
const auto &
I : Insn) {
1568 MachineInstrBuilder MIB;
1576 MIB.
add(
MI.getOperand(1));
1578 case AArch64::LDRXui:
1585 case AArch64::MOVKXi: {
1593 auto Tag =
MI.getOperand(1);
1595 Tag.setOffset(0x100000000);
1603 case AArch64::ADDXri:
1605 .
add(
MI.getOperand(0))
1607 .
add(
MI.getOperand(2))
1619 transferImpOps(
MI, FirstMIB, LastMIB);
1620 MI.eraseFromParent();
1623 case AArch64::ADDlowTLS:
1626 .
add(
MI.getOperand(0))
1627 .
add(
MI.getOperand(1))
1628 .
add(
MI.getOperand(2))
1630 MI.eraseFromParent();
1633 case AArch64::MOVbaseTLS: {
1635 auto SysReg = AArch64SysReg::TPIDR_EL0;
1637 if (MF->
getSubtarget<AArch64Subtarget>().useEL3ForTP())
1638 SysReg = AArch64SysReg::TPIDR_EL3;
1639 else if (MF->
getSubtarget<AArch64Subtarget>().useEL2ForTP())
1640 SysReg = AArch64SysReg::TPIDR_EL2;
1641 else if (MF->
getSubtarget<AArch64Subtarget>().useEL1ForTP())
1642 SysReg = AArch64SysReg::TPIDR_EL1;
1643 else if (MF->
getSubtarget<AArch64Subtarget>().useROEL0ForTP())
1644 SysReg = AArch64SysReg::TPIDRRO_EL0;
1647 MI.eraseFromParent();
1651 case AArch64::MOVi32imm:
1653 case AArch64::MOVi64imm:
1655 case AArch64::RET_ReallyLR: {
1661 MachineInstrBuilder MIB =
1663 .
addReg(AArch64::LR, RegState::Undef);
1664 transferImpOps(
MI, MIB, MIB);
1665 MI.eraseFromParent();
1668 case AArch64::CMP_SWAP_8:
1669 return expandCMP_SWAP(
MBB,
MBBI, AArch64::LDAXRB, AArch64::STLXRB,
1672 AArch64::WZR, NextMBBI);
1673 case AArch64::CMP_SWAP_16:
1674 return expandCMP_SWAP(
MBB,
MBBI, AArch64::LDAXRH, AArch64::STLXRH,
1677 AArch64::WZR, NextMBBI);
1678 case AArch64::CMP_SWAP_32:
1679 return expandCMP_SWAP(
MBB,
MBBI, AArch64::LDAXRW, AArch64::STLXRW,
1682 AArch64::WZR, NextMBBI);
1683 case AArch64::CMP_SWAP_64:
1684 return expandCMP_SWAP(
MBB,
MBBI,
1685 AArch64::LDAXRX, AArch64::STLXRX, AArch64::SUBSXrs,
1687 AArch64::XZR, NextMBBI);
1688 case AArch64::CMP_SWAP_128:
1689 case AArch64::CMP_SWAP_128_RELEASE:
1690 case AArch64::CMP_SWAP_128_ACQUIRE:
1691 case AArch64::CMP_SWAP_128_MONOTONIC:
1692 return expandCMP_SWAP_128(
MBB,
MBBI, NextMBBI);
1694 case AArch64::AESMCrrTied:
1695 case AArch64::AESIMCrrTied: {
1696 MachineInstrBuilder MIB =
1698 TII->get(Opcode == AArch64::AESMCrrTied ? AArch64::AESMCrr :
1700 .
add(
MI.getOperand(0))
1701 .
add(
MI.getOperand(1));
1702 transferImpOps(
MI, MIB, MIB);
1703 MI.eraseFromParent();
1706 case AArch64::IRGstack: {
1708 const AArch64FunctionInfo *AFI = MF.
getInfo<AArch64FunctionInfo>();
1709 const AArch64FrameLowering *TFI =
1710 MF.
getSubtarget<AArch64Subtarget>().getFrameLowering();
1717 StackOffset FrameRegOffset = TFI->resolveFrameOffsetReference(
1723 if (FrameRegOffset) {
1725 SrcReg =
MI.getOperand(0).getReg();
1727 FrameRegOffset,
TII);
1730 .
add(
MI.getOperand(0))
1732 .
add(
MI.getOperand(2));
1733 MI.eraseFromParent();
1736 case AArch64::TAGPstack: {
1737 int64_t
Offset =
MI.getOperand(2).getImm();
1739 TII->get(
Offset >= 0 ? AArch64::ADDG : AArch64::SUBG))
1740 .
add(
MI.getOperand(0))
1741 .
add(
MI.getOperand(1))
1743 .
add(
MI.getOperand(4));
1744 MI.eraseFromParent();
1747 case AArch64::STGloop_wback:
1748 case AArch64::STZGloop_wback:
1749 return expandSetTagLoop(
MBB,
MBBI, NextMBBI);
1750 case AArch64::STGloop:
1751 case AArch64::STZGloop:
1753 "Non-writeback variants of STGloop / STZGloop should not "
1754 "survive past PrologEpilogInserter.");
1755 case AArch64::STR_ZZZZXI:
1756 case AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS:
1757 return expandSVESpillFill(
MBB,
MBBI, AArch64::STR_ZXI, 4);
1758 case AArch64::STR_ZZZXI:
1759 return expandSVESpillFill(
MBB,
MBBI, AArch64::STR_ZXI, 3);
1760 case AArch64::STR_ZZXI:
1761 case AArch64::STR_ZZXI_STRIDED_CONTIGUOUS:
1762 return expandSVESpillFill(
MBB,
MBBI, AArch64::STR_ZXI, 2);
1763 case AArch64::STR_PPXI:
1764 return expandSVESpillFill(
MBB,
MBBI, AArch64::STR_PXI, 2);
1765 case AArch64::LDR_ZZZZXI:
1766 case AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS:
1767 return expandSVESpillFill(
MBB,
MBBI, AArch64::LDR_ZXI, 4);
1768 case AArch64::LDR_ZZZXI:
1769 return expandSVESpillFill(
MBB,
MBBI, AArch64::LDR_ZXI, 3);
1770 case AArch64::LDR_ZZXI:
1771 case AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS:
1772 return expandSVESpillFill(
MBB,
MBBI, AArch64::LDR_ZXI, 2);
1773 case AArch64::LDR_PPXI:
1774 return expandSVESpillFill(
MBB,
MBBI, AArch64::LDR_PXI, 2);
1775 case AArch64::BLR_RVMARKER:
1776 case AArch64::BLRA_RVMARKER:
1777 return expandCALL_RVMARKER(
MBB,
MBBI);
1778 case AArch64::BLR_BTI:
1779 return expandCALL_BTI(
MBB,
MBBI);
1780 case AArch64::StoreSwiftAsyncContext:
1781 return expandStoreSwiftAsyncContext(
MBB,
MBBI);
1782 case AArch64::RestoreZAPseudo:
1783 case AArch64::CommitZASavePseudo:
1784 case AArch64::MSRpstatePseudo: {
1785 auto *NewMBB = [&] {
1787 case AArch64::RestoreZAPseudo:
1788 return expandRestoreZASave(
MBB,
MBBI);
1789 case AArch64::CommitZASavePseudo:
1790 return expandCommitZASave(
MBB,
MBBI);
1791 case AArch64::MSRpstatePseudo:
1792 return expandCondSMToggle(
MBB,
MBBI);
1801 case AArch64::InOutZAUsePseudo:
1802 case AArch64::RequiresZASavePseudo:
1803 case AArch64::RequiresZT0SavePseudo:
1804 case AArch64::SMEStateAllocPseudo:
1805 case AArch64::COALESCER_BARRIER_FPR16:
1806 case AArch64::COALESCER_BARRIER_FPR32:
1807 case AArch64::COALESCER_BARRIER_FPR64:
1808 case AArch64::COALESCER_BARRIER_FPR128:
1809 MI.eraseFromParent();
1811 case AArch64::LD1B_2Z_IMM_PSEUDO:
1812 return expandMultiVecPseudo(
1813 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1814 AArch64::LD1B_2Z_IMM, AArch64::LD1B_2Z_STRIDED_IMM);
1815 case AArch64::LD1H_2Z_IMM_PSEUDO:
1816 return expandMultiVecPseudo(
1817 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1818 AArch64::LD1H_2Z_IMM, AArch64::LD1H_2Z_STRIDED_IMM);
1819 case AArch64::LD1W_2Z_IMM_PSEUDO:
1820 return expandMultiVecPseudo(
1821 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1822 AArch64::LD1W_2Z_IMM, AArch64::LD1W_2Z_STRIDED_IMM);
1823 case AArch64::LD1D_2Z_IMM_PSEUDO:
1824 return expandMultiVecPseudo(
1825 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1826 AArch64::LD1D_2Z_IMM, AArch64::LD1D_2Z_STRIDED_IMM);
1827 case AArch64::LDNT1B_2Z_IMM_PSEUDO:
1828 return expandMultiVecPseudo(
1829 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1830 AArch64::LDNT1B_2Z_IMM, AArch64::LDNT1B_2Z_STRIDED_IMM);
1831 case AArch64::LDNT1H_2Z_IMM_PSEUDO:
1832 return expandMultiVecPseudo(
1833 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1834 AArch64::LDNT1H_2Z_IMM, AArch64::LDNT1H_2Z_STRIDED_IMM);
1835 case AArch64::LDNT1W_2Z_IMM_PSEUDO:
1836 return expandMultiVecPseudo(
1837 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1838 AArch64::LDNT1W_2Z_IMM, AArch64::LDNT1W_2Z_STRIDED_IMM);
1839 case AArch64::LDNT1D_2Z_IMM_PSEUDO:
1840 return expandMultiVecPseudo(
1841 MBB,
MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1842 AArch64::LDNT1D_2Z_IMM, AArch64::LDNT1D_2Z_STRIDED_IMM);
1843 case AArch64::LD1B_2Z_PSEUDO:
1844 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1845 AArch64::ZPR2StridedRegClass, AArch64::LD1B_2Z,
1846 AArch64::LD1B_2Z_STRIDED);
1847 case AArch64::LD1H_2Z_PSEUDO:
1848 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1849 AArch64::ZPR2StridedRegClass, AArch64::LD1H_2Z,
1850 AArch64::LD1H_2Z_STRIDED);
1851 case AArch64::LD1W_2Z_PSEUDO:
1852 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1853 AArch64::ZPR2StridedRegClass, AArch64::LD1W_2Z,
1854 AArch64::LD1W_2Z_STRIDED);
1855 case AArch64::LD1D_2Z_PSEUDO:
1856 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1857 AArch64::ZPR2StridedRegClass, AArch64::LD1D_2Z,
1858 AArch64::LD1D_2Z_STRIDED);
1859 case AArch64::LDNT1B_2Z_PSEUDO:
1860 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1861 AArch64::ZPR2StridedRegClass,
1862 AArch64::LDNT1B_2Z, AArch64::LDNT1B_2Z_STRIDED);
1863 case AArch64::LDNT1H_2Z_PSEUDO:
1864 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1865 AArch64::ZPR2StridedRegClass,
1866 AArch64::LDNT1H_2Z, AArch64::LDNT1H_2Z_STRIDED);
1867 case AArch64::LDNT1W_2Z_PSEUDO:
1868 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1869 AArch64::ZPR2StridedRegClass,
1870 AArch64::LDNT1W_2Z, AArch64::LDNT1W_2Z_STRIDED);
1871 case AArch64::LDNT1D_2Z_PSEUDO:
1872 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR2RegClass,
1873 AArch64::ZPR2StridedRegClass,
1874 AArch64::LDNT1D_2Z, AArch64::LDNT1D_2Z_STRIDED);
1875 case AArch64::LD1B_4Z_IMM_PSEUDO:
1876 return expandMultiVecPseudo(
1877 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1878 AArch64::LD1B_4Z_IMM, AArch64::LD1B_4Z_STRIDED_IMM);
1879 case AArch64::LD1H_4Z_IMM_PSEUDO:
1880 return expandMultiVecPseudo(
1881 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1882 AArch64::LD1H_4Z_IMM, AArch64::LD1H_4Z_STRIDED_IMM);
1883 case AArch64::LD1W_4Z_IMM_PSEUDO:
1884 return expandMultiVecPseudo(
1885 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1886 AArch64::LD1W_4Z_IMM, AArch64::LD1W_4Z_STRIDED_IMM);
1887 case AArch64::LD1D_4Z_IMM_PSEUDO:
1888 return expandMultiVecPseudo(
1889 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1890 AArch64::LD1D_4Z_IMM, AArch64::LD1D_4Z_STRIDED_IMM);
1891 case AArch64::LDNT1B_4Z_IMM_PSEUDO:
1892 return expandMultiVecPseudo(
1893 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1894 AArch64::LDNT1B_4Z_IMM, AArch64::LDNT1B_4Z_STRIDED_IMM);
1895 case AArch64::LDNT1H_4Z_IMM_PSEUDO:
1896 return expandMultiVecPseudo(
1897 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1898 AArch64::LDNT1H_4Z_IMM, AArch64::LDNT1H_4Z_STRIDED_IMM);
1899 case AArch64::LDNT1W_4Z_IMM_PSEUDO:
1900 return expandMultiVecPseudo(
1901 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1902 AArch64::LDNT1W_4Z_IMM, AArch64::LDNT1W_4Z_STRIDED_IMM);
1903 case AArch64::LDNT1D_4Z_IMM_PSEUDO:
1904 return expandMultiVecPseudo(
1905 MBB,
MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1906 AArch64::LDNT1D_4Z_IMM, AArch64::LDNT1D_4Z_STRIDED_IMM);
1907 case AArch64::LD1B_4Z_PSEUDO:
1908 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1909 AArch64::ZPR4StridedRegClass, AArch64::LD1B_4Z,
1910 AArch64::LD1B_4Z_STRIDED);
1911 case AArch64::LD1H_4Z_PSEUDO:
1912 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1913 AArch64::ZPR4StridedRegClass, AArch64::LD1H_4Z,
1914 AArch64::LD1H_4Z_STRIDED);
1915 case AArch64::LD1W_4Z_PSEUDO:
1916 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1917 AArch64::ZPR4StridedRegClass, AArch64::LD1W_4Z,
1918 AArch64::LD1W_4Z_STRIDED);
1919 case AArch64::LD1D_4Z_PSEUDO:
1920 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1921 AArch64::ZPR4StridedRegClass, AArch64::LD1D_4Z,
1922 AArch64::LD1D_4Z_STRIDED);
1923 case AArch64::LDNT1B_4Z_PSEUDO:
1924 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1925 AArch64::ZPR4StridedRegClass,
1926 AArch64::LDNT1B_4Z, AArch64::LDNT1B_4Z_STRIDED);
1927 case AArch64::LDNT1H_4Z_PSEUDO:
1928 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1929 AArch64::ZPR4StridedRegClass,
1930 AArch64::LDNT1H_4Z, AArch64::LDNT1H_4Z_STRIDED);
1931 case AArch64::LDNT1W_4Z_PSEUDO:
1932 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1933 AArch64::ZPR4StridedRegClass,
1934 AArch64::LDNT1W_4Z, AArch64::LDNT1W_4Z_STRIDED);
1935 case AArch64::LDNT1D_4Z_PSEUDO:
1936 return expandMultiVecPseudo(
MBB,
MBBI, AArch64::ZPR4RegClass,
1937 AArch64::ZPR4StridedRegClass,
1938 AArch64::LDNT1D_4Z, AArch64::LDNT1D_4Z_STRIDED);
1939 case AArch64::COPY_INTO_TRANSPOSED_TUPLE:
1940 return expandCopyIntoTuplePseudo(
MI,
MBB,
MBBI);
1941 case AArch64::EON_ZZZ:
1942 case AArch64::NAND_ZZZ:
1943 case AArch64::NOR_ZZZ:
1944 return expandSVEBitwisePseudo(
MI,
MBB,
MBBI);
1951bool AArch64ExpandPseudoImpl::expandMBB(MachineBasicBlock &
MBB) {
1957 if (
MBBI->isPseudo())
1965bool AArch64ExpandPseudoImpl::run(MachineFunction &MF) {
1969 for (
auto &
MBB : MF)
1974bool AArch64ExpandPseudoLegacy::runOnMachineFunction(MachineFunction &MF) {
1975 return AArch64ExpandPseudoImpl().run(MF);
1980 return new AArch64ExpandPseudoLegacy();
1986 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.