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