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