Skip to content

Commit 8fc6907

Browse files
committed
[AArch64] Fix offset in FP-based epilogue restore for popless ret.
In a swiftcorocc function, on the restoreless epilogue path (using llvm.ret.popless), we're using FP-based addressing to restore callee-saved registers, as we can't rely on SP having been restored to its initial value, since we're not restoring it at all. FP-based CSR restore is novel and bound to find interesting divergence from all of our existing epilogues. In this case, at least the problem is pretty simple, and was even visible in one of the original test case: we were missing the statically-sized locals. I haven't gotten to the point of convincing myself this is sufficient yet, and I'm confident I'm missing some other convoluted PEI-ism, but with this we can actually successfully run a bunch of end-to-end swift tests! While there, add an assert that checks that the FP/LR frame record itself is only ever loaded from FP+0, without an offset. If there's an offset from FP, we must have goofed somewhere, since that breaks the frame record linked list. rdar://147838968
1 parent 384770e commit 8fc6907

File tree

2 files changed

+13
-6
lines changed

2 files changed

+13
-6
lines changed

llvm/lib/Target/AArch64/AArch64FrameLowering.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1578,7 +1578,7 @@ static MachineBasicBlock::iterator convertCalleeSaveRestoreToSPPrePostIncDec(
15781578
}
15791579

15801580
static void fixupCalleeSaveRestoreToFPBased(MachineInstr &MI,
1581-
uint64_t FPSPOffset) {
1581+
int64_t FPSPOffset) {
15821582
assert(!AArch64InstrInfo::isSEHInstruction(MI));
15831583

15841584
unsigned Opc = MI.getOpcode();
@@ -1615,7 +1615,13 @@ static void fixupCalleeSaveRestoreToFPBased(MachineInstr &MI,
16151615
MachineOperand &OffsetOpnd = MI.getOperand(OffsetIdx);
16161616
// All generated opcodes have scaled offsets.
16171617
assert(FPSPOffset % Scale == 0);
1618-
OffsetOpnd.setImm(OffsetOpnd.getImm() - FPSPOffset / Scale);
1618+
int64_t ResidualOffset = OffsetOpnd.getImm() - (FPSPOffset / Scale);
1619+
OffsetOpnd.setImm(ResidualOffset);
1620+
1621+
assert((!MI.getOperand(0).isReg() ||
1622+
MI.getOperand(0).getReg() != AArch64::FP || ResidualOffset == 0) &&
1623+
"FP/LR frame record should be restored from FP+0");
1624+
16191625
}
16201626

16211627
// Fixup callee-save register save/restore instructions to take into account
@@ -2550,8 +2556,9 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF,
25502556
fixupCalleeSaveRestoreStackOffset(*LastPopI, AFI->getLocalStackSize(),
25512557
NeedsWinCFI, &HasWinCFI);
25522558
// if FP-based addressing, rewrite CSR restores from SP to FP
2553-
fixupCalleeSaveRestoreToFPBased(
2554-
*LastPopI, AFI->getCalleeSaveBaseToFrameRecordOffset());
2559+
int64_t FPOffset = AFI->getCalleeSaveBaseToFrameRecordOffset() +
2560+
AFI->getLocalStackSize();
2561+
fixupCalleeSaveRestoreToFPBased(*LastPopI, FPOffset);
25552562
} else if (CombineSPBump)
25562563
fixupCalleeSaveRestoreStackOffset(*LastPopI, AFI->getLocalStackSize(),
25572564
NeedsWinCFI, &HasWinCFI);

llvm/test/CodeGen/AArch64/swiftcorocc-ret-popless.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ define swiftcorocc i64 @test_intrin() #0 {
4242
; CHECK-NEXT: cbz x0, LBB1_2
4343
; CHECK-NEXT: ; %bb.1: ; %else
4444
; CHECK-NEXT: add x16, x29, #16
45-
; CHECK-NEXT: ldp x26, x25, [x29] ; 16-byte Folded Reload
46-
; CHECK-NEXT: ldp x29, x30, [x29, #16] ; 16-byte Folded Reload
45+
; CHECK-NEXT: ldp x26, x25, [x29, #-16] ; 16-byte Folded Reload
46+
; CHECK-NEXT: ldp x29, x30, [x29] ; 16-byte Folded Reload
4747
; CHECK-NEXT: autib x30, x16
4848
; CHECK-NEXT: ret
4949
; CHECK-NEXT: LBB1_2: ; %then

0 commit comments

Comments
 (0)