Clang Project

clang_source_code/test/CodeGen/fp16-ops.c
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
13typedef unsigned cond_t;
14
15volatile cond_t test;
16volatile int i0;
17volatile __fp16 h0 = 0.0, h1 = 1.0, h2;
18volatile float f0, f1, f2;
19volatile double d0;
20short s0;
21
22void 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