xref: /llvm-project/llvm/test/CodeGen/ARM/tail-call-float.ll (revision 1a908c6be3317bbbac73e6a6fc52cabefbdebf7d)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
2; RUN: llc -mtriple armv7 -target-abi aapcs -float-abi soft -O0 -o - < %s \
3; RUN:   | FileCheck %s -check-prefix CHECK-SOFT
4; RUN: llc -mtriple armv7 -target-abi aapcs -float-abi hard -O0 -o - < %s \
5; RUN:   | FileCheck %s -check-prefix CHECK-HARD
6
7; Tests for passing floating-point regs. Variadic functions will always use
8; general-purpose registers. Standard functions will use the floating-point
9; registers if there is hardware FP available.
10
11declare i1 @non_variadic(float, float, float, float)
12declare i1 @non_variadic_big(float, float, float, float, float, float)
13declare i1 @variadic(float, ...)
14
15define void @non_variadic_fp(float %x, float %y) {
16; CHECK-SOFT-LABEL: non_variadic_fp:
17; CHECK-SOFT:       @ %bb.0: @ %entry
18; CHECK-SOFT-NEXT:    mov r3, r1
19; CHECK-SOFT-NEXT:    mov r2, r0
20; CHECK-SOFT-NEXT:    mov r0, r3
21; CHECK-SOFT-NEXT:    mov r1, r2
22; CHECK-SOFT-NEXT:    b non_variadic
23;
24; CHECK-HARD-LABEL: non_variadic_fp:
25; CHECK-HARD:       @ %bb.0: @ %entry
26; CHECK-HARD-NEXT:    vmov.f32 s3, s1
27; CHECK-HARD-NEXT:    vmov.f32 s2, s0
28; CHECK-HARD-NEXT:    vmov.f32 s0, s3
29; CHECK-HARD-NEXT:    vmov.f32 s1, s2
30; CHECK-HARD-NEXT:    b non_variadic
31entry:
32  %call = tail call i1 (float, float, float, float) @non_variadic(float %y, float %x, float %x, float %y)
33  ret void
34}
35
36define void @variadic_fp(float %x, float %y) {
37; CHECK-SOFT-LABEL: variadic_fp:
38; CHECK-SOFT:       @ %bb.0: @ %entry
39; CHECK-SOFT-NEXT:    mov r3, r1
40; CHECK-SOFT-NEXT:    mov r2, r0
41; CHECK-SOFT-NEXT:    mov r0, r3
42; CHECK-SOFT-NEXT:    mov r1, r2
43; CHECK-SOFT-NEXT:    b variadic
44;
45; CHECK-HARD-LABEL: variadic_fp:
46; CHECK-HARD:       @ %bb.0: @ %entry
47; CHECK-HARD-NEXT:    vmov r2, s0
48; CHECK-HARD-NEXT:    vmov r3, s1
49; CHECK-HARD-NEXT:    mov r0, r3
50; CHECK-HARD-NEXT:    mov r1, r2
51; CHECK-HARD-NEXT:    b variadic
52entry:
53  %call = tail call i1 (float, ...) @variadic(float %y, float %x, float %x, float %y)
54  ret void
55}
56
57; With soft-float, general-purpose registers are used and there are not enough
58; of them to handle the 6 arguments. With hard-float, we have plenty of regs
59; (s0-s15) to pass FP arguments.
60define void @non_variadic_fp_big(float %x, float %y) {
61; CHECK-SOFT-LABEL: non_variadic_fp_big:
62; CHECK-SOFT:       @ %bb.0: @ %entry
63; CHECK-SOFT-NEXT:    push {r11, lr}
64; CHECK-SOFT-NEXT:    sub sp, sp, #8
65; CHECK-SOFT-NEXT:    mov r3, r1
66; CHECK-SOFT-NEXT:    mov r2, r0
67; CHECK-SOFT-NEXT:    vmov s0, r3
68; CHECK-SOFT-NEXT:    vmov s0, r2
69; CHECK-SOFT-NEXT:    mov r0, sp
70; CHECK-SOFT-NEXT:    str r3, [r0, #4]
71; CHECK-SOFT-NEXT:    str r2, [r0]
72; CHECK-SOFT-NEXT:    mov r0, r3
73; CHECK-SOFT-NEXT:    mov r1, r2
74; CHECK-SOFT-NEXT:    bl non_variadic_big
75; CHECK-SOFT-NEXT:    add sp, sp, #8
76; CHECK-SOFT-NEXT:    pop {r11, pc}
77;
78; CHECK-HARD-LABEL: non_variadic_fp_big:
79; CHECK-HARD:       @ %bb.0: @ %entry
80; CHECK-HARD-NEXT:    vmov.f32 s5, s1
81; CHECK-HARD-NEXT:    vmov.f32 s4, s0
82; CHECK-HARD-NEXT:    vmov.f32 s0, s5
83; CHECK-HARD-NEXT:    vmov.f32 s1, s4
84; CHECK-HARD-NEXT:    vmov.f32 s2, s4
85; CHECK-HARD-NEXT:    vmov.f32 s3, s5
86; CHECK-HARD-NEXT:    b non_variadic_big
87entry:
88  %call = tail call i1 (float, float, float, float, float, float) @non_variadic_big(float %y, float %x, float %x, float %y, float %x, float %y)
89  ret void
90}
91
92; Variadic functions cannot use FP regs to pass arguments; only GP regs.
93define void @variadic_fp_big(float %x, float %y) {
94; CHECK-SOFT-LABEL: variadic_fp_big:
95; CHECK-SOFT:       @ %bb.0: @ %entry
96; CHECK-SOFT-NEXT:    push {r11, lr}
97; CHECK-SOFT-NEXT:    sub sp, sp, #8
98; CHECK-SOFT-NEXT:    mov r3, r1
99; CHECK-SOFT-NEXT:    mov r2, r0
100; CHECK-SOFT-NEXT:    vmov s0, r3
101; CHECK-SOFT-NEXT:    vmov s0, r2
102; CHECK-SOFT-NEXT:    mov r0, sp
103; CHECK-SOFT-NEXT:    str r3, [r0, #4]
104; CHECK-SOFT-NEXT:    str r2, [r0]
105; CHECK-SOFT-NEXT:    mov r0, r3
106; CHECK-SOFT-NEXT:    mov r1, r2
107; CHECK-SOFT-NEXT:    bl variadic
108; CHECK-SOFT-NEXT:    add sp, sp, #8
109; CHECK-SOFT-NEXT:    pop {r11, pc}
110;
111; CHECK-HARD-LABEL: variadic_fp_big:
112; CHECK-HARD:       @ %bb.0: @ %entry
113; CHECK-HARD-NEXT:    push {r11, lr}
114; CHECK-HARD-NEXT:    sub sp, sp, #8
115; CHECK-HARD-NEXT:    mov r0, sp
116; CHECK-HARD-NEXT:    vstr s1, [r0, #4]
117; CHECK-HARD-NEXT:    vstr s0, [r0]
118; CHECK-HARD-NEXT:    vmov r2, s0
119; CHECK-HARD-NEXT:    vmov r3, s1
120; CHECK-HARD-NEXT:    mov r0, r3
121; CHECK-HARD-NEXT:    mov r1, r2
122; CHECK-HARD-NEXT:    bl variadic
123; CHECK-HARD-NEXT:    add sp, sp, #8
124; CHECK-HARD-NEXT:    pop {r11, pc}
125entry:
126  %call = tail call i1 (float, ...) @variadic(float %y, float %x, float %x, float %y, float %x, float %y)
127  ret void
128}
129;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
130; CHECK: {{.*}}
131