Skip to content

Commit 67200f5

Browse files
committed
[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.
1 parent e080be5 commit 67200f5

File tree

5 files changed

+120
-55
lines changed

5 files changed

+120
-55
lines changed

llvm/lib/Target/ARM/ARMBaseRegisterInfo.cpp

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -62,27 +62,30 @@ ARMBaseRegisterInfo::ARMBaseRegisterInfo()
6262
const MCPhysReg*
6363
ARMBaseRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
6464
const ARMSubtarget &STI = MF->getSubtarget<ARMSubtarget>();
65-
bool UseSplitPush = STI.splitFramePushPop(*MF);
65+
ARMSubtarget::PushPopSplitVariation PushPopSplit =
66+
STI.getPushPopSplitVariation(*MF);
6667
const Function &F = MF->getFunction();
6768

6869
if (F.getCallingConv() == CallingConv::GHC) {
6970
// GHC set of callee saved regs is empty as all those regs are
7071
// used for passing STG regs around
7172
return CSR_NoRegs_SaveList;
72-
} else if (STI.splitFramePointerPush(*MF)) {
73+
} else if (PushPopSplit == ARMSubtarget::SplitR11WindowsSEH) {
7374
return CSR_Win_SplitFP_SaveList;
7475
} else if (F.getCallingConv() == CallingConv::CFGuard_Check) {
7576
return CSR_Win_AAPCS_CFGuard_Check_SaveList;
7677
} else if (F.getCallingConv() == CallingConv::SwiftTail) {
77-
return STI.isTargetDarwin()
78-
? CSR_iOS_SwiftTail_SaveList
79-
: (UseSplitPush ? CSR_ATPCS_SplitPush_SwiftTail_SaveList
80-
: CSR_AAPCS_SwiftTail_SaveList);
78+
return STI.isTargetDarwin() ? CSR_iOS_SwiftTail_SaveList
79+
: (PushPopSplit == ARMSubtarget::SplitR7
80+
? CSR_ATPCS_SplitPush_SwiftTail_SaveList
81+
: CSR_AAPCS_SwiftTail_SaveList);
8182
} else if (F.hasFnAttribute("interrupt")) {
8283
if (STI.isMClass()) {
8384
// M-class CPUs have hardware which saves the registers needed to allow a
8485
// function conforming to the AAPCS to function as a handler.
85-
return UseSplitPush ? CSR_ATPCS_SplitPush_SaveList : CSR_AAPCS_SaveList;
86+
return PushPopSplit == ARMSubtarget::SplitR7
87+
? CSR_ATPCS_SplitPush_SaveList
88+
: CSR_AAPCS_SaveList;
8689
} else if (F.getFnAttribute("interrupt").getValueAsString() == "FIQ") {
8790
// Fast interrupt mode gives the handler a private copy of R8-R14, so less
8891
// need to be saved to restore user-mode state.
@@ -99,8 +102,9 @@ ARMBaseRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
99102
if (STI.isTargetDarwin())
100103
return CSR_iOS_SwiftError_SaveList;
101104

102-
return UseSplitPush ? CSR_ATPCS_SplitPush_SwiftError_SaveList :
103-
CSR_AAPCS_SwiftError_SaveList;
105+
return PushPopSplit == ARMSubtarget::SplitR7
106+
? CSR_ATPCS_SplitPush_SwiftError_SaveList
107+
: CSR_AAPCS_SwiftError_SaveList;
104108
}
105109

106110
if (STI.isTargetDarwin() && F.getCallingConv() == CallingConv::CXX_FAST_TLS)
@@ -111,7 +115,7 @@ ARMBaseRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
111115
if (STI.isTargetDarwin())
112116
return CSR_iOS_SaveList;
113117

114-
if (UseSplitPush)
118+
if (PushPopSplit == ARMSubtarget::SplitR7)
115119
return STI.createAAPCSFrameChain() ? CSR_AAPCS_SplitPush_SaveList
116120
: CSR_ATPCS_SplitPush_SaveList;
117121

llvm/lib/Target/ARM/ARMFrameLowering.cpp

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -713,16 +713,17 @@ static void emitAligningInstructions(MachineFunction &MF, ARMFunctionInfo *AFI,
713713
/// this to produce a conservative estimate that we check in an assert() later.
714714
static int getMaxFPOffset(const ARMSubtarget &STI, const ARMFunctionInfo &AFI,
715715
const MachineFunction &MF) {
716+
ARMSubtarget::PushPopSplitVariation PushPopSplit =
717+
STI.getPushPopSplitVariation(MF);
716718
// For Thumb1, push.w isn't available, so the first push will always push
717719
// r7 and lr onto the stack first.
718720
if (AFI.isThumb1OnlyFunction())
719721
return -AFI.getArgRegsSaveSize() - (2 * 4);
720722
// This is a conservative estimation: Assume the frame pointer being r7 and
721723
// pc("r15") up to r8 getting spilled before (= 8 registers).
722724
int MaxRegBytes = 8 * 4;
723-
if (STI.splitFramePointerPush(MF)) {
724-
// Here, r11 can be stored below all of r4-r15 (3 registers more than
725-
// above), plus d8-d15.
725+
if (PushPopSplit == ARMSubtarget::SplitR11WindowsSEH) {
726+
// Here, r11 can be stored below all of r4-r15 plus d8-d15.
726727
MaxRegBytes = 11 * 4 + 8 * 8;
727728
}
728729
int FPCXTSaveSize =
@@ -749,6 +750,8 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
749750
const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
750751
int FPCXTSaveSize = 0;
751752
bool NeedsWinCFI = needsWinCFI(MF);
753+
ARMSubtarget::PushPopSplitVariation PushPopSplit =
754+
STI.getPushPopSplitVariation(MF);
752755

753756
// Debug location must be unknown since the first debug location is used
754757
// to determine the end of the prologue.
@@ -789,7 +792,7 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
789792
}
790793

791794
// Determine spill area sizes.
792-
if (STI.splitFramePointerPush(MF)) {
795+
if (PushPopSplit == ARMSubtarget::SplitR11WindowsSEH) {
793796
for (const CalleeSavedInfo &I : CSI) {
794797
Register Reg = I.getReg();
795798
int FI = I.getFrameIdx();
@@ -835,7 +838,7 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
835838
case ARM::R10:
836839
case ARM::R11:
837840
case ARM::R12:
838-
if (STI.splitFramePushPop(MF)) {
841+
if (PushPopSplit == ARMSubtarget::SplitR7) {
839842
GPRCS2Size += 4;
840843
break;
841844
}
@@ -898,13 +901,13 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
898901
unsigned GPRCS2Offset = GPRCS1Offset - GPRCS2Size;
899902
Align DPRAlign = DPRCSSize ? std::min(Align(8), Alignment) : Align(4);
900903
unsigned DPRGapSize = GPRCS1Size + FPCXTSaveSize + ArgRegsSaveSize;
901-
if (!STI.splitFramePointerPush(MF)) {
904+
if (PushPopSplit != ARMSubtarget::SplitR11WindowsSEH) {
902905
DPRGapSize += GPRCS2Size;
903906
}
904907
DPRGapSize %= DPRAlign.value();
905908

906909
unsigned DPRCSOffset;
907-
if (STI.splitFramePointerPush(MF)) {
910+
if (PushPopSplit == ARMSubtarget::SplitR11WindowsSEH) {
908911
DPRCSOffset = GPRCS1Offset - DPRGapSize - DPRCSSize;
909912
GPRCS2Offset = DPRCSOffset - GPRCS2Size;
910913
} else {
@@ -923,8 +926,9 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
923926
AFI->setGPRCalleeSavedArea2Offset(GPRCS2Offset);
924927
AFI->setDPRCalleeSavedAreaOffset(DPRCSOffset);
925928

926-
// Move past area 2.
927-
if (GPRCS2Size > 0 && !STI.splitFramePointerPush(MF)) {
929+
// Move GPRCS2, unless using SplitR11WindowsSEH, in which case it will be
930+
// after DPRCS1.
931+
if (GPRCS2Size > 0 && PushPopSplit != ARMSubtarget::SplitR11WindowsSEH) {
928932
GPRCS2Push = LastPush = MBBI++;
929933
DefCFAOffsetCandidates.addInst(LastPush, GPRCS2Size);
930934
}
@@ -943,7 +947,7 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
943947
}
944948
}
945949

946-
// Move past area 3.
950+
// Move past DPRCS1.
947951
if (DPRCSSize > 0) {
948952
// Since vpush register list cannot have gaps, there may be multiple vpush
949953
// instructions in the prologue.
@@ -964,13 +968,14 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
964968
} else
965969
NumBytes = DPRCSOffset;
966970

967-
if (GPRCS2Size > 0 && STI.splitFramePointerPush(MF)) {
971+
// Move GPRCS2, if using using SplitR11WindowsSEH.
972+
if (GPRCS2Size > 0 && PushPopSplit == ARMSubtarget::SplitR11WindowsSEH) {
968973
GPRCS2Push = LastPush = MBBI++;
969974
DefCFAOffsetCandidates.addInst(LastPush, GPRCS2Size);
970975
}
971976

972977
bool NeedsWinCFIStackAlloc = NeedsWinCFI;
973-
if (STI.splitFramePointerPush(MF) && HasFP)
978+
if (PushPopSplit == ARMSubtarget::SplitR11WindowsSEH && HasFP)
974979
NeedsWinCFIStackAlloc = false;
975980

976981
if (STI.isTargetWindows() && WindowsRequiresStackProbe(MF, NumBytes)) {
@@ -1075,7 +1080,7 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
10751080
AfterPush = std::next(GPRCS1Push);
10761081
unsigned PushSize = sizeOfSPAdjustment(*GPRCS1Push);
10771082
int FPOffset = PushSize + FramePtrOffsetInPush;
1078-
if (STI.splitFramePointerPush(MF)) {
1083+
if (PushPopSplit == ARMSubtarget::SplitR11WindowsSEH) {
10791084
AfterPush = std::next(GPRCS2Push);
10801085
emitRegPlusImmediate(!AFI->isThumbFunction(), MBB, AfterPush, dl, TII,
10811086
FramePtr, ARM::SP, 0, MachineInstr::FrameSetup);
@@ -1107,7 +1112,7 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
11071112
// instructions below don't need to be replayed to unwind the stack.
11081113
if (NeedsWinCFI && MBBI != MBB.begin()) {
11091114
MachineBasicBlock::iterator End = MBBI;
1110-
if (HasFP && STI.splitFramePointerPush(MF))
1115+
if (HasFP && PushPopSplit == ARMSubtarget::SplitR11WindowsSEH)
11111116
End = AfterPush;
11121117
insertSEHRange(MBB, {}, End, TII, MachineInstr::FrameSetup);
11131118
BuildMI(MBB, End, dl, TII.get(ARM::SEH_PrologEnd))
@@ -1130,7 +1135,7 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
11301135
case ARM::R10:
11311136
case ARM::R11:
11321137
case ARM::R12:
1133-
if (STI.splitFramePushPop(MF))
1138+
if (PushPopSplit == ARMSubtarget::SplitR7)
11341139
break;
11351140
[[fallthrough]];
11361141
case ARM::R0:
@@ -1163,7 +1168,7 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
11631168
case ARM::R10:
11641169
case ARM::R11:
11651170
case ARM::R12:
1166-
if (STI.splitFramePushPop(MF)) {
1171+
if (PushPopSplit == ARMSubtarget::SplitR7) {
11671172
unsigned DwarfReg = MRI->getDwarfRegNum(
11681173
Reg == ARM::R12 ? ARM::RA_AUTH_CODE : Reg, true);
11691174
int64_t Offset = MFI.getObjectOffset(FI);
@@ -1280,6 +1285,8 @@ void ARMFrameLowering::emitEpilogue(MachineFunction &MF,
12801285
assert(!AFI->isThumb1OnlyFunction() &&
12811286
"This emitEpilogue does not support Thumb1!");
12821287
bool isARM = !AFI->isThumbFunction();
1288+
ARMSubtarget::PushPopSplitVariation PushPopSplit =
1289+
STI.getPushPopSplitVariation(MF);
12831290

12841291
// Amount of stack space we reserved next to incoming args for either
12851292
// varargs registers or stack arguments in tail calls made by this function.
@@ -1383,7 +1390,8 @@ void ARMFrameLowering::emitEpilogue(MachineFunction &MF,
13831390
MachineInstr::FrameDestroy);
13841391

13851392
// Increment past our save areas.
1386-
if (AFI->getGPRCalleeSavedArea2Size() && STI.splitFramePointerPush(MF))
1393+
if (AFI->getGPRCalleeSavedArea2Size() &&
1394+
PushPopSplit == ARMSubtarget::SplitR11WindowsSEH)
13871395
MBBI++;
13881396

13891397
if (MBBI != MBB.end() && AFI->getDPRCalleeSavedAreaSize()) {
@@ -1400,7 +1408,8 @@ void ARMFrameLowering::emitEpilogue(MachineFunction &MF,
14001408
MachineInstr::FrameDestroy);
14011409
}
14021410

1403-
if (AFI->getGPRCalleeSavedArea2Size() && !STI.splitFramePointerPush(MF))
1411+
if (AFI->getGPRCalleeSavedArea2Size() &&
1412+
PushPopSplit != ARMSubtarget::SplitR11WindowsSEH)
14041413
MBBI++;
14051414
if (AFI->getGPRCalleeSavedArea1Size()) MBBI++;
14061415

@@ -1529,6 +1538,8 @@ void ARMFrameLowering::emitPushInst(MachineBasicBlock &MBB,
15291538
MachineFunction &MF = *MBB.getParent();
15301539
const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
15311540
const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
1541+
ARMSubtarget::PushPopSplitVariation PushPopSplit =
1542+
STI.getPushPopSplitVariation(MF);
15321543

15331544
DebugLoc DL;
15341545

@@ -1540,7 +1551,8 @@ void ARMFrameLowering::emitPushInst(MachineBasicBlock &MBB,
15401551
unsigned LastReg = 0;
15411552
for (; i != 0; --i) {
15421553
Register Reg = CSI[i-1].getReg();
1543-
if (!(Func)(Reg, STI.splitFramePushPop(MF))) continue;
1554+
if (!(Func)(Reg, PushPopSplit == ARMSubtarget::SplitR7))
1555+
continue;
15441556

15451557
// D-registers in the aligned area DPRCS2 are NOT spilled here.
15461558
if (Reg >= ARM::D8 && Reg < ARM::D8 + NumAlignedDPRCS2Regs)
@@ -1613,6 +1625,8 @@ void ARMFrameLowering::emitPopInst(MachineBasicBlock &MBB,
16131625
bool isInterrupt = false;
16141626
bool isTrap = false;
16151627
bool isCmseEntry = false;
1628+
ARMSubtarget::PushPopSplitVariation PushPopSplit =
1629+
STI.getPushPopSplitVariation(MF);
16161630
if (MBB.end() != MI) {
16171631
DL = MI->getDebugLoc();
16181632
unsigned RetOpcode = MI->getOpcode();
@@ -1635,15 +1649,16 @@ void ARMFrameLowering::emitPopInst(MachineBasicBlock &MBB,
16351649
for (; i != 0; --i) {
16361650
CalleeSavedInfo &Info = CSI[i-1];
16371651
Register Reg = Info.getReg();
1638-
if (!(Func)(Reg, STI.splitFramePushPop(MF))) continue;
1652+
if (!(Func)(Reg, PushPopSplit == ARMSubtarget::SplitR7))
1653+
continue;
16391654

16401655
// The aligned reloads from area DPRCS2 are not inserted here.
16411656
if (Reg >= ARM::D8 && Reg < ARM::D8 + NumAlignedDPRCS2Regs)
16421657
continue;
16431658
if (Reg == ARM::LR && !isTailCall && !isVarArg && !isInterrupt &&
16441659
!isCmseEntry && !isTrap && AFI->getArgumentStackToRestore() == 0 &&
16451660
STI.hasV5TOps() && MBB.succ_empty() && !hasPAC &&
1646-
!STI.splitFramePointerPush(MF)) {
1661+
PushPopSplit != ARMSubtarget::SplitR11WindowsSEH) {
16471662
Reg = ARM::PC;
16481663
// Fold the return instruction into the LDM.
16491664
DeleteRet = true;
@@ -1983,6 +1998,8 @@ bool ARMFrameLowering::spillCalleeSavedRegisters(
19831998

19841999
MachineFunction &MF = *MBB.getParent();
19852000
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
2001+
ARMSubtarget::PushPopSplitVariation PushPopSplit =
2002+
STI.getPushPopSplitVariation(MF);
19862003

19872004
unsigned PushOpc = AFI->isThumbFunction() ? ARM::t2STMDB_UPD : ARM::STMDB_UPD;
19882005
unsigned PushOneOpc = AFI->isThumbFunction() ?
@@ -2004,7 +2021,7 @@ bool ARMFrameLowering::spillCalleeSavedRegisters(
20042021
.addImm(-4)
20052022
.add(predOps(ARMCC::AL));
20062023
}
2007-
if (STI.splitFramePointerPush(MF)) {
2024+
if (PushPopSplit == ARMSubtarget::SplitR11WindowsSEH) {
20082025
emitPushInst(MBB, MI, CSI, PushOpc, PushOneOpc, false,
20092026
&isSplitFPArea1Register, 0, MachineInstr::FrameSetup);
20102027
emitPushInst(MBB, MI, CSI, FltOpc, 0, true, &isARMArea3Register,
@@ -2039,6 +2056,8 @@ bool ARMFrameLowering::restoreCalleeSavedRegisters(
20392056
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
20402057
bool isVarArg = AFI->getArgRegsSaveSize() > 0;
20412058
unsigned NumAlignedDPRCS2Regs = AFI->getNumAlignedDPRCS2Regs();
2059+
ARMSubtarget::PushPopSplitVariation PushPopSplit =
2060+
STI.getPushPopSplitVariation(MF);
20422061

20432062
// The emitPopInst calls below do not insert reloads for the aligned DPRCS2
20442063
// registers. Do that here instead.
@@ -2049,7 +2068,7 @@ bool ARMFrameLowering::restoreCalleeSavedRegisters(
20492068
unsigned LdrOpc =
20502069
AFI->isThumbFunction() ? ARM::t2LDR_POST : ARM::LDR_POST_IMM;
20512070
unsigned FltOpc = ARM::VLDMDIA_UPD;
2052-
if (STI.splitFramePointerPush(MF)) {
2071+
if (PushPopSplit == ARMSubtarget::SplitR11WindowsSEH) {
20532072
emitPopInst(MBB, MI, CSI, PopOpc, LdrOpc, isVarArg, false,
20542073
&isSplitFPArea2Register, 0);
20552074
emitPopInst(MBB, MI, CSI, FltOpc, 0, isVarArg, true, &isARMArea3Register,
@@ -2287,6 +2306,8 @@ void ARMFrameLowering::determineCalleeSaves(MachineFunction &MF,
22872306
const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
22882307
(void)TRI; // Silence unused warning in non-assert builds.
22892308
Register FramePtr = RegInfo->getFrameRegister(MF);
2309+
ARMSubtarget::PushPopSplitVariation PushPopSplit =
2310+
STI.getPushPopSplitVariation(MF);
22902311

22912312
// Spill R4 if Thumb2 function requires stack realignment - it will be used as
22922313
// scratch register. Also spill R4 if Thumb2 function has varsized objects,
@@ -2365,7 +2386,7 @@ void ARMFrameLowering::determineCalleeSaves(MachineFunction &MF,
23652386
if (Spilled) {
23662387
NumGPRSpills++;
23672388

2368-
if (!STI.splitFramePushPop(MF)) {
2389+
if (PushPopSplit != ARMSubtarget::SplitR7) {
23692390
if (Reg == ARM::LR)
23702391
LRSpilled = true;
23712392
CS1Spilled = true;
@@ -2387,7 +2408,7 @@ void ARMFrameLowering::determineCalleeSaves(MachineFunction &MF,
23872408
break;
23882409
}
23892410
} else {
2390-
if (!STI.splitFramePushPop(MF)) {
2411+
if (PushPopSplit != ARMSubtarget::SplitR7) {
23912412
UnspilledCS1GPRs.push_back(Reg);
23922413
continue;
23932414
}

llvm/lib/Target/ARM/ARMSubtarget.cpp

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -485,11 +485,34 @@ bool ARMSubtarget::ignoreCSRForAllocationOrder(const MachineFunction &MF,
485485
ARM::GPRRegClass.contains(PhysReg);
486486
}
487487

488-
bool ARMSubtarget::splitFramePointerPush(const MachineFunction &MF) const {
488+
ARMSubtarget::PushPopSplitVariation
489+
ARMSubtarget::getPushPopSplitVariation(const MachineFunction &MF) const {
489490
const Function &F = MF.getFunction();
490-
if (!MF.getTarget().getMCAsmInfo()->usesWindowsCFI() ||
491-
!F.needsUnwindTableEntry())
492-
return false;
493491
const MachineFrameInfo &MFI = MF.getFrameInfo();
494-
return MFI.hasVarSizedObjects() || getRegisterInfo()->hasStackRealignment(MF);
492+
const std::vector<CalleeSavedInfo> CSI =
493+
MF.getFrameInfo().getCalleeSavedInfo();
494+
495+
// Returns SplitR7 if the frame setup must be split into two separate pushes
496+
// of r0-r7,lr and another containing r8-r11 (+r12 if necessary). This is
497+
// always required on Thumb1-only targets, as the push and pop instructions
498+
// can't access the high registers. This is also required when R7 is the frame
499+
// pointer and frame pointer elimiination is disabled, or branch signing is
500+
// enabled and AAPCS is disabled.
501+
if ((MF.getInfo<ARMFunctionInfo>()->shouldSignReturnAddress() &&
502+
!createAAPCSFrameChain()) ||
503+
(getFramePointerReg() == ARM::R7 &&
504+
MF.getTarget().Options.DisableFramePointerElim(MF)) ||
505+
isThumb1Only())
506+
return SplitR7;
507+
508+
// Returns SplitR11WindowsSEH when the stack pointer needs to be
509+
// restored from the frame pointer r11 + an offset and Windows CFI is enabled.
510+
// This stack unwinding cannot be expressed with SEH unwind opcodes when done
511+
// with a single push, making it necessary to split the push into r4-r10, and
512+
// another containing r11+lr.
513+
if (MF.getTarget().getMCAsmInfo()->usesWindowsCFI() &&
514+
F.needsUnwindTableEntry() &&
515+
(MFI.hasVarSizedObjects() || getRegisterInfo()->hasStackRealignment(MF)))
516+
return SplitR11WindowsSEH;
517+
return NoSplit;
495518
}

0 commit comments

Comments
 (0)