@@ -296,7 +296,8 @@ static int64_t getArgumentStackToRestore(MachineFunction &MF,
296
296
static bool produceCompactUnwindFrame (MachineFunction &MF);
297
297
static bool needsWinCFI (const MachineFunction &MF);
298
298
static StackOffset getSVEStackSize (const MachineFunction &MF);
299
- static unsigned findScratchNonCalleeSaveRegister (MachineBasicBlock *MBB);
299
+ static unsigned findScratchNonCalleeSaveRegister (MachineBasicBlock *MBB,
300
+ unsigned FirstScratchReg = 0 );
300
301
301
302
// / Returns true if a homogeneous prolog or epilog code can be emitted
302
303
// / for the size optimization. If possible, a frame helper call is injected.
@@ -870,17 +871,24 @@ void AArch64FrameLowering::emitZeroCallUsedRegs(BitVector RegsToZero,
870
871
// but we would then have to make sure that we were in fact saving at least one
871
872
// callee-save register in the prologue, which is additional complexity that
872
873
// doesn't seem worth the benefit.
873
- static unsigned findScratchNonCalleeSaveRegister (MachineBasicBlock *MBB) {
874
+ //
875
+ // If \p FirstScratchReg is not 0, it specifies the register that was chosen as
876
+ // first scratch register and indicates that it should return another scratch
877
+ // register, if possible.
878
+ static unsigned findScratchNonCalleeSaveRegister (MachineBasicBlock *MBB,
879
+ unsigned FirstScratchReg) {
874
880
MachineFunction *MF = MBB->getParent ();
875
881
876
882
// If MBB is an entry block, use X9 as the scratch register
877
- if (&MF->front () == MBB)
883
+ if (&MF->front () == MBB && !FirstScratchReg )
878
884
return AArch64::X9;
879
885
880
886
const AArch64Subtarget &Subtarget = MF->getSubtarget <AArch64Subtarget>();
881
887
const AArch64RegisterInfo &TRI = *Subtarget.getRegisterInfo ();
882
888
LivePhysRegs LiveRegs (TRI);
883
889
LiveRegs.addLiveIns (*MBB);
890
+ if (FirstScratchReg)
891
+ LiveRegs.addReg (FirstScratchReg);
884
892
885
893
// Mark callee saved registers as used so we will not choose them.
886
894
const MCPhysReg *CSRegs = MF->getRegInfo ().getCalleeSavedRegs ();
@@ -905,6 +913,17 @@ bool AArch64FrameLowering::canUseAsPrologue(
905
913
MachineBasicBlock *TmpMBB = const_cast <MachineBasicBlock *>(&MBB);
906
914
const AArch64Subtarget &Subtarget = MF->getSubtarget <AArch64Subtarget>();
907
915
const AArch64RegisterInfo *RegInfo = Subtarget.getRegisterInfo ();
916
+ const AArch64FunctionInfo *AFI = MF->getInfo <AArch64FunctionInfo>();
917
+
918
+ if (AFI->hasSwiftAsyncContext ()) {
919
+ // Expanding StoreSwiftAsyncContext requires 2 scratch registers.
920
+ unsigned FirstScratchReg = findScratchNonCalleeSaveRegister (TmpMBB);
921
+ unsigned SecondScratchReg =
922
+ findScratchNonCalleeSaveRegister (TmpMBB, FirstScratchReg);
923
+ if (FirstScratchReg == AArch64::NoRegister ||
924
+ SecondScratchReg == AArch64::NoRegister)
925
+ return false ;
926
+ }
908
927
909
928
// Don't need a scratch register if we're not going to re-align the stack.
910
929
if (!RegInfo->hasStackRealignment (*MF))
@@ -1681,11 +1700,16 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
1681
1700
bool HaveInitialContext = Attrs.hasAttrSomewhere (Attribute::SwiftAsync);
1682
1701
if (HaveInitialContext)
1683
1702
MBB.addLiveIn (AArch64::X22);
1703
+ unsigned FirstScratchReg = findScratchNonCalleeSaveRegister (&MBB);
1704
+ unsigned SecondScratchReg =
1705
+ findScratchNonCalleeSaveRegister (&MBB, FirstScratchReg);
1684
1706
Register Reg = HaveInitialContext ? AArch64::X22 : AArch64::XZR;
1685
1707
BuildMI (MBB, MBBI, DL, TII->get (AArch64::StoreSwiftAsyncContext))
1686
1708
.addUse (Reg)
1687
1709
.addUse (AArch64::SP)
1688
1710
.addImm (FPOffset - 8 )
1711
+ .addDef (FirstScratchReg, RegState::Implicit)
1712
+ .addDef (SecondScratchReg, RegState::Implicit)
1689
1713
.setMIFlags (MachineInstr::FrameSetup);
1690
1714
if (NeedsWinCFI) {
1691
1715
// WinCFI and arm64e, where StoreSwiftAsyncContext is expanded
0 commit comments