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
12typedef unsigned cond_t;
13
14volatile cond_t test;
15volatile int i0;
16volatile __fp16 h0 = 0.0, h1 = 1.0, h2;
17volatile float f0, f1, f2;
18volatile double d0;
19
20void 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