1; Test passing variable argument lists in 64-bit calls on z/OS. 2; RUN: llc < %s -mtriple=s390x-ibm-zos -mcpu=z10 | FileCheck %s 3; RUN: llc < %s -mtriple=s390x-ibm-zos -mcpu=z14 | FileCheck %s -check-prefix=ARCH12 4; CHECK-LABEL: call_vararg_double0 5; CHECK: llihf 3, 1074118262 6; CHECK-NEXT: oilf 3, 3367254360 7; CHECK: lghi 1, 1 8; CHECK: lghi 2, 2 9define i64 @call_vararg_double0() { 10entry: 11 %retval = call i64 (i64, i64, ...) @pass_vararg0(i64 1, i64 2, double 2.718000e+00) 12 ret i64 %retval 13} 14 15; CHECK-LABEL: call_vararg_double1 16; CHECK: llihf 0, 1074118262 17; CHECK-NEXT: oilf 0, 3367254360 18; CHECK: llihf 3, 1074340036 19; CHECK-NEXT: oilf 3, 2611340116 20; CHECK: lghi 1, 1 21; CHECK: lghi 2, 2 22; CHECK: stg 0, 2200(4) 23define i64 @call_vararg_double1() { 24entry: 25 %retval = call i64 (i64, i64, ...) @pass_vararg0(i64 1, i64 2, double 3.141000e+00, double 2.718000e+00) 26 ret i64 %retval 27} 28 29; CHECK-LABEL: call_vararg_double2 30; CHECK-NOT: llihf 0 31; CHECK-NOT: oilf 0 32; CHECK: llihf 2, 1074118262 33; CHECK-NEXT: oilf 2, 3367254360 34; CHECK: lghi 1, 8200 35define i64 @call_vararg_double2() { 36entry: 37 %retval = call i64 (i64, ...) @pass_vararg2(i64 8200, double 2.718000e+00) 38 ret i64 %retval 39} 40 41; CHECK-LABEL: call_vararg_double3 42; CHECK: llihf 0, 1072703839 43; CHECK-NEXT: oilf 0, 2861204133 44; CHECK: llihf 1, 1074118262 45; CHECK-NEXT: oilf 1, 3367254360 46; CHECK: llihf 2, 1074340036 47; CHECK-NEXT: oilf 2, 2611340116 48; CHECK: llihf 3, 1073127358 49; CHECK-NEXT: oilf 3, 1992864825 50; CHECK: stg 0, 2200(4) 51define i64 @call_vararg_double3() { 52entry: 53 %retval = call i64 (...) @pass_vararg3(double 2.718000e+00, double 3.141000e+00, double 1.414000e+00, double 1.010101e+00) 54 ret i64 %retval 55} 56 57; CHECK-LABEL: call_vararg_both0 58; CHECK: lgr 2, 1 59; CHECK: lgdr 1, 0 60define i64 @call_vararg_both0(i64 %arg0, double %arg1) { 61 %retval = call i64(...) @pass_vararg3(double %arg1, i64 %arg0) 62 ret i64 %retval 63} 64 65; CHECK-LABEL: call_vararg_long_double0 66; CHECK: larl 1, @CPI5_0 67; CHECK-NEXT: ld 0, 0(1) 68; CHECK-NEXT: ld 2, 8(1) 69; CHECK-NEXT: lgdr 3, 0 70; CHECK: lghi 1, 1 71; CHECK: lghi 2, 2 72; CHECK: std 0, 2192(4) 73; CHECK-NEXT: std 2, 2200(4) 74define i64 @call_vararg_long_double0() { 75entry: 76 %retval = call i64 (i64, i64, ...) @pass_vararg0(i64 1, i64 2, fp128 0xLE0FC1518450562CD4000921FB5444261) 77 ret i64 %retval 78} 79 80; CHECK-LABEL: call_vararg_long_double1 81; CHECK: lgdr 3, 0 82; CHECK: lghi 1, 1 83; CHECK: lghi 2, 2 84; CHECK: std 0, 2192(4) 85; CHECK-NEXT: std 2, 2200(4) 86define i64 @call_vararg_long_double1(fp128 %arg0) { 87entry: 88 %retval = call i64 (i64, i64, ...) @pass_vararg0(i64 1, i64 2, fp128 %arg0) 89 ret i64 %retval 90} 91 92; CHECK-LABEL: call_vararg_long_double2 93; CHECK: std 4, 2208(4) 94; CHECK-NEXT: std 6, 2216(4) 95; CHECK: lgdr 3, 0 96; CHECK: lghi 1, 1 97; CHECK: lghi 2, 2 98; CHECK: std 0, 2192(4) 99; CHECK-NEXT: std 2, 2200(4) 100define i64 @call_vararg_long_double2(fp128 %arg0, fp128 %arg1) { 101entry: 102 %retval = call i64 (i64, i64, ...) @pass_vararg0(i64 1, i64 2, fp128 %arg0, fp128 %arg1) 103 ret i64 %retval 104} 105 106; CHECK-LABEL: call_vararg_long_double3 107; CHECK: lgdr 3, 2 108; CHECK-NEXT: lgdr 2, 0 109define i64 @call_vararg_long_double3(fp128 %arg0) { 110entry: 111 %retval = call i64 (...) @pass_vararg3(fp128 %arg0) 112 ret i64 %retval 113} 114 115; ARCH12-LABEL: call_vec_vararg_test0 116; ARCH12: vlgvg 3, 24, 1 117; ARCH12: vlgvg 2, 24, 0 118; ARCH12: lghi 1, 1 119define void @call_vec_vararg_test0(<2 x double> %v) { 120 %retval = call i64(i64, ...) @pass_vararg2(i64 1, <2 x double> %v) 121 ret void 122} 123 124; ARCH12-LABEL: call_vec_vararg_test1 125; ARCH12: larl 1, @CPI10_0 126; ARCH12: vl 0, 0(1), 3 127; ARCH12: vlgvg 3, 24, 0 128; ARCH12: vrepg 2, 0, 1 129; ARCH12: vst 25, 2208(4), 3 130; ARCH12: vst 24, 2192(4), 3 131define void @call_vec_vararg_test1(<4 x i32> %v, <2 x i64> %w) { 132 %retval = call i64(fp128, ...) @pass_vararg1(fp128 0xLE0FC1518450562CD4000921FB5444261, <4 x i32> %v, <2 x i64> %w) 133 ret void 134} 135 136; ARCH12-LABEL: call_vec_char_vararg_straddle 137; ARCH12: vlgvg 3, 24, 0 138; ARCH12: lghi 1, 1 139; ARCH12: lghi 2, 2 140; ARCH12: vst 24, 2192(4), 3 141define void @call_vec_char_vararg_straddle(<16 x i8> %v) { 142 %retval = call i64(i64, i64, ...) @pass_vararg0(i64 1, i64 2, <16 x i8> %v) 143 ret void 144} 145 146; ARCH12-LABEL: call_vec_short_vararg_straddle 147; ARCH12: vlgvg 3, 24, 0 148; ARCH12: lghi 1, 1 149; ARCH12: lghi 2, 2 150; ARCH12: vst 24, 2192(4), 3 151define void @call_vec_short_vararg_straddle(<8 x i16> %v) { 152 %retval = call i64(i64, i64, ...) @pass_vararg0(i64 1, i64 2, <8 x i16> %v) 153 ret void 154} 155 156; ARCH12-LABEL: call_vec_int_vararg_straddle 157; ARCH12: vlgvg 3, 24, 0 158; ARCH12: lghi 1, 1 159; ARCH12: lghi 2, 2 160; ARCH12: vst 24, 2192(4), 3 161define void @call_vec_int_vararg_straddle(<4 x i32> %v) { 162 %retval = call i64(i64, i64, ...) @pass_vararg0(i64 1, i64 2, <4 x i32> %v) 163 ret void 164} 165 166; ARCH12-LABEL: call_vec_double_vararg_straddle 167; ARCH12: vlgvg 3, 24, 0 168; ARCH12: lghi 1, 1 169; ARCH12: lghi 2, 2 170; ARCH12: vst 24, 2192(4), 3 171define void @call_vec_double_vararg_straddle(<2 x double> %v) { 172 %retval = call i64(i64, i64, ...) @pass_vararg0(i64 1, i64 2, <2 x double> %v) 173 ret void 174} 175 176; CHECK-LABEL: call_vararg_integral0 177; Since arguments 0, 1, and 2 are already in the correct 178; registers, we should have no loads of any sort into 179; GPRs 1, 2, and 3. 180; CHECK-NOT: lg 1 181; CHECK-NOT: lgr 1 182; CHECK-NOT: lg 2 183; CHECK-NOT: lgr 2 184; CHECK-NOT: lg 3 185; CHECK-NOT: lgr 3 186define i64 @call_vararg_integral0(i32 signext %arg0, i16 signext %arg1, i64 signext %arg2, i8 signext %arg3) { 187entry: 188 %retval = call i64(...) @pass_vararg3(i32 signext %arg0, i16 signext %arg1, i64 signext %arg2, i8 signext %arg3) 189 ret i64 %retval 190} 191 192; CHECK-LABEL: call_vararg_float0 193; CHECK: lghi 1, 1 194; CHECK: llihf 2, 1073692672 195define i64 @call_vararg_float0() { 196entry: 197 %retval = call i64 (i64, ...) @pass_vararg2(i64 1, float 1.953125) 198 ret i64 %retval 199} 200 201; CHECK-LABEL: call_vararg_float1 202; CHECK: larl 1, @CPI17_0 203; CHECK: le 0, 0(1) 204; CHECK: llihf 0, 1073692672 205; CHECK: llihh 2, 16384 206; CHECK: llihh 3, 16392 207; CHECK: stg 0, 2200(4) 208define i64 @call_vararg_float1() { 209entry: 210 %retval = call i64 (float, ...) @pass_vararg4(float 1.0, float 2.0, float 3.0, float 1.953125) 211 ret i64 %retval 212} 213 214; Derived from C source: 215; #define _VARARG_EXT_ 216; #include <stdarg.h> 217; 218; long pass(long x, ...) { 219; va_list va; 220; va_start(va, x); 221; long ret = va_arg(va, long); 222; va_end(va); 223; return ret; 224; } 225; 226; CHECK-LABEL: pass_vararg: 227; CHECK: aghi 4, -160 228; CHECK: la 0, 2208(4) 229; CHECK: stg 0, 2200(4) 230define hidden i64 @pass_vararg(i64 %x, ...) { 231entry: 232 %va = alloca i8*, align 8 233 %va1 = bitcast i8** %va to i8* 234 call void @llvm.va_start(i8* %va1) 235 %argp.cur = load i8*, i8** %va, align 8 236 %argp.next = getelementptr inbounds i8, i8* %argp.cur, i64 8 237 store i8* %argp.next, i8** %va, align 8 238 %0 = bitcast i8* %argp.cur to i64* 239 %ret = load i64, i64* %0, align 8 240 %va2 = bitcast i8** %va to i8* 241 call void @llvm.va_end(i8* %va2) 242 ret i64 %ret 243} 244 245declare void @llvm.va_start(i8*) 246declare void @llvm.va_end(i8*) 247 248declare i64 @pass_vararg0(i64 %arg0, i64 %arg1, ...) 249declare i64 @pass_vararg1(fp128 %arg0, ...) 250declare i64 @pass_vararg2(i64 %arg0, ...) 251declare i64 @pass_vararg3(...) 252declare i64 @pass_vararg4(float, ...) 253