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