[llvm] 3ab1c97 - [AVR] Fix stack size in functions with a frame pointer

Ayke van Laethem via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 16 04:54:16 PDT 2020


Author: Ayke van Laethem
Date: 2020-06-16T13:53:32+02:00
New Revision: 3ab1c97e35164f51f97b5d727d1c684ed1c1e213

URL: https://github.com/llvm/llvm-project/commit/3ab1c97e35164f51f97b5d727d1c684ed1c1e213
DIFF: https://github.com/llvm/llvm-project/commit/3ab1c97e35164f51f97b5d727d1c684ed1c1e213.diff

LOG: [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

Added: 
    

Modified: 
    llvm/lib/Target/AVR/AVRFrameLowering.cpp
    llvm/test/CodeGen/AVR/calling-conv/c/stack.ll
    llvm/test/CodeGen/AVR/return.ll
    llvm/test/CodeGen/AVR/varargs.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/AVR/AVRFrameLowering.cpp b/llvm/lib/Target/AVR/AVRFrameLowering.cpp
index 7fc15f0af77d..a1cb29d08360 100644
--- a/llvm/lib/Target/AVR/AVRFrameLowering.cpp
+++ b/llvm/lib/Target/AVR/AVRFrameLowering.cpp
@@ -65,13 +65,6 @@ void AVRFrameLowering::emitPrologue(MachineFunction &MF,
         .setMIFlag(MachineInstr::FrameSetup);
   }
 
-  // Save the frame pointer if we have one.
-  if (HasFP) {
-    BuildMI(MBB, MBBI, DL, TII.get(AVR::PUSHWRr))
-        .addReg(AVR::R29R28, RegState::Kill)
-        .setMIFlag(MachineInstr::FrameSetup);
-  }
-
   // Emit special prologue code to save R1, R0 and SREG in interrupt/signal
   // handlers before saving any other registers.
   if (AFI->isInterruptOrSignalHandler()) {
@@ -168,9 +161,6 @@ void AVRFrameLowering::emitEpilogue(MachineFunction &MF,
     BuildMI(MBB, MBBI, DL, TII.get(AVR::POPWRd), AVR::R1R0);
   }
 
-  if (hasFP(MF))
-    BuildMI(MBB, MBBI, DL, TII.get(AVR::POPWRd), AVR::R29R28);
-
   // Early exit if there is no need to restore the frame pointer.
   if (!FrameSize) {
     return;
@@ -411,8 +401,10 @@ void AVRFrameLowering::determineCalleeSaves(MachineFunction &MF,
   TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
 
   // If we have a frame pointer, the Y register needs to be saved as well.
-  // We don't do that here however - the prologue and epilogue generation
-  // code will handle it specially.
+  if (hasFP(MF)) {
+    SavedRegs.set(AVR::R29);
+    SavedRegs.set(AVR::R28);
+  }
 }
 /// The frame analyzer pass.
 ///

diff  --git a/llvm/test/CodeGen/AVR/calling-conv/c/stack.ll b/llvm/test/CodeGen/AVR/calling-conv/c/stack.ll
index 52b6427476ab..00ff7d1acd80 100644
--- a/llvm/test/CodeGen/AVR/calling-conv/c/stack.ll
+++ b/llvm/test/CodeGen/AVR/calling-conv/c/stack.ll
@@ -11,15 +11,15 @@ define void @ret_void_args_i64_i64_i32(i64 %a, i64 %b, i32 %c) {
   ; CHECK-NEXT: in      r29, 62
 
   ; Load the top two bytes from the 32-bit int.
-  ; CHECK-NEXT: ldd     r24, Y+5
-  ; CHECK-NEXT: ldd     r25, Y+6
+  ; CHECK-NEXT: ldd     r24, Y+7
+  ; CHECK-NEXT: ldd     r25, Y+8
   ; Store the top two bytes of the 32-bit int to memory.
   ; CHECK-NEXT: sts     7, r25
   ; CHECK-NEXT: sts     6, r24
 
   ; Load the bottom two bytes from the 32-bit int.
-  ; CHECK-NEXT: ldd     r24, Y+3
-  ; CHECK-NEXT: ldd     r25, Y+4
+  ; CHECK-NEXT: ldd     r24, Y+5
+  ; CHECK-NEXT: ldd     r25, Y+6
   ; Store the bottom two bytes of the 32-bit int to memory.
   ; CHECK-NEXT: sts     5, r25
   ; CHECK-NEXT: sts     4, r24

diff  --git a/llvm/test/CodeGen/AVR/return.ll b/llvm/test/CodeGen/AVR/return.ll
index 70d281ea4c08..f5f62aedc958 100644
--- a/llvm/test/CodeGen/AVR/return.ll
+++ b/llvm/test/CodeGen/AVR/return.ll
@@ -96,14 +96,14 @@ define i64 @return64_arg2(i64 %x, i64 %y, i64 %z) {
 ; CHECK-LABEL: return64_arg2:
 ; CHECK: push r28
 ; CHECK: push r29
-; CHECK: ldd r18, Y+3
-; CHECK: ldd r19, Y+4
-; CHECK: ldd r20, Y+5
-; CHECK: ldd r21, Y+6
-; CHECK: ldd r22, Y+7
-; CHECK: ldd r23, Y+8
-; CHECK: ldd r24, Y+9
-; CHECK: ldd r25, Y+10
+; CHECK: ldd r18, Y+5
+; CHECK: ldd r19, Y+6
+; CHECK: ldd r20, Y+7
+; CHECK: ldd r21, Y+8
+; CHECK: ldd r22, Y+9
+; CHECK: ldd r23, Y+10
+; CHECK: ldd r24, Y+11
+; CHECK: ldd r25, Y+12
 ; CHECK: pop r29
 ; CHECK: pop r28
     ret i64 %z
@@ -113,10 +113,10 @@ define i32 @return64_trunc(i32 %a, i32 %b, i32 %c, i64 %d) {
 ; CHECK-LABEL: return64_trunc:
 ; CHECK: push r28
 ; CHECK: push r29
-; CHECK: ldd r22, Y+3
-; CHECK: ldd r23, Y+4
-; CHECK: ldd r24, Y+5
-; CHECK: ldd r25, Y+6
+; CHECK: ldd r22, Y+5
+; CHECK: ldd r23, Y+6
+; CHECK: ldd r24, Y+7
+; CHECK: ldd r25, Y+8
 ; CHECK: pop r29
 ; CHECK: pop r28
   %result = trunc i64 %d to i32

diff  --git a/llvm/test/CodeGen/AVR/varargs.ll b/llvm/test/CodeGen/AVR/varargs.ll
index 7224ac3f2b8d..c2046d84b48b 100644
--- a/llvm/test/CodeGen/AVR/varargs.ll
+++ b/llvm/test/CodeGen/AVR/varargs.ll
@@ -7,12 +7,12 @@ declare void @llvm.va_end(i8*)
 define i16 @varargs1(i8* nocapture %x, ...) {
 ; CHECK-LABEL: varargs1:
 ; CHECK: movw r20, r28
-; CHECK: subi r20, 217
+; CHECK: subi r20, 215
 ; CHECK: sbci r21, 255
 ; CHECK: movw r24, r28
 ; CHECK: adiw r24, 3
-; CHECK: ldd r22, Y+37
-; CHECK: ldd r23, Y+38
+; CHECK: ldd r22, Y+39
+; CHECK: ldd r23, Y+40
 ; CHECK: call
   %buffer = alloca [32 x i8]
   %ap = alloca i8*


        


More information about the llvm-commits mailing list