-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[SystemZ] Emit optional argument area length field #169679
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
Conversation
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 reseverd on stack extension. Creating this field when alloca() is used may reduce the needed stack space in case alloca() causes a stack extension.
|
@llvm/pr-subscribers-backend-systemz Author: Kai Nacke (redstar) ChangesThe 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 reseverd on stack Full diff: https://github.com/llvm/llvm-project/pull/169679.diff 2 Files Affected:
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
index e31d7c6a86476..f6dd60fa8b199 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
@@ -1270,7 +1270,7 @@ void SystemZAsmPrinter::emitFunctionBodyEnd() {
static void emitPPA1Flags(std::unique_ptr<MCStreamer> &OutStreamer, bool VarArg,
bool StackProtector, bool FPRMask, bool VRMask,
- bool EHBlock, bool HasName) {
+ bool EHBlock, bool HasArgAreaLength, bool HasName) {
enum class PPA1Flag1 : uint8_t {
DSA64Bit = (0x80 >> 0),
VarArg = (0x80 >> 7),
@@ -1282,8 +1282,9 @@ static void emitPPA1Flags(std::unique_ptr<MCStreamer> &OutStreamer, bool VarArg,
LLVM_MARK_AS_BITMASK_ENUM(ExternalProcedure)
};
enum class PPA1Flag3 : uint8_t {
+ HasArgAreaLength = (0x80 >> 1),
FPRMask = (0x80 >> 2),
- LLVM_MARK_AS_BITMASK_ENUM(FPRMask)
+ LLVM_MARK_AS_BITMASK_ENUM(HasArgAreaLength)
};
enum class PPA1Flag4 : uint8_t {
EPMOffsetPresent = (0x80 >> 0),
@@ -1307,6 +1308,9 @@ static void emitPPA1Flags(std::unique_ptr<MCStreamer> &OutStreamer, bool VarArg,
if (StackProtector)
Flags2 |= PPA1Flag2::STACKPROTECTOR;
+ if (HasArgAreaLength)
+ Flags3 |= PPA1Flag3::HasArgAreaLength; // Add emit ArgAreaLength flag.
+
// SavedGPRMask, SavedFPRMask, and SavedVRMask are precomputed in.
if (FPRMask)
Flags3 |= PPA1Flag3::FPRMask; // Add emit FPR mask flag.
@@ -1339,6 +1343,10 @@ static void emitPPA1Flags(std::unique_ptr<MCStreamer> &OutStreamer, bool VarArg,
OutStreamer->emitInt8(static_cast<uint8_t>(Flags2)); // Flags 2.
OutStreamer->AddComment("PPA1 Flags 3");
+ if ((Flags3 & PPA1Flag3::HasArgAreaLength) ==
+ PPA1Flag3::HasArgAreaLength)
+ OutStreamer->AddComment(
+ " Bit 1: 1 = Argument Area Length is in optional area");
if ((Flags3 & PPA1Flag3::FPRMask) == PPA1Flag3::FPRMask)
OutStreamer->AddComment(" Bit 2: 1 = FP Reg Mask is in optional area");
OutStreamer->emitInt8(
@@ -1477,12 +1485,26 @@ void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) {
bool NeedEmitEHBlock = !MF->getLandingPads().empty();
+ // Optional Argument Area Length.
+ // Note: This represents the length of the argument area that we reserve
+ // in our stack for setting up arguments for calls to other
+ // routines. If this optional field is not set, LE will reserve
+ // 128 bytes for the argument area. This optional field is
+ // created if greater than 128 bytes is required - to guarantee
+ // the required space is reserved on stack extension in the new
+ // extension. This optional field is also created if the
+ // routine has alloca(). This may reduce stack space
+ // if alloca() call causes a stack extension.
+ bool HasArgAreaLength =
+ (AllocaReg != 0) || (MFFrame.getMaxCallFrameSize() > 128);
+
bool HasName =
MF->getFunction().hasName() && MF->getFunction().getName().size() > 0;
emitPPA1Flags(OutStreamer, MF->getFunction().isVarArg(),
MFFrame.hasStackProtectorIndex(), SavedFPRMask != 0,
- TargetHasVector && SavedVRMask != 0, NeedEmitEHBlock, HasName);
+ TargetHasVector && SavedVRMask != 0, NeedEmitEHBlock,
+ HasArgAreaLength, HasName);
OutStreamer->AddComment("Length/4 of Parms");
OutStreamer->emitInt16(
@@ -1490,6 +1512,11 @@ void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) {
OutStreamer->AddComment("Length of Code");
OutStreamer->emitAbsoluteSymbolDiff(FnEndSym, CurrentFnEPMarkerSym, 4);
+ if (HasArgAreaLength) {
+ OutStreamer->AddComment("Argument Area Length");
+ OutStreamer->emitInt32(MFFrame.getMaxCallFrameSize());
+ }
+
// Emit saved FPR mask and offset to FPR save area (0x20 of flags 3).
if (SavedFPRMask) {
OutStreamer->AddComment("FPR mask");
diff --git a/llvm/test/CodeGen/SystemZ/zos-ppa1-argarea.ll b/llvm/test/CodeGen/SystemZ/zos-ppa1-argarea.ll
new file mode 100644
index 0000000000000..511bc46567607
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/zos-ppa1-argarea.ll
@@ -0,0 +1,66 @@
+; RUN: llc < %s -mtriple=s390x-ibm-zos -emit-gnuas-syntax-on-zos=0 | FileCheck %s
+%struct.LargeStruct_t = type { [33 x i32] }
+
+@GlobLargeS = hidden global %struct.LargeStruct_t zeroinitializer, align 4
+@GlobInt = hidden global i32 0, align 4
+
+; === Check that function with small frame does not emit PPA1 Argument Area Length.
+define void @fSmallOutArgArea() {
+; CHECK-LABEL: L#EPM_fSmallOutArgArea_0 DS 0H
+; CHECK: * Bit 1: 1 = Leaf function
+; CHECK: * Bit 2: 0 = Does not use alloca
+; CHECK: DC XL4'00000008'
+; CHECK: fSmallOutArgArea DS 0H
+; CHECK: L#PPA1_fSmallOutArgArea_0 DS 0H
+; CHECK: * PPA1 Flags 3
+; CHECK: DC XL1'00'
+ ret void
+}
+
+; === Check that function with large frame does emit PPA1 Argument Area Length.
+define void @fLargeOutArgArea() {
+; CHECK-LABEL: L#EPM_fLargeOutArgArea_0 DS 0H
+; CHECK: * Bit 1: 0 = Non-leaf function
+; CHECK: * Bit 2: 0 = Does not use alloca
+; CHECK: DC XL4'00000220'
+; CHECK: fLargeOutArgArea DS 0H
+; CHECK: L#PPA1_fLargeOutArgArea_0 DS 0H
+; CHECK: * PPA1 Flags 3
+; CHECK: * Bit 1: 1 = Argument Area Length is in optional area
+; CHECK: DC XL1'40'
+; CHECK: * Argument Area Length
+; CHECK: DC XL4'00000140'
+ %1 = load [33 x i32], ptr @GlobLargeS, align 4
+ call void @fLargeParm([33 x i32] inreg %1)
+ ret void
+}
+
+; === Check that function with parameter does emit PPA1 Length/4 of parms
+define void @fLargeParm([33 x i64] inreg %arr) {
+; CHECK-LABEL: L#EPM_fLargeParm_0 DS 0H
+; CHECK: * Length/4 of Parms
+; CHECK: DC XL2'0042'
+ %1 = extractvalue [33 x i64] %arr, 1
+ call void @foo(i64 %1)
+ ret void
+}
+
+; === Check that function with alloca call does emit PPA1 Argument Area Length.
+define hidden void @fHasAlloca() {
+; CHECK-LABEL: L#EPM_fHasAlloca_0 DS 0H
+; CHECK: * Bit 2: 1 = Uses alloca
+; CHECK: fHasAlloca DS 0H
+; CHECK: L#PPA1_fHasAlloca_0 DS 0H
+; CHECK: * PPA1 Flags 3
+; CHECK: * Bit 1: 1 = Argument Area Length is in optional area
+; CHECK: DC XL1'40'
+; CHECK: * Argument Area Length
+; CHECK: DC XL4'00000040'
+ %p = alloca ptr, align 4
+ %1 = load i32, ptr @GlobInt, align 4
+ %2 = alloca i8, i32 %1, align 8
+ store ptr %2, ptr %p, align 4
+ ret void
+}
+
+declare void @foo(i64)
|
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
uweigand
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks!
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.
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.
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 reseverd on stack
extension. Creating this field when alloca() is used may reduce the needed stack space in case alloca() causes a stack extension.