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