ARM64: initial backend import
[oota-llvm.git] / test / CodeGen / ARM64 / abi.ll
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"
4
5 ; rdar://9932559
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 {
7 entry:
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
39   ret i64 %conv17
40 }
41
42 define i32 @i8i16caller() nounwind readnone {
43 entry:
44 ; CHECK: i8i16caller
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]
51 ; CHECK: bl
52 ; FAST: i8i16caller
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]
57 ; FAST: bl
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
60   ret i32 %conv
61 }
62
63 ; rdar://12651543
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
67 ; CHECK: bl
68   ret double %call
69 }
70 declare double @ext([2 x float])
71
72 ; rdar://12656141
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 {
76 entry:
77 ; CHECK: fixed_4i
78 ; CHECK: str [[REG_1:q[0-9]+]], [sp, #16]
79 ; FAST: fixed_4i
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)
84   ret double %call
85 }
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)
87
88 ; rdar://12695237
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 {
93 entry:
94 ; CHECK: test1
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
104   ret void
105 }
106
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 {
110 entry:
111 ; CHECK: test2
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
123   ret void
124 }
125
126 ; rdar://12648441
127 ; Check alignment on stack for v64, f64, i64, f32, i32.
128 define double @test3(<2 x i32>* nocapture %in) nounwind {
129 entry:
130 ; CHECK: test3
131 ; CHECK: str [[REG_1:d[0-9]+]], [sp, #8]
132 ; FAST: test3
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)
139   ret double %call
140 }
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)
143
144 define double @test4(double* nocapture %in) nounwind {
145 entry:
146 ; CHECK: test4
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)
154   ret double %call
155 }
156 declare double @args_f64(double, double, double, double, double, double, double,
157                double, float, double, i8 signext)
158
159 define i64 @test5(i64* nocapture %in) nounwind {
160 entry:
161 ; CHECK: test5
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)
168   ret i64 %call
169 }
170 declare i64 @args_i64(i64, i64, i64, i64, i64, i64, i64, i64, i32, i64,
171              i8 signext)
172
173 define i32 @test6(float* nocapture %in) nounwind {
174 entry:
175 ; CHECK: test6
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,
183           i8 signext 3)
184   ret i32 %call
185 }
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)
189
190 define i32 @test7(i32* nocapture %in) nounwind {
191 entry:
192 ; CHECK: test7
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)
199   ret i32 %call
200 }
201 declare i32 @args_i32(i32, i32, i32, i32, i32, i32, i32, i32, i16 signext, i32,
202              i8 signext)
203
204 define i32 @test8(i32 %argc, i8** nocapture %argv) nounwind {
205 entry:
206 ; CHECK: test8
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]
211 ; CHECK: bl
212 ; FAST: test8
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]
217 ; FAST: bl
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)
222   ret i32 0
223 }
224
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)
228
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]
233 ; CHECK: ret
234   %v = zext i1 %j to i32
235   ret i32 %v
236 }