Files
clang-p2996/llvm/test/CodeGen/SystemZ/call-zos-vararg.ll
Jonas Paulsson 16b7cc69ef [SystemZ] Eliminate call sequence instructions early. (#77812)
On SystemZ, the outgoing argument area which is big enough for all calls
in the function is created once during the prolog, as opposed to
adjusting the stack around each call. The call-sequence instructions are
therefore not really useful any more than to compute the maximum call
frame size, which has so far been done by PEI, but can just as well be
done at an earlier point.

This patch removes the mapping of the CallFrameSetupOpcode and
CallFrameDestroyOpcode and instead computes the MaxCallFrameSize
directly after instruction selection and then removes the ADJCALLSTACK
pseudos. This removes the confusing pseudos and also avoids the problem
of having to keep the call frame size accurate when creating new MBBs.

This fixes #76618 which exposed the need to maintain the call frame size
when splitting blocks (which was not done).
2024-03-28 18:26:38 +01:00

359 lines
10 KiB
LLVM

; Test passing variable argument lists in 64-bit calls on z/OS.
; RUN: llc < %s -mtriple=s390x-ibm-zos -mcpu=z10 | FileCheck %s
; RUN: llc < %s -mtriple=s390x-ibm-zos -mcpu=z14 | FileCheck %s -check-prefix=ARCH12
; CHECK-LABEL: call_vararg_double0:
; CHECK: stmg 6, 7, 1872(4)
; CHECK-NEXT: aghi 4, -192
; CHECK-NEXT: lg 6, 8(5)
; CHECK-NEXT: lg 5, 0(5)
; CHECK-NEXT: llihf 3, 1074118262
; CHECK-NEXT: oilf 3, 3367254360
; CHECK-NEXT: lghi 1, 1
; CHECK-NEXT: lghi 2, 2
; CHECK-NEXT: basr 7, 6
; CHECK-NEXT: bcr 0, 0
; CHECK-NEXT: lg 7, 2072(4)
; CHECK-NEXT: aghi 4, 192
; CHECK-NEXT: b 2(7)
define i64 @call_vararg_double0() {
entry:
%retval = call i64 (i64, i64, ...) @pass_vararg0(i64 1, i64 2, double 2.718000e+00)
ret i64 %retval
}
; CHECK-LABEL: call_vararg_double1:
; CHECK: stmg 6, 7, 1872(4)
; CHECK-NEXT: aghi 4, -192
; CHECK-NEXT: llihf 0, 1074118262
; CHECK-NEXT: oilf 0, 3367254360
; CHECK-NEXT: lg 6, 8(5)
; CHECK-NEXT: lg 5, 0(5)
; CHECK-NEXT: llihf 3, 1074340036
; CHECK-NEXT: oilf 3, 2611340116
; CHECK-NEXT: lghi 1, 1
; CHECK-NEXT: lghi 2, 2
; CHECK-NEXT: stg 0, 2200(4)
; CHECK-NEXT: basr 7, 6
; CHECK-NEXT: bcr 0, 0
; CHECK-NEXT: lg 7, 2072(4)
; CHECK-NEXT: aghi 4, 192
; CHECK-NEXT: b 2(7)
define i64 @call_vararg_double1() {
entry:
%retval = call i64 (i64, i64, ...) @pass_vararg0(i64 1, i64 2, double 3.141000e+00, double 2.718000e+00)
ret i64 %retval
}
; CHECK-LABEL: call_vararg_double2:
; CHECK: stmg 6, 7, 1872(4)
; CHECK-NEXT: aghi 4, -192
; CHECK-NEXT: lg 6, 24(5)
; CHECK-NEXT: lg 5, 16(5)
; CHECK-NEXT: llihf 2, 1074118262
; CHECK-NEXT: oilf 2, 3367254360
; CHECK-NEXT: lghi 1, 8200
; CHECK-NEXT: basr 7, 6
; CHECK-NEXT: bcr 0, 0
; CHECK-NEXT: lg 7, 2072(4)
; CHECK-NEXT: aghi 4, 192
; CHECK-NEXT: b 2(7)
define i64 @call_vararg_double2() {
entry:
%retval = call i64 (i64, ...) @pass_vararg2(i64 8200, double 2.718000e+00)
ret i64 %retval
}
; CHECK-LABEL: call_vararg_double3:
; CHECK: stmg 6, 7, 1872(4)
; CHECK-NEXT: aghi 4, -192
; CHECK-NEXT: llihf 0, 1072703839
; CHECK-NEXT: oilf 0, 2861204133
; CHECK-NEXT: lg 6, 40(5)
; CHECK-NEXT: lg 5, 32(5)
; CHECK-NEXT: llihf 1, 1074118262
; CHECK-NEXT: oilf 1, 3367254360
; CHECK-NEXT: llihf 2, 1074340036
; CHECK-NEXT: oilf 2, 2611340116
; CHECK-NEXT: llihf 3, 1073127358
; CHECK-NEXT: oilf 3, 1992864825
; CHECK-NEXT: stg 0, 2200(4)
; CHECK-NEXT: basr 7, 6
; CHECK-NEXT: bcr 0, 0
; CHECK-NEXT: lg 7, 2072(4)
; CHECK-NEXT: aghi 4, 192
; CHECK-NEXT: b 2(7)
define i64 @call_vararg_double3() {
entry:
%retval = call i64 (...) @pass_vararg3(double 2.718000e+00, double 3.141000e+00, double 1.414000e+00, double 1.010101e+00)
ret i64 %retval
}
;; TODO: The extra COPY after LGDR is unnecessary (machine-scheduler introduces the overlap).
; CHECK-LABEL: call_vararg_both0:
; CHECK: stmg 6, 7, 1872(4)
; CHECK-NEXT: aghi 4, -192
; CHECK-NEXT: lg 6, 40(5)
; CHECK-NEXT: lg 5, 32(5)
; CHECK-NEXT: lgdr 0, 0
; CHECK-NEXT: lgr 2, 1
; CHECK-NEXT: lgr 1, 0
; CHECK-NEXT: basr 7, 6
; CHECK-NEXT: bcr 0, 0
; CHECK-NEXT: lg 7, 2072(4)
; CHECK-NEXT: aghi 4, 192
; CHECK-NEXT: b 2(7)
define i64 @call_vararg_both0(i64 %arg0, double %arg1) {
%retval = call i64(...) @pass_vararg3(double %arg1, i64 %arg0)
ret i64 %retval
}
; CHECK-LABEL: call_vararg_long_double0:
; CHECK: stmg 6, 7, 1872(4)
; CHECK-NEXT: aghi 4, -192
; CHECK-NEXT: larl 1, L#CPI5_0
; CHECK-NEXT: ld 0, 0(1)
; CHECK-NEXT: ld 2, 8(1)
; CHECK-NEXT: lg 6, 8(5)
; CHECK-NEXT: lg 5, 0(5)
; CHECK-NEXT: lgdr 3, 0
; CHECK-NEXT: lghi 1, 1
; CHECK-NEXT: lghi 2, 2
; CHECK-NEXT: std 0, 2192(4)
; CHECK-NEXT: std 2, 2200(4)
; CHECK-NEXT: basr 7, 6
; CHECK-NEXT: bcr 0, 0
; CHECK-NEXT: lg 7, 2072(4)
; CHECK-NEXT: aghi 4, 192
; CHECK-NEXT: b 2(7)
define i64 @call_vararg_long_double0() {
entry:
%retval = call i64 (i64, i64, ...) @pass_vararg0(i64 1, i64 2, fp128 0xLE0FC1518450562CD4000921FB5444261)
ret i64 %retval
}
; CHECK-LABEL: call_vararg_long_double1:
; CHECK: stmg 6, 7, 1872(4)
; CHECK-NEXT: aghi 4, -192
; CHECK-NEXT: lg 6, 8(5)
; CHECK-NEXT: lg 5, 0(5)
; CHECK-NEXT: lgdr 3, 0
; CHECK-NEXT: lghi 1, 1
; CHECK-NEXT: lghi 2, 2
; CHECK-NEXT: std 0, 2192(4)
; CHECK-NEXT: std 2, 2200(4)
; CHECK-NEXT: basr 7, 6
; CHECK-NEXT: bcr 0, 0
; CHECK-NEXT: lg 7, 2072(4)
; CHECK-NEXT: aghi 4, 192
; CHECK-NEXT: b 2(7)
define i64 @call_vararg_long_double1(fp128 %arg0) {
entry:
%retval = call i64 (i64, i64, ...) @pass_vararg0(i64 1, i64 2, fp128 %arg0)
ret i64 %retval
}
; CHECK-LABEL: call_vararg_long_double2
; CHECK-LABEL: call_vararg_long_double2:
; CHECK: stmg 6, 7, 1872(4)
; CHECK-NEXT: aghi 4, -192
; CHECK-NEXT: std 4, 2208(4)
; CHECK-NEXT: std 6, 2216(4)
; CHECK-NEXT: lg 6, 8(5)
; CHECK-NEXT: lg 5, 0(5)
; CHECK-NEXT: lgdr 3, 0
; CHECK-NEXT: lghi 1, 1
; CHECK-NEXT: lghi 2, 2
; CHECK-NEXT: std 0, 2192(4)
; CHECK-NEXT: std 2, 2200(4)
; CHECK-NEXT: basr 7, 6
; CHECK-NEXT: bcr 0, 0
; CHECK-NEXT: lg 7, 2072(4)
; CHECK-NEXT: aghi 4, 192
; CHECK-NEXT: b 2(7)
define i64 @call_vararg_long_double2(fp128 %arg0, fp128 %arg1) {
entry:
%retval = call i64 (i64, i64, ...) @pass_vararg0(i64 1, i64 2, fp128 %arg0, fp128 %arg1)
ret i64 %retval
}
; CHECK-LABEL: call_vararg_long_double3:
; CHECK: stmg 6, 7, 1872(4)
; CHECK-NEXT: aghi 4, -192
; CHECK-NEXT: lg 6, 40(5)
; CHECK-NEXT: lg 5, 32(5)
; CHECK-NEXT: lgdr 3, 2
; CHECK-NEXT: lgdr 2, 0
; CHECK-NEXT: basr 7, 6
; CHECK-NEXT: bcr 0, 0
; CHECK-NEXT: lg 7, 2072(4)
; CHECK-NEXT: aghi 4, 192
; CHECK-NEXT: b 2(7)
define i64 @call_vararg_long_double3(fp128 %arg0) {
entry:
%retval = call i64 (...) @pass_vararg3(fp128 %arg0)
ret i64 %retval
}
; ARCH12-LABEL: call_vec_vararg_test0
; ARCH12: vlgvg 3, 24, 1
; ARCH12: vlgvg 2, 24, 0
; ARCH12: lghi 1, 1
define void @call_vec_vararg_test0(<2 x double> %v) {
%retval = call i64(i64, ...) @pass_vararg2(i64 1, <2 x double> %v)
ret void
}
; ARCH12-LABEL: call_vec_vararg_test1
; ARCH12: larl 1, L#CPI10_0
; ARCH12: vl 0, 0(1), 3
; ARCH12: vlgvg 3, 24, 0
; ARCH12: vrepg 2, 0, 1
; ARCH12: vst 25, 2208(4), 3
; ARCH12: vst 24, 2192(4), 3
define void @call_vec_vararg_test1(<4 x i32> %v, <2 x i64> %w) {
%retval = call i64(fp128, ...) @pass_vararg1(fp128 0xLE0FC1518450562CD4000921FB5444261, <4 x i32> %v, <2 x i64> %w)
ret void
}
; ARCH12-LABEL: call_vec_char_vararg_straddle
; ARCH12: vlgvg 3, 24, 0
; ARCH12: lghi 1, 1
; ARCH12: lghi 2, 2
; ARCH12: vst 24, 2192(4), 3
define void @call_vec_char_vararg_straddle(<16 x i8> %v) {
%retval = call i64(i64, i64, ...) @pass_vararg0(i64 1, i64 2, <16 x i8> %v)
ret void
}
; ARCH12-LABEL: call_vec_short_vararg_straddle
; ARCH12: vlgvg 3, 24, 0
; ARCH12: lghi 1, 1
; ARCH12: lghi 2, 2
; ARCH12: vst 24, 2192(4), 3
define void @call_vec_short_vararg_straddle(<8 x i16> %v) {
%retval = call i64(i64, i64, ...) @pass_vararg0(i64 1, i64 2, <8 x i16> %v)
ret void
}
; ARCH12-LABEL: call_vec_int_vararg_straddle
; ARCH12: vlgvg 3, 24, 0
; ARCH12: lghi 1, 1
; ARCH12: lghi 2, 2
; ARCH12: vst 24, 2192(4), 3
define void @call_vec_int_vararg_straddle(<4 x i32> %v) {
%retval = call i64(i64, i64, ...) @pass_vararg0(i64 1, i64 2, <4 x i32> %v)
ret void
}
; ARCH12-LABEL: call_vec_double_vararg_straddle
; ARCH12: vlgvg 3, 24, 0
; ARCH12: lghi 1, 1
; ARCH12: lghi 2, 2
; ARCH12: vst 24, 2192(4), 3
define void @call_vec_double_vararg_straddle(<2 x double> %v) {
%retval = call i64(i64, i64, ...) @pass_vararg0(i64 1, i64 2, <2 x double> %v)
ret void
}
; CHECK-LABEL: call_vararg_integral0:
; CHECK: stmg 6, 7, 1872(4)
; CHECK-NEXT: aghi 4, -192
; CHECK-NEXT: lg 0, 2392(4)
; CHECK-NEXT: lg 6, 40(5)
; CHECK-NEXT: lg 5, 32(5)
; CHECK-NEXT: stg 0, 2200(4)
; CHECK-NEXT: basr 7, 6
; CHECK-NEXT: bcr 0, 0
; CHECK-NEXT: lg 7, 2072(4)
; CHECK-NEXT: aghi 4, 192
; CHECK-NEXT: b 2(7)
define i64 @call_vararg_integral0(i32 signext %arg0, i16 signext %arg1, i64 signext %arg2, i8 signext %arg3) {
entry:
%retval = call i64(...) @pass_vararg3(i32 signext %arg0, i16 signext %arg1, i64 signext %arg2, i8 signext %arg3)
ret i64 %retval
}
; CHECK-LABEL: call_vararg_float0:
; CHECK: stmg 6, 7, 1872(4)
; CHECK-NEXT: aghi 4, -192
; CHECK-NEXT: lg 6, 24(5)
; CHECK-NEXT: lg 5, 16(5)
; CHECK-NEXT: lghi 1, 1
; CHECK-NEXT: llihf 2, 1073692672
; CHECK-NEXT: basr 7, 6
; CHECK-NEXT: bcr 0, 0
; CHECK-NEXT: lg 7, 2072(4)
; CHECK-NEXT: aghi 4, 192
; CHECK-NEXT: b 2(7)
define i64 @call_vararg_float0() {
entry:
%retval = call i64 (i64, ...) @pass_vararg2(i64 1, float 1.953125)
ret i64 %retval
}
; CHECK-LABEL: call_vararg_float1:
; CHECK: stmg 6, 7, 1872(4)
; CHECK-NEXT: aghi 4, -192
; CHECK-NEXT: lg 6, 72(5)
; CHECK-NEXT: lg 5, 64(5)
; CHECK-NEXT: larl 1, L#CPI17_0
; CHECK-NEXT: le 0, 0(1)
; CHECK-NEXT: llihf 0, 1073692672
; CHECK-NEXT: llihh 2, 16384
; CHECK-NEXT: llihh 3, 16392
; CHECK-NEXT: stg 0, 2200(4)
; CHECK-NEXT: basr 7, 6
; CHECK-NEXT: bcr 0, 0
; CHECK-NEXT: lg 7, 2072(4)
; CHECK-NEXT: aghi 4, 192
; CHECK-NEXT: b 2(7)
define i64 @call_vararg_float1() {
entry:
%retval = call i64 (float, ...) @pass_vararg4(float 1.0, float 2.0, float 3.0, float 1.953125)
ret i64 %retval
}
; Derived from C source:
; #define _VARARG_EXT_
; #include <stdarg.h>
;
; long pass(long x, ...) {
; va_list va;
; va_start(va, x);
; long ret = va_arg(va, long);
; va_end(va);
; return ret;
; }
;
; CHECK-LABEL: pass_vararg:
; CHECK: stmg 6, 7, 1904(4)
; CHECK-NEXT: aghi 4, -160
; CHECK-NEXT: stg 2, 2344(4)
; CHECK-NEXT: stg 3, 2352(4)
; CHECK-NEXT: la 0, 2352(4)
; CHECK-NEXT: stg 0, 2200(4)
; CHECK-NEXT: lg 3, 2344(4)
; CHECK-NEXT: lg 7, 2072(4)
; CHECK-NEXT: aghi 4, 160
; CHECK-NEXT: b 2(7)
define hidden i64 @pass_vararg(i64 %x, ...) {
entry:
%va = alloca ptr, align 8
call void @llvm.va_start(ptr %va)
%argp.cur = load ptr, ptr %va, align 8
%argp.next = getelementptr inbounds i8, ptr %argp.cur, i64 8
store ptr %argp.next, ptr %va, align 8
%ret = load i64, ptr %argp.cur, align 8
call void @llvm.va_end(ptr %va)
ret i64 %ret
}
declare void @llvm.va_start(ptr)
declare void @llvm.va_end(ptr)
declare i64 @pass_vararg0(i64 %arg0, i64 %arg1, ...)
declare i64 @pass_vararg1(fp128 %arg0, ...)
declare i64 @pass_vararg2(i64 %arg0, ...)
declare i64 @pass_vararg3(...)
declare i64 @pass_vararg4(float, ...)