Skip to content

Commit 143e146

Browse files
aykevldylanmckay
authored andcommitted
[AVR] Fix stack size in functions with a frame pointer
This patch fixes a bug in stack save/restore code. Because the frame pointer was saved/restored manually (not by marking it as clobbered) the StackSize variable was not updated accordingly. Most code still worked, but code that tried to load a parameter passed on the stack did not. This commit fixes this by marking the frame pointer as a callee-clobbered register. This will let it be saved without any effort in prolog/epilog code and will make sure the correct address is calculated for loading parameters that are passed on the stack. This approach is used by most other targets (such as X86, AArch64 and RISC-V). Differential Revision: https://reviews.llvm.org/D78579
1 parent 6b2445d commit 143e146

File tree

4 files changed

+23
-31
lines changed

4 files changed

+23
-31
lines changed

llvm/lib/Target/AVR/AVRFrameLowering.cpp

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,6 @@ void AVRFrameLowering::emitPrologue(MachineFunction &MF,
6767
.setMIFlag(MachineInstr::FrameSetup);
6868
}
6969

70-
// Save the frame pointer if we have one.
71-
if (HasFP) {
72-
BuildMI(MBB, MBBI, DL, TII.get(AVR::PUSHWRr))
73-
.addReg(AVR::R29R28, RegState::Kill)
74-
.setMIFlag(MachineInstr::FrameSetup);
75-
}
76-
7770
// Emit special prologue code to save R1, R0 and SREG in interrupt/signal
7871
// handlers before saving any other registers.
7972
if (AFI->isInterruptOrSignalHandler()) {
@@ -170,9 +163,6 @@ void AVRFrameLowering::emitEpilogue(MachineFunction &MF,
170163
BuildMI(MBB, MBBI, DL, TII.get(AVR::POPWRd), AVR::R1R0);
171164
}
172165

173-
if (hasFP(MF))
174-
BuildMI(MBB, MBBI, DL, TII.get(AVR::POPWRd), AVR::R29R28);
175-
176166
// Early exit if there is no need to restore the frame pointer.
177167
if (!FrameSize) {
178168
return;
@@ -415,8 +405,10 @@ void AVRFrameLowering::determineCalleeSaves(MachineFunction &MF,
415405
TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
416406

417407
// If we have a frame pointer, the Y register needs to be saved as well.
418-
// We don't do that here however - the prologue and epilogue generation
419-
// code will handle it specially.
408+
if (hasFP(MF)) {
409+
SavedRegs.set(AVR::R29);
410+
SavedRegs.set(AVR::R28);
411+
}
420412
}
421413
/// The frame analyzer pass.
422414
///

llvm/test/CodeGen/AVR/calling-conv/c/stack.ll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ define void @ret_void_args_i64_i64_i32(i64 %a, i64 %b, i32 %c) {
1111
; CHECK-NEXT: in r29, 62
1212

1313
; Load the top two bytes from the 32-bit int.
14-
; CHECK-NEXT: ldd r24, Y+5
15-
; CHECK-NEXT: ldd r25, Y+6
14+
; CHECK-NEXT: ldd r24, Y+7
15+
; CHECK-NEXT: ldd r25, Y+8
1616
; Store the top two bytes of the 32-bit int to memory.
1717
; CHECK-NEXT: sts 7, r25
1818
; CHECK-NEXT: sts 6, r24
1919

2020
; Load the bottom two bytes from the 32-bit int.
21-
; CHECK-NEXT: ldd r24, Y+3
22-
; CHECK-NEXT: ldd r25, Y+4
21+
; CHECK-NEXT: ldd r24, Y+5
22+
; CHECK-NEXT: ldd r25, Y+6
2323
; Store the bottom two bytes of the 32-bit int to memory.
2424
; CHECK-NEXT: sts 5, r25
2525
; CHECK-NEXT: sts 4, r24

llvm/test/CodeGen/AVR/return.ll

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -96,14 +96,14 @@ define i64 @return64_arg2(i64 %x, i64 %y, i64 %z) {
9696
; CHECK-LABEL: return64_arg2:
9797
; CHECK: push r28
9898
; CHECK: push r29
99-
; CHECK: ldd r18, Y+3
100-
; CHECK: ldd r19, Y+4
101-
; CHECK: ldd r20, Y+5
102-
; CHECK: ldd r21, Y+6
103-
; CHECK: ldd r22, Y+7
104-
; CHECK: ldd r23, Y+8
105-
; CHECK: ldd r24, Y+9
106-
; CHECK: ldd r25, Y+10
99+
; CHECK: ldd r18, Y+5
100+
; CHECK: ldd r19, Y+6
101+
; CHECK: ldd r20, Y+7
102+
; CHECK: ldd r21, Y+8
103+
; CHECK: ldd r22, Y+9
104+
; CHECK: ldd r23, Y+10
105+
; CHECK: ldd r24, Y+11
106+
; CHECK: ldd r25, Y+12
107107
; CHECK: pop r29
108108
; CHECK: pop r28
109109
ret i64 %z
@@ -113,10 +113,10 @@ define i32 @return64_trunc(i32 %a, i32 %b, i32 %c, i64 %d) {
113113
; CHECK-LABEL: return64_trunc:
114114
; CHECK: push r28
115115
; CHECK: push r29
116-
; CHECK: ldd r22, Y+3
117-
; CHECK: ldd r23, Y+4
118-
; CHECK: ldd r24, Y+5
119-
; CHECK: ldd r25, Y+6
116+
; CHECK: ldd r22, Y+5
117+
; CHECK: ldd r23, Y+6
118+
; CHECK: ldd r24, Y+7
119+
; CHECK: ldd r25, Y+8
120120
; CHECK: pop r29
121121
; CHECK: pop r28
122122
%result = trunc i64 %d to i32

llvm/test/CodeGen/AVR/varargs.ll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ declare void @llvm.va_end(i8*)
77
define i16 @varargs1(i8* nocapture %x, ...) {
88
; CHECK-LABEL: varargs1:
99
; CHECK: movw r20, r28
10-
; CHECK: subi r20, 217
10+
; CHECK: subi r20, 215
1111
; CHECK: sbci r21, 255
1212
; CHECK: movw r24, r28
1313
; CHECK: adiw r24, 3
14-
; CHECK: ldd r22, Y+37
15-
; CHECK: ldd r23, Y+38
14+
; CHECK: ldd r22, Y+39
15+
; CHECK: ldd r23, Y+40
1616
; CHECK: call
1717
%buffer = alloca [32 x i8]
1818
%ap = alloca i8*

0 commit comments

Comments
 (0)