• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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