Skip to content

Commit 47efff7

Browse files
authored
[SystemZ] Emit optional argument area length field (#169679)
The Language Environment (LE) reserves 128 byte for the argument area when the optional field is not present. If the argument area is larger, then the field must be present to guarantee that the space is reserved on stack extension. Creating this field when alloca() is used may reduce the needed stack space in case alloca() causes a stack extension.
1 parent 8e4208f commit 47efff7

File tree

2 files changed

+95
-3
lines changed

2 files changed

+95
-3
lines changed

llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1270,7 +1270,7 @@ void SystemZAsmPrinter::emitFunctionBodyEnd() {
12701270

12711271
static void emitPPA1Flags(std::unique_ptr<MCStreamer> &OutStreamer, bool VarArg,
12721272
bool StackProtector, bool FPRMask, bool VRMask,
1273-
bool EHBlock, bool HasName) {
1273+
bool EHBlock, bool HasArgAreaLength, bool HasName) {
12741274
enum class PPA1Flag1 : uint8_t {
12751275
DSA64Bit = (0x80 >> 0),
12761276
VarArg = (0x80 >> 7),
@@ -1282,8 +1282,9 @@ static void emitPPA1Flags(std::unique_ptr<MCStreamer> &OutStreamer, bool VarArg,
12821282
LLVM_MARK_AS_BITMASK_ENUM(ExternalProcedure)
12831283
};
12841284
enum class PPA1Flag3 : uint8_t {
1285+
HasArgAreaLength = (0x80 >> 1),
12851286
FPRMask = (0x80 >> 2),
1286-
LLVM_MARK_AS_BITMASK_ENUM(FPRMask)
1287+
LLVM_MARK_AS_BITMASK_ENUM(HasArgAreaLength)
12871288
};
12881289
enum class PPA1Flag4 : uint8_t {
12891290
EPMOffsetPresent = (0x80 >> 0),
@@ -1307,6 +1308,9 @@ static void emitPPA1Flags(std::unique_ptr<MCStreamer> &OutStreamer, bool VarArg,
13071308
if (StackProtector)
13081309
Flags2 |= PPA1Flag2::STACKPROTECTOR;
13091310

1311+
if (HasArgAreaLength)
1312+
Flags3 |= PPA1Flag3::HasArgAreaLength; // Add emit ArgAreaLength flag.
1313+
13101314
// SavedGPRMask, SavedFPRMask, and SavedVRMask are precomputed in.
13111315
if (FPRMask)
13121316
Flags3 |= PPA1Flag3::FPRMask; // Add emit FPR mask flag.
@@ -1339,6 +1343,9 @@ static void emitPPA1Flags(std::unique_ptr<MCStreamer> &OutStreamer, bool VarArg,
13391343
OutStreamer->emitInt8(static_cast<uint8_t>(Flags2)); // Flags 2.
13401344

13411345
OutStreamer->AddComment("PPA1 Flags 3");
1346+
if ((Flags3 & PPA1Flag3::HasArgAreaLength) == PPA1Flag3::HasArgAreaLength)
1347+
OutStreamer->AddComment(
1348+
" Bit 1: 1 = Argument Area Length is in optional area");
13421349
if ((Flags3 & PPA1Flag3::FPRMask) == PPA1Flag3::FPRMask)
13431350
OutStreamer->AddComment(" Bit 2: 1 = FP Reg Mask is in optional area");
13441351
OutStreamer->emitInt8(
@@ -1477,19 +1484,38 @@ void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) {
14771484

14781485
bool NeedEmitEHBlock = !MF->getLandingPads().empty();
14791486

1487+
// Optional Argument Area Length.
1488+
// Note: This represents the length of the argument area that we reserve
1489+
// in our stack for setting up arguments for calls to other
1490+
// routines. If this optional field is not set, LE will reserve
1491+
// 128 bytes for the argument area. This optional field is
1492+
// created if greater than 128 bytes is required - to guarantee
1493+
// the required space is reserved on stack extension in the new
1494+
// extension. This optional field is also created if the
1495+
// routine has alloca(). This may reduce stack space
1496+
// if alloca() call causes a stack extension.
1497+
bool HasArgAreaLength =
1498+
(AllocaReg != 0) || (MFFrame.getMaxCallFrameSize() > 128);
1499+
14801500
bool HasName =
14811501
MF->getFunction().hasName() && MF->getFunction().getName().size() > 0;
14821502

14831503
emitPPA1Flags(OutStreamer, MF->getFunction().isVarArg(),
14841504
MFFrame.hasStackProtectorIndex(), SavedFPRMask != 0,
1485-
TargetHasVector && SavedVRMask != 0, NeedEmitEHBlock, HasName);
1505+
TargetHasVector && SavedVRMask != 0, NeedEmitEHBlock,
1506+
HasArgAreaLength, HasName);
14861507

14871508
OutStreamer->AddComment("Length/4 of Parms");
14881509
OutStreamer->emitInt16(
14891510
static_cast<uint16_t>(ZFI->getSizeOfFnParams() / 4)); // Parms/4.
14901511
OutStreamer->AddComment("Length of Code");
14911512
OutStreamer->emitAbsoluteSymbolDiff(FnEndSym, CurrentFnEPMarkerSym, 4);
14921513

1514+
if (HasArgAreaLength) {
1515+
OutStreamer->AddComment("Argument Area Length");
1516+
OutStreamer->emitInt32(MFFrame.getMaxCallFrameSize());
1517+
}
1518+
14931519
// Emit saved FPR mask and offset to FPR save area (0x20 of flags 3).
14941520
if (SavedFPRMask) {
14951521
OutStreamer->AddComment("FPR mask");
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
; RUN: llc < %s -mtriple=s390x-ibm-zos -emit-gnuas-syntax-on-zos=0 | FileCheck %s
2+
%struct.LargeStruct_t = type { [33 x i32] }
3+
4+
@GlobLargeS = hidden global %struct.LargeStruct_t zeroinitializer, align 4
5+
@GlobInt = hidden global i32 0, align 4
6+
7+
; === Check that function with small frame does not emit PPA1 Argument Area Length.
8+
define void @fSmallOutArgArea() {
9+
; CHECK-LABEL: L#EPM_fSmallOutArgArea_0 DS 0H
10+
; CHECK: * Bit 1: 1 = Leaf function
11+
; CHECK: * Bit 2: 0 = Does not use alloca
12+
; CHECK: DC XL4'00000008'
13+
; CHECK: fSmallOutArgArea DS 0H
14+
; CHECK: L#PPA1_fSmallOutArgArea_0 DS 0H
15+
; CHECK: * PPA1 Flags 3
16+
; CHECK: DC XL1'00'
17+
ret void
18+
}
19+
20+
; === Check that function with large frame does emit PPA1 Argument Area Length.
21+
define void @fLargeOutArgArea() {
22+
; CHECK-LABEL: L#EPM_fLargeOutArgArea_0 DS 0H
23+
; CHECK: * Bit 1: 0 = Non-leaf function
24+
; CHECK: * Bit 2: 0 = Does not use alloca
25+
; CHECK: DC XL4'00000220'
26+
; CHECK: fLargeOutArgArea DS 0H
27+
; CHECK: L#PPA1_fLargeOutArgArea_0 DS 0H
28+
; CHECK: * PPA1 Flags 3
29+
; CHECK: * Bit 1: 1 = Argument Area Length is in optional area
30+
; CHECK: DC XL1'40'
31+
; CHECK: * Argument Area Length
32+
; CHECK: DC XL4'00000140'
33+
%1 = load [33 x i32], ptr @GlobLargeS, align 4
34+
call void @fLargeParm([33 x i32] inreg %1)
35+
ret void
36+
}
37+
38+
; === Check that function with parameter does emit PPA1 Length/4 of parms
39+
define void @fLargeParm([33 x i64] inreg %arr) {
40+
; CHECK-LABEL: L#EPM_fLargeParm_0 DS 0H
41+
; CHECK: * Length/4 of Parms
42+
; CHECK: DC XL2'0042'
43+
%1 = extractvalue [33 x i64] %arr, 1
44+
call void @foo(i64 %1)
45+
ret void
46+
}
47+
48+
; === Check that function with alloca call does emit PPA1 Argument Area Length.
49+
define hidden void @fHasAlloca() {
50+
; CHECK-LABEL: L#EPM_fHasAlloca_0 DS 0H
51+
; CHECK: * Bit 2: 1 = Uses alloca
52+
; CHECK: fHasAlloca DS 0H
53+
; CHECK: L#PPA1_fHasAlloca_0 DS 0H
54+
; CHECK: * PPA1 Flags 3
55+
; CHECK: * Bit 1: 1 = Argument Area Length is in optional area
56+
; CHECK: DC XL1'40'
57+
; CHECK: * Argument Area Length
58+
; CHECK: DC XL4'00000040'
59+
%p = alloca ptr, align 4
60+
%1 = load i32, ptr @GlobInt, align 4
61+
%2 = alloca i8, i32 %1, align 8
62+
store ptr %2, ptr %p, align 4
63+
ret void
64+
}
65+
66+
declare void @foo(i64)

0 commit comments

Comments
 (0)