1 // REQUIRES: arm-registered-target
2 // RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-linux-gnueabi %s | FileCheck %s --check-prefix=NOHALF --check-prefix=CHECK
3 // RUN: %clang_cc1 -emit-llvm -o - -triple aarch64-none-linux-gnueabi %s | FileCheck %s --check-prefix=NOHALF --check-prefix=CHECK
4 // RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-linux-gnueabi -fallow-half-arguments-and-returns %s | FileCheck %s --check-prefix=HALF --check-prefix=CHECK
5 // RUN: %clang_cc1 -emit-llvm -o - -triple aarch64-none-linux-gnueabi -fallow-half-arguments-and-returns %s | FileCheck %s --check-prefix=HALF --check-prefix=CHECK
6 // RUN: %clang_cc1 -emit-llvm -o - -triple arm-none-linux-gnueabi -fnative-half-type %s \
7 // RUN: | FileCheck %s --check-prefix=NATIVE-HALF
8 // RUN: %clang_cc1 -emit-llvm -o - -triple aarch64-none-linux-gnueabi -fnative-half-type %s \
9 // RUN: | FileCheck %s --check-prefix=NATIVE-HALF
10 typedef unsigned cond_t;
11
12 volatile cond_t test;
13 volatile __fp16 h0 = 0.0, h1 = 1.0, h2;
14 volatile float f0, f1, f2;
15 volatile double d0;
16
foo(void)17 void foo(void) {
18 // CHECK-LABEL: define void @foo()
19
20 // Check unary ops
21
22 // NOHALF: [[F16TOF32:call float @llvm.convert.from.fp16.f32]]
23 // HALF: [[F16TOF32:fpext half]]
24 // CHECK: fptoui float
25 // NATIVE-HALF: fptoui half
26 test = (h0);
27 // CHECK: uitofp i32
28 // NOHALF: [[F32TOF16:call i16 @llvm.convert.to.fp16.f32]]
29 // HALF: [[F32TOF16:fptrunc float]]
30 // NATIVE-HALF: uitofp i32 {{.*}} to half
31 h0 = (test);
32 // CHECK: [[F16TOF32]]
33 // CHECK: fcmp une float
34 // NATIVE-HALF: fcmp une half
35 test = (!h1);
36 // CHECK: [[F16TOF32]]
37 // CHECK: fsub float
38 // NOHALF: [[F32TOF16]]
39 // HALF: [[F32TOF16]]
40 // NATIVE-HALF: fsub half
41 h1 = -h1;
42 // CHECK: [[F16TOF32]]
43 // CHECK: [[F32TOF16]]
44 // NATIVE-HALF: load volatile half
45 // NATIVE-HALF-NEXT: store volatile half
46 h1 = +h1;
47 // CHECK: [[F16TOF32]]
48 // CHECK: fadd float
49 // CHECK: [[F32TOF16]]
50 // NATIVE-HALF: fadd half
51 h1++;
52 // CHECK: [[F16TOF32]]
53 // CHECK: fadd float
54 // CHECK: [[F32TOF16]]
55 // NATIVE-HALF: fadd half
56 ++h1;
57 // CHECK: [[F16TOF32]]
58 // CHECK: fadd float
59 // CHECK: [[F32TOF16]]
60 // NATIVE-HALF: fadd half
61 --h1;
62 // CHECK: [[F16TOF32]]
63 // CHECK: fadd float
64 // CHECK: [[F32TOF16]]
65 // NATIVE-HALF: fadd half
66 h1--;
67
68 // Check binary ops with various operands
69 // CHECK: [[F16TOF32]]
70 // CHECK: [[F16TOF32]]
71 // CHECK: fmul float
72 // CHECK: [[F32TOF16]]
73 // NATIVE-HALF: fmul half
74 h1 = h0 * h2;
75 // CHECK: [[F16TOF32]]
76 // NOHALF: [[F32TOF16]]
77 // NOHALF: [[F16TOF32]]
78 // CHECK: fmul float
79 // CHECK: [[F32TOF16]]
80 // NATIVE-HALF: fmul half
81 h1 = h0 * (__fp16) -2.0f;
82 // CHECK: [[F16TOF32]]
83 // CHECK: fmul float
84 // CHECK: [[F32TOF16]]
85 // NATIVE-HALF: fpext half
86 // NATIVE-HALF: fmul float
87 h1 = h0 * f2;
88 // CHECK: [[F16TOF32]]
89 // CHECK: fmul float
90 // CHECK: [[F32TOF16]]
91 // NATIVE-HALF: fpext half
92 // NATIVE-HALF: fmul float
93 h1 = f0 * h2;
94
95 // CHECK: [[F16TOF32]]
96 // CHECK: [[F16TOF32]]
97 // CHECK: fdiv float
98 // CHECK: [[F32TOF16]]
99 // NATIVE-HALF: fdiv half
100 h1 = (h0 / h2);
101 // CHECK: [[F16TOF32]]
102 // NOHALF: [[F16TOF32]]
103 // CHECK: fdiv float
104 // CHECK: [[F32TOF16]]
105 // NATIVE-HALF: fdiv half
106 h1 = (h0 / (__fp16) -2.0f);
107 // CHECK: [[F16TOF32]]
108 // CHECK: fdiv float
109 // CHECK: [[F32TOF16]]
110 // NATIVE-HALF: fpext half
111 // NATIVE-HALF: fdiv float
112 h1 = (h0 / f2);
113 // CHECK: [[F16TOF32]]
114 // CHECK: fdiv float
115 // CHECK: [[F32TOF16]]
116 // NATIVE-HALF: fpext half
117 // NATIVE-HALF: fdiv float
118 h1 = (f0 / h2);
119
120 // CHECK: [[F16TOF32]]
121 // CHECK: [[F16TOF32]]
122 // CHECK: fadd float
123 // CHECK: [[F32TOF16]]
124 // NATIVE-HALF: fadd half
125 h1 = (h2 + h0);
126 // CHECK: [[F16TOF32]]
127 // NOHALF: [[F16TOF32]]
128 // CHECK: fadd float
129 // CHECK: [[F32TOF16]]
130 // NATIVE-HALF: fadd half
131 h1 = ((__fp16)-2.0 + h0);
132 // CHECK: [[F16TOF32]]
133 // CHECK: fadd float
134 // CHECK: [[F32TOF16]]
135 // NATIVE-HALF: fpext half
136 // NATIVE-HALF: fadd float
137 h1 = (h2 + f0);
138 // CHECK: [[F16TOF32]]
139 // CHECK: fadd float
140 // CHECK: [[F32TOF16]]
141 // NATIVE-HALF: fpext half
142 // NATIVE-HALF: fadd float
143 h1 = (f2 + h0);
144
145 // CHECK: [[F16TOF32]]
146 // CHECK: [[F16TOF32]]
147 // CHECK: fsub float
148 // CHECK: [[F32TOF16]]
149 // NATIVE-HALF: fsub half
150 h1 = (h2 - h0);
151 // CHECK: [[F16TOF32]]
152 // NOHALF: [[F16TOF32]]
153 // CHECK: fsub float
154 // CHECK: [[F32TOF16]]
155 // NATIVE-HALF: fsub half
156 h1 = ((__fp16)-2.0f - h0);
157 // CHECK: [[F16TOF32]]
158 // CHECK: fsub float
159 // CHECK: [[F32TOF16]]
160 // NATIVE-HALF: fpext half
161 // NATIVE-HALF: fsub float
162 h1 = (h2 - f0);
163 // CHECK: [[F16TOF32]]
164 // CHECK: fsub float
165 // CHECK: [[F32TOF16]]
166 // NATIVE-HALF: fpext half
167 // NATIVE-HALF: fsub float
168 h1 = (f2 - h0);
169
170 // CHECK: [[F16TOF32]]
171 // CHECK: [[F16TOF32]]
172 // CHECK: fcmp olt float
173 // NATIVE-HALF: fcmp olt half
174 test = (h2 < h0);
175 // CHECK: [[F16TOF32]]
176 // NOHALF: [[F16TOF32]]
177 // CHECK: fcmp olt float
178 // NATIVE-HALF: fcmp olt half
179 test = (h2 < (__fp16)42.0);
180 // CHECK: [[F16TOF32]]
181 // CHECK: fcmp olt float
182 // NATIVE-HALF: fpext half
183 // NATIVE-HALF: fcmp olt float
184 test = (h2 < f0);
185 // CHECK: [[F16TOF32]]
186 // CHECK: fcmp olt float
187 // NATIVE-HALF: fpext half
188 // NATIVE-HALF: fcmp olt float
189 test = (f2 < h0);
190
191 // CHECK: [[F16TOF32]]
192 // CHECK: [[F16TOF32]]
193 // CHECK: fcmp ogt float
194 // NATIVE-HALF: fcmp ogt half
195 test = (h0 > h2);
196 // CHECK: [[F16TOF32]]
197 // NOHALF: [[F16TOF32]]
198 // CHECK: fcmp ogt float
199 // NATIVE-HALF: fcmp ogt half
200 test = ((__fp16)42.0 > h2);
201 // CHECK: [[F16TOF32]]
202 // CHECK: fcmp ogt float
203 // NATIVE-HALF: fpext half
204 // NATIVE-HALF: fcmp ogt float
205 test = (h0 > f2);
206 // CHECK: [[F16TOF32]]
207 // CHECK: fcmp ogt float
208 // NATIVE-HALF: fpext half
209 // NATIVE-HALF: fcmp ogt float
210 test = (f0 > h2);
211
212 // CHECK: [[F16TOF32]]
213 // CHECK: [[F16TOF32]]
214 // CHECK: fcmp ole float
215 // NATIVE-HALF: fcmp ole half
216 test = (h2 <= h0);
217 // CHECK: [[F16TOF32]]
218 // NOHALF: [[F16TOF32]]
219 // CHECK: fcmp ole float
220 // NATIVE-HALF: fcmp ole half
221 test = (h2 <= (__fp16)42.0);
222 // CHECK: [[F16TOF32]]
223 // CHECK: fcmp ole float
224 // NATIVE-HALF: fpext half
225 // NATIVE-HALF: fcmp ole float
226 test = (h2 <= f0);
227 // CHECK: [[F16TOF32]]
228 // CHECK: fcmp ole float
229 // NATIVE-HALF: fpext half
230 // NATIVE-HALF: fcmp ole float
231 test = (f2 <= h0);
232
233 // CHECK: [[F16TOF32]]
234 // CHECK: [[F16TOF32]]
235 // CHECK: fcmp oge float
236 // NATIVE-HALF: fcmp oge half
237 test = (h0 >= h2);
238 // CHECK: [[F16TOF32]]
239 // NOHALF: [[F16TOF32]]
240 // CHECK: fcmp oge float
241 // NATIVE-HALF: fcmp oge half
242 test = (h0 >= (__fp16)-2.0);
243 // CHECK: [[F16TOF32]]
244 // CHECK: fcmp oge float
245 // NATIVE-HALF: fpext half
246 // NATIVE-HALF: fcmp oge float
247 test = (h0 >= f2);
248 // CHECK: [[F16TOF32]]
249 // CHECK: fcmp oge float
250 // NATIVE-HALF: fpext half
251 // NATIVE-HALF: fcmp oge float
252 test = (f0 >= h2);
253
254 // CHECK: [[F16TOF32]]
255 // CHECK: [[F16TOF32]]
256 // CHECK: fcmp oeq float
257 // NATIVE-HALF: fcmp oeq half
258 test = (h1 == h2);
259 // CHECK: [[F16TOF32]]
260 // NOHALF: [[F16TOF32]]
261 // CHECK: fcmp oeq float
262 // NATIVE-HALF: fcmp oeq half
263 test = (h1 == (__fp16)1.0);
264 // CHECK: [[F16TOF32]]
265 // CHECK: fcmp oeq float
266 // NATIVE-HALF: fpext half
267 // NATIVE-HALF: fcmp oeq float
268 test = (h1 == f1);
269 // CHECK: [[F16TOF32]]
270 // CHECK: fcmp oeq float
271 // NATIVE-HALF: fpext half
272 // NATIVE-HALF: fcmp oeq float
273 test = (f1 == h1);
274
275 // CHECK: [[F16TOF32]]
276 // CHECK: [[F16TOF32]]
277 // CHECK: fcmp une float
278 // NATIVE-HALF: fcmp une half
279 test = (h1 != h2);
280 // CHECK: [[F16TOF32]]
281 // NOHALF: [[F16TOF32]]
282 // CHECK: fcmp une float
283 // NATIVE-HALF: fcmp une half
284 test = (h1 != (__fp16)1.0);
285 // CHECK: [[F16TOF32]]
286 // CHECK: fcmp une float
287 // NATIVE-HALF: fpext half
288 // NATIVE-HALF: fcmp une float
289 test = (h1 != f1);
290 // CHECK: [[F16TOF32]]
291 // CHECK: fcmp une float
292 // NATIVE-HALF: fpext half
293 // NATIVE-HALF: fcmp une float
294 test = (f1 != h1);
295
296 // CHECK: [[F16TOF32]]
297 // CHECK: fcmp une float
298 // CHECK: [[F16TOF32]]
299 // CHECK: [[F16TOF32]]
300 // CHECK: [[F32TOF16]]
301 // NATIVE-HALF: fcmp une half {{.*}}, 0xH0000
302 h1 = (h1 ? h2 : h0);
303 // Check assignments (inc. compound)
304 h0 = h1;
305 // NOHALF: [[F32TOF16]]
306 // HALF: store {{.*}} half 0xHC000
307 // NATIVE-HALF: store {{.*}} half 0xHC000
308 h0 = (__fp16)-2.0f;
309 // CHECK: [[F32TOF16]]
310 // NATIVE-HALF: fptrunc float
311 h0 = f0;
312
313 // CHECK: [[F16TOF32]]
314 // CHECK: [[F16TOF32]]
315 // CHECK: fadd float
316 // CHECK: [[F32TOF16]]
317 // NATIVE-HALF: fadd half
318 h0 += h1;
319 // CHECK: [[F16TOF32]]
320 // NOHALF: [[F16TOF32]]
321 // CHECK: fadd float
322 // CHECK: [[F32TOF16]]
323 // NATIVE-HALF: fadd half
324 h0 += (__fp16)1.0f;
325 // CHECK: [[F16TOF32]]
326 // CHECK: fadd float
327 // CHECK: [[F32TOF16]]
328 // NATIVE-HALF: fpext half
329 // NATIVE-HALF: fadd float
330 // NATIVE-HALF: fptrunc float
331 h0 += f2;
332
333 // CHECK: [[F16TOF32]]
334 // CHECK: [[F16TOF32]]
335 // CHECK: fsub float
336 // CHECK: [[F32TOF16]]
337 // NATIVE-HALF: fsub half
338 h0 -= h1;
339 // CHECK: [[F16TOF32]]
340 // NOHALF: [[F16TOF32]]
341 // CHECK: fsub float
342 // CHECK: [[F32TOF16]]
343 // NATIVE-HALF: fsub half
344 h0 -= (__fp16)1.0;
345 // CHECK: [[F16TOF32]]
346 // CHECK: fsub float
347 // CHECK: [[F32TOF16]]
348 // NATIVE-HALF: fpext half
349 // NATIVE-HALF: fsub float
350 // NATIVE-HALF: fptrunc float
351 h0 -= f2;
352
353 // CHECK: [[F16TOF32]]
354 // CHECK: [[F16TOF32]]
355 // CHECK: fmul float
356 // CHECK: [[F32TOF16]]
357 // NATIVE-HALF: fmul half
358 h0 *= h1;
359 // CHECK: [[F16TOF32]]
360 // NOHALF: [[F16TOF32]]
361 // CHECK: fmul float
362 // CHECK: [[F32TOF16]]
363 // NATIVE-HALF: fmul half
364 h0 *= (__fp16)1.0;
365 // CHECK: [[F16TOF32]]
366 // CHECK: fmul float
367 // CHECK: [[F32TOF16]]
368 // NATIVE-HALF: fpext half
369 // NATIVE-HALF: fmul float
370 // NATIVE-HALF: fptrunc float
371 h0 *= f2;
372
373 // CHECK: [[F16TOF32]]
374 // CHECK: [[F16TOF32]]
375 // CHECK: fdiv float
376 // CHECK: [[F32TOF16]]
377 // NATIVE-HALF: fdiv half
378 h0 /= h1;
379 // CHECK: [[F16TOF32]]
380 // NOHALF: [[F16TOF32]]
381 // CHECK: fdiv float
382 // CHECK: [[F32TOF16]]
383 // NATIVE-HALF: fdiv half
384 h0 /= (__fp16)1.0;
385 // CHECK: [[F16TOF32]]
386 // CHECK: fdiv float
387 // CHECK: [[F32TOF16]]
388 // NATIVE-HALF: fpext half
389 // NATIVE-HALF: fdiv float
390 // NATIVE-HALF: fptrunc float
391 h0 /= f2;
392
393 // Check conversions to/from double
394 // NOHALF: call i16 @llvm.convert.to.fp16.f64(
395 // HALF: fptrunc double {{.*}} to half
396 // NATIVE-HALF: fptrunc double {{.*}} to half
397 h0 = d0;
398
399 // CHECK: [[MID:%.*]] = fptrunc double {{%.*}} to float
400 // NOHALF: call i16 @llvm.convert.to.fp16.f32(float [[MID]])
401 // HALF: fptrunc float [[MID]] to half
402 // NATIVE-HALF: [[MID:%.*]] = fptrunc double {{%.*}} to float
403 // NATIVE-HALF: fptrunc float {{.*}} to half
404 h0 = (float)d0;
405
406 // NOHALF: call double @llvm.convert.from.fp16.f64(
407 // HALF: fpext half {{.*}} to double
408 // NATIVE-HALF: fpext half {{.*}} to double
409 d0 = h0;
410
411 // NOHALF: [[MID:%.*]] = call float @llvm.convert.from.fp16.f32(
412 // HALF: [[MID:%.*]] = fpext half {{.*}} to float
413 // CHECK: fpext float [[MID]] to double
414 // NATIVE-HALF: [[MID:%.*]] = fpext half {{.*}} to float
415 // NATIVE-HALF: fpext float [[MID]] to double
416 d0 = (float)h0;
417 }
418