[llvm] [SystemZ][z/OS] Allocate a stack frame when callee-saved registers are saved (PR #226681)

via llvm-commits llvm-commits at lists.llvm.org
Sat Sep 26 04:48:40 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-systemz

Author: MMS IT GmbH (mms-it-ch)

<details>
<summary>Changes</summary>

On z/OS (XPLINK64), a function without calls and without stack objects that uses callee-saved registers got a stack size of 0. No stack frame was allocated, so `STMG` stored the registers relative to the unchanged stack pointer, i.e. into the register save area of the caller's DSA, overwriting the caller's saved return address. Only skip the frame when there is nothing to save.

Two existing tests (`zos-ret-addr.ll`, `zos-frameaddr.ll`) encoded this store into the caller's frame and are updated; the values returned by `llvm.returnaddress`/`llvm.frameaddress` are unchanged (the old stack pointer is still read from offset 2048 of the current frame). New test `zos-frame-callee-saved.ll`.

Found with GMP 6.3.0 on z/OS 3.1 (`mpn_mul_1`): code after the call ran twice, then S0C4/S0C6. With this change GMP works.

Tests: `llvm-lit test/CodeGen/SystemZ test/MC/SystemZ test/MC/GOFF` passes (1304 passed, 19 unsupported).

Fixes #<!-- -->226657.

Assisted-by: Claude Code (Anthropic)

🤖 Generated with [Claude Code](https://claude.com/claude-code)


---
Full diff: https://github.com/llvm/llvm-project/pull/226681.diff


4 Files Affected:

- (modified) llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp (+5-1) 
- (added) llvm/test/CodeGen/SystemZ/zos-frame-callee-saved.ll (+28) 
- (modified) llvm/test/CodeGen/SystemZ/zos-frameaddr.ll (+10-2) 
- (modified) llvm/test/CodeGen/SystemZ/zos-ret-addr.ll (+10-2) 


``````````diff
diff --git a/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp b/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp
index 145db33a41c74..0762465a61431 100644
--- a/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp
@@ -1557,7 +1557,11 @@ void SystemZXPLINKFrameLowering::determineFrameLayout(
       static_cast<SystemZXPLINK64Registers *>(Subtarget.getSpecialRegisters());
 
   uint64_t StackSize = MFFrame.getStackSize();
-  if (StackSize == 0)
+  // A function which saves callee-saved registers needs a register save area of
+  // its own, even if it has no other stack objects. Otherwise the registers are
+  // stored relative to the unchanged stack pointer, i.e. into the save area of
+  // the caller's DSA.
+  if (StackSize == 0 && MFFrame.getCalleeSavedInfo().empty())
     return;
 
   // Add the size of the register save area and the reserved area to the size.
diff --git a/llvm/test/CodeGen/SystemZ/zos-frame-callee-saved.ll b/llvm/test/CodeGen/SystemZ/zos-frame-callee-saved.ll
new file mode 100644
index 0000000000000..90c9dea227e8c
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/zos-frame-callee-saved.ll
@@ -0,0 +1,28 @@
+; A function without calls and without stack objects that uses callee-saved
+; registers must get a stack frame of its own. Otherwise the registers are
+; stored relative to the unchanged stack pointer, i.e. into the register save
+; area of the caller's DSA, overwriting the caller's saved return address.
+;
+; RUN: llc < %s -mtriple=s390x-ibm-zos | FileCheck %s
+
+define void @leaf() {
+; CHECK-LABEL: leaf DS 0H
+; CHECK:         stmg 6,9,1936(4)
+; CHECK-NEXT:    L#stack_update0 DS 0H
+; CHECK-NEXT:    aghi 4,-128
+; CHECK:         lmg 7,9,2072(4)
+; CHECK-NEXT:    aghi 4,128
+; CHECK-NEXT:    b 2(7)
+  call void asm sideeffect "", "~{r8},~{r9}"()
+  ret void
+}
+
+; A true leaf (no callee-saved registers) still gets no stack frame.
+define i64 @trueleaf(i64 %a) {
+; CHECK-LABEL: trueleaf DS 0H
+; CHECK-NOT:     stmg
+; CHECK-NOT:     aghi 4,
+; CHECK:         b 2(7)
+  %r = add i64 %a, 1
+  ret i64 %r
+}
diff --git a/llvm/test/CodeGen/SystemZ/zos-frameaddr.ll b/llvm/test/CodeGen/SystemZ/zos-frameaddr.ll
index 66177d56eb6d5..b25f710657058 100644
--- a/llvm/test/CodeGen/SystemZ/zos-frameaddr.ll
+++ b/llvm/test/CodeGen/SystemZ/zos-frameaddr.ll
@@ -34,7 +34,11 @@ entry:
 ; Check the caller's frame address.
 define ptr @fpcaller() nounwind "backchain" {
 ; CHECK-LABEL: fpcaller DS 0H
-; CHECK:         stmg 4,7,2048(4)
+; CHECK:         stmg 4,7,1920(4)
+; CHECK-NEXT:    L#stack_update1 DS 0H
+; CHECK-NEXT:    aghi 4,-128
+; CHECK-NEXT:    *FENCE
+; CHECK-NEXT:    L#end_of_prologue1 DS 0H
 ; CHECK-NEXT:    lg 3,2048(4)
 ; CHECK-NEXT:    lmg 4,7,2048(4)
 ; CHECK-NEXT:    b 2(7)
@@ -46,7 +50,11 @@ entry:
 ; Check the caller's frame address.
 define ptr @fpcallercaller() nounwind "backchain" {
 ; CHECK-LABEL: fpcallercaller DS 0H
-; CHECK:         stmg 4,7,2048(4)
+; CHECK:         stmg 4,7,1920(4)
+; CHECK-NEXT:    L#stack_update2 DS 0H
+; CHECK-NEXT:    aghi 4,-128
+; CHECK-NEXT:    *FENCE
+; CHECK-NEXT:    L#end_of_prologue2 DS 0H
 ; CHECK-NEXT:    lg 1,2048(4)
 ; CHECK-NEXT:    lg 3,0(1)
 ; CHECK-NEXT:    lmg 4,7,2048(4)
diff --git a/llvm/test/CodeGen/SystemZ/zos-ret-addr.ll b/llvm/test/CodeGen/SystemZ/zos-ret-addr.ll
index ce59020dda4b2..aa7e99fcfa57c 100644
--- a/llvm/test/CodeGen/SystemZ/zos-ret-addr.ll
+++ b/llvm/test/CodeGen/SystemZ/zos-ret-addr.ll
@@ -14,7 +14,11 @@ entry:
 ; Check the caller's return address.
 define ptr @rtcaller() nounwind "backchain" {
 ; CHECK-LABEL: rtcaller DS 0H
-; CHECK:         stmg 4,7,2048(4)
+; CHECK:         stmg 4,7,1920(4)
+; CHECK-NEXT:    L#stack_update0 DS 0H
+; CHECK-NEXT:    aghi 4,-128
+; CHECK-NEXT:    *FENCE
+; CHECK-NEXT:    L#end_of_prologue0 DS 0H
 ; CHECK-NEXT:    lg 1,2048(4)
 ; CHECK-NEXT:    lg 3,24(1)
 ; CHECK-NEXT:    lmg 4,7,2048(4)
@@ -27,7 +31,11 @@ entry:
 ; Check the caller's caller's return address.
 define ptr @rtcallercaller() nounwind "backchain" {
 ; CHECK-LABEL: rtcallercaller DS 0H
-; CHECK:         stmg 4,7,2048(4)
+; CHECK:         stmg 4,7,1920(4)
+; CHECK-NEXT:    L#stack_update1 DS 0H
+; CHECK-NEXT:    aghi 4,-128
+; CHECK-NEXT:    *FENCE
+; CHECK-NEXT:    L#end_of_prologue1 DS 0H
 ; CHECK-NEXT:    lg 1,2048(4)
 ; CHECK-NEXT:    lg 1,0(1)
 ; CHECK-NEXT:    lg 3,24(1)

``````````

</details>


https://github.com/llvm/llvm-project/pull/226681


More information about the llvm-commits mailing list