1 // RUN: %clang_cc1 -O0 -triple spir -emit-llvm %s -o - | FileCheck %s
2 // RUN: %clang_cc1 -O0 -triple spir64 -emit-llvm %s -o - | FileCheck %s
3 // RUN: %clang_cc1 -O0 -triple spir -fexperimental-new-pass-manager -emit-llvm %s -o - | FileCheck %s
4 // RUN: %clang_cc1 -O0 -triple spir64 -fexperimental-new-pass-manager -emit-llvm %s -o - | FileCheck %s
5 
6 // This file tests that using the _Float16 type with the spir target will not
7 // use the llvm intrinsics but instead will use the half arithmetic
8 // instructions directly.
9 
10 // Previously attempting to use a constant _Float16 with a comparison
11 // instruction when the target is spir or spir64 lead to an assert being hit.
12 bool fcmp_const() {
13   _Float16 a = 0.0f16;
14   const _Float16 b = 1.0f16;
15 
16   // CHECK-NOT: llvm.convert.to.fp16
17   // CHECK-NOT: llvm.convert.from.fp16
18 
19   // CHECK: [[REG1:%.*]] = load half, half* %a, align 2
20   // CHECK-NEXT: fcmp olt half [[REG1]], 0xH3C00
21 
22   // CHECK: [[REG2:%.*]] = load half, half* %a, align 2
23   // CHECK-NEXT: fcmp olt half [[REG2]], 0xH4000
24 
25   // CHECK: [[REG3:%.*]] = load half, half* %a, align 2
26   // CHECK-NEXT: fcmp ogt half [[REG3]], 0xH3C00
27 
28   // CHECK: [[REG4:%.*]] = load half, half* %a, align 2
29   // CHECK-NEXT: fcmp ogt half [[REG4]], 0xH4200
30 
31   // CHECK: [[REG5:%.*]] = load half, half* %a, align 2
32   // CHECK-NEXT: fcmp oeq half [[REG5]], 0xH3C00
33 
34   // CHECK: [[REG7:%.*]] = load half, half* %a, align 2
35   // CHECK-NEXT: fcmp oeq half [[REG7]], 0xH4400
36 
37   // CHECK: [[REG8:%.*]] = load half, half* %a, align 2
38   // CHECK-NEXT: fcmp une half [[REG8]], 0xH3C00
39 
40   // CHECK: [[REG9:%.*]] = load half, half* %a, align 2
41   // CHECK-NEXT: fcmp une half [[REG9]], 0xH4500
42 
43   // CHECK: [[REG10:%.*]] = load half, half* %a, align 2
44   // CHECK-NEXT: fcmp ole half [[REG10]], 0xH3C00
45 
46   // CHECK: [[REG11:%.*]] = load half, half* %a, align 2
47   // CHECK-NEXT: fcmp ole half [[REG11]], 0xH4600
48 
49   // CHECK: [[REG12:%.*]] = load half, half* %a, align 2
50   // CHECK-NEXT: fcmp oge half [[REG12]], 0xH3C00
51 
52   // CHECK: [[REG13:%.*]] = load half, half* %a, align 2
53   // CHECK-NEXT: fcmp oge half [[REG13]], 0xH4700
54   return a < b || a < 2.0f16 || a > b || a > 3.0f16 || a == b || a == 4.0f16 ||
55          a != b || a != 5.0f16 || a <= b || a <= 6.0f16 || a >= b ||
56          a >= 7.0f16;
57 }
58 
59 bool fcmp() {
60   _Float16 a = 0.0f16;
61   _Float16 b = 1.0f16;
62 
63   // CHECK-NOT: llvm.convert.to.fp16
64   // CHECK-NOT: llvm.convert.from.fp16
65   // CHECK: [[REG1:%.*]] = load half, half* %a, align 2
66   // CHECK-NEXT: [[REG2:%.*]] = load half, half* %b, align 2
67   // CHECK-NEXT: fcmp olt half [[REG1]], [[REG2]]
68 
69   // CHECK: [[REG3:%.*]] = load half, half* %a, align 2
70   // CHECK-NEXT: [[REG4:%.*]] = load half, half* %b, align 2
71   // CHECK-NEXT: fcmp ogt half [[REG3]], [[REG4]]
72 
73   // CHECK: [[REG5:%.*]] = load half, half* %a, align 2
74   // CHECK-NEXT: [[REG6:%.*]] = load half, half* %b, align 2
75   // CHECK-NEXT: fcmp oeq half [[REG5]], [[REG6]]
76 
77   // CHECK: [[REG7:%.*]] = load half, half* %a, align 2
78   // CHECK-NEXT: [[REG8:%.*]] = load half, half* %b, align 2
79   // CHECK-NEXT: fcmp une half [[REG7]], [[REG8]]
80 
81   // CHECK: [[REG7:%.*]] = load half, half* %a, align 2
82   // CHECK-NEXT: [[REG8:%.*]] = load half, half* %b, align 2
83   // CHECK-NEXT: fcmp ole half [[REG7]], [[REG8]]
84 
85   // CHECK: [[REG7:%.*]] = load half, half* %a, align 2
86   // CHECK-NEXT: [[REG8:%.*]] = load half, half* %b, align 2
87   // CHECK-NEXT: fcmp oge half [[REG7]], [[REG8]]
88   return a < b || a > b || a == b || a != b || a <= b || a >= b;
89 }
90 
91 _Float16 fadd() {
92   _Float16 a = 1.0f16;
93   const _Float16 b = 2.0f16;
94 
95   // CHECK-NOT: llvm.convert.to.fp16
96   // CHECK-NOT: llvm.convert.from.fp16
97 
98   // CHECK: [[REG1:%.*]] = load half, half* %a, align 2
99   // CHECK-NEXT: [[REG2:%.*]] = fadd half [[REG1]], 0xH4000
100   // CHECK-NEXT: [[REG3:%.*]] = fadd half [[REG2]], 0xH4200
101   // CHECK-NEXT: ret half [[REG3]]
102   return a + b + 3.0f16;
103 }
104 
105 _Float16 fsub() {
106   _Float16 a = 1.0f16;
107   const _Float16 b = 2.0f16;
108 
109   // CHECK-NOT: llvm.convert.to.fp16
110   // CHECK-NOT: llvm.convert.from.fp16
111 
112   // CHECK: [[REG1:%.*]] = load half, half* %a, align 2
113   // CHECK-NEXT: [[REG2:%.*]] = fsub half [[REG1]], 0xH4000
114   // CHECK-NEXT: [[REG3:%.*]] = fsub half [[REG2]], 0xH4200
115   // CHECK-NEXT: ret half [[REG3]]
116   return a - b - 3.0f16;
117 }
118 
119 // CHECK: define{{.*}} spir_func half @_Z4fmulDF16_(half %arg)
120 _Float16 fmul(_Float16 arg) {
121   _Float16 a = 1.0f16;
122   const _Float16 b = 2.0f16;
123 
124   // CHECK-NOT: llvm.convert.to.fp16
125   // CHECK-NOT: llvm.convert.from.fp16
126 
127   // CHECK: [[REG1:%.*]] = load half, half* %a, align 2
128   // CHECK-NEXT: [[REG2:%.*]] = load half, half* %arg.addr, align 2
129   // CHECK-NEXT: [[REG3:%.*]] = fmul half [[REG1]], [[REG2]]
130   // CHECK-NEXT: [[REG4:%.*]] = fmul half [[REG3]], 0xH4000
131   // CHECK-NEXT: [[REG5:%.*]] = fmul half [[REG4]], 0xH4200
132   // CHECK-NEXT: ret half [[REG5]]
133   return a * arg * b * 3.0f16;
134 }
135 
136 _Float16 fdiv() {
137   _Float16 a = 1.0f16;
138   const _Float16 b = 2.0f16;
139 
140   // CHECK-NOT: llvm.convert.to.fp16
141   // CHECK-NOT: llvm.convert.from.fp16
142 
143   // CHECK: [[REG1:%.*]] = load half, half* %a, align 2
144   // CHECK-NEXT: [[REG2:%.*]] = fdiv half [[REG1]], 0xH4000
145   // CHECK-NEXT: [[REG3:%.*]] = fdiv half [[REG2]], 0xH4200
146   // CHECK-NEXT: ret half [[REG3]]
147   return a / b / 3.0f16;
148 }
149