Skip to content

Commit a48e686

Browse files
committed
[ARM] Factor out code to determine spill areas (NFC)
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 02f008a commit a48e686

File tree

1 file changed

+150
-144
lines changed

1 file changed

+150
-144
lines changed

llvm/lib/Target/ARM/ARMFrameLowering.cpp

Lines changed: 150 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,95 @@ 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: case ARM::R1: case ARM::R2: case ARM::R3:
219+
case ARM::R4: case ARM::R5: case ARM::R6: case ARM::R7:
220+
return SpillArea::GPRCS1;
221+
222+
case ARM::R8: case ARM::R9: case ARM::R10:
223+
if (Variation == ARMSubtarget::SplitR7)
224+
return SpillArea::GPRCS2;
225+
else
226+
return SpillArea::GPRCS1;
227+
228+
case ARM::R11:
229+
if (Variation == ARMSubtarget::NoSplit)
230+
return SpillArea::GPRCS1;
231+
else
232+
return SpillArea::GPRCS2;
233+
234+
case ARM::R12:
235+
if (Variation == ARMSubtarget::SplitR7)
236+
return SpillArea::GPRCS2;
237+
else
238+
return SpillArea::GPRCS1;
239+
240+
case ARM::LR:
241+
if (Variation == ARMSubtarget::SplitR11WindowsSEH)
242+
return SpillArea::GPRCS2;
243+
else
244+
return SpillArea::GPRCS1;
245+
246+
case ARM::D0: case ARM::D1: case ARM::D2: case ARM::D3:
247+
case ARM::D4: case ARM::D5: case ARM::D6: case ARM::D7:
248+
return SpillArea::DPRCS1;
249+
250+
case ARM::D8: case ARM::D9: case ARM::D10: case ARM::D11:
251+
case ARM::D12: case ARM::D13: case ARM::D14: case ARM::D15:
252+
if (Reg >= ARM::D8 && Reg < ARM::D8 + NumAlignedDPRCS2Regs)
253+
return SpillArea::DPRCS2;
254+
else
255+
return SpillArea::DPRCS1;
256+
257+
case ARM::D16: case ARM::D17: case ARM::D18: case ARM::D19:
258+
case ARM::D20: case ARM::D21: case ARM::D22: case ARM::D23:
259+
case ARM::D24: case ARM::D25: case ARM::D26: case ARM::D27:
260+
case ARM::D28: case ARM::D29: case ARM::D30: case ARM::D31:
261+
return SpillArea::DPRCS1;
262+
}
263+
}
264+
176265
ARMFrameLowering::ARMFrameLowering(const ARMSubtarget &sti)
177266
: TargetFrameLowering(StackGrowsDown, sti.getStackAlignment(), 0, Align(4)),
178267
STI(sti) {}
@@ -791,81 +880,32 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
791880
return;
792881
}
793882

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-
}
883+
// Determine spill area sizes, and some important frame indices.
884+
for (const CalleeSavedInfo &I : CSI) {
885+
Register Reg = I.getReg();
886+
int FI = I.getFrameIdx();
887+
888+
if (Reg == FramePtr)
889+
FramePtrSpillFI = FI;
890+
if (Reg == ARM::D8)
891+
D8SpillFI = FI;
892+
893+
switch (getSpillArea(Reg, PushPopSplit, AFI->getNumAlignedDPRCS2Regs(),
894+
RegInfo)) {
895+
case SpillArea::FPCXT:
896+
FPCXTSaveSize += 4;
897+
break;
898+
case SpillArea::GPRCS1:
899+
GPRCS1Size += 4;
900+
break;
901+
case SpillArea::GPRCS2:
902+
GPRCS2Size += 4;
903+
break;
904+
case SpillArea::DPRCS1:
905+
DPRCSSize += 8;
906+
break;
907+
case SpillArea::DPRCS2:
908+
break;
869909
}
870910
}
871911

@@ -895,7 +935,10 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
895935
DefCFAOffsetCandidates.addInst(LastPush, GPRCS1Size, true);
896936
}
897937

898-
// Determine starting offsets of spill areas.
938+
// Determine starting offsets of spill areas. These offsets are all positive
939+
// offsets from the bottom of the lowest-addressed callee-save area
940+
// (excluding DPRCS2, which is th the re-aligned stack region) to the bottom
941+
// of the spill area in question.
899942
unsigned FPCXTOffset = NumBytes - ArgRegsSaveSize - FPCXTSaveSize;
900943
unsigned GPRCS1Offset = FPCXTOffset - GPRCS1Size;
901944
unsigned GPRCS2Offset = GPRCS1Offset - GPRCS2Size;
@@ -915,10 +958,19 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
915958
}
916959
int FramePtrOffsetInPush = 0;
917960
if (HasFP) {
961+
// Offset from the CFA to the saved frame pointer, will be negative.
918962
int FPOffset = MFI.getObjectOffset(FramePtrSpillFI);
963+
LLVM_DEBUG(dbgs() << "FramePtrSpillFI: " << FramePtrSpillFI
964+
<< ", FPOffset: " << FPOffset << "\n");
919965
assert(getMaxFPOffset(STI, *AFI, MF) <= FPOffset &&
920966
"Max FP estimation is wrong");
967+
// Offset from the top of the GPRCS1 area to the saved frame pointer, will
968+
// be negative.
921969
FramePtrOffsetInPush = FPOffset + ArgRegsSaveSize + FPCXTSaveSize;
970+
LLVM_DEBUG(dbgs() << "FramePtrOffsetInPush=" << FramePtrOffsetInPush
971+
<< ", FramePtrSpillOffset="
972+
<< (MFI.getObjectOffset(FramePtrSpillFI) + NumBytes)
973+
<< "\n");
922974
AFI->setFramePtrSpillOffset(MFI.getObjectOffset(FramePtrSpillFI) +
923975
NumBytes);
924976
}
@@ -1123,80 +1175,34 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
11231175
// Now that the prologue's actual instructions are finalised, we can insert
11241176
// the necessary DWARF cf instructions to describe the situation. Start by
11251177
// 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) {
1178+
if (!NeedsWinCFI) {
1179+
for (const auto &Entry : reverse(CSI)) {
11301180
Register Reg = Entry.getReg();
11311181
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);
1182+
MachineBasicBlock::iterator CFIPos;
1183+
switch (getSpillArea(Reg, PushPopSplit, AFI->getNumAlignedDPRCS2Regs(),
1184+
RegInfo)) {
1185+
case SpillArea::GPRCS1:
1186+
CFIPos = std::next(GPRCS1Push);
11551187
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-
}
1188+
case SpillArea::GPRCS2:
1189+
CFIPos = std::next(GPRCS2Push);
1190+
break;
1191+
case SpillArea::DPRCS1:
1192+
CFIPos = std::next(LastPush);
1193+
break;
1194+
case SpillArea::FPCXT:
1195+
case SpillArea::DPRCS2:
1196+
// FPCXT and DPRCS2 are not represented in the DWARF info.
11811197
break;
11821198
}
1183-
}
1184-
}
11851199

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))
1200+
if (CFIPos.isValid()) {
1201+
int CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
1202+
nullptr,
1203+
MRI->getDwarfRegNum(Reg == ARM::R12 ? ARM::RA_AUTH_CODE : Reg, true),
1204+
MFI.getObjectOffset(FI)));
1205+
BuildMI(MBB, CFIPos, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
12001206
.addCFIIndex(CFIIndex)
12011207
.setMIFlags(MachineInstr::FrameSetup);
12021208
}

0 commit comments

Comments
 (0)