1; RUN: llc -mtriple=arm64-apple-darwin -mcpu=cyclone -enable-misched=false < %s | FileCheck %s 2; RUN: llc -O0 -fast-isel -mtriple=arm64-apple-darwin < %s | FileCheck --check-prefix=FAST %s 3 4; rdar://9932559 5define i64 @i8i16callee(i64 %a1, i64 %a2, i64 %a3, i8 signext %a4, i16 signext %a5, i64 %a6, i64 %a7, i64 %a8, i8 signext %b1, i16 signext %b2, i8 signext %b3, i8 signext %b4) nounwind readnone noinline { 6entry: 7; CHECK-LABEL: i8i16callee: 8; The 8th, 9th, 10th and 11th arguments are passed at sp, sp+2, sp+4, sp+5. 9; They are i8, i16, i8 and i8. 10; CHECK-DAG: ldrsb {{w[0-9]+}}, [sp, #5] 11; CHECK-DAG: ldrsb {{w[0-9]+}}, [sp, #4] 12; CHECK-DAG: ldrsh {{w[0-9]+}}, [sp, #2] 13; CHECK-DAG: ldrsb {{w[0-9]+}}, [sp] 14; FAST-LABEL: i8i16callee: 15; FAST-DAG: ldrsb {{w[0-9]+}}, [sp, #5] 16; FAST-DAG: ldrsb {{w[0-9]+}}, [sp, #4] 17; FAST-DAG: ldrsh {{w[0-9]+}}, [sp, #2] 18; FAST-DAG: ldrsb {{w[0-9]+}}, [sp] 19 %conv = sext i8 %a4 to i64 20 %conv3 = sext i16 %a5 to i64 21 %conv8 = sext i8 %b1 to i64 22 %conv9 = sext i16 %b2 to i64 23 %conv11 = sext i8 %b3 to i64 24 %conv13 = sext i8 %b4 to i64 25 %add10 = add i64 %a2, %a1 26 %add12 = add i64 %add10, %a3 27 %add14 = add i64 %add12, %conv 28 %add = add i64 %add14, %conv3 29 %add1 = add i64 %add, %a6 30 %add2 = add i64 %add1, %a7 31 %add4 = add i64 %add2, %a8 32 %add5 = add i64 %add4, %conv8 33 %add6 = add i64 %add5, %conv9 34 %add7 = add i64 %add6, %conv11 35 %add15 = add i64 %add7, %conv13 36 %sext = shl i64 %add15, 32 37 %conv17 = ashr exact i64 %sext, 32 38 ret i64 %conv17 39} 40 41define i32 @i8i16caller() nounwind readnone { 42entry: 43; CHECK-LABEL: i8i16caller 44; The 8th, 9th, 10th and 11th arguments are passed at sp, sp+2, sp+4, sp+5. 45; They are i8, i16, i8 and i8. 46; CHECK-DAG: stur {{w[0-9]+}}, [sp, #2] 47; CHECK-DAG: strb {{w[0-9]+}}, [sp] 48; CHECK: bl 49; FAST-LABEL: i8i16caller 50; FAST: strb {{w[0-9]+}}, [sp] 51; FAST: strh {{w[0-9]+}}, [sp, #2] 52; FAST: strb {{w[0-9]+}}, [sp, #4] 53; FAST: strb {{w[0-9]+}}, [sp, #5] 54; FAST: bl 55 %call = tail call i64 @i8i16callee(i64 0, i64 1, i64 2, i8 signext 3, i16 signext 4, i64 5, i64 6, i64 7, i8 signext 97, i16 signext 98, i8 signext 99, i8 signext 100) 56 %conv = trunc i64 %call to i32 57 ret i32 %conv 58} 59 60; rdar://12651543 61define double @circle_center([2 x float] %a) nounwind ssp { 62 %call = tail call double @ext([2 x float] %a) nounwind 63; CHECK-LABEL: circle_center 64; CHECK: bl 65 ret double %call 66} 67declare double @ext([2 x float]) 68 69; rdar://12656141 70; 16-byte vector should be aligned at 16-byte when passing on stack. 71; A double argument will be passed on stack, so vecotr should be at sp+16. 72define double @fixed_4i(<4 x i32>* nocapture %in) nounwind { 73entry: 74; CHECK-LABEL: fixed_4i 75; CHECK: str [[REG_1:q[0-9]+]], [sp, #16] 76; FAST-LABEL: fixed_4i 77; FAST: sub sp, sp 78; FAST: mov x[[ADDR:[0-9]+]], sp 79; FAST: str [[REG_1:q[0-9]+]], [x[[ADDR]], #16] 80 %0 = load <4 x i32>, <4 x i32>* %in, align 16 81 %call = tail call double @args_vec_4i(double 3.000000e+00, <4 x i32> %0, <4 x i32> %0, <4 x i32> %0, <4 x i32> %0, <4 x i32> %0, <4 x i32> %0, <4 x i32> %0, double 3.000000e+00, <4 x i32> %0, i8 signext 3) 82 ret double %call 83} 84declare double @args_vec_4i(double, <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32>, double, <4 x i32>, i8 signext) 85 86; rdar://12695237 87; d8 at sp, i in register w0. 88@g_d = common global double 0.000000e+00, align 8 89define void @test1(float %f1, double %d1, double %d2, double %d3, double %d4, 90 double %d5, double %d6, double %d7, double %d8, i32 %i) nounwind ssp { 91entry: 92; CHECK-LABEL: test1 93; CHECK: ldr [[REG_1:d[0-9]+]], [sp] 94; CHECK: scvtf [[REG_2:s[0-9]+]], w0 95; CHECK: fadd s0, [[REG_2]], s0 96 %conv = sitofp i32 %i to float 97 %add = fadd float %conv, %f1 98 %conv1 = fpext float %add to double 99 %add2 = fadd double %conv1, %d7 100 %add3 = fadd double %add2, %d8 101 store double %add3, double* @g_d, align 8 102 ret void 103} 104 105; i9 at sp, d1 in register s0. 106define void @test2(i32 %i1, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, 107 i32 %i7, i32 %i8, i32 %i9, float %d1) nounwind ssp { 108entry: 109; CHECK-LABEL: test2 110; CHECK: scvtf [[REG_2:s[0-9]+]], w0 111; CHECK: fadd s0, [[REG_2]], s0 112; CHECK: ldr [[REG_1:s[0-9]+]], [sp] 113 %conv = sitofp i32 %i1 to float 114 %add = fadd float %conv, %d1 115 %conv1 = fpext float %add to double 116 %conv2 = sitofp i32 %i8 to double 117 %add3 = fadd double %conv2, %conv1 118 %conv4 = sitofp i32 %i9 to double 119 %add5 = fadd double %conv4, %add3 120 store double %add5, double* @g_d, align 8 121 ret void 122} 123 124; rdar://12648441 125; Check alignment on stack for v64, f64, i64, f32, i32. 126define double @test3(<2 x i32>* nocapture %in) nounwind { 127entry: 128; CHECK-LABEL: test3 129; CHECK: str [[REG_1:d[0-9]+]], [sp, #8] 130; FAST-LABEL: test3 131; FAST: sub sp, sp, #48 132; FAST: mov x[[ADDR:[0-9]+]], sp 133; FAST: str [[REG_1:d[0-9]+]], [x[[ADDR]], #8] 134 %0 = load <2 x i32>, <2 x i32>* %in, align 8 135 %call = tail call double @args_vec_2i(double 3.000000e+00, <2 x i32> %0, 136 <2 x i32> %0, <2 x i32> %0, <2 x i32> %0, <2 x i32> %0, <2 x i32> %0, 137 <2 x i32> %0, float 3.000000e+00, <2 x i32> %0, i8 signext 3) 138 ret double %call 139} 140declare double @args_vec_2i(double, <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32>, 141 <2 x i32>, <2 x i32>, <2 x i32>, float, <2 x i32>, i8 signext) 142 143define double @test4(double* nocapture %in) nounwind { 144entry: 145; CHECK-LABEL: test4 146; CHECK: str [[REG_1:d[0-9]+]], [sp, #8] 147; CHECK: str [[REG_2:w[0-9]+]], [sp] 148; CHECK: orr w0, wzr, #0x3 149 %0 = load double, double* %in, align 8 150 %call = tail call double @args_f64(double 3.000000e+00, double %0, double %0, 151 double %0, double %0, double %0, double %0, double %0, 152 float 3.000000e+00, double %0, i8 signext 3) 153 ret double %call 154} 155declare double @args_f64(double, double, double, double, double, double, double, 156 double, float, double, i8 signext) 157 158define i64 @test5(i64* nocapture %in) nounwind { 159entry: 160; CHECK-LABEL: test5 161; CHECK: strb [[REG_3:w[0-9]+]], [sp, #16] 162; CHECK: str [[REG_1:x[0-9]+]], [sp, #8] 163; CHECK: str [[REG_2:w[0-9]+]], [sp] 164 %0 = load i64, i64* %in, align 8 165 %call = tail call i64 @args_i64(i64 3, i64 %0, i64 %0, i64 %0, i64 %0, i64 %0, 166 i64 %0, i64 %0, i32 3, i64 %0, i8 signext 3) 167 ret i64 %call 168} 169declare i64 @args_i64(i64, i64, i64, i64, i64, i64, i64, i64, i32, i64, 170 i8 signext) 171 172define i32 @test6(float* nocapture %in) nounwind { 173entry: 174; CHECK-LABEL: test6 175; CHECK: strb [[REG_2:w[0-9]+]], [sp, #8] 176; CHECK: str [[REG_1:s[0-9]+]], [sp, #4] 177; CHECK: strh [[REG_3:w[0-9]+]], [sp] 178 %0 = load float, float* %in, align 4 179 %call = tail call i32 @args_f32(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, 180 i32 7, i32 8, float 1.0, float 2.0, float 3.0, float 4.0, float 5.0, 181 float 6.0, float 7.0, float 8.0, i16 signext 3, float %0, 182 i8 signext 3) 183 ret i32 %call 184} 185declare i32 @args_f32(i32, i32, i32, i32, i32, i32, i32, i32, 186 float, float, float, float, float, float, float, float, 187 i16 signext, float, i8 signext) 188 189define i32 @test7(i32* nocapture %in) nounwind { 190entry: 191; CHECK-LABEL: test7 192; CHECK: strb [[REG_2:w[0-9]+]], [sp, #8] 193; CHECK: str [[REG_1:w[0-9]+]], [sp, #4] 194; CHECK: strh [[REG_3:w[0-9]+]], [sp] 195 %0 = load i32, i32* %in, align 4 196 %call = tail call i32 @args_i32(i32 3, i32 %0, i32 %0, i32 %0, i32 %0, i32 %0, 197 i32 %0, i32 %0, i16 signext 3, i32 %0, i8 signext 4) 198 ret i32 %call 199} 200declare i32 @args_i32(i32, i32, i32, i32, i32, i32, i32, i32, i16 signext, i32, 201 i8 signext) 202 203define i32 @test8(i32 %argc, i8** nocapture %argv) nounwind { 204entry: 205; CHECK-LABEL: test8 206; CHECK: str w8, [sp] 207; CHECK: bl 208; FAST-LABEL: test8 209; FAST: strb {{w[0-9]+}}, [sp] 210; FAST: strb {{w[0-9]+}}, [sp, #1] 211; FAST: strb {{w[0-9]+}}, [sp, #2] 212; FAST: strb {{w[0-9]+}}, [sp, #3] 213; FAST: bl 214 tail call void @args_i1(i1 zeroext false, i1 zeroext true, i1 zeroext false, 215 i1 zeroext true, i1 zeroext false, i1 zeroext true, 216 i1 zeroext false, i1 zeroext true, i1 zeroext false, 217 i1 zeroext true, i1 zeroext false, i1 zeroext true) 218 ret i32 0 219} 220 221declare void @args_i1(i1 zeroext, i1 zeroext, i1 zeroext, i1 zeroext, 222 i1 zeroext, i1 zeroext, i1 zeroext, i1 zeroext, 223 i1 zeroext, i1 zeroext, i1 zeroext, i1 zeroext) 224 225define i32 @i1_stack_incoming(i64 %a, i64 %b, i64 %c, i64 %d, i64 %e, i64 %f, 226 i64 %g, i64 %h, i64 %i, i1 zeroext %j) { 227; CHECK-LABEL: i1_stack_incoming: 228; CHECK: ldrb w0, [sp, #8] 229; CHECK: ret 230 %v = zext i1 %j to i32 231 ret i32 %v 232} 233