@@ -793,10 +793,9 @@ void AArch64PrologueEmitter::emitPrologue() {
793793 CFAOffset += AllocateBeforePPRs;
794794 assert (PPRRange.End == ZPRRange.Begin &&
795795 " Expected ZPR callee saves after PPR locals" );
796- allocateStackSpace (PPRRange.End , RealignmentPadding, AllocateAfterPPRs,
797- EmitAsyncCFI && !HasFP, CFAOffset,
798- MFI.hasVarSizedObjects () || ZPR.LocalsSize ||
799- NonSVELocalsSize);
796+ allocateStackSpace (
797+ PPRRange.End , 0 , AllocateAfterPPRs, EmitAsyncCFI && !HasFP, CFAOffset,
798+ MFI.hasVarSizedObjects () || ZPR.LocalsSize || NonSVELocalsSize);
800799 CFAOffset += AllocateAfterPPRs;
801800 } else {
802801 assert (SVELayout == SVEStackLayout::CalleeSavesAboveFrameRecord);
@@ -1308,6 +1307,26 @@ AArch64EpilogueEmitter::AArch64EpilogueEmitter(MachineFunction &MF,
13081307 SEHEpilogueStartI = MBB.end ();
13091308}
13101309
1310+ void AArch64EpilogueEmitter::moveSPBelowFP (MachineBasicBlock::iterator MBBI,
1311+ StackOffset Offset) {
1312+ // Other combinations could be supported, but are not currently needed.
1313+ assert (Offset.getScalable () < 0 && Offset.getFixed () <= 0 &&
1314+ " expected negative offset (with optional fixed portion)" );
1315+ Register Base = AArch64::FP;
1316+ if (int64_t FixedOffset = Offset.getFixed ()) {
1317+ // If we have a negative fixed offset, we need to first subtract it in a
1318+ // temporary register first (to avoid briefly deallocating the scalable
1319+ // portion of the offset).
1320+ Base = MF.getRegInfo ().createVirtualRegister (&AArch64::GPR64RegClass);
1321+ emitFrameOffset (MBB, MBBI, DL, Base, AArch64::FP,
1322+ StackOffset::getFixed (FixedOffset), TII,
1323+ MachineInstr::FrameDestroy);
1324+ }
1325+ emitFrameOffset (MBB, MBBI, DL, AArch64::SP, Base,
1326+ StackOffset::getScalable (Offset.getScalable ()), TII,
1327+ MachineInstr::FrameDestroy);
1328+ }
1329+
13111330void AArch64EpilogueEmitter::emitEpilogue () {
13121331 MachineBasicBlock::iterator EpilogueEndI = MBB.getLastNonDebugInstr ();
13131332 if (MBB.end () != EpilogueEndI) {
@@ -1408,6 +1427,7 @@ void AArch64EpilogueEmitter::emitEpilogue() {
14081427 AfterCSRPopSize += ProloguePopSize;
14091428 }
14101429 }
1430+
14111431 // Move past the restores of the callee-saved registers.
14121432 // If we plan on combining the sp bump of the local stack size and the callee
14131433 // save stack size, we might need to adjust the CSR save and restore offsets.
@@ -1474,8 +1494,6 @@ void AArch64EpilogueEmitter::emitEpilogue() {
14741494 StackOffset SVECalleeSavesSize = ZPR.CalleeSavesSize + PPR.CalleeSavesSize ;
14751495 StackOffset SVEStackSize =
14761496 SVECalleeSavesSize + PPR.LocalsSize + ZPR.LocalsSize ;
1477- MachineBasicBlock::iterator RestoreBegin = ZPRRange.Begin ;
1478- MachineBasicBlock::iterator RestoreEnd = PPRRange.End ;
14791497
14801498 // Deallocate the SVE area.
14811499 if (SVELayout == SVEStackLayout::CalleeSavesAboveFrameRecord) {
@@ -1490,7 +1508,7 @@ void AArch64EpilogueEmitter::emitEpilogue() {
14901508 }
14911509
14921510 // Deallocate callee-save SVE registers.
1493- emitFrameOffset (MBB, RestoreEnd , DL, AArch64::SP, AArch64::SP,
1511+ emitFrameOffset (MBB, PPRRange. End , DL, AArch64::SP, AArch64::SP,
14941512 SVECalleeSavesSize, TII, MachineInstr::FrameDestroy, false ,
14951513 NeedsWinCFI, &HasWinCFI);
14961514 } else if (AFI->hasSVEStackSize ()) {
@@ -1501,28 +1519,26 @@ void AArch64EpilogueEmitter::emitEpilogue() {
15011519 (AFI->isStackRealigned () || MFI.hasVarSizedObjects ()) ? AArch64::FP
15021520 : AArch64::SP;
15031521 if (SVECalleeSavesSize && BaseForSVEDealloc == AArch64::FP) {
1504- // TODO: Support stack realigment and variable-sized objects.
1505- assert (
1506- SVELayout != SVEStackLayout::Split &&
1507- " unexpected stack realignment or variable sized objects with split "
1508- " SVE stack objects" );
1509-
1510- Register CalleeSaveBase = AArch64::FP;
1511- if (int64_t CalleeSaveBaseOffset =
1512- AFI->getCalleeSaveBaseToFrameRecordOffset ()) {
1513- // If we have have an non-zero offset to the non-SVE CS base we need to
1514- // compute the base address by subtracting the offest in a temporary
1515- // register first (to avoid briefly deallocating the SVE CS).
1516- CalleeSaveBase = MBB.getParent ()->getRegInfo ().createVirtualRegister (
1517- &AArch64::GPR64RegClass);
1518- emitFrameOffset (MBB, RestoreBegin, DL, CalleeSaveBase, AArch64::FP,
1519- StackOffset::getFixed (-CalleeSaveBaseOffset), TII,
1522+ // The offset from the frame-pointer to the start of the ZPR/PPR CSRs.
1523+ StackOffset FPOffsetZPRCSRs =
1524+ -SVECalleeSavesSize -
1525+ StackOffset::getFixed (AFI->getCalleeSaveBaseToFrameRecordOffset ());
1526+ StackOffset FPOffsetPPRCSRs = FPOffsetZPRCSRs + ZPR.CalleeSavesSize ;
1527+
1528+ // With split SVE, the PPR locals are above the ZPR callee-saves.
1529+ if (ZPR.CalleeSavesSize && SVELayout == SVEStackLayout::Split)
1530+ FPOffsetZPRCSRs -= PPR.LocalsSize ;
1531+
1532+ // The code below will deallocate the stack space space by moving the SP
1533+ // to the start of the ZPR/PPR callee-save area.
1534+ moveSPBelowFP (ZPRRange.Begin , FPOffsetZPRCSRs);
1535+
1536+ if (PPR.CalleeSavesSize && SVELayout == SVEStackLayout::Split) {
1537+ // Move to the start of the PPR area (this offset may be zero).
1538+ emitFrameOffset (MBB, ZPRRange.End , DL, AArch64::SP, AArch64::SP,
1539+ FPOffsetPPRCSRs - FPOffsetZPRCSRs, TII,
15201540 MachineInstr::FrameDestroy);
15211541 }
1522- // The code below will deallocate the stack space space by moving the SP
1523- // to the start of the SVE callee-save area.
1524- emitFrameOffset (MBB, RestoreBegin, DL, AArch64::SP, CalleeSaveBase,
1525- -SVECalleeSavesSize, TII, MachineInstr::FrameDestroy);
15261542 } else if (BaseForSVEDealloc == AArch64::SP) {
15271543 auto CFAOffset =
15281544 SVEStackSize + StackOffset::getFixed (NumBytes + PrologueSaveSize);
0 commit comments