1 | // REQUIRES: arm-registered-target |
2 | // RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-linux-gnueabi %s | FileCheck %s |
3 | // RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-linux-gnueabihf %s | FileCheck %s |
4 | // RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-linux-gnueabi -target-feature "+soft-float" -target-feature "+soft-float-abi" %s | FileCheck %s |
5 | // RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-linux-gnueabi -target-feature "+soft-float" %s | FileCheck %s |
6 | // RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-eabi %s | FileCheck %s |
7 | // RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-eabi -meabi gnu %s | FileCheck %s |
8 | // RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-eabi %s | FileCheck %s |
9 | // RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-eabi -target-feature "+soft-float" -target-feature "+soft-float-abi" -meabi gnu %s | FileCheck %s |
10 | // RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-eabi -target-feature "+soft-float" -meabi gnu %s | FileCheck %s |
11 | // RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-eabihf %s | FileCheck %s |
12 | // RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-eabihf -meabi gnu %s | FileCheck %s |
13 | |
14 | // The Runtime ABI for the ARM Architecture IHI0043 section 4.1.2 The |
15 | // floating-point helper functions to always use the base AAPCS (soft-float) |
16 | // calling convention. |
17 | // |
18 | // These helper functions such as __aeabi_fadd are not explicitly called by |
19 | // clang, instead they are generated by the ARMISelLowering when they are |
20 | // needed; clang relies on llvm to use the base AAPCS. |
21 | // |
22 | // In this test we check that clang is not directly calling the __aeabi_ |
23 | // functions. We rely on llvm to test that the base AAPCS is used for any |
24 | // __aeabi_ function from 4.1.2 that is used. |
25 | // |
26 | // When compiled to an object file with -mfloat-abi=soft each function F |
27 | // below should result in a call to __aeabi_F. If clang is changed to call any |
28 | // of these functions directly the test will need to be altered to check that |
29 | // arm_aapcscc is used. |
30 | // |
31 | // Note that it is only the functions in 4.1.2 that must use the base AAPCS, |
32 | // other runtime functions such as the _Complex helper routines are not covered. |
33 | |
34 | float fadd(float a, float b) { return a + b; } |
35 | // CHECK-LABEL: define float @fadd(float %a, float %b) |
36 | // CHECK-NOT: __aeabi_fadd |
37 | // CHECK: %add = fadd float {{.*}}, {{.*}} |
38 | |
39 | float fdiv(float a, float b) { return a / b; } |
40 | // CHECK-LABEL: define float @fdiv(float %a, float %b) |
41 | // CHECK-NOT: __aeabi_fdiv |
42 | // CHECK: %div = fdiv float {{.*}}, {{.*}} |
43 | |
44 | float fmul(float a, float b) { return a * b; } |
45 | // CHECK-LABEL: define float @fmul(float %a, float %b) |
46 | // CHECK-NOT: __aeabi_fmul |
47 | // CHECK: %mul = fmul float {{.*}}, {{.*}} |
48 | |
49 | float fsub(float a, float b) { return a - b; } |
50 | // CHECK-LABEL: define float @fsub(float %a, float %b) |
51 | // CHECK-NOT: __aeabi_fsub |
52 | // CHECK: %sub = fsub float {{.*}}, {{.*}} |
53 | |
54 | int fcmpeq(float a, float b) { return a == b; } |
55 | // CHECK-LABEL: define i32 @fcmpeq(float %a, float %b) |
56 | // CHECK-NOT: __aeabi_fcmpeq |
57 | // CHECK: %cmp = fcmp oeq float {{.*}}, {{.*}} |
58 | |
59 | int fcmplt(float a, float b) { return a < b; } |
60 | // CHECK-LABEL: define i32 @fcmplt(float %a, float %b) |
61 | // CHECK-NOT: __aeabi_fcmplt |
62 | // CHECK: %cmp = fcmp olt float {{.*}}, {{.*}} |
63 | |
64 | int fcmple(float a, float b) { return a <= b; } |
65 | // CHECK-LABEL: define i32 @fcmple(float %a, float %b) |
66 | // CHECK-NOT: __aeabi_fcmple |
67 | // CHECK: %cmp = fcmp ole float {{.*}}, {{.*}} |
68 | |
69 | int fcmpge(float a, float b) { return a >= b; } |
70 | // CHECK-LABEL: define i32 @fcmpge(float %a, float %b) |
71 | // CHECK-NOT: __aeabi_fcmpge |
72 | // CHECK: %cmp = fcmp oge float {{.*}}, {{.*}} |
73 | |
74 | int fcmpgt(float a, float b) { return a > b; } |
75 | // CHECK-LABEL: define i32 @fcmpgt(float %a, float %b) |
76 | // CHECK-NOT: __aeabi_fcmpgt |
77 | // CHECK: %cmp = fcmp ogt float {{.*}}, {{.*}} |
78 | |
79 | int fcmpun(float a, float b) { return __builtin_isunordered(a, b); } |
80 | // CHECK-LABEL: define i32 @fcmpun(float %a, float %b) |
81 | // CHECK-NOT: __aeabi_fcmpun |
82 | // CHECK: %cmp = fcmp uno double %conv, %conv1 |
83 | |
84 | double dadd(double a, double b) { return a + b; } |
85 | // CHECK-LABEL: define double @dadd(double %a, double %b) |
86 | // CHECK-NOT: __aeabi_dadd |
87 | // CHECK: %add = fadd double {{.*}}, {{.*}} |
88 | |
89 | double ddiv(double a, double b) { return a / b; } |
90 | // CHECK-LABEL: define double @ddiv(double %a, double %b) |
91 | // CHECK-NOT: __aeabi_ddiv |
92 | // CHECK: %div = fdiv double {{.*}}, {{.*}} |
93 | |
94 | double dmul(double a, double b) { return a * b; } |
95 | // CHECK-LABEL: define double @dmul(double %a, double %b) |
96 | // CHECK-NOT: __aeabi_dmul |
97 | // CHECK: %mul = fmul double {{.*}}, {{.*}} |
98 | |
99 | double dsub(double a, double b) { return a - b; } |
100 | // CHECK-LABEL: define double @dsub(double %a, double %b) |
101 | // CHECK-NOT: __aeabi_dsub |
102 | // CHECK: %sub = fsub double {{.*}}, {{.*}} |
103 | |
104 | int dcmpeq(double a, double b) { return a == b; } |
105 | // CHECK-LABEL: define i32 @dcmpeq(double %a, double %b) |
106 | // CHECK-NOT: __aeabi_dcmpeq |
107 | // CHECK: %cmp = fcmp oeq double {{.*}}, {{.*}} |
108 | |
109 | int dcmplt(double a, double b) { return a < b; } |
110 | // CHECK-LABEL: define i32 @dcmplt(double %a, double %b) |
111 | // CHECK-NOT: __aeabi_dcmplt |
112 | // CHECK: %cmp = fcmp olt double {{.*}}, {{.*}} |
113 | |
114 | int dcmple(double a, double b) { return a <= b; } |
115 | // CHECK-LABEL: define i32 @dcmple(double %a, double %b) |
116 | // CHECK-NOT: __aeabi_dcmple |
117 | // CHECK: %cmp = fcmp ole double {{.*}}, {{.*}} |
118 | |
119 | int dcmpge(double a, double b) { return a >= b; } |
120 | // CHECK-LABEL: define i32 @dcmpge(double %a, double %b) |
121 | // CHECK-NOT: __aeabi_dcmpge |
122 | // CHECK: %cmp = fcmp oge double {{.*}}, {{.*}} |
123 | |
124 | int dcmpgt(double a, double b) { return a > b; } |
125 | // CHECK-LABEL: define i32 @dcmpgt(double %a, double %b) |
126 | // CHECK-NOT: __aeabi_dcmpgt |
127 | // CHECK: %cmp = fcmp ogt double {{.*}}, {{.*}} |
128 | |
129 | int dcmpun(double a, double b) { return __builtin_isunordered(a, b); } |
130 | // CHECK-LABEL: define i32 @dcmpun(double %a, double %b) |
131 | // CHECK-NOT: __aeabi_dcmpun |
132 | // CHECK: %cmp = fcmp uno double {{.*}}, {{.*}} |
133 | |
134 | int d2iz(double a) { return (int)a; } |
135 | // CHECK-LABEL: define i32 @d2iz(double %a) |
136 | // CHECK-NOT: __aeabi_d2iz |
137 | // CHECK: %conv = fptosi double {{.*}} to i32 |
138 | |
139 | unsigned int d2uiz(double a) { return (unsigned int)a; } |
140 | // CHECK-LABEL: define i32 @d2uiz(double %a) |
141 | // CHECK-NOT: __aeabi_d2uiz |
142 | // CHECK: %conv = fptoui double {{.*}} to i32 |
143 | |
144 | long long d2lz(double a) { return (long long)a; } |
145 | // CHECK-LABEL: define i64 @d2lz(double %a) |
146 | // CHECK-NOT: __aeabi_d2lz |
147 | // CHECK: %conv = fptosi double {{.*}} to i64 |
148 | |
149 | unsigned long long d2ulz(double a) { return (unsigned long long)a; } |
150 | // CHECK-LABEL: define i64 @d2ulz(double %a) |
151 | // CHECK-NOT: __aeabi_d2ulz |
152 | // CHECK: %conv = fptoui double {{.*}} to i64 |
153 | |
154 | int f2iz(float a) { return (int)a; } |
155 | // CHECK-LABEL: define i32 @f2iz(float %a) |
156 | // CHECK-NOT: __aeabi_f2iz |
157 | // CHECK: %conv = fptosi float {{.*}} to i32 |
158 | |
159 | unsigned int f2uiz(float a) { return (unsigned int)a; } |
160 | // CHECK-LABEL: define i32 @f2uiz(float %a) |
161 | // CHECK-NOT: __aeabi_f2uiz |
162 | // CHECK: %conv = fptoui float {{.*}} to i32 |
163 | |
164 | long long f2lz(float a) { return (long long)a; } |
165 | // CHECK-LABEL: define i64 @f2lz(float %a) |
166 | // CHECK-NOT: __aeabi_f2lz |
167 | // CHECK: %conv = fptosi float {{.*}} to i64 |
168 | |
169 | unsigned long long f2ulz(float a) { return (unsigned long long)a; } |
170 | // CHECK-LABEL: define i64 @f2ulz(float %a) |
171 | // CHECK-NOT: __aeabi_f2ulz |
172 | // CHECK: %conv = fptoui float {{.*}} to i64 |
173 | |
174 | float d2f(double a) { return (float)a; } |
175 | // CHECK-LABEL: define float @d2f(double %a) |
176 | // CHECK-NOT: __aeabi_d2f |
177 | // CHECK: %conv = fptrunc double {{.*}} to float |
178 | |
179 | double f2d(float a) { return (double)a; } |
180 | // CHECK-LABEL: define double @f2d(float %a) |
181 | // CHECK-NOT: __aeabi_f2d |
182 | // CHECK: %conv = fpext float {{.*}} to double |
183 | |
184 | double i2d(int a) { return (double)a; } |
185 | // CHECK-LABEL: define double @i2d(i32 %a) |
186 | // CHECK-NOT: __aeabi_i2d |
187 | // CHECK: %conv = sitofp i32 {{.*}} to double |
188 | |
189 | double ui2d(unsigned int a) { return (double)a; } |
190 | // CHECK-LABEL: define double @ui2d(i32 %a) |
191 | // CHECK-NOT: __aeabi_ui2d |
192 | // CHECK: %conv = uitofp i32 {{.*}} to double |
193 | |
194 | double l2d(long long a) { return (double)a; } |
195 | // CHECK-LABEL: define double @l2d(i64 %a) |
196 | // CHECK-NOT: __aeabi_l2d |
197 | // CHECK: %conv = sitofp i64 {{.*}} to double |
198 | |
199 | double ul2d(unsigned long long a) { return (unsigned long long)a; } |
200 | // CHECK-LABEL: define double @ul2d(i64 %a) |
201 | // CHECK-NOT: __aeabi_ul2d |
202 | // CHECK: %conv = uitofp i64 {{.*}} to double |
203 | |
204 | float i2f(int a) { return (int)a; } |
205 | // CHECK-LABEL: define float @i2f(i32 %a) |
206 | // CHECK-NOT: __aeabi_i2f |
207 | // CHECK: %conv = sitofp i32 {{.*}} to float |
208 | |
209 | float ui2f(unsigned int a) { return (unsigned int)a; } |
210 | // CHECK-LABEL: define float @ui2f(i32 %a) |
211 | // CHECK-NOT: __aeabi_ui2f |
212 | // CHECK: %conv = uitofp i32 {{.*}} to float |
213 | |
214 | float l2f(long long a) { return (long long)a; } |
215 | // CHECK-LABEL: define float @l2f(i64 %a) |
216 | // CHECK-NOT: __aeabi_l2f |
217 | // CHECK: %conv = sitofp i64 {{.*}} to float |
218 | |
219 | float ul2f(unsigned long long a) { return (unsigned long long)a; } |
220 | // CHECK-LABEL: define float @ul2f(i64 %a) |
221 | // CHECK-NOT: __aeabi_ul2f |
222 | // CHECK: %conv = uitofp i64 {{.*}} to float |
223 | |
224 | // Functions in section 4.1.2 not used by llvm and don't easily map directly to |
225 | // C source code. |
226 | // cfcmpeq |
227 | // cfcmple |
228 | // cfrcmple |
229 | // cdcmpeq |
230 | // cdcmple |
231 | // cdrcmple |
232 | // frsub |
233 | // drsub |
234 | |