Skip to content

[SystemZ] Address issue with supper large stack frames #96318

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
42 changes: 42 additions & 0 deletions llvm/test/CodeGen/SystemZ/systemz-large-stack-frames.ll
Original file line number Diff line number Diff line change
@@ -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
}
8 changes: 4 additions & 4 deletions llvm/test/CodeGen/SystemZ/zos-prologue-epilog.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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)
Expand All @@ -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
Expand Down
Loading