Skip to content

Commit 02f008a

Browse files
committed
[ARM] Tidy up stack frame strategy code (NFC)
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 llvm#82801 and llvm#81249, with some tidy-ups done by Mark Murray and myself.
1 parent 8dd817b commit 02f008a

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)