Skip to content

Commit 2ecf2e2

Browse files
committed
[ARM] Factor out code to determine spill areas (NFC) (#110283)
There were multiple loops in ARMFrameLowering which sort the callee saved registers into spill areas, which were hard to understand and modify. This splits the information about which register is in which save area into a separate function.
1 parent 67200f5 commit 2ecf2e2

File tree

1 file changed

+183
-144
lines changed

1 file changed

+183
-144
lines changed

llvm/lib/Target/ARM/ARMFrameLowering.cpp

Lines changed: 183 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,127 @@ static MachineBasicBlock::iterator
173173
skipAlignedDPRCS2Spills(MachineBasicBlock::iterator MI,
174174
unsigned NumAlignedDPRCS2Regs);
175175

176+
enum class SpillArea {
177+
GPRCS1,
178+
GPRCS2,
179+
DPRCS1,
180+
DPRCS2,
181+
FPCXT,
182+
};
183+
184+
/// Get the spill area that Reg should be saved into in the prologue.
185+
SpillArea getSpillArea(Register Reg,
186+
ARMSubtarget::PushPopSplitVariation Variation,
187+
unsigned NumAlignedDPRCS2Regs,
188+
const ARMBaseRegisterInfo *RegInfo) {
189+
// NoSplit:
190+
// push {r0-r12, lr} GPRCS1
191+
// vpush {r8-d15} DPRCS1
192+
//
193+
// SplitR7:
194+
// push {r0-r7, lr} GPRCS1
195+
// push {r8-r12} GPRCS2
196+
// vpush {r8-d15} DPRCS1
197+
//
198+
// SplitR11WindowsSEH:
199+
// push {r0-r10, r12} GPRCS1
200+
// vpush {r8-d15} DPRCS1
201+
// push {r11, lr} GPRCS2
202+
203+
// If FPCXTNS is spilled (for CMSE secure entryfunctions), it is always at
204+
// the top of the stack frame.
205+
// The DPRCS2 region is used for ABIs which only guarantee 4-byte alignment
206+
// of SP. If used, it will be below the other save areas, after the stack has
207+
// been re-aligned.
208+
209+
switch (Reg) {
210+
default:
211+
dbgs() << "Don't know where to spill " << printReg(Reg, RegInfo) << "\n";
212+
llvm_unreachable("Don't know where to spill this register");
213+
break;
214+
215+
case ARM::FPCXTNS:
216+
return SpillArea::FPCXT;
217+
218+
case ARM::R0:
219+
case ARM::R1:
220+
case ARM::R2:
221+
case ARM::R3:
222+
case ARM::R4:
223+
case ARM::R5:
224+
case ARM::R6:
225+
case ARM::R7:
226+
return SpillArea::GPRCS1;
227+
228+
case ARM::R8:
229+
case ARM::R9:
230+
case ARM::R10:
231+
if (Variation == ARMSubtarget::SplitR7)
232+
return SpillArea::GPRCS2;
233+
else
234+
return SpillArea::GPRCS1;
235+
236+
case ARM::R11:
237+
if (Variation == ARMSubtarget::NoSplit)
238+
return SpillArea::GPRCS1;
239+
else
240+
return SpillArea::GPRCS2;
241+
242+
case ARM::R12:
243+
if (Variation == ARMSubtarget::SplitR7)
244+
return SpillArea::GPRCS2;
245+
else
246+
return SpillArea::GPRCS1;
247+
248+
case ARM::LR:
249+
if (Variation == ARMSubtarget::SplitR11WindowsSEH)
250+
return SpillArea::GPRCS2;
251+
else
252+
return SpillArea::GPRCS1;
253+
254+
case ARM::D0:
255+
case ARM::D1:
256+
case ARM::D2:
257+
case ARM::D3:
258+
case ARM::D4:
259+
case ARM::D5:
260+
case ARM::D6:
261+
case ARM::D7:
262+
return SpillArea::DPRCS1;
263+
264+
case ARM::D8:
265+
case ARM::D9:
266+
case ARM::D10:
267+
case ARM::D11:
268+
case ARM::D12:
269+
case ARM::D13:
270+
case ARM::D14:
271+
case ARM::D15:
272+
if (Reg >= ARM::D8 && Reg < ARM::D8 + NumAlignedDPRCS2Regs)
273+
return SpillArea::DPRCS2;
274+
else
275+
return SpillArea::DPRCS1;
276+
277+
case ARM::D16:
278+
case ARM::D17:
279+
case ARM::D18:
280+
case ARM::D19:
281+
case ARM::D20:
282+
case ARM::D21:
283+
case ARM::D22:
284+
case ARM::D23:
285+
case ARM::D24:
286+
case ARM::D25:
287+
case ARM::D26:
288+
case ARM::D27:
289+
case ARM::D28:
290+
case ARM::D29:
291+
case ARM::D30:
292+
case ARM::D31:
293+
return SpillArea::DPRCS1;
294+
}
295+
}
296+
176297
ARMFrameLowering::ARMFrameLowering(const ARMSubtarget &sti)
177298
: TargetFrameLowering(StackGrowsDown, sti.getStackAlignment(), 0, Align(4)),
178299
STI(sti) {}
@@ -791,81 +912,32 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
791912
return;
792913
}
793914

794-
// Determine spill area sizes.
795-
if (PushPopSplit == ARMSubtarget::SplitR11WindowsSEH) {
796-
for (const CalleeSavedInfo &I : CSI) {
797-
Register Reg = I.getReg();
798-
int FI = I.getFrameIdx();
799-
switch (Reg) {
800-
case ARM::R11:
801-
case ARM::LR:
802-
if (Reg == FramePtr)
803-
FramePtrSpillFI = FI;
804-
GPRCS2Size += 4;
805-
break;
806-
case ARM::R0:
807-
case ARM::R1:
808-
case ARM::R2:
809-
case ARM::R3:
810-
case ARM::R4:
811-
case ARM::R5:
812-
case ARM::R6:
813-
case ARM::R7:
814-
case ARM::R8:
815-
case ARM::R9:
816-
case ARM::R10:
817-
case ARM::R12:
818-
GPRCS1Size += 4;
819-
break;
820-
case ARM::FPCXTNS:
821-
FPCXTSaveSize = 4;
822-
break;
823-
default:
824-
// This is a DPR. Exclude the aligned DPRCS2 spills.
825-
if (Reg == ARM::D8)
826-
D8SpillFI = FI;
827-
if (Reg < ARM::D8 || Reg >= ARM::D8 + AFI->getNumAlignedDPRCS2Regs())
828-
DPRCSSize += 8;
829-
}
830-
}
831-
} else {
832-
for (const CalleeSavedInfo &I : CSI) {
833-
Register Reg = I.getReg();
834-
int FI = I.getFrameIdx();
835-
switch (Reg) {
836-
case ARM::R8:
837-
case ARM::R9:
838-
case ARM::R10:
839-
case ARM::R11:
840-
case ARM::R12:
841-
if (PushPopSplit == ARMSubtarget::SplitR7) {
842-
GPRCS2Size += 4;
843-
break;
844-
}
845-
[[fallthrough]];
846-
case ARM::R0:
847-
case ARM::R1:
848-
case ARM::R2:
849-
case ARM::R3:
850-
case ARM::R4:
851-
case ARM::R5:
852-
case ARM::R6:
853-
case ARM::R7:
854-
case ARM::LR:
855-
if (Reg == FramePtr)
856-
FramePtrSpillFI = FI;
857-
GPRCS1Size += 4;
858-
break;
859-
case ARM::FPCXTNS:
860-
FPCXTSaveSize = 4;
861-
break;
862-
default:
863-
// This is a DPR. Exclude the aligned DPRCS2 spills.
864-
if (Reg == ARM::D8)
865-
D8SpillFI = FI;
866-
if (Reg < ARM::D8 || Reg >= ARM::D8 + AFI->getNumAlignedDPRCS2Regs())
867-
DPRCSSize += 8;
868-
}
915+
// Determine spill area sizes, and some important frame indices.
916+
for (const CalleeSavedInfo &I : CSI) {
917+
Register Reg = I.getReg();
918+
int FI = I.getFrameIdx();
919+
920+
if (Reg == FramePtr)
921+
FramePtrSpillFI = FI;
922+
if (Reg == ARM::D8)
923+
D8SpillFI = FI;
924+
925+
switch (getSpillArea(Reg, PushPopSplit, AFI->getNumAlignedDPRCS2Regs(),
926+
RegInfo)) {
927+
case SpillArea::FPCXT:
928+
FPCXTSaveSize += 4;
929+
break;
930+
case SpillArea::GPRCS1:
931+
GPRCS1Size += 4;
932+
break;
933+
case SpillArea::GPRCS2:
934+
GPRCS2Size += 4;
935+
break;
936+
case SpillArea::DPRCS1:
937+
DPRCSSize += 8;
938+
break;
939+
case SpillArea::DPRCS2:
940+
break;
869941
}
870942
}
871943

@@ -895,7 +967,10 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
895967
DefCFAOffsetCandidates.addInst(LastPush, GPRCS1Size, true);
896968
}
897969

898-
// Determine starting offsets of spill areas.
970+
// Determine starting offsets of spill areas. These offsets are all positive
971+
// offsets from the bottom of the lowest-addressed callee-save area
972+
// (excluding DPRCS2, which is th the re-aligned stack region) to the bottom
973+
// of the spill area in question.
899974
unsigned FPCXTOffset = NumBytes - ArgRegsSaveSize - FPCXTSaveSize;
900975
unsigned GPRCS1Offset = FPCXTOffset - GPRCS1Size;
901976
unsigned GPRCS2Offset = GPRCS1Offset - GPRCS2Size;
@@ -915,10 +990,19 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
915990
}
916991
int FramePtrOffsetInPush = 0;
917992
if (HasFP) {
993+
// Offset from the CFA to the saved frame pointer, will be negative.
918994
int FPOffset = MFI.getObjectOffset(FramePtrSpillFI);
995+
LLVM_DEBUG(dbgs() << "FramePtrSpillFI: " << FramePtrSpillFI
996+
<< ", FPOffset: " << FPOffset << "\n");
919997
assert(getMaxFPOffset(STI, *AFI, MF) <= FPOffset &&
920998
"Max FP estimation is wrong");
999+
// Offset from the top of the GPRCS1 area to the saved frame pointer, will
1000+
// be negative.
9211001
FramePtrOffsetInPush = FPOffset + ArgRegsSaveSize + FPCXTSaveSize;
1002+
LLVM_DEBUG(dbgs() << "FramePtrOffsetInPush=" << FramePtrOffsetInPush
1003+
<< ", FramePtrSpillOffset="
1004+
<< (MFI.getObjectOffset(FramePtrSpillFI) + NumBytes)
1005+
<< "\n");
9221006
AFI->setFramePtrSpillOffset(MFI.getObjectOffset(FramePtrSpillFI) +
9231007
NumBytes);
9241008
}
@@ -1123,80 +1207,35 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
11231207
// Now that the prologue's actual instructions are finalised, we can insert
11241208
// the necessary DWARF cf instructions to describe the situation. Start by
11251209
// recording where each register ended up:
1126-
if (GPRCS1Size > 0 && !NeedsWinCFI) {
1127-
MachineBasicBlock::iterator Pos = std::next(GPRCS1Push);
1128-
int CFIIndex;
1129-
for (const auto &Entry : CSI) {
1210+
if (!NeedsWinCFI) {
1211+
for (const auto &Entry : reverse(CSI)) {
11301212
Register Reg = Entry.getReg();
11311213
int FI = Entry.getFrameIdx();
1132-
switch (Reg) {
1133-
case ARM::R8:
1134-
case ARM::R9:
1135-
case ARM::R10:
1136-
case ARM::R11:
1137-
case ARM::R12:
1138-
if (PushPopSplit == ARMSubtarget::SplitR7)
1139-
break;
1140-
[[fallthrough]];
1141-
case ARM::R0:
1142-
case ARM::R1:
1143-
case ARM::R2:
1144-
case ARM::R3:
1145-
case ARM::R4:
1146-
case ARM::R5:
1147-
case ARM::R6:
1148-
case ARM::R7:
1149-
case ARM::LR:
1150-
CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
1151-
nullptr, MRI->getDwarfRegNum(Reg, true), MFI.getObjectOffset(FI)));
1152-
BuildMI(MBB, Pos, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
1153-
.addCFIIndex(CFIIndex)
1154-
.setMIFlags(MachineInstr::FrameSetup);
1214+
MachineBasicBlock::iterator CFIPos;
1215+
switch (getSpillArea(Reg, PushPopSplit, AFI->getNumAlignedDPRCS2Regs(),
1216+
RegInfo)) {
1217+
case SpillArea::GPRCS1:
1218+
CFIPos = std::next(GPRCS1Push);
11551219
break;
1156-
}
1157-
}
1158-
}
1159-
1160-
if (GPRCS2Size > 0 && !NeedsWinCFI) {
1161-
MachineBasicBlock::iterator Pos = std::next(GPRCS2Push);
1162-
for (const auto &Entry : CSI) {
1163-
Register Reg = Entry.getReg();
1164-
int FI = Entry.getFrameIdx();
1165-
switch (Reg) {
1166-
case ARM::R8:
1167-
case ARM::R9:
1168-
case ARM::R10:
1169-
case ARM::R11:
1170-
case ARM::R12:
1171-
if (PushPopSplit == ARMSubtarget::SplitR7) {
1172-
unsigned DwarfReg = MRI->getDwarfRegNum(
1173-
Reg == ARM::R12 ? ARM::RA_AUTH_CODE : Reg, true);
1174-
int64_t Offset = MFI.getObjectOffset(FI);
1175-
unsigned CFIIndex = MF.addFrameInst(
1176-
MCCFIInstruction::createOffset(nullptr, DwarfReg, Offset));
1177-
BuildMI(MBB, Pos, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
1178-
.addCFIIndex(CFIIndex)
1179-
.setMIFlags(MachineInstr::FrameSetup);
1180-
}
1220+
case SpillArea::GPRCS2:
1221+
CFIPos = std::next(GPRCS2Push);
1222+
break;
1223+
case SpillArea::DPRCS1:
1224+
CFIPos = std::next(LastPush);
1225+
break;
1226+
case SpillArea::FPCXT:
1227+
case SpillArea::DPRCS2:
1228+
// FPCXT and DPRCS2 are not represented in the DWARF info.
11811229
break;
11821230
}
1183-
}
1184-
}
11851231

1186-
if (DPRCSSize > 0 && !NeedsWinCFI) {
1187-
// Since vpush register list cannot have gaps, there may be multiple vpush
1188-
// instructions in the prologue.
1189-
MachineBasicBlock::iterator Pos = std::next(LastPush);
1190-
for (const auto &Entry : CSI) {
1191-
Register Reg = Entry.getReg();
1192-
int FI = Entry.getFrameIdx();
1193-
if ((Reg >= ARM::D0 && Reg <= ARM::D31) &&
1194-
(Reg < ARM::D8 || Reg >= ARM::D8 + AFI->getNumAlignedDPRCS2Regs())) {
1195-
unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true);
1196-
int64_t Offset = MFI.getObjectOffset(FI);
1197-
unsigned CFIIndex = MF.addFrameInst(
1198-
MCCFIInstruction::createOffset(nullptr, DwarfReg, Offset));
1199-
BuildMI(MBB, Pos, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
1232+
if (CFIPos.isValid()) {
1233+
int CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
1234+
nullptr,
1235+
MRI->getDwarfRegNum(Reg == ARM::R12 ? ARM::RA_AUTH_CODE : Reg,
1236+
true),
1237+
MFI.getObjectOffset(FI)));
1238+
BuildMI(MBB, CFIPos, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
12001239
.addCFIIndex(CFIIndex)
12011240
.setMIFlags(MachineInstr::FrameSetup);
12021241
}

0 commit comments

Comments
 (0)