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