1 ; RUN: llc < %s -march=arm64 -mcpu=cyclone -enable-misched=false | FileCheck %s
2 ; RUN: llc < %s -O0 | FileCheck -check-prefix=FAST %s
4 target triple = "arm64-apple-darwin"
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 {
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
43 define i32 @i8i16caller() nounwind readnone {
45 ; CHECK-LABEL: 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]
53 ; FAST-LABEL: 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]
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
65 define double @circle_center([2 x float] %a) nounwind ssp {
66 %call = tail call double @ext([2 x float] %a) nounwind
67 ; CHECK-LABEL: circle_center
71 declare double @ext([2 x float])
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 {
78 ; CHECK-LABEL: fixed_4i
79 ; CHECK: str [[REG_1:q[0-9]+]], [sp, #16]
80 ; FAST-LABEL: 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)
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)
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 {
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
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 {
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
129 ; Check alignment on stack for v64, f64, i64, f32, i32.
130 define double @test3(<2 x i32>* nocapture %in) nounwind {
133 ; CHECK: str [[REG_1:d[0-9]+]], [sp, #8]
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)
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)
147 define double @test4(double* nocapture %in) nounwind {
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)
159 declare double @args_f64(double, double, double, double, double, double, double,
160 double, float, double, i8 signext)
162 define i64 @test5(i64* nocapture %in) nounwind {
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)
173 declare i64 @args_i64(i64, i64, i64, i64, i64, i64, i64, i64, i32, i64,
176 define i32 @test6(float* nocapture %in) nounwind {
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,
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)
193 define i32 @test7(i32* nocapture %in) nounwind {
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)
204 declare i32 @args_i32(i32, i32, i32, i32, i32, i32, i32, i32, i16 signext, i32,
207 define i32 @test8(i32 %argc, i8** nocapture %argv) nounwind {
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]
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]
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)
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)
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]
237 %v = zext i1 %j to i32