AArch64: mark small types (i1, i8, i16) as promoted
[oota-llvm.git] / test / CodeGen / AArch64 / arm64-abi.ll
1 ; RUN: llc < %s -debug -march=arm64 -mcpu=cyclone -enable-misched=false | FileCheck %s
2 ; RUN: llc < %s -O0 | FileCheck -check-prefix=FAST %s
3 ; REQUIRES: asserts
4 target triple = "arm64-apple-darwin"
5
6 ; rdar://9932559
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 {
8 entry:
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
40   ret i64 %conv17
41 }
42
43 define i32 @i8i16caller() nounwind readnone {
44 entry:
45 ; CHECK: 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]
52 ; CHECK: bl
53 ; FAST: 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]
58 ; FAST: bl
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
61   ret i32 %conv
62 }
63
64 ; rdar://12651543
65 define double @circle_center([2 x float] %a) nounwind ssp {
66   %call = tail call double @ext([2 x float] %a) nounwind
67 ; CHECK: circle_center
68 ; CHECK: bl
69   ret double %call
70 }
71 declare double @ext([2 x float])
72
73 ; rdar://12656141
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 {
77 entry:
78 ; CHECK: fixed_4i
79 ; CHECK: str [[REG_1:q[0-9]+]], [sp, #16]
80 ; FAST: 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)
86   ret double %call
87 }
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)
89
90 ; rdar://12695237
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 {
95 entry:
96 ; CHECK: test1
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
106   ret void
107 }
108
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 {
112 entry:
113 ; CHECK: test2
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
125   ret void
126 }
127
128 ; rdar://12648441
129 ; Check alignment on stack for v64, f64, i64, f32, i32.
130 define double @test3(<2 x i32>* nocapture %in) nounwind {
131 entry:
132 ; CHECK: test3
133 ; CHECK: str [[REG_1:d[0-9]+]], [sp, #8]
134 ; FAST: test3
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)
142   ret double %call
143 }
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)
146
147 define double @test4(double* nocapture %in) nounwind {
148 entry:
149 ; CHECK: test4
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)
157   ret double %call
158 }
159 declare double @args_f64(double, double, double, double, double, double, double,
160                double, float, double, i8 signext)
161
162 define i64 @test5(i64* nocapture %in) nounwind {
163 entry:
164 ; CHECK: test5
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)
171   ret i64 %call
172 }
173 declare i64 @args_i64(i64, i64, i64, i64, i64, i64, i64, i64, i32, i64,
174              i8 signext)
175
176 define i32 @test6(float* nocapture %in) nounwind {
177 entry:
178 ; CHECK: test6
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,
186           i8 signext 3)
187   ret i32 %call
188 }
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)
192
193 define i32 @test7(i32* nocapture %in) nounwind {
194 entry:
195 ; CHECK: test7
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)
202   ret i32 %call
203 }
204 declare i32 @args_i32(i32, i32, i32, i32, i32, i32, i32, i32, i16 signext, i32,
205              i8 signext)
206
207 define i32 @test8(i32 %argc, i8** nocapture %argv) nounwind {
208 entry:
209 ; CHECK: test8
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]
214 ; CHECK: bl
215 ; FAST: test8
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]
220 ; FAST: bl
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)
225   ret i32 0
226 }
227
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)
231
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]
236 ; CHECK: ret
237   %v = zext i1 %j to i32
238   ret i32 %v
239 }