@@ -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+
10621095MachineBasicBlock *
10631096AArch64ExpandPseudo::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
11661181bool 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