1 ; RUN: llc < %s -march=arm64 -mcpu=cyclone -enable-misched=false | FileCheck %s
2 ; RUN: llc < %s -O0 | FileCheck -check-prefix=FAST %s
3 target triple = "arm64-apple-darwin"
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: ldrsb {{w[0-9]+}}, [sp, #5]
12 ; CHECK: ldrsh {{w[0-9]+}}, [sp, #2]
13 ; CHECK: ldrsb {{w[0-9]+}}, [sp]
14 ; CHECK: ldrsb {{w[0-9]+}}, [sp, #4]
15 ; FAST-LABEL: i8i16callee:
16 ; FAST: ldrb {{w[0-9]+}}, [sp, #5]
17 ; FAST: ldrb {{w[0-9]+}}, [sp, #4]
18 ; FAST: ldrh {{w[0-9]+}}, [sp, #2]
19 ; FAST: ldrb {{w[0-9]+}}, [sp]
20 %conv = sext i8 %a4 to i64
21 %conv3 = sext i16 %a5 to i64
22 %conv8 = sext i8 %b1 to i64
23 %conv9 = sext i16 %b2 to i64
24 %conv11 = sext i8 %b3 to i64
25 %conv13 = sext i8 %b4 to i64
26 %add10 = add i64 %a2, %a1
27 %add12 = add i64 %add10, %a3
28 %add14 = add i64 %add12, %conv
29 %add = add i64 %add14, %conv3
30 %add1 = add i64 %add, %a6
31 %add2 = add i64 %add1, %a7
32 %add4 = add i64 %add2, %a8
33 %add5 = add i64 %add4, %conv8
34 %add6 = add i64 %add5, %conv9
35 %add7 = add i64 %add6, %conv11
36 %add15 = add i64 %add7, %conv13
37 %sext = shl i64 %add15, 32
38 %conv17 = ashr exact i64 %sext, 32
42 define i32 @i8i16caller() nounwind readnone {
45 ; The 8th, 9th, 10th and 11th arguments are passed at sp, sp+2, sp+4, sp+5.
46 ; They are i8, i16, i8 and i8.
47 ; CHECK: strb {{w[0-9]+}}, [sp, #5]
48 ; CHECK: strb {{w[0-9]+}}, [sp, #4]
49 ; CHECK: strh {{w[0-9]+}}, [sp, #2]
50 ; CHECK: strb {{w[0-9]+}}, [sp]
53 ; FAST: strb {{w[0-9]+}}, [sp]
54 ; FAST: strh {{w[0-9]+}}, [sp, #2]
55 ; FAST: strb {{w[0-9]+}}, [sp, #4]
56 ; FAST: strb {{w[0-9]+}}, [sp, #5]
58 %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)
59 %conv = trunc i64 %call to i32
64 define double @circle_center([2 x float] %a) nounwind ssp {
65 %call = tail call double @ext([2 x float] %a) nounwind
66 ; CHECK: circle_center
70 declare double @ext([2 x float])
73 ; 16-byte vector should be aligned at 16-byte when passing on stack.
74 ; A double argument will be passed on stack, so vecotr should be at sp+16.
75 define double @fixed_4i(<4 x i32>* nocapture %in) nounwind {
78 ; CHECK: str [[REG_1:q[0-9]+]], [sp, #16]
80 ; FAST: mov x[[ADDR:[0-9]+]], sp
81 ; FAST: str [[REG_1:q[0-9]+]], [x[[ADDR]], #16]
82 %0 = load <4 x i32>* %in, align 16
83 %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 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 ; d8 at sp, i in register w0.
90 @g_d = common global double 0.000000e+00, align 8
91 define void @test1(float %f1, double %d1, double %d2, double %d3, double %d4,
92 double %d5, double %d6, double %d7, double %d8, i32 %i) nounwind ssp {
95 ; CHECK: ldr [[REG_1:d[0-9]+]], [sp]
96 ; CHECK: scvtf [[REG_2:s[0-9]+]], w0
97 ; CHECK: fadd s0, [[REG_2]], s0
98 %conv = sitofp i32 %i to float
99 %add = fadd float %conv, %f1
100 %conv1 = fpext float %add to double
101 %add2 = fadd double %conv1, %d7
102 %add3 = fadd double %add2, %d8
103 store double %add3, double* @g_d, align 8
107 ; i9 at sp, d1 in register s0.
108 define void @test2(i32 %i1, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6,
109 i32 %i7, i32 %i8, i32 %i9, float %d1) nounwind ssp {
112 ; CHECK: scvtf [[REG_2:s[0-9]+]], w0
113 ; CHECK: fadd s0, [[REG_2]], s0
114 ; CHECK: ldr [[REG_1:s[0-9]+]], [sp]
115 %conv = sitofp i32 %i1 to float
116 %add = fadd float %conv, %d1
117 %conv1 = fpext float %add to double
118 %conv2 = sitofp i32 %i8 to double
119 %add3 = fadd double %conv2, %conv1
120 %conv4 = sitofp i32 %i9 to double
121 %add5 = fadd double %conv4, %add3
122 store double %add5, double* @g_d, align 8
127 ; Check alignment on stack for v64, f64, i64, f32, i32.
128 define double @test3(<2 x i32>* nocapture %in) nounwind {
131 ; CHECK: str [[REG_1:d[0-9]+]], [sp, #8]
133 ; FAST: mov x[[ADDR:[0-9]+]], sp
134 ; FAST: str [[REG_1:d[0-9]+]], [x[[ADDR]], #8]
135 %0 = load <2 x i32>* %in, align 8
136 %call = tail call double @args_vec_2i(double 3.000000e+00, <2 x i32> %0,
137 <2 x i32> %0, <2 x i32> %0, <2 x i32> %0, <2 x i32> %0, <2 x i32> %0,
138 <2 x i32> %0, float 3.000000e+00, <2 x i32> %0, i8 signext 3)
141 declare double @args_vec_2i(double, <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32>,
142 <2 x i32>, <2 x i32>, <2 x i32>, float, <2 x i32>, i8 signext)
144 define double @test4(double* nocapture %in) nounwind {
147 ; CHECK: str [[REG_1:d[0-9]+]], [sp, #8]
148 ; CHECK: str [[REG_2:w[0-9]+]], [sp]
149 ; CHECK: orr w0, wzr, #0x3
150 %0 = load double* %in, align 8
151 %call = tail call double @args_f64(double 3.000000e+00, double %0, double %0,
152 double %0, double %0, double %0, double %0, double %0,
153 float 3.000000e+00, double %0, i8 signext 3)
156 declare double @args_f64(double, double, double, double, double, double, double,
157 double, float, double, i8 signext)
159 define i64 @test5(i64* nocapture %in) nounwind {
162 ; CHECK: strb [[REG_3:w[0-9]+]], [sp, #16]
163 ; CHECK: str [[REG_1:x[0-9]+]], [sp, #8]
164 ; CHECK: str [[REG_2:w[0-9]+]], [sp]
165 %0 = load i64* %in, align 8
166 %call = tail call i64 @args_i64(i64 3, i64 %0, i64 %0, i64 %0, i64 %0, i64 %0,
167 i64 %0, i64 %0, i32 3, i64 %0, i8 signext 3)
170 declare i64 @args_i64(i64, i64, i64, i64, i64, i64, i64, i64, i32, i64,
173 define i32 @test6(float* nocapture %in) nounwind {
176 ; CHECK: strb [[REG_2:w[0-9]+]], [sp, #8]
177 ; CHECK: str [[REG_1:s[0-9]+]], [sp, #4]
178 ; CHECK: strh [[REG_3:w[0-9]+]], [sp]
179 %0 = load float* %in, align 4
180 %call = tail call i32 @args_f32(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6,
181 i32 7, i32 8, float 1.0, float 2.0, float 3.0, float 4.0, float 5.0,
182 float 6.0, float 7.0, float 8.0, i16 signext 3, float %0,
186 declare i32 @args_f32(i32, i32, i32, i32, i32, i32, i32, i32,
187 float, float, float, float, float, float, float, float,
188 i16 signext, float, i8 signext)
190 define i32 @test7(i32* nocapture %in) nounwind {
193 ; CHECK: strb [[REG_2:w[0-9]+]], [sp, #8]
194 ; CHECK: str [[REG_1:w[0-9]+]], [sp, #4]
195 ; CHECK: strh [[REG_3:w[0-9]+]], [sp]
196 %0 = load i32* %in, align 4
197 %call = tail call i32 @args_i32(i32 3, i32 %0, i32 %0, i32 %0, i32 %0, i32 %0,
198 i32 %0, i32 %0, i16 signext 3, i32 %0, i8 signext 4)
201 declare i32 @args_i32(i32, i32, i32, i32, i32, i32, i32, i32, i16 signext, i32,
204 define i32 @test8(i32 %argc, i8** nocapture %argv) nounwind {
207 ; CHECK: strb {{w[0-9]+}}, [sp, #3]
208 ; CHECK: strb wzr, [sp, #2]
209 ; CHECK: strb {{w[0-9]+}}, [sp, #1]
210 ; CHECK: strb wzr, [sp]
213 ; FAST: strb {{w[0-9]+}}, [sp]
214 ; FAST: strb {{w[0-9]+}}, [sp, #1]
215 ; FAST: strb {{w[0-9]+}}, [sp, #2]
216 ; FAST: strb {{w[0-9]+}}, [sp, #3]
218 tail call void @args_i1(i1 zeroext false, i1 zeroext true, i1 zeroext false,
219 i1 zeroext true, i1 zeroext false, i1 zeroext true,
220 i1 zeroext false, i1 zeroext true, i1 zeroext false,
221 i1 zeroext true, i1 zeroext false, i1 zeroext true)
225 declare void @args_i1(i1 zeroext, i1 zeroext, i1 zeroext, i1 zeroext,
226 i1 zeroext, i1 zeroext, i1 zeroext, i1 zeroext,
227 i1 zeroext, i1 zeroext, i1 zeroext, i1 zeroext)
229 define i32 @i1_stack_incoming(i64 %a, i64 %b, i64 %c, i64 %d, i64 %e, i64 %f,
230 i64 %g, i64 %h, i64 %i, i1 zeroext %j) {
231 ; CHECK-LABEL: i1_stack_incoming:
232 ; CHECK: ldrb w0, [sp, #8]
234 %v = zext i1 %j to i32