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