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
6 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 ; 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
47 define i32 @i8i16caller() nounwind readnone {
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]
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]
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
67 define 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
73 declare double @ext([2 x float])
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.
78 define double @fixed_4i(ptr nocapture %in) nounwind {
80 ; CHECK-LABEL: fixed_4i
81 ; CHECK: str [[REG_1:q[0-9]+]], [sp, #16]
82 ; FAST-LABEL: fixed_4i
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)
90 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)
93 ; d8 at sp, i in register w0.
94 @g_d = common global double 0.000000e+00, align 8
95 define 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 {
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
111 ; i9 at sp, d1 in register s0.
112 define 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 {
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
131 ; Check alignment on stack for v64, f64, i64, f32, i32.
132 define double @test3(ptr nocapture %in) nounwind {
135 ; CHECK: str [[REG_1:d[0-9]+]], [sp, #8]
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)
146 declare 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)
149 define double @test4(ptr nocapture %in) nounwind {
152 ; CHECK: str [[REG_1:d[0-9]+]], [sp, #8]
153 ; CHECK: str [[REG_2:w[0-9]+]], [sp]
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)
161 declare double @args_f64(double, double, double, double, double, double, double,
162 double, float, double, i8 signext)
164 define i64 @test5(ptr nocapture %in) nounwind {
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)
175 declare i64 @args_i64(i64, i64, i64, i64, i64, i64, i64, i64, i32, i64,
178 define i32 @test6(ptr nocapture %in) nounwind {
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,
191 declare 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)
195 define i32 @test7(ptr nocapture %in) nounwind {
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)
206 declare i32 @args_i32(i32, i32, i32, i32, i32, i32, i32, i32, i16 signext, i32,
209 define i32 @test8(i32 %argc, ptr nocapture %argv) nounwind {
212 ; CHECK: str w8, [sp]
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]
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)
227 declare 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)
231 define 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]
236 ; GISEL-LABEL: i1_stack_incoming:
237 ; GISEL: ldrb w0, [sp, #8]
239 %v = zext i1 %j to i32