[llvm] 1de1818 - [SystemZ] Address issue with supper large stack frames (#96318)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 27 06:23:39 PDT 2024


Author: Zibi Sarbinowski
Date: 2024-06-27T09:23:35-04:00
New Revision: 1de1818fabb474d724741ee28baa5a7e1d972b00

URL: https://github.com/llvm/llvm-project/commit/1de1818fabb474d724741ee28baa5a7e1d972b00
DIFF: https://github.com/llvm/llvm-project/commit/1de1818fabb474d724741ee28baa5a7e1d972b00.diff

LOG: [SystemZ] Address issue with supper large stack frames (#96318)

This PR fixes the following failure by adjusting the calculation of
maximum displacement from Stack Pointer.

`LLVM ERROR: Error while trying to spill R5D from class ADDR64Bit:
Cannot scavenge register without an emergency spill slot!
`

Added: 
    llvm/test/CodeGen/SystemZ/systemz-large-stack-frames.ll

Modified: 
    llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp
    llvm/test/CodeGen/SystemZ/zos-prologue-epilog.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp b/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp
index fa20977ec0187..a769fdeff5684 100644
--- a/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp
@@ -1475,6 +1475,28 @@ void SystemZXPLINKFrameLowering::processFunctionBeforeFrameFinalized(
   // with existing compilers.
   MFFrame.setMaxCallFrameSize(
       std::max(64U, (unsigned)alignTo(MFFrame.getMaxCallFrameSize(), 64)));
+
+  // Add frame values with positive object offsets. Since the displacement from
+  // the SP/FP is calculated by ObjectOffset + StackSize + Bias, object offsets
+  // with positive values are in the caller's stack frame. We need to include
+  // that since it is accessed by displacement to SP/FP.
+  int64_t LargestArgOffset = 0;
+  for (int I = MFFrame.getObjectIndexBegin(); I != 0; ++I) {
+    if (MFFrame.getObjectOffset(I) >= 0) {
+      int64_t ObjOffset = MFFrame.getObjectOffset(I) + MFFrame.getObjectSize(I);
+      LargestArgOffset = std::max(ObjOffset, LargestArgOffset);
+    }
+  }
+
+  uint64_t MaxReach = (StackSize + Regs.getCallFrameSize() +
+                       Regs.getStackPointerBias() + LargestArgOffset);
+
+  if (!isUInt<12>(MaxReach)) {
+    // We may need register scavenging slots if some parts of the frame
+    // are outside the reach of an unsigned 12-bit displacement.
+    RS->addScavengingFrameIndex(MFFrame.CreateStackObject(8, Align(8), false));
+    RS->addScavengingFrameIndex(MFFrame.CreateStackObject(8, Align(8), false));
+  }
 }
 
 // Determines the size of the frame, and creates the deferred spill objects.

diff  --git a/llvm/test/CodeGen/SystemZ/systemz-large-stack-frames.ll b/llvm/test/CodeGen/SystemZ/systemz-large-stack-frames.ll
new file mode 100644
index 0000000000000..51997a6c17c65
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/systemz-large-stack-frames.ll
@@ -0,0 +1,42 @@
+; REQUIRES: asserts
+; REQUIRES: systemz-registered-target
+; Used to fail with: LLVM ERROR: Error while trying to spill R5D from class ADDR64Bit: Cannot scavenge register without an emergency spill slot!
+
+
+; RUN: llc %s --mtriple s390x-ibm-zos -filetype obj -o %t
+
+; ModuleID = 'main.cpp'
+source_filename = "main.cpp"
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; ModuleID = 'large-stack-frames.cpp'
+source_filename = "large-stack-frames.cpp"
+target datalayout = "E-m:l-p1:32:32-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64"
+target triple = "s390x-ibm-zos"
+%struct.slice.108 = type { ptr, ptr, [8 x i64], [8 x i64], [8 x i64] }
+declare void @dealloc(ptr) local_unnamed_addr #0
+define internal void @foo([26 x i64] %co1, [26 x i64] %co2, [26 x i64] %co3, [26 x i64] %co4, [26 x i64] %co5, [26 x i64] %co6, [26 x i64] %co7, [26 x i64] %co8, i32 %skip_dispatch, ptr %0, i1 %1) #0 {
+entry:
+  %ref.tmp = alloca %struct.slice.108, align 8
+  br i1 %1, label %error, label %if.end95
+if.end95:
+  br i1 %1, label %if.else.i1546, label %object.exit1547
+if.else.i1546:
+  tail call void @dealloc(ptr noundef nonnull %0)
+  br label %object.exit1547
+object.exit1547:
+  %call96 = tail call fastcc noundef ptr @slice([26 x i64] inreg %co7, i32 noundef signext 1, ptr noundef nonnull @get_float, ptr noundef nonnull @object, i32 noundef signext 0)
+  ret void
+error:
+  ret void
+}
+declare dso_local fastcc ptr @slice([26 x i64], i32, ptr, ptr, i32) unnamed_addr #0
+define internal ptr @get_float(ptr %itemp, ptr %2) #0 {
+entry:
+  ret ptr %2
+}
+define internal i32 @object(ptr %itemp, ptr %obj) #0 {
+entry:
+  ret i32 1
+}

diff  --git a/llvm/test/CodeGen/SystemZ/zos-prologue-epilog.ll b/llvm/test/CodeGen/SystemZ/zos-prologue-epilog.ll
index d3e5823fcb1fe..3a8e3a35e2ef7 100644
--- a/llvm/test/CodeGen/SystemZ/zos-prologue-epilog.ll
+++ b/llvm/test/CodeGen/SystemZ/zos-prologue-epilog.ll
@@ -303,7 +303,7 @@ define i64 @func4(i64 %n) {
 ; Require saving of r4 and in addition, a displacement large enough
 ; to force use of agfi before stmg.
 ; CHECK64: lgr	0, 4
-; CHECK64: agfi	4, -1040192
+; CHECK64: agfi	4, -1040224
 ; CHECK64: stmg  4, 10, 2048(4)
 ; CHECK64: lgr     8, 4
 ; CHECK64: basr   7, 6
@@ -317,7 +317,7 @@ define i64 @func5(i64 %n) {
 }
 
 ; CHECK-LABEL: large_stack
-; CHECK64: agfi  4, -1048768
+; CHECK64: agfi  4, -1048800
 ; CHECK64-NEXT: llgt  3, 1208
 ; CHECK64-NEXT: cg  4, 64(3)
 ; CHECK64-NEXT: jhe
@@ -332,7 +332,7 @@ define void @large_stack0() {
 }
 
 ; CHECK-LABEL: large_stack1
-; CHECK64: agfi  4, -1048768
+; CHECK64: agfi  4, -1048800
 ; CHECK64: lgr 0, 3
 ; CHECK64: llgt  3, 1208
 ; CHECK64: cg  4, 64(3)
@@ -358,7 +358,7 @@ define void @large_stack1(i64 %n1, i64 %n2, i64 %n3) {
 ; CHECK-LABEL: large_stack2
 ; CHECK64: lgr 0, 4
 ; CHECK64: stg 3, 2192(4)
-; CHECK64: agfi  4, -1048768
+; CHECK64: agfi  4, -1048800
 ; CHECK64: llgt  3, 1208
 ; CHECK64: cg  4, 64(3)
 ; CHECK64: jhe L#BB8_2


        


More information about the llvm-commits mailing list