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