Skip to content

Commit fc5fa13

Browse files
Nikola PericNikola Peric
authored andcommitted
NanoMips: Frame pointer setup
If function uses FP, it will now point to address -4096 from the beginning of function's stack. After FP setup following offsets will be relative to SP if function has no var-sized objects. If it has var-sized objects offsets will be relative to FP. Also, stack realignment now happens with INS instruction.
1 parent 9a56b55 commit fc5fa13

File tree

7 files changed

+210
-49
lines changed

7 files changed

+210
-49
lines changed

llvm/lib/Target/Mips/MipsRegisterInfo.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,11 +303,21 @@ Register MipsRegisterInfo::
303303
getFrameRegister(const MachineFunction &MF) const {
304304
const MipsSubtarget &Subtarget = MF.getSubtarget<MipsSubtarget>();
305305
const TargetFrameLowering *TFI = Subtarget.getFrameLowering();
306+
const MachineFrameInfo &MFI = MF.getFrameInfo();
307+
const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
306308
bool IsN64 =
307309
static_cast<const MipsTargetMachine &>(MF.getTarget()).getABI().IsN64();
308310
bool IsP32 =
309311
static_cast<const MipsTargetMachine &>(MF.getTarget()).getABI().IsP32();
310312

313+
// If function doesn't have var-sized objects and function doesn't need stack
314+
// realignment but frame pointer elimination is disabled we want offsets to be
315+
// relative to sp instead of fp
316+
if (Subtarget.hasNanoMips())
317+
if (!MFI.hasVarSizedObjects() && !TRI->hasStackRealignment(MF) &&
318+
MF.getTarget().Options.DisableFramePointerElim(MF))
319+
return Mips::SP_NM;
320+
311321
if (Subtarget.inMips16Mode())
312322
return TFI->hasFP(MF) ? Mips::S0 : Mips::SP;
313323
else

llvm/lib/Target/Mips/MipsSEFrameLowering.cpp

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -569,23 +569,40 @@ void MipsSEFrameLowering::emitPrologue(MachineFunction &MF,
569569

570570
// if framepointer enabled, set it to point to the stack pointer.
571571
if (hasFP(MF)) {
572-
// Insert instruction "move $fp, $sp" at this location.
573-
BuildMI(MBB, MBBI, dl, TII.get(MOVE), FP).addReg(SP).addReg(ZERO)
574-
.setMIFlag(MachineInstr::FrameSetup);
575572

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)
573+
if (STI.hasNanoMips()) {
574+
575+
BuildMI(MBB, MBBI_2, dl, TII.get(ADDiu), FP)
576+
.addReg(SP)
577+
.addImm(-4096 + StackSize);
578+
579+
// emit ".cfi_def_cfa_register $fp"
580+
unsigned CFIIndex =
581+
MF.addFrameInst(MCCFIInstruction::createDefCfaRegister(
582+
nullptr, MRI->getDwarfRegNum(FP, true)));
583+
BuildMI(MBB, MBBI_2, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
584+
.addCFIIndex(CFIIndex);
585+
586+
// emit ".cfi_def_cfa_offset 4096"
587+
unsigned CFIIndex_1 =
588+
MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, 4096));
589+
BuildMI(MBB, MBBI_2, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
590+
.addCFIIndex(CFIIndex_1);
591+
592+
} else {
593+
// Insert instruction "move $fp, $sp" at this location.
594+
BuildMI(MBB, MBBI, dl, TII.get(MOVE), FP)
580595
.addReg(SP)
581596
.addReg(ZERO)
582597
.setMIFlag(MachineInstr::FrameSetup);
583598

584-
// emit ".cfi_def_cfa_register $fp"
585-
unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createDefCfaRegister(
586-
nullptr, MRI->getDwarfRegNum(FP, true)));
587-
BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
588-
.addCFIIndex(CFIIndex);
599+
// emit ".cfi_def_cfa_register $fp"
600+
unsigned CFIIndex =
601+
MF.addFrameInst(MCCFIInstruction::createDefCfaRegister(
602+
nullptr, MRI->getDwarfRegNum(FP, true)));
603+
BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
604+
.addCFIIndex(CFIIndex);
605+
}
589606

590607
if (RegInfo.hasStackRealignment(MF)) {
591608
// addiu $Reg, $zero, -MaxAlignment
@@ -595,13 +612,19 @@ void MipsSEFrameLowering::emitPrologue(MachineFunction &MF,
595612
"Function's alignment size requirement is not supported.");
596613
int64_t MaxAlign = -(int64_t)MFI.getMaxAlign().value();
597614

598-
if (ABI.IsP32())
599-
BuildMI(MBB, MBBI, dl, TII.get(Mips::Li_NM), VR).addImm(MaxAlign);
600-
else
615+
if (ABI.IsP32()) {
616+
uint64_t MaxAlignment = MFI.getMaxAlign().value();
617+
BuildMI(MBB, MBBI, dl, TII.get(Mips::INS_NM), SP)
618+
.addReg(ZERO)
619+
.addImm(0)
620+
.addImm(Log2_64(MaxAlignment))
621+
.addReg(SP);
622+
} else {
601623
BuildMI(MBB, MBBI, dl, TII.get(ADDiu), VR)
602624
.addReg(ZERO)
603625
.addImm(MaxAlign);
604-
BuildMI(MBB, MBBI, dl, TII.get(AND), SP).addReg(SP).addReg(VR);
626+
BuildMI(MBB, MBBI, dl, TII.get(AND), SP).addReg(SP).addReg(VR);
627+
}
605628

606629
if (hasBP(MF)) {
607630
// move $s7, $sp
@@ -759,7 +782,7 @@ void MipsSEFrameLowering::emitEpilogue(MachineFunction &MF,
759782
unsigned MOVE = ABI.GetGPRMoveOp();
760783

761784
// if framepointer enabled, restore the stack pointer.
762-
if (hasFP(MF)) {
785+
if (hasFP(MF) && !STI.hasNanoMips()) {
763786
// Find the first instruction that restores a callee-saved register.
764787
MachineBasicBlock::iterator I = MBBI;
765788

llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -461,8 +461,8 @@ bool MipsSEDAGToDAGISel::selectIntAddrLSL2MM(SDValue Addr, SDValue &Base,
461461

462462
bool MipsSEDAGToDAGISel::selectIntAddrSImm9(SDValue Addr, SDValue &Base,
463463
SDValue &Offset) const {
464-
return selectAddrFrameIndex(Addr, Base, Offset) ||
465-
selectAddrFrameIndexOffset(Addr, Base, Offset, 9);
464+
return selectAddrFrameIndexOffset(Addr, Base, Offset, 9) &&
465+
!isa<FrameIndexSDNode>(Base);
466466
}
467467

468468
bool MipsSEDAGToDAGISel::selectIntAddrSImm10(SDValue Addr, SDValue &Base,
@@ -541,7 +541,8 @@ bool MipsSEDAGToDAGISel::selectAddrFrameIndexUOffset(
541541

542542
bool MipsSEDAGToDAGISel::selectIntAddrUImm12(SDValue Addr, SDValue &Base,
543543
SDValue &Offset) const {
544-
return selectAddrFrameIndexUOffset(Addr, Base, Offset, 12, 0);
544+
return selectAddrFrameIndex(Addr, Base, Offset) ||
545+
selectAddrFrameIndexUOffset(Addr, Base, Offset, 12, 0);
545546
}
546547

547548
// A load/store 'x' indexed (reg + reg)

llvm/lib/Target/Mips/MipsSERegisterInfo.cpp

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,8 @@ void MipsSERegisterInfo::eliminateFI(MachineBasicBlock::iterator II,
175175
static_cast<const MipsTargetMachine &>(MF.getTarget()).getABI();
176176
const MipsRegisterInfo *RegInfo =
177177
static_cast<const MipsRegisterInfo *>(MF.getSubtarget().getRegisterInfo());
178+
const MipsSubtarget &STI =
179+
*static_cast<const MipsSubtarget *>(&MF.getSubtarget());
178180

179181
const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
180182
int MinCSFI = 0;
@@ -220,14 +222,25 @@ void MipsSERegisterInfo::eliminateFI(MachineBasicBlock::iterator II,
220222
bool IsKill = false;
221223
int64_t Offset;
222224

223-
if (MipsFI->isTwoStepStackSetup(MF)) {
225+
if (STI.hasNanoMips()) {
224226

225-
int64_t CalleeSavedStackSize = MipsFI->getCalleeSavedStackSize();
227+
if (MipsFI->isTwoStepStackSetup(MF)) {
226228

227-
if (FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI)
228-
Offset = SPOffset + (int64_t)CalleeSavedStackSize;
229-
else
230-
Offset = SPOffset + StackSize;
229+
int64_t CalleeSavedStackSize = MipsFI->getCalleeSavedStackSize();
230+
if (FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI)
231+
Offset = SPOffset + (int64_t)CalleeSavedStackSize;
232+
else if (FrameReg == Mips::FP_NM)
233+
Offset = SPOffset + 4096;
234+
else
235+
Offset = SPOffset + StackSize;
236+
237+
} else {
238+
239+
if (FrameReg == Mips::FP_NM)
240+
Offset = SPOffset + 4096;
241+
else
242+
Offset = SPOffset + StackSize;
243+
}
231244

232245
} else
233246
Offset = SPOffset + (int64_t)StackSize;
@@ -258,7 +271,9 @@ void MipsSERegisterInfo::eliminateFI(MachineBasicBlock::iterator II,
258271
// TODO: This doesn't work well for nanoMIPS, because it has unsigned
259272
// offsets and this check assumes signed.
260273
if (OffsetBitSize < 16 && isInt<16>(Offset) &&
261-
(!isIntN(OffsetBitSize, Offset) || !isAligned(OffsetAlign, Offset))) {
274+
(STI.hasNanoMips() ? !isUIntN(OffsetBitSize, Offset)
275+
: !isIntN(OffsetBitSize, Offset) ||
276+
!isAligned(OffsetAlign, Offset))) {
262277
// If we have an offset that needs to fit into a signed n-bit immediate
263278
// (where n < 16) and doesn't, but does fit into 16-bits then use an ADDiu
264279
MachineBasicBlock &MBB = *MI.getParent();
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
; RUN: llc -mtriple=nanomips -asm-show-inst -verify-machineinstrs < %s | FileCheck %s
2+
3+
; Check if fp is set correctly if function wants to use it.
4+
; We want it to point to -4096 from the beginning of the stack.
5+
define void @test1(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f) #0 {
6+
entry:
7+
; CHECK: save 64, $fp, $ra, $s0, $s1, $s2, $s3, $s4
8+
; CHECK: addiu $fp, $sp, -4032
9+
; CHECK: sw $a0, 32($sp)
10+
; CHECK: restore.jrc 64, $fp, $ra, $s0, $s1, $s2, $s3, $s4
11+
%a.addr = alloca i32, align 4
12+
%b.addr = alloca i32, align 4
13+
%c.addr = alloca i32, align 4
14+
%d.addr = alloca i32, align 4
15+
%e.addr = alloca i32, align 4
16+
%f.addr = alloca i32, align 4
17+
store i32 %a, i32* %a.addr, align 4
18+
store i32 %b, i32* %b.addr, align 4
19+
store i32 %c, i32* %c.addr, align 4
20+
store i32 %d, i32* %d.addr, align 4
21+
store i32 %e, i32* %e.addr, align 4
22+
store i32 %f, i32* %f.addr, align 4
23+
call void asm sideeffect "", "~{$16},~{$17},~{$18},~{$19},~{$20},~{$1}"()
24+
25+
ret void
26+
}
27+
28+
; Check if offsets after fp setup are relative to fp if varible-sized
29+
; objects are present in function.
30+
declare void @callee2(i8*)
31+
define void @test2(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f) #0 {
32+
entry:
33+
; CHECK: save 64, $fp, $ra, $s0, $s1, $s2, $s3, $s4
34+
; CHECK: addiu $fp, $sp, -4032
35+
; CHECK: sw $a0, 4064($fp)
36+
; CHECK: restore.jrc 64, $fp, $ra, $s0, $s1, $s2, $s3, $s4
37+
%a.addr = alloca i32, align 4
38+
%b.addr = alloca i32, align 4
39+
%c.addr = alloca i32, align 4
40+
%d.addr = alloca i32, align 4
41+
%e.addr = alloca i32, align 4
42+
%f.addr = alloca i32, align 4
43+
store i32 %a, i32* %a.addr, align 4
44+
store i32 %b, i32* %b.addr, align 4
45+
store i32 %c, i32* %c.addr, align 4
46+
store i32 %d, i32* %d.addr, align 4
47+
store i32 %e, i32* %e.addr, align 4
48+
store i32 %f, i32* %f.addr, align 4
49+
50+
%0 = alloca i8, i32 %a
51+
call void @callee2(i8* %0)
52+
53+
call void asm sideeffect "", "~{$16},~{$17},~{$18},~{$19},~{$20},~{$1}"()
54+
55+
ret void
56+
}
57+
58+
; Check if offsets after fp setup stays relative to sp if
59+
; function needs stack realignment
60+
declare void @callee3(i32*)
61+
define void @test3(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f) #0 {
62+
entry:
63+
; CHECK: save 64, $fp, $ra, $s0, $s1, $s2, $s3, $s4
64+
; CHECK: addiu $fp, $sp, -4032
65+
; CHECK: sw $a0, 32($sp)
66+
; CHECK: restore.jrc 64, $fp, $ra, $s0, $s1, $s2, $s3, $s4
67+
%a.addr = alloca i32, align 4
68+
%b.addr = alloca i32, align 4
69+
%c.addr = alloca i32, align 4
70+
%d.addr = alloca i32, align 4
71+
%e.addr = alloca i32, align 4
72+
%f.addr = alloca i32, align 4
73+
store i32 %a, i32* %a.addr, align 4
74+
store i32 %b, i32* %b.addr, align 4
75+
store i32 %c, i32* %c.addr, align 4
76+
store i32 %d, i32* %d.addr, align 4
77+
store i32 %e, i32* %e.addr, align 4
78+
store i32 %f, i32* %f.addr, align 4
79+
80+
%0 = alloca i32, align 64
81+
call void @callee3(i32 *%0)
82+
83+
call void asm sideeffect "", "~{$16},~{$17},~{$18},~{$19},~{$20},~{$1}"()
84+
85+
ret void
86+
}
87+
88+
; Check if offsets after fp setup are relative to BasePtr if varible-sized
89+
; objects are present in function and function needs stack realignment
90+
declare void @callee4(i8*, i32*)
91+
define void @test4(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f) #0 {
92+
entry:
93+
; CHECK: save 192, $fp, $ra, $s0, $s1, $s2, $s3, $s4, $s5, $s6, $s7
94+
; CHECK: addiu $fp, $sp, -3904
95+
; CHECK: sw $a0, 148($s7)
96+
; CHECK: restore.jrc 192, $fp, $ra, $s0, $s1, $s2, $s3, $s4, $s5, $s6, $s7
97+
%a.addr = alloca i32, align 4
98+
%b.addr = alloca i32, align 4
99+
%c.addr = alloca i32, align 4
100+
%d.addr = alloca i32, align 4
101+
%e.addr = alloca i32, align 4
102+
%f.addr = alloca i32, align 4
103+
store i32 %a, i32* %a.addr, align 4
104+
store i32 %b, i32* %b.addr, align 4
105+
store i32 %c, i32* %c.addr, align 4
106+
store i32 %d, i32* %d.addr, align 4
107+
store i32 %e, i32* %e.addr, align 4
108+
store i32 %f, i32* %f.addr, align 4
109+
110+
%0 = alloca i8, i32 %a
111+
%1 = alloca i32, align 64
112+
call void @callee4(i8* %0, i32 *%1)
113+
114+
call void asm sideeffect "", "~{$16},~{$17},~{$18},~{$19},~{$20},~{$1}"()
115+
116+
ret void
117+
}
118+
119+
attributes #0 = {"frame-pointer"="all"}
120+
!llvm.module.flags = !{!0}
121+
!0 = !{i32 7, !"frame-pointer", i32 2}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
; RUN: llc -mtriple=nanomips -asm-show-inst -verify-machineinstrs < %s | FileCheck %s
2+
3+
; Check if stack realignment is done using INS instruction
4+
; if function needs it.
5+
declare void @callee(i32*)
6+
define void @test() {
7+
entry:
8+
; CHECK: ins $sp, $zero, 0, 6
9+
%0 = alloca i32, align 64
10+
call void @callee(i32 *%0)
11+
ret void
12+
}
13+

llvm/test/CodeGen/Mips/nanomips/two-step-stack-setup.ll

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,25 +12,3 @@ define void @test1() {
1212
; CHECK: addiu $sp, $sp, 4096
1313
; CHECK: restore.jrc 32, $s0, $s1, $s2, $s3, $s4
1414
}
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)