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