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 __fp16 h0 = 0.0, h1 = 1.0, h2;
14 volatile float f0, f1, f2;
15 volatile double d0;
16 
foo(void)17 void 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