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