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