Skip to content

Commit d8cc2e9

Browse files
committed
[AArch64][SME] Add common helper for expanding conditional pseudos (NFC)
Factors out some common slightly tricky code. Hopefully makes adding new pseudos simpler.
1 parent d606eae commit d8cc2e9

File tree

1 file changed

+106
-85
lines changed

1 file changed

+106
-85
lines changed

llvm/lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp

Lines changed: 106 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,17 @@ class AArch64ExpandPseudo : public MachineFunctionPass {
9292
bool expandCALL_BTI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI);
9393
bool expandStoreSwiftAsyncContext(MachineBasicBlock &MBB,
9494
MachineBasicBlock::iterator MBBI);
95+
9596
MachineBasicBlock *
96-
expandCommitOrRestoreZASave(MachineBasicBlock &MBB,
97-
MachineBasicBlock::iterator MBBI);
97+
expandConditionalPseudo(MachineBasicBlock &MBB,
98+
MachineBasicBlock::iterator MBBI, DebugLoc DL,
99+
MachineInstrBuilder &Branch,
100+
function_ref<void(MachineBasicBlock &)> InsertBody);
101+
102+
MachineBasicBlock *expandRestoreZASave(MachineBasicBlock &MBB,
103+
MachineBasicBlock::iterator MBBI);
104+
MachineBasicBlock *expandCommitZASave(MachineBasicBlock &MBB,
105+
MachineBasicBlock::iterator MBBI);
98106
MachineBasicBlock *expandCondSMToggle(MachineBasicBlock &MBB,
99107
MachineBasicBlock::iterator MBBI);
100108
};
@@ -991,74 +999,99 @@ bool AArch64ExpandPseudo::expandStoreSwiftAsyncContext(
991999
return true;
9921000
}
9931001

994-
static constexpr unsigned ZERO_ALL_ZA_MASK = 0b11111111;
995-
996-
MachineBasicBlock *AArch64ExpandPseudo::expandCommitOrRestoreZASave(
997-
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) {
1002+
MachineBasicBlock *AArch64ExpandPseudo::expandConditionalPseudo(
1003+
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, DebugLoc DL,
1004+
MachineInstrBuilder &Branch,
1005+
function_ref<void(MachineBasicBlock &)> InsertBody) {
9981006
MachineInstr &MI = *MBBI;
999-
bool IsRestoreZA = MI.getOpcode() == AArch64::RestoreZAPseudo;
1000-
assert((MI.getOpcode() == AArch64::RestoreZAPseudo ||
1001-
MI.getOpcode() == AArch64::CommitZASavePseudo) &&
1002-
"Expected ZA commit or restore");
10031007
assert((std::next(MBBI) != MBB.end() ||
10041008
MI.getParent()->successors().begin() !=
10051009
MI.getParent()->successors().end()) &&
1006-
"Unexpected unreachable in block that restores ZA");
1007-
1008-
// Compare TPIDR2_EL0 value against 0.
1009-
DebugLoc DL = MI.getDebugLoc();
1010-
MachineInstrBuilder Branch =
1011-
BuildMI(MBB, MBBI, DL,
1012-
TII->get(IsRestoreZA ? AArch64::CBZX : AArch64::CBNZX))
1013-
.add(MI.getOperand(0));
1010+
"Unexpected unreachable in block");
10141011

10151012
// Split MBB and create two new blocks:
1016-
// - MBB now contains all instructions before RestoreZAPseudo.
1017-
// - SMBB contains the [Commit|RestoreZA]Pseudo instruction only.
1018-
// - EndBB contains all instructions after [Commit|RestoreZA]Pseudo.
1013+
// - MBB now contains all instructions before the conditional pseudo.
1014+
// - SMBB contains the conditional pseudo instruction only.
1015+
// - EndBB contains all instructions after the conditional pseudo.
10191016
MachineInstr &PrevMI = *std::prev(MBBI);
10201017
MachineBasicBlock *SMBB = MBB.splitAt(PrevMI, /*UpdateLiveIns*/ true);
10211018
MachineBasicBlock *EndBB = std::next(MI.getIterator()) == SMBB->end()
10221019
? *SMBB->successors().begin()
10231020
: SMBB->splitAt(MI, /*UpdateLiveIns*/ true);
10241021

1025-
// Add the SMBB label to the CB[N]Z instruction & create a branch to EndBB.
1022+
// Add the SMBB label to the branch instruction & create a branch to EndBB.
10261023
Branch.addMBB(SMBB);
10271024
BuildMI(&MBB, DL, TII->get(AArch64::B))
10281025
.addMBB(EndBB);
10291026
MBB.addSuccessor(EndBB);
10301027

1031-
// Replace the pseudo with a call (BL).
1032-
MachineInstrBuilder MIB =
1033-
BuildMI(*SMBB, SMBB->end(), DL, TII->get(AArch64::BL));
1034-
// Copy operands (mainly the regmask) from the pseudo.
1035-
for (unsigned I = 2; I < MI.getNumOperands(); ++I)
1036-
MIB.add(MI.getOperand(I));
1037-
1038-
if (IsRestoreZA) {
1039-
// Mark the TPIDR2 block pointer (X0) as an implicit use.
1040-
MIB.addReg(MI.getOperand(1).getReg(), RegState::Implicit);
1041-
} else /*CommitZA*/ {
1042-
[[maybe_unused]] auto *TRI =
1043-
MBB.getParent()->getSubtarget().getRegisterInfo();
1044-
// Clear TPIDR2_EL0.
1045-
BuildMI(*SMBB, SMBB->end(), DL, TII->get(AArch64::MSR))
1046-
.addImm(AArch64SysReg::TPIDR2_EL0)
1047-
.addReg(AArch64::XZR);
1048-
bool ZeroZA = MI.getOperand(1).getImm() != 0;
1049-
if (ZeroZA) {
1050-
assert(MI.definesRegister(AArch64::ZAB0, TRI) && "should define ZA!");
1051-
BuildMI(*SMBB, SMBB->end(), DL, TII->get(AArch64::ZERO_M))
1052-
.addImm(ZERO_ALL_ZA_MASK)
1053-
.addDef(AArch64::ZAB0, RegState::ImplicitDefine);
1054-
}
1055-
}
1028+
// Insert the conditional pseudo expansion.
1029+
InsertBody(*SMBB);
10561030

10571031
BuildMI(SMBB, DL, TII->get(AArch64::B)).addMBB(EndBB);
10581032
MI.eraseFromParent();
10591033
return EndBB;
10601034
}
10611035

1036+
MachineBasicBlock *
1037+
AArch64ExpandPseudo::expandRestoreZASave(MachineBasicBlock &MBB,
1038+
MachineBasicBlock::iterator MBBI) {
1039+
MachineInstr &MI = *MBBI;
1040+
DebugLoc DL = MI.getDebugLoc();
1041+
1042+
// Compare TPIDR2_EL0 against 0. Restore ZA if TPIDR2_EL0 is zero.
1043+
MachineInstrBuilder Branch =
1044+
BuildMI(MBB, MBBI, DL, TII->get(AArch64::CBZX)).add(MI.getOperand(0));
1045+
1046+
return expandConditionalPseudo(
1047+
MBB, MBBI, DL, Branch, [&](MachineBasicBlock &SMBB) {
1048+
// Replace the pseudo with a call (BL).
1049+
MachineInstrBuilder MIB =
1050+
BuildMI(SMBB, SMBB.end(), DL, TII->get(AArch64::BL));
1051+
// Copy operands (mainly the regmask) from the pseudo.
1052+
for (unsigned I = 2; I < MI.getNumOperands(); ++I)
1053+
MIB.add(MI.getOperand(I));
1054+
// Mark the TPIDR2 block pointer (X0) as an implicit use.
1055+
MIB.addReg(MI.getOperand(1).getReg(), RegState::Implicit);
1056+
});
1057+
}
1058+
1059+
static constexpr unsigned ZERO_ALL_ZA_MASK = 0b11111111;
1060+
1061+
MachineBasicBlock *
1062+
AArch64ExpandPseudo::expandCommitZASave(MachineBasicBlock &MBB,
1063+
MachineBasicBlock::iterator MBBI) {
1064+
MachineInstr &MI = *MBBI;
1065+
DebugLoc DL = MI.getDebugLoc();
1066+
[[maybe_unused]] auto *TRI =
1067+
MBB.getParent()->getSubtarget().getRegisterInfo();
1068+
1069+
// Compare TPIDR2_EL0 against 0. Commit ZA if TPIDR2_EL0 is non-zero.
1070+
MachineInstrBuilder Branch =
1071+
BuildMI(MBB, MBBI, DL, TII->get(AArch64::CBNZX)).add(MI.getOperand(0));
1072+
1073+
return expandConditionalPseudo(
1074+
MBB, MBBI, DL, Branch, [&](MachineBasicBlock &SMBB) {
1075+
// Replace the pseudo with a call (BL).
1076+
MachineInstrBuilder MIB =
1077+
BuildMI(SMBB, SMBB.end(), DL, TII->get(AArch64::BL));
1078+
// Copy operands (mainly the regmask) from the pseudo.
1079+
for (unsigned I = 2; I < MI.getNumOperands(); ++I)
1080+
MIB.add(MI.getOperand(I));
1081+
// Clear TPIDR2_EL0.
1082+
BuildMI(SMBB, SMBB.end(), DL, TII->get(AArch64::MSR))
1083+
.addImm(AArch64SysReg::TPIDR2_EL0)
1084+
.addReg(AArch64::XZR);
1085+
bool ZeroZA = MI.getOperand(1).getImm() != 0;
1086+
if (ZeroZA) {
1087+
assert(MI.definesRegister(AArch64::ZAB0, TRI) && "should define ZA!");
1088+
BuildMI(SMBB, SMBB.end(), DL, TII->get(AArch64::ZERO_M))
1089+
.addImm(ZERO_ALL_ZA_MASK)
1090+
.addDef(AArch64::ZAB0, RegState::ImplicitDefine);
1091+
}
1092+
});
1093+
}
1094+
10621095
MachineBasicBlock *
10631096
AArch64ExpandPseudo::expandCondSMToggle(MachineBasicBlock &MBB,
10641097
MachineBasicBlock::iterator MBBI) {
@@ -1130,37 +1163,19 @@ AArch64ExpandPseudo::expandCondSMToggle(MachineBasicBlock &MBB,
11301163
MachineInstrBuilder Tbx =
11311164
BuildMI(MBB, MBBI, DL, TII->get(Opc)).addReg(SMReg32).addImm(0);
11321165

1133-
// Split MBB and create two new blocks:
1134-
// - MBB now contains all instructions before MSRcond_pstatesvcrImm1.
1135-
// - SMBB contains the MSRcond_pstatesvcrImm1 instruction only.
1136-
// - EndBB contains all instructions after MSRcond_pstatesvcrImm1.
1137-
MachineInstr &PrevMI = *std::prev(MBBI);
1138-
MachineBasicBlock *SMBB = MBB.splitAt(PrevMI, /*UpdateLiveIns*/ true);
1139-
MachineBasicBlock *EndBB = std::next(MI.getIterator()) == SMBB->end()
1140-
? *SMBB->successors().begin()
1141-
: SMBB->splitAt(MI, /*UpdateLiveIns*/ true);
1142-
1143-
// Add the SMBB label to the TB[N]Z instruction & create a branch to EndBB.
1144-
Tbx.addMBB(SMBB);
1145-
BuildMI(&MBB, DL, TII->get(AArch64::B))
1146-
.addMBB(EndBB);
1147-
MBB.addSuccessor(EndBB);
1148-
1149-
// Create the SMSTART/SMSTOP (MSRpstatesvcrImm1) instruction in SMBB.
1150-
MachineInstrBuilder MIB = BuildMI(*SMBB, SMBB->begin(), MI.getDebugLoc(),
1151-
TII->get(AArch64::MSRpstatesvcrImm1));
1152-
// Copy all but the second and third operands of MSRcond_pstatesvcrImm1 (as
1153-
// these contain the CopyFromReg for the first argument and the flag to
1154-
// indicate whether the callee is streaming or normal).
1155-
MIB.add(MI.getOperand(0));
1156-
MIB.add(MI.getOperand(1));
1157-
for (unsigned i = 4; i < MI.getNumOperands(); ++i)
1158-
MIB.add(MI.getOperand(i));
1159-
1160-
BuildMI(SMBB, DL, TII->get(AArch64::B)).addMBB(EndBB);
1161-
1162-
MI.eraseFromParent();
1163-
return EndBB;
1166+
return expandConditionalPseudo(
1167+
MBB, MBBI, DL, Tbx, [&](MachineBasicBlock &SMBB) {
1168+
// Create the SMSTART/SMSTOP (MSRpstatesvcrImm1) instruction in SMBB.
1169+
MachineInstrBuilder MIB = BuildMI(SMBB, SMBB.begin(), MI.getDebugLoc(),
1170+
TII->get(AArch64::MSRpstatesvcrImm1));
1171+
// Copy all but the second and third operands of MSRcond_pstatesvcrImm1
1172+
// (as these contain the CopyFromReg for the first argument and the flag
1173+
// to indicate whether the callee is streaming or normal).
1174+
MIB.add(MI.getOperand(0));
1175+
MIB.add(MI.getOperand(1));
1176+
for (unsigned i = 4; i < MI.getNumOperands(); ++i)
1177+
MIB.add(MI.getOperand(i));
1178+
});
11641179
}
11651180

11661181
bool AArch64ExpandPseudo::expandMultiVecPseudo(
@@ -1673,15 +1688,21 @@ bool AArch64ExpandPseudo::expandMI(MachineBasicBlock &MBB,
16731688
return expandCALL_BTI(MBB, MBBI);
16741689
case AArch64::StoreSwiftAsyncContext:
16751690
return expandStoreSwiftAsyncContext(MBB, MBBI);
1691+
case AArch64::RestoreZAPseudo:
16761692
case AArch64::CommitZASavePseudo:
1677-
case AArch64::RestoreZAPseudo: {
1678-
auto *NewMBB = expandCommitOrRestoreZASave(MBB, MBBI);
1679-
if (NewMBB != &MBB)
1680-
NextMBBI = MBB.end(); // The NextMBBI iterator is invalidated.
1681-
return true;
1682-
}
16831693
case AArch64::MSRpstatePseudo: {
1684-
auto *NewMBB = expandCondSMToggle(MBB, MBBI);
1694+
auto *NewMBB = [&] {
1695+
switch (Opcode) {
1696+
case AArch64::RestoreZAPseudo:
1697+
return expandRestoreZASave(MBB, MBBI);
1698+
case AArch64::CommitZASavePseudo:
1699+
return expandCommitZASave(MBB, MBBI);
1700+
case AArch64::MSRpstatePseudo:
1701+
return expandCondSMToggle(MBB, MBBI);
1702+
default:
1703+
llvm_unreachable("Unexpected conditional pseudo!");
1704+
}
1705+
}();
16851706
if (NewMBB != &MBB)
16861707
NextMBBI = MBB.end(); // The NextMBBI iterator is invalidated.
16871708
return true;

0 commit comments

Comments
 (0)