[llvm] 67200f5 - [ARM] Tidy up stack frame strategy code (NFC) (#110283)
Oliver Stannard via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 9 01:29:36 PDT 2024
Author: Oliver Stannard
Date: 2024-10-09T09:29:27+01:00
New Revision: 67200f5dc8a662edd05928f97940c2fcabf42043
URL: https://github.com/llvm/llvm-project/commit/67200f5dc8a662edd05928f97940c2fcabf42043
DIFF: https://github.com/llvm/llvm-project/commit/67200f5dc8a662edd05928f97940c2fcabf42043.diff
LOG: [ARM] Tidy up stack frame strategy code (NFC) (#110283)
We have two different ways of splitting the pushes of callee-saved
registers onto the stack, controlled by the confusingly similar names
STI.splitFramePushPop() and STI.splitFramePointerPush(). This removes
those functions and replaces them with a single function which returns
an enum. This is in preparation for adding another value to that enum.
The original work of this patch was done by James Westwood, reviewed as
#82801 and #81249, with some tidy-ups done by Mark Murray and myself.
Added:
Modified:
llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp
llvm/lib/Target/ARM/ARMFrameLowering.cpp
llvm/lib/Target/ARM/ARMSubtarget.cpp
llvm/lib/Target/ARM/ARMSubtarget.h
llvm/lib/Target/ARM/Thumb1FrameLowering.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp
index c149db3144c7c2..3f28ce8ca4b559 100644
--- a/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp
+++ b/llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp
@@ -62,27 +62,30 @@ ARMBaseRegisterInfo::ARMBaseRegisterInfo()
const MCPhysReg*
ARMBaseRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
const ARMSubtarget &STI = MF->getSubtarget<ARMSubtarget>();
- bool UseSplitPush = STI.splitFramePushPop(*MF);
+ ARMSubtarget::PushPopSplitVariation PushPopSplit =
+ STI.getPushPopSplitVariation(*MF);
const Function &F = MF->getFunction();
if (F.getCallingConv() == CallingConv::GHC) {
// GHC set of callee saved regs is empty as all those regs are
// used for passing STG regs around
return CSR_NoRegs_SaveList;
- } else if (STI.splitFramePointerPush(*MF)) {
+ } else if (PushPopSplit == ARMSubtarget::SplitR11WindowsSEH) {
return CSR_Win_SplitFP_SaveList;
} else if (F.getCallingConv() == CallingConv::CFGuard_Check) {
return CSR_Win_AAPCS_CFGuard_Check_SaveList;
} else if (F.getCallingConv() == CallingConv::SwiftTail) {
- return STI.isTargetDarwin()
- ? CSR_iOS_SwiftTail_SaveList
- : (UseSplitPush ? CSR_ATPCS_SplitPush_SwiftTail_SaveList
- : CSR_AAPCS_SwiftTail_SaveList);
+ return STI.isTargetDarwin() ? CSR_iOS_SwiftTail_SaveList
+ : (PushPopSplit == ARMSubtarget::SplitR7
+ ? CSR_ATPCS_SplitPush_SwiftTail_SaveList
+ : CSR_AAPCS_SwiftTail_SaveList);
} else if (F.hasFnAttribute("interrupt")) {
if (STI.isMClass()) {
// M-class CPUs have hardware which saves the registers needed to allow a
// function conforming to the AAPCS to function as a handler.
- return UseSplitPush ? CSR_ATPCS_SplitPush_SaveList : CSR_AAPCS_SaveList;
+ return PushPopSplit == ARMSubtarget::SplitR7
+ ? CSR_ATPCS_SplitPush_SaveList
+ : CSR_AAPCS_SaveList;
} else if (F.getFnAttribute("interrupt").getValueAsString() == "FIQ") {
// Fast interrupt mode gives the handler a private copy of R8-R14, so less
// need to be saved to restore user-mode state.
@@ -99,8 +102,9 @@ ARMBaseRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
if (STI.isTargetDarwin())
return CSR_iOS_SwiftError_SaveList;
- return UseSplitPush ? CSR_ATPCS_SplitPush_SwiftError_SaveList :
- CSR_AAPCS_SwiftError_SaveList;
+ return PushPopSplit == ARMSubtarget::SplitR7
+ ? CSR_ATPCS_SplitPush_SwiftError_SaveList
+ : CSR_AAPCS_SwiftError_SaveList;
}
if (STI.isTargetDarwin() && F.getCallingConv() == CallingConv::CXX_FAST_TLS)
@@ -111,7 +115,7 @@ ARMBaseRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
if (STI.isTargetDarwin())
return CSR_iOS_SaveList;
- if (UseSplitPush)
+ if (PushPopSplit == ARMSubtarget::SplitR7)
return STI.createAAPCSFrameChain() ? CSR_AAPCS_SplitPush_SaveList
: CSR_ATPCS_SplitPush_SaveList;
diff --git a/llvm/lib/Target/ARM/ARMFrameLowering.cpp b/llvm/lib/Target/ARM/ARMFrameLowering.cpp
index 40354f99559896..900672f477e8e0 100644
--- a/llvm/lib/Target/ARM/ARMFrameLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMFrameLowering.cpp
@@ -713,6 +713,8 @@ static void emitAligningInstructions(MachineFunction &MF, ARMFunctionInfo *AFI,
/// this to produce a conservative estimate that we check in an assert() later.
static int getMaxFPOffset(const ARMSubtarget &STI, const ARMFunctionInfo &AFI,
const MachineFunction &MF) {
+ ARMSubtarget::PushPopSplitVariation PushPopSplit =
+ STI.getPushPopSplitVariation(MF);
// For Thumb1, push.w isn't available, so the first push will always push
// r7 and lr onto the stack first.
if (AFI.isThumb1OnlyFunction())
@@ -720,9 +722,8 @@ static int getMaxFPOffset(const ARMSubtarget &STI, const ARMFunctionInfo &AFI,
// This is a conservative estimation: Assume the frame pointer being r7 and
// pc("r15") up to r8 getting spilled before (= 8 registers).
int MaxRegBytes = 8 * 4;
- if (STI.splitFramePointerPush(MF)) {
- // Here, r11 can be stored below all of r4-r15 (3 registers more than
- // above), plus d8-d15.
+ if (PushPopSplit == ARMSubtarget::SplitR11WindowsSEH) {
+ // Here, r11 can be stored below all of r4-r15 plus d8-d15.
MaxRegBytes = 11 * 4 + 8 * 8;
}
int FPCXTSaveSize =
@@ -749,6 +750,8 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
int FPCXTSaveSize = 0;
bool NeedsWinCFI = needsWinCFI(MF);
+ ARMSubtarget::PushPopSplitVariation PushPopSplit =
+ STI.getPushPopSplitVariation(MF);
// Debug location must be unknown since the first debug location is used
// to determine the end of the prologue.
@@ -789,7 +792,7 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
}
// Determine spill area sizes.
- if (STI.splitFramePointerPush(MF)) {
+ if (PushPopSplit == ARMSubtarget::SplitR11WindowsSEH) {
for (const CalleeSavedInfo &I : CSI) {
Register Reg = I.getReg();
int FI = I.getFrameIdx();
@@ -835,7 +838,7 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
case ARM::R10:
case ARM::R11:
case ARM::R12:
- if (STI.splitFramePushPop(MF)) {
+ if (PushPopSplit == ARMSubtarget::SplitR7) {
GPRCS2Size += 4;
break;
}
@@ -898,13 +901,13 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
unsigned GPRCS2Offset = GPRCS1Offset - GPRCS2Size;
Align DPRAlign = DPRCSSize ? std::min(Align(8), Alignment) : Align(4);
unsigned DPRGapSize = GPRCS1Size + FPCXTSaveSize + ArgRegsSaveSize;
- if (!STI.splitFramePointerPush(MF)) {
+ if (PushPopSplit != ARMSubtarget::SplitR11WindowsSEH) {
DPRGapSize += GPRCS2Size;
}
DPRGapSize %= DPRAlign.value();
unsigned DPRCSOffset;
- if (STI.splitFramePointerPush(MF)) {
+ if (PushPopSplit == ARMSubtarget::SplitR11WindowsSEH) {
DPRCSOffset = GPRCS1Offset - DPRGapSize - DPRCSSize;
GPRCS2Offset = DPRCSOffset - GPRCS2Size;
} else {
@@ -923,8 +926,9 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
AFI->setGPRCalleeSavedArea2Offset(GPRCS2Offset);
AFI->setDPRCalleeSavedAreaOffset(DPRCSOffset);
- // Move past area 2.
- if (GPRCS2Size > 0 && !STI.splitFramePointerPush(MF)) {
+ // Move GPRCS2, unless using SplitR11WindowsSEH, in which case it will be
+ // after DPRCS1.
+ if (GPRCS2Size > 0 && PushPopSplit != ARMSubtarget::SplitR11WindowsSEH) {
GPRCS2Push = LastPush = MBBI++;
DefCFAOffsetCandidates.addInst(LastPush, GPRCS2Size);
}
@@ -943,7 +947,7 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
}
}
- // Move past area 3.
+ // Move past DPRCS1.
if (DPRCSSize > 0) {
// Since vpush register list cannot have gaps, there may be multiple vpush
// instructions in the prologue.
@@ -964,13 +968,14 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
} else
NumBytes = DPRCSOffset;
- if (GPRCS2Size > 0 && STI.splitFramePointerPush(MF)) {
+ // Move GPRCS2, if using using SplitR11WindowsSEH.
+ if (GPRCS2Size > 0 && PushPopSplit == ARMSubtarget::SplitR11WindowsSEH) {
GPRCS2Push = LastPush = MBBI++;
DefCFAOffsetCandidates.addInst(LastPush, GPRCS2Size);
}
bool NeedsWinCFIStackAlloc = NeedsWinCFI;
- if (STI.splitFramePointerPush(MF) && HasFP)
+ if (PushPopSplit == ARMSubtarget::SplitR11WindowsSEH && HasFP)
NeedsWinCFIStackAlloc = false;
if (STI.isTargetWindows() && WindowsRequiresStackProbe(MF, NumBytes)) {
@@ -1075,7 +1080,7 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
AfterPush = std::next(GPRCS1Push);
unsigned PushSize = sizeOfSPAdjustment(*GPRCS1Push);
int FPOffset = PushSize + FramePtrOffsetInPush;
- if (STI.splitFramePointerPush(MF)) {
+ if (PushPopSplit == ARMSubtarget::SplitR11WindowsSEH) {
AfterPush = std::next(GPRCS2Push);
emitRegPlusImmediate(!AFI->isThumbFunction(), MBB, AfterPush, dl, TII,
FramePtr, ARM::SP, 0, MachineInstr::FrameSetup);
@@ -1107,7 +1112,7 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
// instructions below don't need to be replayed to unwind the stack.
if (NeedsWinCFI && MBBI != MBB.begin()) {
MachineBasicBlock::iterator End = MBBI;
- if (HasFP && STI.splitFramePointerPush(MF))
+ if (HasFP && PushPopSplit == ARMSubtarget::SplitR11WindowsSEH)
End = AfterPush;
insertSEHRange(MBB, {}, End, TII, MachineInstr::FrameSetup);
BuildMI(MBB, End, dl, TII.get(ARM::SEH_PrologEnd))
@@ -1130,7 +1135,7 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
case ARM::R10:
case ARM::R11:
case ARM::R12:
- if (STI.splitFramePushPop(MF))
+ if (PushPopSplit == ARMSubtarget::SplitR7)
break;
[[fallthrough]];
case ARM::R0:
@@ -1163,7 +1168,7 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
case ARM::R10:
case ARM::R11:
case ARM::R12:
- if (STI.splitFramePushPop(MF)) {
+ if (PushPopSplit == ARMSubtarget::SplitR7) {
unsigned DwarfReg = MRI->getDwarfRegNum(
Reg == ARM::R12 ? ARM::RA_AUTH_CODE : Reg, true);
int64_t Offset = MFI.getObjectOffset(FI);
@@ -1280,6 +1285,8 @@ void ARMFrameLowering::emitEpilogue(MachineFunction &MF,
assert(!AFI->isThumb1OnlyFunction() &&
"This emitEpilogue does not support Thumb1!");
bool isARM = !AFI->isThumbFunction();
+ ARMSubtarget::PushPopSplitVariation PushPopSplit =
+ STI.getPushPopSplitVariation(MF);
// Amount of stack space we reserved next to incoming args for either
// varargs registers or stack arguments in tail calls made by this function.
@@ -1383,7 +1390,8 @@ void ARMFrameLowering::emitEpilogue(MachineFunction &MF,
MachineInstr::FrameDestroy);
// Increment past our save areas.
- if (AFI->getGPRCalleeSavedArea2Size() && STI.splitFramePointerPush(MF))
+ if (AFI->getGPRCalleeSavedArea2Size() &&
+ PushPopSplit == ARMSubtarget::SplitR11WindowsSEH)
MBBI++;
if (MBBI != MBB.end() && AFI->getDPRCalleeSavedAreaSize()) {
@@ -1400,7 +1408,8 @@ void ARMFrameLowering::emitEpilogue(MachineFunction &MF,
MachineInstr::FrameDestroy);
}
- if (AFI->getGPRCalleeSavedArea2Size() && !STI.splitFramePointerPush(MF))
+ if (AFI->getGPRCalleeSavedArea2Size() &&
+ PushPopSplit != ARMSubtarget::SplitR11WindowsSEH)
MBBI++;
if (AFI->getGPRCalleeSavedArea1Size()) MBBI++;
@@ -1529,6 +1538,8 @@ void ARMFrameLowering::emitPushInst(MachineBasicBlock &MBB,
MachineFunction &MF = *MBB.getParent();
const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
+ ARMSubtarget::PushPopSplitVariation PushPopSplit =
+ STI.getPushPopSplitVariation(MF);
DebugLoc DL;
@@ -1540,7 +1551,8 @@ void ARMFrameLowering::emitPushInst(MachineBasicBlock &MBB,
unsigned LastReg = 0;
for (; i != 0; --i) {
Register Reg = CSI[i-1].getReg();
- if (!(Func)(Reg, STI.splitFramePushPop(MF))) continue;
+ if (!(Func)(Reg, PushPopSplit == ARMSubtarget::SplitR7))
+ continue;
// D-registers in the aligned area DPRCS2 are NOT spilled here.
if (Reg >= ARM::D8 && Reg < ARM::D8 + NumAlignedDPRCS2Regs)
@@ -1613,6 +1625,8 @@ void ARMFrameLowering::emitPopInst(MachineBasicBlock &MBB,
bool isInterrupt = false;
bool isTrap = false;
bool isCmseEntry = false;
+ ARMSubtarget::PushPopSplitVariation PushPopSplit =
+ STI.getPushPopSplitVariation(MF);
if (MBB.end() != MI) {
DL = MI->getDebugLoc();
unsigned RetOpcode = MI->getOpcode();
@@ -1635,7 +1649,8 @@ void ARMFrameLowering::emitPopInst(MachineBasicBlock &MBB,
for (; i != 0; --i) {
CalleeSavedInfo &Info = CSI[i-1];
Register Reg = Info.getReg();
- if (!(Func)(Reg, STI.splitFramePushPop(MF))) continue;
+ if (!(Func)(Reg, PushPopSplit == ARMSubtarget::SplitR7))
+ continue;
// The aligned reloads from area DPRCS2 are not inserted here.
if (Reg >= ARM::D8 && Reg < ARM::D8 + NumAlignedDPRCS2Regs)
@@ -1643,7 +1658,7 @@ void ARMFrameLowering::emitPopInst(MachineBasicBlock &MBB,
if (Reg == ARM::LR && !isTailCall && !isVarArg && !isInterrupt &&
!isCmseEntry && !isTrap && AFI->getArgumentStackToRestore() == 0 &&
STI.hasV5TOps() && MBB.succ_empty() && !hasPAC &&
- !STI.splitFramePointerPush(MF)) {
+ PushPopSplit != ARMSubtarget::SplitR11WindowsSEH) {
Reg = ARM::PC;
// Fold the return instruction into the LDM.
DeleteRet = true;
@@ -1983,6 +1998,8 @@ bool ARMFrameLowering::spillCalleeSavedRegisters(
MachineFunction &MF = *MBB.getParent();
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
+ ARMSubtarget::PushPopSplitVariation PushPopSplit =
+ STI.getPushPopSplitVariation(MF);
unsigned PushOpc = AFI->isThumbFunction() ? ARM::t2STMDB_UPD : ARM::STMDB_UPD;
unsigned PushOneOpc = AFI->isThumbFunction() ?
@@ -2004,7 +2021,7 @@ bool ARMFrameLowering::spillCalleeSavedRegisters(
.addImm(-4)
.add(predOps(ARMCC::AL));
}
- if (STI.splitFramePointerPush(MF)) {
+ if (PushPopSplit == ARMSubtarget::SplitR11WindowsSEH) {
emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false,
&isSplitFPArea1Register, 0, MachineInstr::FrameSetup);
emitPushInst(MBB, MI, CSI, FltOpc, 0, true, &isARMArea3Register,
@@ -2039,6 +2056,8 @@ bool ARMFrameLowering::restoreCalleeSavedRegisters(
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
bool isVarArg = AFI->getArgRegsSaveSize() > 0;
unsigned NumAlignedDPRCS2Regs = AFI->getNumAlignedDPRCS2Regs();
+ ARMSubtarget::PushPopSplitVariation PushPopSplit =
+ STI.getPushPopSplitVariation(MF);
// The emitPopInst calls below do not insert reloads for the aligned DPRCS2
// registers. Do that here instead.
@@ -2049,7 +2068,7 @@ bool ARMFrameLowering::restoreCalleeSavedRegisters(
unsigned LdrOpc =
AFI->isThumbFunction() ? ARM::t2LDR_POST : ARM::LDR_POST_IMM;
unsigned FltOpc = ARM::VLDMDIA_UPD;
- if (STI.splitFramePointerPush(MF)) {
+ if (PushPopSplit == ARMSubtarget::SplitR11WindowsSEH) {
emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg, false,
&isSplitFPArea2Register, 0);
emitPopInst(MBB, MI, CSI, FltOpc, 0, isVarArg, true, &isARMArea3Register,
@@ -2287,6 +2306,8 @@ void ARMFrameLowering::determineCalleeSaves(MachineFunction &MF,
const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
(void)TRI; // Silence unused warning in non-assert builds.
Register FramePtr = RegInfo->getFrameRegister(MF);
+ ARMSubtarget::PushPopSplitVariation PushPopSplit =
+ STI.getPushPopSplitVariation(MF);
// Spill R4 if Thumb2 function requires stack realignment - it will be used as
// scratch register. Also spill R4 if Thumb2 function has varsized objects,
@@ -2365,7 +2386,7 @@ void ARMFrameLowering::determineCalleeSaves(MachineFunction &MF,
if (Spilled) {
NumGPRSpills++;
- if (!STI.splitFramePushPop(MF)) {
+ if (PushPopSplit != ARMSubtarget::SplitR7) {
if (Reg == ARM::LR)
LRSpilled = true;
CS1Spilled = true;
@@ -2387,7 +2408,7 @@ void ARMFrameLowering::determineCalleeSaves(MachineFunction &MF,
break;
}
} else {
- if (!STI.splitFramePushPop(MF)) {
+ if (PushPopSplit != ARMSubtarget::SplitR7) {
UnspilledCS1GPRs.push_back(Reg);
continue;
}
diff --git a/llvm/lib/Target/ARM/ARMSubtarget.cpp b/llvm/lib/Target/ARM/ARMSubtarget.cpp
index f9d822873bb004..c4a782bc40910a 100644
--- a/llvm/lib/Target/ARM/ARMSubtarget.cpp
+++ b/llvm/lib/Target/ARM/ARMSubtarget.cpp
@@ -485,11 +485,34 @@ bool ARMSubtarget::ignoreCSRForAllocationOrder(const MachineFunction &MF,
ARM::GPRRegClass.contains(PhysReg);
}
-bool ARMSubtarget::splitFramePointerPush(const MachineFunction &MF) const {
+ARMSubtarget::PushPopSplitVariation
+ARMSubtarget::getPushPopSplitVariation(const MachineFunction &MF) const {
const Function &F = MF.getFunction();
- if (!MF.getTarget().getMCAsmInfo()->usesWindowsCFI() ||
- !F.needsUnwindTableEntry())
- return false;
const MachineFrameInfo &MFI = MF.getFrameInfo();
- return MFI.hasVarSizedObjects() || getRegisterInfo()->hasStackRealignment(MF);
+ const std::vector<CalleeSavedInfo> CSI =
+ MF.getFrameInfo().getCalleeSavedInfo();
+
+ // Returns SplitR7 if the frame setup must be split into two separate pushes
+ // of r0-r7,lr and another containing r8-r11 (+r12 if necessary). This is
+ // always required on Thumb1-only targets, as the push and pop instructions
+ // can't access the high registers. This is also required when R7 is the frame
+ // pointer and frame pointer elimiination is disabled, or branch signing is
+ // enabled and AAPCS is disabled.
+ if ((MF.getInfo<ARMFunctionInfo>()->shouldSignReturnAddress() &&
+ !createAAPCSFrameChain()) ||
+ (getFramePointerReg() == ARM::R7 &&
+ MF.getTarget().Options.DisableFramePointerElim(MF)) ||
+ isThumb1Only())
+ return SplitR7;
+
+ // Returns SplitR11WindowsSEH when the stack pointer needs to be
+ // restored from the frame pointer r11 + an offset and Windows CFI is enabled.
+ // This stack unwinding cannot be expressed with SEH unwind opcodes when done
+ // with a single push, making it necessary to split the push into r4-r10, and
+ // another containing r11+lr.
+ if (MF.getTarget().getMCAsmInfo()->usesWindowsCFI() &&
+ F.needsUnwindTableEntry() &&
+ (MFI.hasVarSizedObjects() || getRegisterInfo()->hasStackRealignment(MF)))
+ return SplitR11WindowsSEH;
+ return NoSplit;
}
diff --git a/llvm/lib/Target/ARM/ARMSubtarget.h b/llvm/lib/Target/ARM/ARMSubtarget.h
index 1ca5bd4a620c4c..e68e7833327116 100644
--- a/llvm/lib/Target/ARM/ARMSubtarget.h
+++ b/llvm/lib/Target/ARM/ARMSubtarget.h
@@ -81,6 +81,32 @@ class ARMSubtarget : public ARMGenSubtargetInfo {
SingleIssuePlusExtras,
};
+ /// How the push and pop instructions of callee saved general-purpose
+ /// registers should be split.
+ enum PushPopSplitVariation {
+ /// All GPRs can be pushed in a single instruction.
+ /// push {r0-r12, lr}
+ /// vpush {d8-d15}
+ NoSplit,
+
+ /// R7 and LR must be adjacent, because R7 is the frame pointer, and must
+ /// point to a frame record consisting of the previous frame pointer and the
+ /// return address.
+ /// push {r0-r7, lr}
+ /// push {r8-r12}
+ /// vpush {d8-d15}
+ SplitR7,
+
+ /// When the stack frame size is not known (because of variable-sized
+ /// objects or realignment), Windows SEH requires the callee-saved registers
+ /// to be stored in three regions, with R11 and LR below the floating-point
+ /// registers.
+ /// push {r0-r10, r12}
+ /// vpush {d8-d15}
+ /// push {r11, lr}
+ SplitR11WindowsSEH,
+ };
+
protected:
// Bool members corresponding to the SubtargetFeatures defined in tablegen
#define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \
@@ -371,19 +397,8 @@ class ARMSubtarget : public ARMGenSubtargetInfo {
return ARM::R11;
}
- /// Returns true if the frame setup is split into two separate pushes (first
- /// r0-r7,lr then r8-r11), principally so that the frame pointer is adjacent
- /// to lr. This is always required on Thumb1-only targets, as the push and
- /// pop instructions can't access the high registers.
- bool splitFramePushPop(const MachineFunction &MF) const {
- if (MF.getInfo<ARMFunctionInfo>()->shouldSignReturnAddress())
- return true;
- return (getFramePointerReg() == ARM::R7 &&
- MF.getTarget().Options.DisableFramePointerElim(MF)) ||
- isThumb1Only();
- }
-
- bool splitFramePointerPush(const MachineFunction &MF) const;
+ enum PushPopSplitVariation
+ getPushPopSplitVariation(const MachineFunction &MF) const;
bool useStride4VFPs() const;
diff --git a/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp b/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp
index cb9ded7dee57b9..4fbf378417bca6 100644
--- a/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp
+++ b/llvm/lib/Target/ARM/Thumb1FrameLowering.cpp
@@ -160,6 +160,8 @@ void Thumb1FrameLowering::emitPrologue(MachineFunction &MF,
assert(NumBytes >= ArgRegsSaveSize &&
"ArgRegsSaveSize is included in NumBytes");
const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
+ ARMSubtarget::PushPopSplitVariation PushPopSplit =
+ STI.getPushPopSplitVariation(MF);
// Debug location must be unknown since the first debug location is used
// to determine the end of the prologue.
@@ -221,7 +223,7 @@ void Thumb1FrameLowering::emitPrologue(MachineFunction &MF,
case ARM::R8:
case ARM::R9:
case ARM::R10:
- if (STI.splitFramePushPop(MF)) {
+ if (PushPopSplit == ARMSubtarget::SplitR7) {
GPRCS2Size += 4;
break;
}
@@ -365,7 +367,7 @@ void Thumb1FrameLowering::emitPrologue(MachineFunction &MF,
case ARM::R10:
case ARM::R11:
case ARM::R12:
- if (STI.splitFramePushPop(MF))
+ if (PushPopSplit == ARMSubtarget::SplitR7)
break;
[[fallthrough]];
case ARM::R0:
More information about the llvm-commits
mailing list