Skip to content

Commit 01f28c7

Browse files
zibi2AlexisPerry
authored andcommitted
[SystemZ] Address issue with supper large stack frames (llvm#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! `
1 parent ef73232 commit 01f28c7

File tree

3 files changed

+68
-4
lines changed

3 files changed

+68
-4
lines changed

llvm/lib/Target/SystemZ/SystemZFrameLowering.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1475,6 +1475,28 @@ void SystemZXPLINKFrameLowering::processFunctionBeforeFrameFinalized(
14751475
// with existing compilers.
14761476
MFFrame.setMaxCallFrameSize(
14771477
std::max(64U, (unsigned)alignTo(MFFrame.getMaxCallFrameSize(), 64)));
1478+
1479+
// Add frame values with positive object offsets. Since the displacement from
1480+
// the SP/FP is calculated by ObjectOffset + StackSize + Bias, object offsets
1481+
// with positive values are in the caller's stack frame. We need to include
1482+
// that since it is accessed by displacement to SP/FP.
1483+
int64_t LargestArgOffset = 0;
1484+
for (int I = MFFrame.getObjectIndexBegin(); I != 0; ++I) {
1485+
if (MFFrame.getObjectOffset(I) >= 0) {
1486+
int64_t ObjOffset = MFFrame.getObjectOffset(I) + MFFrame.getObjectSize(I);
1487+
LargestArgOffset = std::max(ObjOffset, LargestArgOffset);
1488+
}
1489+
}
1490+
1491+
uint64_t MaxReach = (StackSize + Regs.getCallFrameSize() +
1492+
Regs.getStackPointerBias() + LargestArgOffset);
1493+
1494+
if (!isUInt<12>(MaxReach)) {
1495+
// We may need register scavenging slots if some parts of the frame
1496+
// are outside the reach of an unsigned 12-bit displacement.
1497+
RS->addScavengingFrameIndex(MFFrame.CreateStackObject(8, Align(8), false));
1498+
RS->addScavengingFrameIndex(MFFrame.CreateStackObject(8, Align(8), false));
1499+
}
14781500
}
14791501

14801502
// Determines the size of the frame, and creates the deferred spill objects.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
; REQUIRES: asserts
2+
; REQUIRES: systemz-registered-target
3+
; Used to fail with: LLVM ERROR: Error while trying to spill R5D from class ADDR64Bit: Cannot scavenge register without an emergency spill slot!
4+
5+
6+
; RUN: llc %s --mtriple s390x-ibm-zos -filetype obj -o %t
7+
8+
; ModuleID = 'main.cpp'
9+
source_filename = "main.cpp"
10+
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"
11+
target triple = "x86_64-unknown-linux-gnu"
12+
13+
; ModuleID = 'large-stack-frames.cpp'
14+
source_filename = "large-stack-frames.cpp"
15+
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"
16+
target triple = "s390x-ibm-zos"
17+
%struct.slice.108 = type { ptr, ptr, [8 x i64], [8 x i64], [8 x i64] }
18+
declare void @dealloc(ptr) local_unnamed_addr #0
19+
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 {
20+
entry:
21+
%ref.tmp = alloca %struct.slice.108, align 8
22+
br i1 %1, label %error, label %if.end95
23+
if.end95:
24+
br i1 %1, label %if.else.i1546, label %object.exit1547
25+
if.else.i1546:
26+
tail call void @dealloc(ptr noundef nonnull %0)
27+
br label %object.exit1547
28+
object.exit1547:
29+
%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)
30+
ret void
31+
error:
32+
ret void
33+
}
34+
declare dso_local fastcc ptr @slice([26 x i64], i32, ptr, ptr, i32) unnamed_addr #0
35+
define internal ptr @get_float(ptr %itemp, ptr %2) #0 {
36+
entry:
37+
ret ptr %2
38+
}
39+
define internal i32 @object(ptr %itemp, ptr %obj) #0 {
40+
entry:
41+
ret i32 1
42+
}

llvm/test/CodeGen/SystemZ/zos-prologue-epilog.ll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ define i64 @func4(i64 %n) {
303303
; Require saving of r4 and in addition, a displacement large enough
304304
; to force use of agfi before stmg.
305305
; CHECK64: lgr 0, 4
306-
; CHECK64: agfi 4, -1040192
306+
; CHECK64: agfi 4, -1040224
307307
; CHECK64: stmg 4, 10, 2048(4)
308308
; CHECK64: lgr 8, 4
309309
; CHECK64: basr 7, 6
@@ -317,7 +317,7 @@ define i64 @func5(i64 %n) {
317317
}
318318

319319
; CHECK-LABEL: large_stack
320-
; CHECK64: agfi 4, -1048768
320+
; CHECK64: agfi 4, -1048800
321321
; CHECK64-NEXT: llgt 3, 1208
322322
; CHECK64-NEXT: cg 4, 64(3)
323323
; CHECK64-NEXT: jhe
@@ -332,7 +332,7 @@ define void @large_stack0() {
332332
}
333333

334334
; CHECK-LABEL: large_stack1
335-
; CHECK64: agfi 4, -1048768
335+
; CHECK64: agfi 4, -1048800
336336
; CHECK64: lgr 0, 3
337337
; CHECK64: llgt 3, 1208
338338
; CHECK64: cg 4, 64(3)
@@ -358,7 +358,7 @@ define void @large_stack1(i64 %n1, i64 %n2, i64 %n3) {
358358
; CHECK-LABEL: large_stack2
359359
; CHECK64: lgr 0, 4
360360
; CHECK64: stg 3, 2192(4)
361-
; CHECK64: agfi 4, -1048768
361+
; CHECK64: agfi 4, -1048800
362362
; CHECK64: llgt 3, 1208
363363
; CHECK64: cg 4, 64(3)
364364
; CHECK64: jhe L#BB8_2

0 commit comments

Comments
 (0)