1; RUN: llc -mtriple arm-unknown -mattr=+vfp2,+v6 -global-isel %s -o - | FileCheck %s
2
3define void @test_void_return() {
4; CHECK-LABEL: test_void_return:
5; CHECK: bx lr
6entry:
7  ret void
8}
9
10define i32 @test_constant_return_i32() {
11; CHECK-LABEL: test_constant_return_i32:
12; CHECK: mov r0, #42
13; CHECK: bx lr
14entry:
15  ret i32 42
16}
17
18define zeroext i1 @test_zext_i1(i1 %x) {
19; CHECK-LABEL: test_zext_i1
20; CHECK: and r0, r0, #1
21; CHECK: bx lr
22entry:
23  ret i1 %x
24}
25
26define signext i1 @test_sext_i1(i1 %x) {
27; CHECK-LABEL: test_sext_i1
28; CHECK: mov	r1, #31
29; CHECK: lsl	r0, r0, r1
30; CHECK: asr	r0, r0, r1
31; CHECK: bx lr
32entry:
33  ret i1 %x
34}
35
36define zeroext i8 @test_ext_i8(i8 %x) {
37; CHECK-LABEL: test_ext_i8:
38; CHECK: uxtb r0, r0
39; CHECK: bx lr
40
41entry:
42  ret i8 %x
43}
44
45define signext i16 @test_ext_i16(i16 %x) {
46; CHECK-LABEL: test_ext_i16:
47; CHECK: mov	r1, #16
48; CHECK: lsl	r0, r0, r1
49; CHECK: asr	r0, r0, r1
50; CHECK: bx lr
51entry:
52  ret i16 %x
53}
54
55define void @test_trunc_i32_i16(i32 %v, i16 *%p) {
56; CHECK-LABEL: test_trunc_i32_i16:
57; The trunc doesn't result in any instructions, but we
58; expect the store to be explicitly 16-bit.
59; CHECK: strh r0, [r1]
60; CHECK: bx lr
61entry:
62  %v16 = trunc i32 %v to i16
63  store i16 %v16, i16 *%p
64  ret void
65}
66
67define void @test_trunc_i32_i8(i32 %v, i8 *%p) {
68; CHECK-LABEL: test_trunc_i32_i8:
69; The trunc doesn't result in any instructions, but we
70; expect the store to be explicitly 8-bit.
71; CHECK: strb r0, [r1]
72; CHECK: bx lr
73entry:
74  %v8 = trunc i32 %v to i8
75  store i8 %v8, i8 *%p
76  ret void
77}
78
79define i8 @test_add_i8(i8 %x, i8 %y) {
80; CHECK-LABEL: test_add_i8:
81; CHECK: add r0, r0, r1
82; CHECK: bx lr
83entry:
84  %sum = add i8 %x, %y
85  ret i8 %sum
86}
87
88define i16 @test_add_i16(i16 %x, i16 %y) {
89; CHECK-LABEL: test_add_i16:
90; CHECK: add r0, r0, r1
91; CHECK: bx lr
92entry:
93  %sum = add i16 %x, %y
94  ret i16 %sum
95}
96
97define i32 @test_add_i32(i32 %x, i32 %y) {
98; CHECK-LABEL: test_add_i32:
99; CHECK: add r0, r0, r1
100; CHECK: bx lr
101entry:
102  %sum = add i32 %x, %y
103  ret i32 %sum
104}
105
106define i8 @test_sub_i8(i8 %x, i8 %y) {
107; CHECK-LABEL: test_sub_i8:
108; CHECK: sub r0, r0, r1
109; CHECK: bx lr
110entry:
111  %sum = sub i8 %x, %y
112  ret i8 %sum
113}
114
115define i16 @test_sub_i16(i16 %x, i16 %y) {
116; CHECK-LABEL: test_sub_i16:
117; CHECK: sub r0, r0, r1
118; CHECK: bx lr
119entry:
120  %sum = sub i16 %x, %y
121  ret i16 %sum
122}
123
124define i32 @test_sub_i32(i32 %x, i32 %y) {
125; CHECK-LABEL: test_sub_i32:
126; CHECK: sub r0, r0, r1
127; CHECK: bx lr
128entry:
129  %sum = sub i32 %x, %y
130  ret i32 %sum
131}
132
133define i8 @test_mul_i8(i8 %x, i8 %y) {
134; CHECK-LABEL: test_mul_i8:
135; CHECK: mul r0, r0, r1
136; CHECK: bx lr
137entry:
138  %sum = mul i8 %x, %y
139  ret i8 %sum
140}
141
142define i16 @test_mul_i16(i16 %x, i16 %y) {
143; CHECK-LABEL: test_mul_i16:
144; CHECK: mul r0, r0, r1
145; CHECK: bx lr
146entry:
147  %sum = mul i16 %x, %y
148  ret i16 %sum
149}
150
151define i32 @test_mul_i32(i32 %x, i32 %y) {
152; CHECK-LABEL: test_mul_i32:
153; CHECK: mul r0, r0, r1
154; CHECK: bx lr
155entry:
156  %sum = mul i32 %x, %y
157  ret i32 %sum
158}
159
160define i8 @test_and_i8(i8 %x, i8 %y) {
161; CHECK-LABEL: test_and_i8:
162; CHECK: and r0, r0, r1
163; CHECK: bx lr
164entry:
165  %sum = and i8 %x, %y
166  ret i8 %sum
167}
168
169define i16 @test_and_i16(i16 %x, i16 %y) {
170; CHECK-LABEL: test_and_i16:
171; CHECK: and r0, r0, r1
172; CHECK: bx lr
173entry:
174  %sum = and i16 %x, %y
175  ret i16 %sum
176}
177
178define i32 @test_and_i32(i32 %x, i32 %y) {
179; CHECK-LABEL: test_and_i32:
180; CHECK: and r0, r0, r1
181; CHECK: bx lr
182entry:
183  %sum = and i32 %x, %y
184  ret i32 %sum
185}
186
187define i8 @test_or_i8(i8 %x, i8 %y) {
188; CHECK-LABEL: test_or_i8:
189; CHECK: orr r0, r0, r1
190; CHECK: bx lr
191entry:
192  %sum = or i8 %x, %y
193  ret i8 %sum
194}
195
196define i16 @test_or_i16(i16 %x, i16 %y) {
197; CHECK-LABEL: test_or_i16:
198; CHECK: orr r0, r0, r1
199; CHECK: bx lr
200entry:
201  %sum = or i16 %x, %y
202  ret i16 %sum
203}
204
205define i32 @test_or_i32(i32 %x, i32 %y) {
206; CHECK-LABEL: test_or_i32:
207; CHECK: orr r0, r0, r1
208; CHECK: bx lr
209entry:
210  %sum = or i32 %x, %y
211  ret i32 %sum
212}
213
214define i8 @test_xor_i8(i8 %x, i8 %y) {
215; CHECK-LABEL: test_xor_i8:
216; CHECK: eor r0, r0, r1
217; CHECK: bx lr
218entry:
219  %sum = xor i8 %x, %y
220  ret i8 %sum
221}
222
223define i16 @test_xor_i16(i16 %x, i16 %y) {
224; CHECK-LABEL: test_xor_i16:
225; CHECK: eor r0, r0, r1
226; CHECK: bx lr
227entry:
228  %sum = xor i16 %x, %y
229  ret i16 %sum
230}
231
232define i32 @test_xor_i32(i32 %x, i32 %y) {
233; CHECK-LABEL: test_xor_i32:
234; CHECK: eor r0, r0, r1
235; CHECK: bx lr
236entry:
237  %sum = xor i32 %x, %y
238  ret i32 %sum
239}
240
241define i32 @test_stack_args_i32(i32 %p0, i32 %p1, i32 %p2, i32 %p3, i32 %p4, i32 %p5) {
242; CHECK-LABEL: test_stack_args_i32:
243; CHECK: add [[P5ADDR:r[0-9]+]], sp, #4
244; CHECK: ldr [[P5:r[0-9]+]], {{.*}}[[P5ADDR]]
245; CHECK: add r0, r2, [[P5]]
246; CHECK: bx lr
247entry:
248  %sum = add i32 %p2, %p5
249  ret i32 %sum
250}
251
252define i16 @test_stack_args_mixed(i32 %p0, i16 %p1, i8 %p2, i1 %p3, i8 %p4, i16 %p5) {
253; CHECK-LABEL: test_stack_args_mixed:
254; CHECK: add [[P5ADDR:r[0-9]+]], sp, #4
255; CHECK: ldrh [[P5:r[0-9]+]], {{.*}}[[P5ADDR]]
256; CHECK: add r0, r1, [[P5]]
257; CHECK: bx lr
258entry:
259  %sum = add i16 %p1, %p5
260  ret i16 %sum
261}
262
263define i16 @test_stack_args_zeroext(i32 %p0, i16 %p1, i8 %p2, i1 %p3, i16 zeroext %p4) {
264; CHECK-LABEL: test_stack_args_zeroext:
265; CHECK: mov [[P4ADDR:r[0-9]+]], sp
266; CHECK: ldr [[P4:r[0-9]+]], {{.*}}[[P4ADDR]]
267; CHECK: add r0, r1, [[P4]]
268; CHECK: bx lr
269entry:
270  %sum = add i16 %p1, %p4
271  ret i16 %sum
272}
273
274define i8 @test_stack_args_signext(i32 %p0, i16 %p1, i8 %p2, i1 %p3, i8 signext %p4) {
275; CHECK-LABEL: test_stack_args_signext:
276; CHECK: mov [[P4ADDR:r[0-9]+]], sp
277; CHECK: ldr [[P4:r[0-9]+]], {{.*}}[[P4ADDR]]
278; CHECK: add r0, r2, [[P4]]
279; CHECK: bx lr
280entry:
281  %sum = add i8 %p2, %p4
282  ret i8 %sum
283}
284
285define i8 @test_stack_args_noext(i32 %p0, i16 %p1, i8 %p2, i1 %p3, i8 %p4) {
286; CHECK-LABEL: test_stack_args_noext:
287; CHECK: mov [[P4ADDR:r[0-9]+]], sp
288; CHECK: ldrb [[P4:r[0-9]+]], {{.*}}[[P4ADDR]]
289; CHECK: add r0, r2, [[P4]]
290; CHECK: bx lr
291entry:
292  %sum = add i8 %p2, %p4
293  ret i8 %sum
294}
295
296define i32 @test_ptr_arg_in_reg(i32* %p) {
297; CHECK-LABEL: test_ptr_arg_in_reg:
298; CHECK: ldr r0, [r0]
299; CHECK: bx lr
300entry:
301  %v = load i32, i32* %p
302  ret i32 %v
303}
304
305define i32 @test_ptr_arg_on_stack(i32 %f0, i32 %f1, i32 %f2, i32 %f3, i32* %p) {
306; CHECK-LABEL: test_ptr_arg_on_stack:
307; CHECK: mov r0, sp
308; CHECK: ldr r0, [r0]
309; CHECK: ldr r0, [r0]
310; CHECK: bx lr
311entry:
312  %v = load i32, i32* %p
313  ret i32 %v
314}
315
316define i8* @test_ptr_ret(i8** %p) {
317; CHECK-LABEL: test_ptr_ret:
318; CHECK: ldr r0, [r0]
319; CHECK: bx lr
320entry:
321  %v = load i8*, i8** %p
322  ret i8* %v
323}
324
325define arm_aapcs_vfpcc float @test_float_hard(float %f0, float %f1) {
326; CHECK-LABEL: test_float_hard:
327; CHECK: vadd.f32 s0, s0, s1
328; CHECK: bx lr
329entry:
330  %v = fadd float %f0, %f1
331  ret float %v
332}
333
334define arm_aapcscc float @test_float_softfp(float %f0, float %f1) {
335; CHECK-LABEL: test_float_softfp:
336; CHECK-DAG: vmov [[F0:s[0-9]+]], r0
337; CHECK-DAG: vmov [[F1:s[0-9]+]], r1
338; CHECK: vadd.f32 [[FV:s[0-9]+]], [[F0]], [[F1]]
339; CHECK: vmov r0, [[FV]]
340; CHECK: bx lr
341entry:
342  %v = fadd float %f0, %f1
343  ret float %v
344}
345
346define arm_aapcs_vfpcc double @test_double_hard(double %f0, double %f1) {
347; CHECK-LABEL: test_double_hard:
348; CHECK: vadd.f64 d0, d0, d1
349; CHECK: bx lr
350entry:
351  %v = fadd double %f0, %f1
352  ret double %v
353}
354
355define arm_aapcscc double @test_double_softfp(double %f0, double %f1) {
356; CHECK-LABEL: test_double_softfp:
357; CHECK-DAG: vmov [[F0:d[0-9]+]], r0, r1
358; CHECK-DAG: vmov [[F1:d[0-9]+]], r2, r3
359; CHECK: vadd.f64 [[FV:d[0-9]+]], [[F0]], [[F1]]
360; CHECK: vmov r0, r1, [[FV]]
361; CHECK: bx lr
362entry:
363  %v = fadd double %f0, %f1
364  ret double %v
365}
366
367define arm_aapcscc i32 @test_cmp_i32_eq(i32 %a, i32 %b) {
368; CHECK-LABEL: test_cmp_i32_eq:
369; CHECK: mov [[V:r[0-9]+]], #0
370; CHECK: cmp r0, r1
371; CHECK: moveq [[V]], #1
372; CHECK: and r0, [[V]], #1
373; CHECK: bx lr
374entry:
375  %v = icmp eq i32 %a, %b
376  %r = zext i1 %v to i32
377  ret i32 %r
378}
379
380define arm_aapcscc i32 @test_cmp_ptr_neq(double *%a, double *%b) {
381; CHECK-LABEL: test_cmp_ptr_neq:
382; CHECK: mov [[V:r[0-9]+]], #0
383; CHECK: cmp r0, r1
384; CHECK: movne [[V]], #1
385; CHECK: and r0, [[V]], #1
386; CHECK: bx lr
387entry:
388  %v = icmp ne double * %a, %b
389  %r = zext i1 %v to i32
390  ret i32 %r
391}
392
393define arm_aapcscc i32 @test_cmp_i16_slt(i16 %a, i16 %b) {
394; CHECK-LABEL: test_cmp_i16_slt:
395; CHECK-DAG: mov [[V:r[0-9]+]], #0
396; CHECK: cmp r0, r1
397; CHECK: movlt [[V]], #1
398; CHECK: and r0, [[V]], #1
399; CHECK: bx lr
400entry:
401  %v = icmp slt i16 %a, %b
402  %r = zext i1 %v to i32
403  ret i32 %r
404}
405
406define arm_aapcscc i32 @test_select_i32(i32 %a, i32 %b, i1 %cond) {
407; CHECK-LABEL: test_select_i32
408; CHECK: cmp r2, #0
409; CHECK: moveq r0, r1
410; CHECK: bx lr
411entry:
412  %r = select i1 %cond, i32 %a, i32 %b
413  ret i32 %r
414}
415
416define arm_aapcscc i32* @test_select_ptr(i32* %a, i32* %b, i1 %cond) {
417; CHECK-LABEL: test_select_ptr
418; CHECK: cmp r2, #0
419; CHECK: moveq r0, r1
420; CHECK: bx lr
421entry:
422  %r = select i1 %cond, i32* %a, i32* %b
423  ret i32* %r
424}
425
426define arm_aapcscc void @test_br() {
427; CHECK-LABEL: test_br
428; CHECK: [[LABEL:.L[[:alnum:]_]+]]:
429; CHECK: b [[LABEL]]
430entry:
431  br label %infinite
432
433infinite:
434  br label %infinite
435}
436
437declare arm_aapcscc void @brcond1()
438declare arm_aapcscc void @brcond2()
439
440define arm_aapcscc void @test_brcond(i32 %n) {
441; CHECK-LABEL: test_brcond
442; CHECK: cmp r0
443; CHECK-NEXT: movgt [[RCMP:r[0-9]+]], #1
444; CHECK: tst [[RCMP]], #1
445; CHECK-NEXT: beq [[FALSE:.L[[:alnum:]_]+]]
446; CHECK: bl brcond1
447; CHECK: [[FALSE]]:
448; CHECK: bl brcond2
449entry:
450  %cmp = icmp sgt i32 %n, 0
451  br i1 %cmp, label %if.true, label %if.false
452
453if.true:
454  call arm_aapcscc void @brcond1()
455  br label %if.end
456
457if.false:
458  call arm_aapcscc void @brcond2()
459  br label %if.end
460
461if.end:
462  ret void
463}
464