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
10typedef unsigned cond_t;
11
12volatile cond_t test;
13volatile __fp16 h0 = 0.0, h1 = 1.0, h2;
14volatile float f0, f1, f2;
15volatile double d0;
16
17void foo(void) {
18  // CHECK-LABEL: define void @foo()
19
20  // Check unary ops
21
22  // NOHALF: [[F16TOF32:call float @llvm.convert.from.fp16.f32]]
23  // HALF: [[F16TOF32:fpext half]]
24  // CHECK: fptoui float
25  // NATIVE-HALF: fptoui half
26  test = (h0);
27  // CHECK: uitofp i32
28  // NOHALF: [[F32TOF16:call i16 @llvm.convert.to.fp16.f32]]
29  // HALF: [[F32TOF16:fptrunc float]]
30  // NATIVE-HALF: uitofp i32 {{.*}} to half
31  h0 = (test);
32  // CHECK: [[F16TOF32]]
33  // CHECK: fcmp une float
34  // NATIVE-HALF: fcmp une half
35  test = (!h1);
36  // CHECK: [[F16TOF32]]
37  // CHECK: fsub float
38  // NOHALF: [[F32TOF16]]
39  // HALF: [[F32TOF16]]
40  // NATIVE-HALF: fsub half
41  h1 = -h1;
42  // CHECK: [[F16TOF32]]
43  // CHECK: [[F32TOF16]]
44  // NATIVE-HALF: load volatile half
45  // NATIVE-HALF-NEXT: store volatile half
46  h1 = +h1;
47  // CHECK: [[F16TOF32]]
48  // CHECK: fadd float
49  // CHECK: [[F32TOF16]]
50  // NATIVE-HALF: fadd half
51  h1++;
52  // CHECK: [[F16TOF32]]
53  // CHECK: fadd float
54  // CHECK: [[F32TOF16]]
55  // NATIVE-HALF: fadd half
56  ++h1;
57  // CHECK: [[F16TOF32]]
58  // CHECK: fadd float
59  // CHECK: [[F32TOF16]]
60  // NATIVE-HALF: fadd half
61  --h1;
62  // CHECK: [[F16TOF32]]
63  // CHECK: fadd float
64  // CHECK: [[F32TOF16]]
65  // NATIVE-HALF: fadd half
66  h1--;
67
68  // Check binary ops with various operands
69  // CHECK: [[F16TOF32]]
70  // CHECK: [[F16TOF32]]
71  // CHECK: fmul float
72  // CHECK: [[F32TOF16]]
73  // NATIVE-HALF: fmul half
74  h1 = h0 * h2;
75  // CHECK: [[F16TOF32]]
76  // NOHALF: [[F32TOF16]]
77  // NOHALF: [[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
95  // CHECK: [[F16TOF32]]
96  // CHECK: [[F16TOF32]]
97  // CHECK: fdiv float
98  // CHECK: [[F32TOF16]]
99  // NATIVE-HALF: fdiv half
100  h1 = (h0 / h2);
101  // CHECK: [[F16TOF32]]
102  // NOHALF: [[F16TOF32]]
103  // CHECK: fdiv float
104  // CHECK: [[F32TOF16]]
105  // NATIVE-HALF: fdiv half
106  h1 = (h0 / (__fp16) -2.0f);
107  // CHECK: [[F16TOF32]]
108  // CHECK: fdiv float
109  // CHECK: [[F32TOF16]]
110  // NATIVE-HALF: fpext half
111  // NATIVE-HALF: fdiv float
112  h1 = (h0 / f2);
113  // CHECK: [[F16TOF32]]
114  // CHECK: fdiv float
115  // CHECK: [[F32TOF16]]
116  // NATIVE-HALF: fpext half
117  // NATIVE-HALF: fdiv float
118  h1 = (f0 / h2);
119
120  // CHECK: [[F16TOF32]]
121  // CHECK: [[F16TOF32]]
122  // CHECK: fadd float
123  // CHECK: [[F32TOF16]]
124  // NATIVE-HALF: fadd half
125  h1 = (h2 + h0);
126  // CHECK: [[F16TOF32]]
127  // NOHALF: [[F16TOF32]]
128  // CHECK: fadd float
129  // CHECK: [[F32TOF16]]
130  // NATIVE-HALF: fadd half
131  h1 = ((__fp16)-2.0 + h0);
132  // CHECK: [[F16TOF32]]
133  // CHECK: fadd float
134  // CHECK: [[F32TOF16]]
135  // NATIVE-HALF: fpext half
136  // NATIVE-HALF: fadd float
137  h1 = (h2 + f0);
138  // CHECK: [[F16TOF32]]
139  // CHECK: fadd float
140  // CHECK: [[F32TOF16]]
141  // NATIVE-HALF: fpext half
142  // NATIVE-HALF: fadd float
143  h1 = (f2 + h0);
144
145  // CHECK: [[F16TOF32]]
146  // CHECK: [[F16TOF32]]
147  // CHECK: fsub float
148  // CHECK: [[F32TOF16]]
149  // NATIVE-HALF: fsub half
150  h1 = (h2 - h0);
151  // CHECK: [[F16TOF32]]
152  // NOHALF: [[F16TOF32]]
153  // CHECK: fsub float
154  // CHECK: [[F32TOF16]]
155  // NATIVE-HALF: fsub half
156  h1 = ((__fp16)-2.0f - h0);
157  // CHECK: [[F16TOF32]]
158  // CHECK: fsub float
159  // CHECK: [[F32TOF16]]
160  // NATIVE-HALF: fpext half
161  // NATIVE-HALF: fsub float
162  h1 = (h2 - f0);
163  // CHECK: [[F16TOF32]]
164  // CHECK: fsub float
165  // CHECK: [[F32TOF16]]
166  // NATIVE-HALF: fpext half
167  // NATIVE-HALF: fsub float
168  h1 = (f2 - h0);
169
170  // CHECK: [[F16TOF32]]
171  // CHECK: [[F16TOF32]]
172  // CHECK: fcmp olt float
173  // NATIVE-HALF: fcmp olt half
174  test = (h2 < h0);
175  // CHECK: [[F16TOF32]]
176  // NOHALF: [[F16TOF32]]
177  // CHECK: fcmp olt float
178  // NATIVE-HALF: fcmp olt half
179  test = (h2 < (__fp16)42.0);
180  // CHECK: [[F16TOF32]]
181  // CHECK: fcmp olt float
182  // NATIVE-HALF: fpext half
183  // NATIVE-HALF: fcmp olt float
184  test = (h2 < f0);
185  // CHECK: [[F16TOF32]]
186  // CHECK: fcmp olt float
187  // NATIVE-HALF: fpext half
188  // NATIVE-HALF: fcmp olt float
189  test = (f2 < h0);
190
191  // CHECK: [[F16TOF32]]
192  // CHECK: [[F16TOF32]]
193  // CHECK: fcmp ogt float
194  // NATIVE-HALF: fcmp ogt half
195  test = (h0 > h2);
196  // CHECK: [[F16TOF32]]
197  // NOHALF: [[F16TOF32]]
198  // CHECK: fcmp ogt float
199  // NATIVE-HALF: fcmp ogt half
200  test = ((__fp16)42.0 > h2);
201  // CHECK: [[F16TOF32]]
202  // CHECK: fcmp ogt float
203  // NATIVE-HALF: fpext half
204  // NATIVE-HALF: fcmp ogt float
205  test = (h0 > f2);
206  // CHECK: [[F16TOF32]]
207  // CHECK: fcmp ogt float
208  // NATIVE-HALF: fpext half
209  // NATIVE-HALF: fcmp ogt float
210  test = (f0 > h2);
211
212  // CHECK: [[F16TOF32]]
213  // CHECK: [[F16TOF32]]
214  // CHECK: fcmp ole float
215  // NATIVE-HALF: fcmp ole half
216  test = (h2 <= h0);
217  // CHECK: [[F16TOF32]]
218  // NOHALF: [[F16TOF32]]
219  // CHECK: fcmp ole float
220  // NATIVE-HALF: fcmp ole half
221  test = (h2 <= (__fp16)42.0);
222  // CHECK: [[F16TOF32]]
223  // CHECK: fcmp ole float
224  // NATIVE-HALF: fpext half
225  // NATIVE-HALF: fcmp ole float
226  test = (h2 <= f0);
227  // CHECK: [[F16TOF32]]
228  // CHECK: fcmp ole float
229  // NATIVE-HALF: fpext half
230  // NATIVE-HALF: fcmp ole float
231  test = (f2 <= h0);
232
233  // CHECK: [[F16TOF32]]
234  // CHECK: [[F16TOF32]]
235  // CHECK: fcmp oge float
236  // NATIVE-HALF: fcmp oge half
237  test = (h0 >= h2);
238  // CHECK: [[F16TOF32]]
239  // NOHALF: [[F16TOF32]]
240  // CHECK: fcmp oge float
241  // NATIVE-HALF: fcmp oge half
242  test = (h0 >= (__fp16)-2.0);
243  // CHECK: [[F16TOF32]]
244  // CHECK: fcmp oge float
245  // NATIVE-HALF: fpext half
246  // NATIVE-HALF: fcmp oge float
247  test = (h0 >= f2);
248  // CHECK: [[F16TOF32]]
249  // CHECK: fcmp oge float
250  // NATIVE-HALF: fpext half
251  // NATIVE-HALF: fcmp oge float
252  test = (f0 >= h2);
253
254  // CHECK: [[F16TOF32]]
255  // CHECK: [[F16TOF32]]
256  // CHECK: fcmp oeq float
257  // NATIVE-HALF: fcmp oeq half
258  test = (h1 == h2);
259  // CHECK: [[F16TOF32]]
260  // NOHALF: [[F16TOF32]]
261  // CHECK: fcmp oeq float
262  // NATIVE-HALF: fcmp oeq half
263  test = (h1 == (__fp16)1.0);
264  // CHECK: [[F16TOF32]]
265  // CHECK: fcmp oeq float
266  // NATIVE-HALF: fpext half
267  // NATIVE-HALF: fcmp oeq float
268  test = (h1 == f1);
269  // CHECK: [[F16TOF32]]
270  // CHECK: fcmp oeq float
271  // NATIVE-HALF: fpext half
272  // NATIVE-HALF: fcmp oeq float
273  test = (f1 == h1);
274
275  // CHECK: [[F16TOF32]]
276  // CHECK: [[F16TOF32]]
277  // CHECK: fcmp une float
278  // NATIVE-HALF: fcmp une half
279  test = (h1 != h2);
280  // CHECK: [[F16TOF32]]
281  // NOHALF: [[F16TOF32]]
282  // CHECK: fcmp une float
283  // NATIVE-HALF: fcmp une half
284  test = (h1 != (__fp16)1.0);
285  // CHECK: [[F16TOF32]]
286  // CHECK: fcmp une float
287  // NATIVE-HALF: fpext half
288  // NATIVE-HALF: fcmp une float
289  test = (h1 != f1);
290  // CHECK: [[F16TOF32]]
291  // CHECK: fcmp une float
292  // NATIVE-HALF: fpext half
293  // NATIVE-HALF: fcmp une float
294  test = (f1 != h1);
295
296  // CHECK: [[F16TOF32]]
297  // CHECK: fcmp une float
298  // CHECK: [[F16TOF32]]
299  // CHECK: [[F16TOF32]]
300  // CHECK: [[F32TOF16]]
301  // NATIVE-HALF: fcmp une half {{.*}}, 0xH0000
302  h1 = (h1 ? h2 : h0);
303  // Check assignments (inc. compound)
304  h0 = h1;
305  // NOHALF: [[F32TOF16]]
306  // HALF: store {{.*}} half 0xHC000
307  // NATIVE-HALF: store {{.*}} half 0xHC000
308  h0 = (__fp16)-2.0f;
309  // CHECK: [[F32TOF16]]
310  // NATIVE-HALF: fptrunc float
311  h0 = f0;
312
313  // CHECK: [[F16TOF32]]
314  // CHECK: [[F16TOF32]]
315  // CHECK: fadd float
316  // CHECK: [[F32TOF16]]
317  // NATIVE-HALF: fadd half
318  h0 += h1;
319  // CHECK: [[F16TOF32]]
320  // NOHALF: [[F16TOF32]]
321  // CHECK: fadd float
322  // CHECK: [[F32TOF16]]
323  // NATIVE-HALF: fadd half
324  h0 += (__fp16)1.0f;
325  // CHECK: [[F16TOF32]]
326  // CHECK: fadd float
327  // CHECK: [[F32TOF16]]
328  // NATIVE-HALF: fpext half
329  // NATIVE-HALF: fadd float
330  // NATIVE-HALF: fptrunc float
331  h0 += f2;
332
333  // CHECK: [[F16TOF32]]
334  // CHECK: [[F16TOF32]]
335  // CHECK: fsub float
336  // CHECK: [[F32TOF16]]
337  // NATIVE-HALF: fsub half
338  h0 -= h1;
339  // CHECK: [[F16TOF32]]
340  // NOHALF: [[F16TOF32]]
341  // CHECK: fsub float
342  // CHECK: [[F32TOF16]]
343  // NATIVE-HALF: fsub half
344  h0 -= (__fp16)1.0;
345  // CHECK: [[F16TOF32]]
346  // CHECK: fsub float
347  // CHECK: [[F32TOF16]]
348  // NATIVE-HALF: fpext half
349  // NATIVE-HALF: fsub float
350  // NATIVE-HALF: fptrunc float
351  h0 -= f2;
352
353  // CHECK: [[F16TOF32]]
354  // CHECK: [[F16TOF32]]
355  // CHECK: fmul float
356  // CHECK: [[F32TOF16]]
357  // NATIVE-HALF: fmul half
358  h0 *= h1;
359  // CHECK: [[F16TOF32]]
360  // NOHALF: [[F16TOF32]]
361  // CHECK: fmul float
362  // CHECK: [[F32TOF16]]
363  // NATIVE-HALF: fmul half
364  h0 *= (__fp16)1.0;
365  // CHECK: [[F16TOF32]]
366  // CHECK: fmul float
367  // CHECK: [[F32TOF16]]
368  // NATIVE-HALF: fpext half
369  // NATIVE-HALF: fmul float
370  // NATIVE-HALF: fptrunc float
371  h0 *= f2;
372
373  // CHECK: [[F16TOF32]]
374  // CHECK: [[F16TOF32]]
375  // CHECK: fdiv float
376  // CHECK: [[F32TOF16]]
377  // NATIVE-HALF: fdiv half
378  h0 /= h1;
379  // CHECK: [[F16TOF32]]
380  // NOHALF: [[F16TOF32]]
381  // CHECK: fdiv float
382  // CHECK: [[F32TOF16]]
383  // NATIVE-HALF: fdiv half
384  h0 /= (__fp16)1.0;
385  // CHECK: [[F16TOF32]]
386  // CHECK: fdiv float
387  // CHECK: [[F32TOF16]]
388  // NATIVE-HALF: fpext half
389  // NATIVE-HALF: fdiv float
390  // NATIVE-HALF: fptrunc float
391  h0 /= f2;
392
393  // Check conversions to/from double
394  // NOHALF: call i16 @llvm.convert.to.fp16.f64(
395  // HALF: fptrunc double {{.*}} to half
396  // NATIVE-HALF: fptrunc double {{.*}} to half
397  h0 = d0;
398
399  // CHECK: [[MID:%.*]] = fptrunc double {{%.*}} to float
400  // NOHALF: call i16 @llvm.convert.to.fp16.f32(float [[MID]])
401  // HALF: fptrunc float [[MID]] to half
402  // NATIVE-HALF: [[MID:%.*]] = fptrunc double {{%.*}} to float
403  // NATIVE-HALF: fptrunc float {{.*}} to half
404  h0 = (float)d0;
405
406  // NOHALF: call double @llvm.convert.from.fp16.f64(
407  // HALF: fpext half {{.*}} to double
408  // NATIVE-HALF: fpext half {{.*}} to double
409  d0 = h0;
410
411  // NOHALF: [[MID:%.*]] = call float @llvm.convert.from.fp16.f32(
412  // HALF: [[MID:%.*]] = fpext half {{.*}} to float
413  // CHECK: fpext float [[MID]] to double
414  // NATIVE-HALF: [[MID:%.*]] = fpext half {{.*}} to float
415  // NATIVE-HALF: fpext float [[MID]] to double
416  d0 = (float)h0;
417}
418