Index: llvm/lib/Target/AArch64/AArch64FrameLowering.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64FrameLowering.cpp +++ llvm/lib/Target/AArch64/AArch64FrameLowering.cpp @@ -1019,7 +1019,8 @@ if (HasFP) { // Only set up FP if we actually need to. - int FPOffset = isTargetDarwin(MF) ? (AFI->getCalleeSavedStackSize() - 16) : 0; + int FPOffset = isTargetDarwin(MF) ? (AFI->getCalleeSavedStackSize() - 16) + : AFI->getFrameRecordOffset(); if (CombineSPBump) FPOffset += AFI->getLocalStackSize(); @@ -1615,7 +1616,8 @@ // be able to save any instructions. if (!IsFunclet && (MFI.hasVarSizedObjects() || AFI->isStackRealigned())) { int64_t OffsetToFrameRecord = - isTargetDarwin(MF) ? (-(int64_t)AFI->getCalleeSavedStackSize() + 16) : 0; + isTargetDarwin(MF) ? (-(int64_t)AFI->getCalleeSavedStackSize() + 16) + : -AFI->getFrameRecordOffset();; emitFrameOffset(MBB, LastPopI, DL, AArch64::SP, AArch64::FP, {OffsetToFrameRecord, MVT::i8}, TII, MachineInstr::FrameDestroy, false, NeedsWinCFI); @@ -2282,6 +2284,13 @@ std::swap(Reg1, Reg2); std::swap(FrameIdxReg1, FrameIdxReg2); } + if (RPI.Type == RegPairInfo::GPR) { + AArch64FunctionInfo *AFI = MF.getInfo(); + if (Reg1 == AArch64::FP) + AFI->setFrameRecordOffset((RPI.Offset + 1) * Size); + if (RPI.isPaired() && Reg2 == AArch64::FP) + AFI->setFrameRecordOffset(RPI.Offset * Size); + } MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, TII.get(LdrOpc)); if (RPI.isPaired()) { MIB.addReg(Reg2, getDefRegState(true)); Index: llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h =================================================================== --- llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h +++ llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h @@ -126,6 +126,10 @@ // stack slot. unsigned TaggedBasePointerOffset = 0; + // Offset from SP-at-entry to frame record (i.e. the spilled frame pointer + // and link address). + int FrameRecordOffset = 0; + public: AArch64FunctionInfo() = default; @@ -325,6 +329,13 @@ TaggedBasePointerOffset = Offset; } + int getFrameRecordOffset() const { + return FrameRecordOffset; + } + void setFrameRecordOffset(int Offset) { + FrameRecordOffset = Offset; + } + private: // Hold the lists of LOHs. MILOHContainer LOHContainerSet; Index: llvm/test/CodeGen/AArch64/framelayout-frame-record.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/framelayout-frame-record.ll @@ -0,0 +1,19 @@ +; RUN: llc < %s -mtriple=aarch64--linux-gnu | FileCheck %s + +target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" +target triple = "aarch64--linux-gnu" + +declare void @escape.i64(i64) +declare void @escape.double(double) + +define void @test_frame_record_offset(i64 %a, i64 %b, double %c, double %d) "no-frame-pointer-elim"="true" { +; CHECK-LABEL: test_frame_record_offset: +; CHECK: stp x29, x30, [sp, #[[OFFSET:[0-9]+]]] +; CHECK: add x29, sp, #[[OFFSET]] + + call void @escape.i64(i64 %a) + call void @escape.i64(i64 %b) + call void @escape.double(double %c) + call void @escape.double(double %d) + ret void +}