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 int i0;
14 volatile __fp16 h0 = 0.0, h1 = 1.0, h2;
15 volatile float f0, f1, f2;
16 volatile double d0;
17
foo(void)18 void foo(void) {
19 // CHECK-LABEL: define void @foo()
20
21 // Check unary ops
22
23 // NOHALF: [[F16TOF32:call float @llvm.convert.from.fp16.f32]]
24 // HALF: [[F16TOF32:fpext half]]
25 // CHECK: fptoui float
26 // NATIVE-HALF: fptoui half
27 test = (h0);
28 // CHECK: uitofp i32
29 // NOHALF: [[F32TOF16:call i16 @llvm.convert.to.fp16.f32]]
30 // HALF: [[F32TOF16:fptrunc float]]
31 // NATIVE-HALF: uitofp i32 {{.*}} to half
32 h0 = (test);
33 // CHECK: [[F16TOF32]]
34 // CHECK: fcmp une float
35 // NATIVE-HALF: fcmp une half
36 test = (!h1);
37 // CHECK: [[F16TOF32]]
38 // CHECK: fsub float
39 // NOHALF: [[F32TOF16]]
40 // HALF: [[F32TOF16]]
41 // NATIVE-HALF: fsub half
42 h1 = -h1;
43 // CHECK: [[F16TOF32]]
44 // CHECK: [[F32TOF16]]
45 // NATIVE-HALF: load volatile half
46 // NATIVE-HALF-NEXT: store volatile half
47 h1 = +h1;
48 // CHECK: [[F16TOF32]]
49 // CHECK: fadd float
50 // CHECK: [[F32TOF16]]
51 // NATIVE-HALF: fadd half
52 h1++;
53 // CHECK: [[F16TOF32]]
54 // CHECK: fadd float
55 // CHECK: [[F32TOF16]]
56 // NATIVE-HALF: fadd half
57 ++h1;
58 // CHECK: [[F16TOF32]]
59 // CHECK: fadd float
60 // CHECK: [[F32TOF16]]
61 // NATIVE-HALF: fadd half
62 --h1;
63 // CHECK: [[F16TOF32]]
64 // CHECK: fadd float
65 // CHECK: [[F32TOF16]]
66 // NATIVE-HALF: fadd half
67 h1--;
68
69 // Check binary ops with various operands
70 // CHECK: [[F16TOF32]]
71 // CHECK: [[F16TOF32]]
72 // CHECK: fmul float
73 // CHECK: [[F32TOF16]]
74 // NATIVE-HALF: fmul half
75 h1 = h0 * h2;
76 // CHECK: [[F16TOF32]]
77 // NOHALF: [[F32TOF16]]
78 // NOHALF: [[F16TOF32]]
79 // CHECK: fmul float
80 // CHECK: [[F32TOF16]]
81 // NATIVE-HALF: fmul half
82 h1 = h0 * (__fp16) -2.0f;
83 // CHECK: [[F16TOF32]]
84 // CHECK: fmul float
85 // CHECK: [[F32TOF16]]
86 // NATIVE-HALF: fpext half
87 // NATIVE-HALF: fmul float
88 h1 = h0 * f2;
89 // CHECK: [[F16TOF32]]
90 // CHECK: fmul float
91 // CHECK: [[F32TOF16]]
92 // NATIVE-HALF: fpext half
93 // NATIVE-HALF: fmul float
94 h1 = f0 * h2;
95 // CHECK: [[F16TOF32]]
96 // CHECK: fmul float
97 // CHECK: [[F32TOF16]]
98 // NATIVE-HALF: fmul half
99 h1 = h0 * i0;
100
101 // CHECK: [[F16TOF32]]
102 // CHECK: [[F16TOF32]]
103 // CHECK: fdiv float
104 // CHECK: [[F32TOF16]]
105 // NATIVE-HALF: fdiv half
106 h1 = (h0 / h2);
107 // CHECK: [[F16TOF32]]
108 // NOHALF: [[F16TOF32]]
109 // CHECK: fdiv float
110 // CHECK: [[F32TOF16]]
111 // NATIVE-HALF: fdiv half
112 h1 = (h0 / (__fp16) -2.0f);
113 // CHECK: [[F16TOF32]]
114 // CHECK: fdiv float
115 // CHECK: [[F32TOF16]]
116 // NATIVE-HALF: fpext half
117 // NATIVE-HALF: fdiv float
118 h1 = (h0 / f2);
119 // CHECK: [[F16TOF32]]
120 // CHECK: fdiv float
121 // CHECK: [[F32TOF16]]
122 // NATIVE-HALF: fpext half
123 // NATIVE-HALF: fdiv float
124 h1 = (f0 / h2);
125 // CHECK: [[F16TOF32]]
126 // CHECK: fdiv float
127 // CHECK: [[F32TOF16]]
128 // NATIVE-HALF: fdiv half
129 h1 = (h0 / i0);
130
131 // CHECK: [[F16TOF32]]
132 // CHECK: [[F16TOF32]]
133 // CHECK: fadd float
134 // CHECK: [[F32TOF16]]
135 // NATIVE-HALF: fadd half
136 h1 = (h2 + h0);
137 // CHECK: [[F16TOF32]]
138 // NOHALF: [[F16TOF32]]
139 // CHECK: fadd float
140 // CHECK: [[F32TOF16]]
141 // NATIVE-HALF: fadd half
142 h1 = ((__fp16)-2.0 + h0);
143 // CHECK: [[F16TOF32]]
144 // CHECK: fadd float
145 // CHECK: [[F32TOF16]]
146 // NATIVE-HALF: fpext half
147 // NATIVE-HALF: fadd float
148 h1 = (h2 + f0);
149 // CHECK: [[F16TOF32]]
150 // CHECK: fadd float
151 // CHECK: [[F32TOF16]]
152 // NATIVE-HALF: fpext half
153 // NATIVE-HALF: fadd float
154 h1 = (f2 + h0);
155 // CHECK: [[F16TOF32]]
156 // CHECK: fadd float
157 // CHECK: [[F32TOF16]]
158 // NATIVE-HALF: fadd half
159 h1 = (h0 + i0);
160
161 // CHECK: [[F16TOF32]]
162 // CHECK: [[F16TOF32]]
163 // CHECK: fsub float
164 // CHECK: [[F32TOF16]]
165 // NATIVE-HALF: fsub half
166 h1 = (h2 - h0);
167 // CHECK: [[F16TOF32]]
168 // NOHALF: [[F16TOF32]]
169 // CHECK: fsub float
170 // CHECK: [[F32TOF16]]
171 // NATIVE-HALF: fsub half
172 h1 = ((__fp16)-2.0f - h0);
173 // CHECK: [[F16TOF32]]
174 // CHECK: fsub float
175 // CHECK: [[F32TOF16]]
176 // NATIVE-HALF: fpext half
177 // NATIVE-HALF: fsub float
178 h1 = (h2 - f0);
179 // CHECK: [[F16TOF32]]
180 // CHECK: fsub float
181 // CHECK: [[F32TOF16]]
182 // NATIVE-HALF: fpext half
183 // NATIVE-HALF: fsub float
184 h1 = (f2 - h0);
185 // CHECK: [[F16TOF32]]
186 // CHECK: fsub float
187 // CHECK: [[F32TOF16]]
188 // NATIVE-HALF: fsub half
189 h1 = (h0 - i0);
190
191 // CHECK: [[F16TOF32]]
192 // CHECK: [[F16TOF32]]
193 // CHECK: fcmp olt float
194 // NATIVE-HALF: fcmp olt half
195 test = (h2 < h0);
196 // CHECK: [[F16TOF32]]
197 // NOHALF: [[F16TOF32]]
198 // CHECK: fcmp olt float
199 // NATIVE-HALF: fcmp olt half
200 test = (h2 < (__fp16)42.0);
201 // CHECK: [[F16TOF32]]
202 // CHECK: fcmp olt float
203 // NATIVE-HALF: fpext half
204 // NATIVE-HALF: fcmp olt float
205 test = (h2 < f0);
206 // CHECK: [[F16TOF32]]
207 // CHECK: fcmp olt float
208 // NATIVE-HALF: fpext half
209 // NATIVE-HALF: fcmp olt float
210 test = (f2 < h0);
211 // CHECK: [[F16TOF32]]
212 // CHECK: fcmp olt float
213 // NATIVE-HALF: fcmp olt half
214 test = (i0 < h0);
215 // CHECK: [[F16TOF32]]
216 // CHECK: fcmp olt float
217 // NATIVE-HALF: fcmp olt half
218 test = (h0 < i0);
219
220 // CHECK: [[F16TOF32]]
221 // CHECK: [[F16TOF32]]
222 // CHECK: fcmp ogt float
223 // NATIVE-HALF: fcmp ogt half
224 test = (h0 > h2);
225 // CHECK: [[F16TOF32]]
226 // NOHALF: [[F16TOF32]]
227 // CHECK: fcmp ogt float
228 // NATIVE-HALF: fcmp ogt half
229 test = ((__fp16)42.0 > h2);
230 // CHECK: [[F16TOF32]]
231 // CHECK: fcmp ogt float
232 // NATIVE-HALF: fpext half
233 // NATIVE-HALF: fcmp ogt float
234 test = (h0 > f2);
235 // CHECK: [[F16TOF32]]
236 // CHECK: fcmp ogt float
237 // NATIVE-HALF: fpext half
238 // NATIVE-HALF: fcmp ogt float
239 test = (f0 > h2);
240 // CHECK: [[F16TOF32]]
241 // CHECK: fcmp ogt float
242 // NATIVE-HALF: fcmp ogt half
243 test = (i0 > h0);
244 // CHECK: [[F16TOF32]]
245 // CHECK: fcmp ogt float
246 // NATIVE-HALF: fcmp ogt half
247 test = (h0 > i0);
248
249 // CHECK: [[F16TOF32]]
250 // CHECK: [[F16TOF32]]
251 // CHECK: fcmp ole float
252 // NATIVE-HALF: fcmp ole half
253 test = (h2 <= h0);
254 // CHECK: [[F16TOF32]]
255 // NOHALF: [[F16TOF32]]
256 // CHECK: fcmp ole float
257 // NATIVE-HALF: fcmp ole half
258 test = (h2 <= (__fp16)42.0);
259 // CHECK: [[F16TOF32]]
260 // CHECK: fcmp ole float
261 // NATIVE-HALF: fpext half
262 // NATIVE-HALF: fcmp ole float
263 test = (h2 <= f0);
264 // CHECK: [[F16TOF32]]
265 // CHECK: fcmp ole float
266 // NATIVE-HALF: fpext half
267 // NATIVE-HALF: fcmp ole float
268 test = (f2 <= h0);
269 // CHECK: [[F16TOF32]]
270 // CHECK: fcmp ole float
271 // NATIVE-HALF: fcmp ole half
272 test = (i0 <= h0);
273 // CHECK: [[F16TOF32]]
274 // CHECK: fcmp ole float
275 // NATIVE-HALF: fcmp ole half
276 test = (h0 <= i0);
277
278
279 // CHECK: [[F16TOF32]]
280 // CHECK: [[F16TOF32]]
281 // CHECK: fcmp oge float
282 // NATIVE-HALF: fcmp oge half
283 test = (h0 >= h2);
284 // CHECK: [[F16TOF32]]
285 // NOHALF: [[F16TOF32]]
286 // CHECK: fcmp oge float
287 // NATIVE-HALF: fcmp oge half
288 test = (h0 >= (__fp16)-2.0);
289 // CHECK: [[F16TOF32]]
290 // CHECK: fcmp oge float
291 // NATIVE-HALF: fpext half
292 // NATIVE-HALF: fcmp oge float
293 test = (h0 >= f2);
294 // CHECK: [[F16TOF32]]
295 // CHECK: fcmp oge float
296 // NATIVE-HALF: fpext half
297 // NATIVE-HALF: fcmp oge float
298 test = (f0 >= h2);
299 // CHECK: [[F16TOF32]]
300 // CHECK: fcmp oge float
301 // NATIVE-HALF: fcmp oge half
302 test = (i0 >= h0);
303 // CHECK: [[F16TOF32]]
304 // CHECK: fcmp oge float
305 // NATIVE-HALF: fcmp oge half
306 test = (h0 >= i0);
307
308 // CHECK: [[F16TOF32]]
309 // CHECK: [[F16TOF32]]
310 // CHECK: fcmp oeq float
311 // NATIVE-HALF: fcmp oeq half
312 test = (h1 == h2);
313 // CHECK: [[F16TOF32]]
314 // NOHALF: [[F16TOF32]]
315 // CHECK: fcmp oeq float
316 // NATIVE-HALF: fcmp oeq half
317 test = (h1 == (__fp16)1.0);
318 // CHECK: [[F16TOF32]]
319 // CHECK: fcmp oeq float
320 // NATIVE-HALF: fpext half
321 // NATIVE-HALF: fcmp oeq float
322 test = (h1 == f1);
323 // CHECK: [[F16TOF32]]
324 // CHECK: fcmp oeq float
325 // NATIVE-HALF: fpext half
326 // NATIVE-HALF: fcmp oeq float
327 test = (f1 == h1);
328 // CHECK: [[F16TOF32]]
329 // CHECK: fcmp oeq float
330 // NATIVE-HALF: fcmp oeq half
331 test = (i0 == h0);
332 // CHECK: [[F16TOF32]]
333 // CHECK: fcmp oeq float
334 // NATIVE-HALF: fcmp oeq half
335 test = (h0 == i0);
336
337 // CHECK: [[F16TOF32]]
338 // CHECK: [[F16TOF32]]
339 // CHECK: fcmp une float
340 // NATIVE-HALF: fcmp une half
341 test = (h1 != h2);
342 // CHECK: [[F16TOF32]]
343 // NOHALF: [[F16TOF32]]
344 // CHECK: fcmp une float
345 // NATIVE-HALF: fcmp une half
346 test = (h1 != (__fp16)1.0);
347 // CHECK: [[F16TOF32]]
348 // CHECK: fcmp une float
349 // NATIVE-HALF: fpext half
350 // NATIVE-HALF: fcmp une float
351 test = (h1 != f1);
352 // CHECK: [[F16TOF32]]
353 // CHECK: fcmp une float
354 // NATIVE-HALF: fpext half
355 // NATIVE-HALF: fcmp une float
356 test = (f1 != h1);
357 // CHECK: [[F16TOF32]]
358 // CHECK: fcmp une float
359 // NATIVE-HALF: fcmp une half
360 test = (i0 != h0);
361 // CHECK: [[F16TOF32]]
362 // CHECK: fcmp une float
363 // NATIVE-HALF: fcmp une half
364 test = (h0 != i0);
365
366 // CHECK: [[F16TOF32]]
367 // CHECK: fcmp une float
368 // CHECK: [[F16TOF32]]
369 // CHECK: [[F16TOF32]]
370 // CHECK: [[F32TOF16]]
371 // NATIVE-HALF: fcmp une half {{.*}}, 0xH0000
372 h1 = (h1 ? h2 : h0);
373 // Check assignments (inc. compound)
374 h0 = h1;
375 // NOHALF: [[F32TOF16]]
376 // HALF: store {{.*}} half 0xHC000
377 // NATIVE-HALF: store {{.*}} half 0xHC000
378 h0 = (__fp16)-2.0f;
379 // CHECK: [[F32TOF16]]
380 // NATIVE-HALF: fptrunc float
381 h0 = f0;
382
383 // CHECK: sitofp i32 {{.*}} to float
384 // CHECK: [[F32TOF16]]
385 // NATIVE-HALF: sitofp i32 {{.*}} to half
386 h0 = i0;
387 // CHECK: [[F16TOF32]]
388 // CHECK: fptosi float {{.*}} to i32
389 // NATIVE-HALF: fptosi half {{.*}} to i32
390 i0 = h0;
391
392 // CHECK: [[F16TOF32]]
393 // CHECK: [[F16TOF32]]
394 // CHECK: fadd float
395 // CHECK: [[F32TOF16]]
396 // NATIVE-HALF: fadd half
397 h0 += h1;
398 // CHECK: [[F16TOF32]]
399 // NOHALF: [[F16TOF32]]
400 // CHECK: fadd float
401 // CHECK: [[F32TOF16]]
402 // NATIVE-HALF: fadd half
403 h0 += (__fp16)1.0f;
404 // CHECK: [[F16TOF32]]
405 // CHECK: fadd float
406 // CHECK: [[F32TOF16]]
407 // NATIVE-HALF: fpext half
408 // NATIVE-HALF: fadd float
409 // NATIVE-HALF: fptrunc float
410 h0 += f2;
411 // CHECK: [[F16TOF32]]
412 // CHECK: sitofp i32 {{.*}} to float
413 // CHECK: fadd float
414 // CHECK: fptosi float {{.*}} to i32
415 // NATIVE-HALF: sitofp i32 {{.*}} to half
416 // NATIVE-HALF: fadd half
417 // NATIVE-HALF: fptosi half {{.*}} to i32
418 i0 += h0;
419 // CHECK: sitofp i32 {{.*}} to float
420 // CHECK: [[F16TOF32]]
421 // CHECK: fadd float
422 // CHECK: [[F32TOF16]]
423 // NATIVE-HALF: sitofp i32 {{.*}} to half
424 // NATIVE-HALF: fadd half
425 h0 += i0;
426
427 // CHECK: [[F16TOF32]]
428 // CHECK: [[F16TOF32]]
429 // CHECK: fsub float
430 // CHECK: [[F32TOF16]]
431 // NATIVE-HALF: fsub half
432 h0 -= h1;
433 // CHECK: [[F16TOF32]]
434 // NOHALF: [[F16TOF32]]
435 // CHECK: fsub float
436 // CHECK: [[F32TOF16]]
437 // NATIVE-HALF: fsub half
438 h0 -= (__fp16)1.0;
439 // CHECK: [[F16TOF32]]
440 // CHECK: fsub float
441 // CHECK: [[F32TOF16]]
442 // NATIVE-HALF: fpext half
443 // NATIVE-HALF: fsub float
444 // NATIVE-HALF: fptrunc float
445 h0 -= f2;
446 // CHECK: [[F16TOF32]]
447 // CHECK: sitofp i32 {{.*}} to float
448 // CHECK: fsub float
449 // CHECK: fptosi float {{.*}} to i32
450 // NATIVE-HALF: sitofp i32 {{.*}} to half
451 // NATIVE-HALF: fsub half
452 // NATIVE-HALF: fptosi half {{.*}} to i32
453 i0 -= h0;
454 // CHECK: sitofp i32 {{.*}} to float
455 // CHECK: [[F16TOF32]]
456 // CHECK: fsub float
457 // CHECK: [[F32TOF16]]
458 // NATIVE-HALF: sitofp i32 {{.*}} to half
459 // NATIVE-HALF: fsub half
460 h0 -= i0;
461
462 // CHECK: [[F16TOF32]]
463 // CHECK: [[F16TOF32]]
464 // CHECK: fmul float
465 // CHECK: [[F32TOF16]]
466 // NATIVE-HALF: fmul half
467 h0 *= h1;
468 // CHECK: [[F16TOF32]]
469 // NOHALF: [[F16TOF32]]
470 // CHECK: fmul float
471 // CHECK: [[F32TOF16]]
472 // NATIVE-HALF: fmul half
473 h0 *= (__fp16)1.0;
474 // CHECK: [[F16TOF32]]
475 // CHECK: fmul float
476 // CHECK: [[F32TOF16]]
477 // NATIVE-HALF: fpext half
478 // NATIVE-HALF: fmul float
479 // NATIVE-HALF: fptrunc float
480 h0 *= f2;
481 // CHECK: [[F16TOF32]]
482 // CHECK: sitofp i32 {{.*}} to float
483 // CHECK: fmul float
484 // CHECK: fptosi float {{.*}} to i32
485 // NATIVE-HALF: sitofp i32 {{.*}} to half
486 // NATIVE-HALF: fmul half
487 // NATIVE-HALF: fptosi half {{.*}} to i32
488 i0 *= h0;
489 // CHECK: sitofp i32 {{.*}} to float
490 // CHECK: [[F16TOF32]]
491 // CHECK: fmul float
492 // CHECK: [[F32TOF16]]
493 // NATIVE-HALF: sitofp i32 {{.*}} to half
494 // NATIVE-HALF: fmul half
495 h0 *= i0;
496
497 // CHECK: [[F16TOF32]]
498 // CHECK: [[F16TOF32]]
499 // CHECK: fdiv float
500 // CHECK: [[F32TOF16]]
501 // NATIVE-HALF: fdiv half
502 h0 /= h1;
503 // CHECK: [[F16TOF32]]
504 // NOHALF: [[F16TOF32]]
505 // CHECK: fdiv float
506 // CHECK: [[F32TOF16]]
507 // NATIVE-HALF: fdiv half
508 h0 /= (__fp16)1.0;
509 // CHECK: [[F16TOF32]]
510 // CHECK: fdiv float
511 // CHECK: [[F32TOF16]]
512 // NATIVE-HALF: fpext half
513 // NATIVE-HALF: fdiv float
514 // NATIVE-HALF: fptrunc float
515 h0 /= f2;
516 // CHECK: [[F16TOF32]]
517 // CHECK: sitofp i32 {{.*}} to float
518 // CHECK: fdiv float
519 // CHECK: fptosi float {{.*}} to i32
520 // NATIVE-HALF: sitofp i32 {{.*}} to half
521 // NATIVE-HALF: fdiv half
522 // NATIVE-HALF: fptosi half {{.*}} to i32
523 i0 /= h0;
524 // CHECK: sitofp i32 {{.*}} to float
525 // CHECK: [[F16TOF32]]
526 // CHECK: fdiv float
527 // CHECK: [[F32TOF16]]
528 // NATIVE-HALF: sitofp i32 {{.*}} to half
529 // NATIVE-HALF: fdiv half
530 h0 /= i0;
531
532 // Check conversions to/from double
533 // NOHALF: call i16 @llvm.convert.to.fp16.f64(
534 // HALF: fptrunc double {{.*}} to half
535 // NATIVE-HALF: fptrunc double {{.*}} to half
536 h0 = d0;
537
538 // CHECK: [[MID:%.*]] = fptrunc double {{%.*}} to float
539 // NOHALF: call i16 @llvm.convert.to.fp16.f32(float [[MID]])
540 // HALF: fptrunc float [[MID]] to half
541 // NATIVE-HALF: [[MID:%.*]] = fptrunc double {{%.*}} to float
542 // NATIVE-HALF: fptrunc float {{.*}} to half
543 h0 = (float)d0;
544
545 // NOHALF: call double @llvm.convert.from.fp16.f64(
546 // HALF: fpext half {{.*}} to double
547 // NATIVE-HALF: fpext half {{.*}} to double
548 d0 = h0;
549
550 // NOHALF: [[MID:%.*]] = call float @llvm.convert.from.fp16.f32(
551 // HALF: [[MID:%.*]] = fpext half {{.*}} to float
552 // CHECK: fpext float [[MID]] to double
553 // NATIVE-HALF: [[MID:%.*]] = fpext half {{.*}} to float
554 // NATIVE-HALF: fpext float [[MID]] to double
555 d0 = (float)h0;
556 }
557