Skip to content

Commit 9a56b55

Browse files
Nikola PericNikola Peric
authored andcommitted
NanoMips: Two-step stack setup
Adjust stack pointer in two steps if offset is larger than 4096. In the first step adjust stack pointer for the size necessary to spill CSR onto the stack. In the second step adjust stack pointer for the size necessary to spill local objects.
1 parent b810f28 commit 9a56b55

File tree

6 files changed

+174
-37
lines changed

6 files changed

+174
-37
lines changed

llvm/lib/Target/Mips/MipsMachineFunction.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,3 +201,19 @@ int MipsFunctionInfo::getMoveF64ViaSpillFI(MachineFunction &MF,
201201
}
202202

203203
void MipsFunctionInfo::anchor() {}
204+
205+
unsigned MipsFunctionInfo::getCalleeSavedStackSize() {
206+
return CalleeSavedStackSize;
207+
}
208+
209+
void MipsFunctionInfo::setCalleeSavedStackSize(unsigned Size) {
210+
CalleeSavedStackSize = Size;
211+
}
212+
213+
bool MipsFunctionInfo::isTwoStepStackSetup(MachineFunction &MF) {
214+
215+
const MipsSubtarget &STI =
216+
*static_cast<const MipsSubtarget *>(&MF.getSubtarget());
217+
218+
return (MF.getFrameInfo().getStackSize() > 4096) && STI.hasNanoMips();
219+
}

llvm/lib/Target/Mips/MipsMachineFunction.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ class MipsFunctionInfo : public MachineFunctionInfo {
108108
JumpTableEntryInfo[Idx]->Signed = Sign;
109109
}
110110
}
111+
unsigned getCalleeSavedStackSize();
112+
void setCalleeSavedStackSize(unsigned Size);
113+
bool isTwoStepStackSetup(MachineFunction &MF);
111114

112115
private:
113116
virtual void anchor();
@@ -168,6 +171,7 @@ class MipsFunctionInfo : public MachineFunctionInfo {
168171
};
169172

170173
SmallVector<NanoMipsJumpTableInfo *, 2> JumpTableEntryInfo;
174+
unsigned CalleeSavedStackSize = 0;
171175
};
172176

173177
} // end namespace llvm

llvm/lib/Target/Mips/MipsSEFrameLowering.cpp

Lines changed: 106 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -432,19 +432,61 @@ void MipsSEFrameLowering::emitPrologue(MachineFunction &MF,
432432
MachineModuleInfo &MMI = MF.getMMI();
433433
const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo();
434434

435-
// Adjust stack.
436-
TII.adjustStackPtr(SP, -StackSize, MBB, MBBI);
435+
const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
436+
437+
int64_t CalleeSavedStackSize;
438+
int64_t LoaclStackSize;
439+
// If we have two-step stack setup MBBI_2 will point to the
440+
// first instruction after calle-saves store sequence
441+
MachineBasicBlock::iterator MBBI_2 = MBBI;
442+
443+
if (MipsFI->isTwoStepStackSetup(MF)) {
444+
445+
CalleeSavedStackSize = MipsFI->getCalleeSavedStackSize();
446+
unsigned NumOfCSI = MFI.getCalleeSavedInfo().size();
447+
448+
// Move MBBI_2 to point to the first instruction after
449+
// calle-saves store sequence. That's the place for the second
450+
// steck pointer adjustment.
451+
std::advance(MBBI_2, NumOfCSI);
452+
453+
// The first stack pointer adjustment to cover space needed
454+
// to spill callee-saved registers on stack.
455+
TII.adjustStackPtr(SP, -CalleeSavedStackSize, MBB, MBBI);
456+
457+
LoaclStackSize = StackSize - CalleeSavedStackSize;
437458

438-
// emit ".cfi_def_cfa_offset StackSize"
439-
unsigned CFIIndex =
440-
MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize));
441-
BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
442-
.addCFIIndex(CFIIndex);
459+
// The second stack pointer adjustment to cover space needed
460+
// to spill local objects on stack.
461+
TII.adjustStackPtr(SP, -LoaclStackSize, MBB, MBBI_2);
462+
463+
} else
464+
// Adjust stack.
465+
TII.adjustStackPtr(SP, -StackSize, MBB, MBBI);
466+
467+
if (MipsFI->isTwoStepStackSetup(MF)) {
468+
// emit ".cfi_def_cfa_offset CalleeSavedStackSize"
469+
// emit ".cfi_def_cfa_offset StackSize = CalleeSavedStackSize +
470+
// LoaclStackSize"
471+
unsigned CFIIndex_1 = MF.addFrameInst(
472+
MCCFIInstruction::cfiDefCfaOffset(nullptr, CalleeSavedStackSize));
473+
unsigned CFIIndex_2 =
474+
MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize));
475+
BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
476+
.addCFIIndex(CFIIndex_1);
477+
BuildMI(MBB, MBBI_2, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
478+
.addCFIIndex(CFIIndex_2);
479+
} else {
480+
// emit ".cfi_def_cfa_offset StackSize"
481+
unsigned CFIIndex =
482+
MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize));
483+
BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
484+
.addCFIIndex(CFIIndex);
485+
}
443486

444487
if (MF.getFunction().hasFnAttribute("interrupt"))
445488
emitInterruptPrologueStub(MF, MBB);
446489

447-
const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
448490

449491
if (!CSI.empty()) {
450492
// Find the instruction past the last instruction that saves a callee-saved
@@ -531,6 +573,14 @@ void MipsSEFrameLowering::emitPrologue(MachineFunction &MF,
531573
BuildMI(MBB, MBBI, dl, TII.get(MOVE), FP).addReg(SP).addReg(ZERO)
532574
.setMIFlag(MachineInstr::FrameSetup);
533575

576+
if (MipsFI->isTwoStepStackSetup(MF))
577+
// If we have two-step stack setup insert instruction "move $fp, $sp"
578+
// after the second stack setup also
579+
BuildMI(MBB, MBBI_2, dl, TII.get(MOVE), FP)
580+
.addReg(SP)
581+
.addReg(ZERO)
582+
.setMIFlag(MachineInstr::FrameSetup);
583+
534584
// emit ".cfi_def_cfa_register $fp"
535585
unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createDefCfaRegister(
536586
nullptr, MRI->getDwarfRegNum(FP, true)));
@@ -747,8 +797,26 @@ void MipsSEFrameLowering::emitEpilogue(MachineFunction &MF,
747797
if (!StackSize)
748798
return;
749799

750-
// Adjust stack.
751-
TII.adjustStackPtr(SP, StackSize, MBB, MBBI);
800+
if (MipsFI->isTwoStepStackSetup(MF)) {
801+
802+
int64_t CalleeSavedStackSize = MipsFI->getCalleeSavedStackSize();
803+
int64_t LoaclStackSize = StackSize - CalleeSavedStackSize;
804+
805+
int64_t NumOfCSI = MFI.getCalleeSavedInfo().size();
806+
807+
MachineBasicBlock::iterator MBBI_2 = MBBI;
808+
// Move MBBI_2 to point to the first instruction in
809+
// calle-saved load sequence. That's the place where we
810+
// need to undo the second stack adjustment
811+
std::advance(MBBI_2, (-1) * NumOfCSI);
812+
813+
// Undo the second stack pointer adjustment
814+
TII.adjustStackPtr(SP, LoaclStackSize, MBB, MBBI_2);
815+
// Undo the first stack pointer adjustment
816+
TII.adjustStackPtr(SP, CalleeSavedStackSize, MBB, MBBI);
817+
} else
818+
// Adjust stack.
819+
TII.adjustStackPtr(SP, StackSize, MBB, MBBI);
752820
}
753821

754822
void MipsSEFrameLowering::emitInterruptEpilogueStub(
@@ -957,25 +1025,38 @@ bool MipsSEFrameLowering::assignCalleeSavedSpillSlots(
9571025
return Regs.at(First.getReg()) < Regs.at(Second.getReg());
9581026
};
9591027

960-
// If CSI list has less than two callee-saved registers we can
961-
// return from method since no insertions nor sorting is needed
962-
if(CSI.size() < 2)
963-
return false;
1028+
// If CSI list has less than two callee-saved registers
1029+
// no insertions nor sorting is needed
1030+
if (CSI.size() >= 2) {
1031+
1032+
SmallBitVector CSNumBitVector(11);
1033+
for (CalleeSavedInfo &CS : CSI)
1034+
CSNumBitVector.set(Regs.at(CS.getReg()));
9641035

965-
SmallBitVector CSNumBitVector(11);
966-
for (CalleeSavedInfo &CS : CSI)
967-
CSNumBitVector.set(Regs.at(CS.getReg()));
1036+
int MinCSNum = CSNumBitVector.find_first();
1037+
int MaxCSNum = CSNumBitVector.find_last();
9681038

969-
int MinCSNum = CSNumBitVector.find_first();
970-
int MaxCSNum = CSNumBitVector.find_last();
1039+
// Inserting all of the missing callee-saved registers between min and max
1040+
// in order to allow further load-store optimizations
1041+
for (int i = MinCSNum + 1; i < MaxCSNum; ++i)
1042+
if (!CSNumBitVector.test(i))
1043+
CSI.push_back(CalleeSavedInfo(CSNumToReg.at(i)));
1044+
1045+
std::sort(CSI.begin(), CSI.end(), CompareCalleeSaves);
1046+
}
9711047

972-
// Inserting all of the missing callee-saved registers between min and max
973-
// in order to allow further load-store optimizations
974-
for (int i = MinCSNum + 1; i < MaxCSNum; ++i)
975-
if (!CSNumBitVector.test(i))
976-
CSI.push_back(CalleeSavedInfo(CSNumToReg.at(i)));
1048+
MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
1049+
const MachineRegisterInfo &MRI = MF.getRegInfo();
1050+
1051+
unsigned CalleeSavedOffsetSize = 0;
1052+
for (CalleeSavedInfo &CS : CSI) {
1053+
Register Reg = CS.getReg();
1054+
auto RegSize = TRI->getRegSizeInBits(Reg, MRI) / 8;
1055+
CalleeSavedOffsetSize += RegSize;
1056+
}
1057+
uint64_t AlignedCSStackSize = alignTo(CalleeSavedOffsetSize, 16);
1058+
MipsFI->setCalleeSavedStackSize(AlignedCSStackSize);
9771059

978-
std::sort(CSI.begin(), CSI.end(), CompareCalleeSaves);
9791060
return false;
9801061
}
9811062

llvm/lib/Target/Mips/MipsSERegisterInfo.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,18 @@ void MipsSERegisterInfo::eliminateFI(MachineBasicBlock::iterator II,
220220
bool IsKill = false;
221221
int64_t Offset;
222222

223-
Offset = SPOffset + (int64_t)StackSize;
223+
if (MipsFI->isTwoStepStackSetup(MF)) {
224+
225+
int64_t CalleeSavedStackSize = MipsFI->getCalleeSavedStackSize();
226+
227+
if (FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI)
228+
Offset = SPOffset + (int64_t)CalleeSavedStackSize;
229+
else
230+
Offset = SPOffset + StackSize;
231+
232+
} else
233+
Offset = SPOffset + (int64_t)StackSize;
234+
224235
Offset += MI.getOperand(OpNo + 1).getImm();
225236

226237
LLVM_DEBUG(errs() << "Offset : " << Offset << "\n"

llvm/test/CodeGen/Mips/nanomips/saverestore.ll

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,6 @@ define void @test() {
77
; CHECK: restore.jrc 32, $s0, $s1, $s2, $s3, $s4, $s5, $s6, $s7
88
}
99

10-
; Make sure that SAVE/RESTORE instructions are not used when the offset is larger than 4092.
11-
define void @test2() {
12-
; CHECK-NOT: save
13-
%foo = alloca [4096 x i8], align 1
14-
%1 = getelementptr inbounds [4096 x i8], [4096 x i8]* %foo, i32 0, i32 0
15-
call void asm sideeffect "", "r,~{$16},~{$17},~{$18},~{$19},~{$20},~{$21},~{$23},~{$22},~{$1}"(i8* %1)
16-
ret void
17-
; CHECK-NOT: restore.jrc
18-
; CHECK-NOT: restore
19-
}
20-
2110
; Make sure that SAVE/SAVE combination is used when incoming arguments need to
2211
; be stored on the stack. First SAVE to move the stack pointer to where s-regs
2312
; need to be stored and second SAVE to actually save the registers. Same logic
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
; RUN: llc -mtriple=nanomips -asm-show-inst -verify-machineinstrs < %s | FileCheck %s
2+
3+
; Check if stack setup is splitted into two-step setup when sp
4+
; offset is larger than 4096
5+
define void @test1() {
6+
; CHECK: save 32, $s0, $s1, $s2, $s3, $s4
7+
; CHECK: addiu $sp, $sp, -4096
8+
%foo = alloca [4096 x i8], align 1
9+
%1 = getelementptr inbounds [4096 x i8], [4096 x i8]* %foo, i32 0, i32 0
10+
call void asm sideeffect "", "r,~{$16},~{$17},~{$18},~{$19},~{$20},~{$1}"(i8* %1)
11+
ret void
12+
; CHECK: addiu $sp, $sp, 4096
13+
; CHECK: restore.jrc 32, $s0, $s1, $s2, $s3, $s4
14+
}
15+
16+
; Check if there are two instructions for storing sp in fp
17+
; if function uses fp and two-step stack setup is present
18+
define void @test2() #0 {
19+
; CHECK: save 32, $fp, $ra, $s0, $s1, $s2, $s3, $s4
20+
; CHECK: or $fp, $sp, $zero
21+
; CHECK: addiu $sp, $sp, -4096
22+
; CHECK: or $fp, $sp, $zero
23+
%foo = alloca [4096 x i8], align 1
24+
%1 = getelementptr inbounds [4096 x i8], [4096 x i8]* %foo, i32 0, i32 0
25+
call void asm sideeffect "", "r,~{$16},~{$17},~{$18},~{$19},~{$20},~{$1}"(i8* %1)
26+
ret void
27+
; CHECK: addiu $sp, $sp, 4096
28+
; CHECK: restore.jrc 32, $fp, $ra, $s0, $s1, $s2, $s3, $s4
29+
}
30+
31+
attributes #0 = { "frame-pointer"="all"}
32+
33+
!llvm.module.flags = !{!0}
34+
35+
!0 = !{i32 7, !"frame-pointer", i32 2}
36+

0 commit comments

Comments
 (0)