1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -passes=instcombine < %s | FileCheck %s
4 define i1 @fcmp_oeq_inf_or_class_normal(half %x) {
5 ; CHECK-LABEL: @fcmp_oeq_inf_or_class_normal(
6 ; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 776)
7 ; CHECK-NEXT: ret i1 [[CLASS]]
9 %oeq.inf = fcmp oeq half %x, 0xH7C00
10 %class = call i1 @llvm.is.fpclass.f16(half %x, i32 264)
11 %or = or i1 %oeq.inf, %class
15 define i1 @class_normal_or_fcmp_oeq_inf(half %x) {
16 ; CHECK-LABEL: @class_normal_or_fcmp_oeq_inf(
17 ; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 776)
18 ; CHECK-NEXT: ret i1 [[CLASS]]
20 %oeq.inf = fcmp oeq half %x, 0xH7C00
21 %class = call i1 @llvm.is.fpclass.f16(half %x, i32 264)
22 %or = or i1 %class, %oeq.inf
26 define <2 x i1> @fcmp_oeq_inf_or_class_normal_vector(<2 x half> %x) {
27 ; CHECK-LABEL: @fcmp_oeq_inf_or_class_normal_vector(
28 ; CHECK-NEXT: [[CLASS:%.*]] = call <2 x i1> @llvm.is.fpclass.v2f16(<2 x half> [[X:%.*]], i32 776)
29 ; CHECK-NEXT: ret <2 x i1> [[CLASS]]
31 %oeq.inf = fcmp oeq <2 x half> %x, <half 0xH7C00, half 0xH7C00>
32 %class = call <2 x i1> @llvm.is.fpclass.v2f16(<2 x half> %x, i32 264)
33 %or = or <2 x i1> %oeq.inf, %class
37 define i1 @fcmp_oeq_inf_multi_use_or_class_normal(half %x, ptr %ptr) {
38 ; CHECK-LABEL: @fcmp_oeq_inf_multi_use_or_class_normal(
39 ; CHECK-NEXT: [[OEQ_INF:%.*]] = fcmp oeq half [[X:%.*]], 0xH7C00
40 ; CHECK-NEXT: store i1 [[OEQ_INF]], ptr [[PTR:%.*]], align 1
41 ; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X]], i32 264)
42 ; CHECK-NEXT: [[OR:%.*]] = or i1 [[OEQ_INF]], [[CLASS]]
43 ; CHECK-NEXT: ret i1 [[OR]]
45 %oeq.inf = fcmp oeq half %x, 0xH7C00
46 store i1 %oeq.inf, ptr %ptr
47 %class = call i1 @llvm.is.fpclass.f16(half %x, i32 264)
48 %or = or i1 %oeq.inf, %class
52 define i1 @fcmp_oeq_inf_or_class_normal_multi_use(half %x, ptr %ptr) {
53 ; CHECK-LABEL: @fcmp_oeq_inf_or_class_normal_multi_use(
54 ; CHECK-NEXT: [[OEQ_INF:%.*]] = fcmp oeq half [[X:%.*]], 0xH7C00
55 ; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X]], i32 264)
56 ; CHECK-NEXT: store i1 [[CLASS]], ptr [[PTR:%.*]], align 1
57 ; CHECK-NEXT: [[OR:%.*]] = or i1 [[OEQ_INF]], [[CLASS]]
58 ; CHECK-NEXT: ret i1 [[OR]]
60 %oeq.inf = fcmp oeq half %x, 0xH7C00
61 %class = call i1 @llvm.is.fpclass.f16(half %x, i32 264)
62 store i1 %class, ptr %ptr
63 %or = or i1 %oeq.inf, %class
68 define i1 @fcmp_ord_or_class_isnan(half %x) {
69 ; CHECK-LABEL: @fcmp_ord_or_class_isnan(
70 ; CHECK-NEXT: ret i1 true
72 %ord = fcmp ord half %x, 0.0
73 %class = call i1 @llvm.is.fpclass.f16(half %x, i32 3)
74 %or = or i1 %ord, %class
78 define i1 @fcmp_ord_or_class_isnan_wrong_operand(half %x, half %y) {
79 ; CHECK-LABEL: @fcmp_ord_or_class_isnan_wrong_operand(
80 ; CHECK-NEXT: [[ORD:%.*]] = fcmp ord half [[X:%.*]], 0xH0000
81 ; CHECK-NEXT: [[CLASS:%.*]] = fcmp uno half [[Y:%.*]], 0xH0000
82 ; CHECK-NEXT: [[OR:%.*]] = or i1 [[ORD]], [[CLASS]]
83 ; CHECK-NEXT: ret i1 [[OR]]
85 %ord = fcmp ord half %x, 0.0
86 %class = call i1 @llvm.is.fpclass.f16(half %y, i32 3)
87 %or = or i1 %ord, %class
92 define i1 @fcmp_ord_and_class_isnan(half %x) {
93 ; CHECK-LABEL: @fcmp_ord_and_class_isnan(
94 ; CHECK-NEXT: ret i1 false
96 %ord = fcmp ord half %x, 0.0
97 %class = call i1 @llvm.is.fpclass.f16(half %x, i32 3)
98 %and = and i1 %ord, %class
103 define i1 @fcmp_ord_or_class_isnan_commute(half %x) {
104 ; CHECK-LABEL: @fcmp_ord_or_class_isnan_commute(
105 ; CHECK-NEXT: ret i1 true
107 %class = call i1 @llvm.is.fpclass.f16(half %x, i32 3)
108 %ord = fcmp ord half %x, 0.0
109 %or = or i1 %class, %ord
114 define i1 @fcmp_ord_and_class_isnan_commute(half %x) {
115 ; CHECK-LABEL: @fcmp_ord_and_class_isnan_commute(
116 ; CHECK-NEXT: ret i1 false
118 %class = call i1 @llvm.is.fpclass.f16(half %x, i32 3)
119 %ord = fcmp ord half %x, 0.0
120 %and = and i1 %class, %ord
124 define i1 @fcmp_isfinite_and_class_subnormal(half %x) {
125 ; CHECK-LABEL: @fcmp_isfinite_and_class_subnormal(
126 ; CHECK-NEXT: [[SUBNORMAL_CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 144)
127 ; CHECK-NEXT: ret i1 [[SUBNORMAL_CLASS]]
129 %fabs = call half @llvm.fabs.f16(half %x)
130 %is.finite = fcmp olt half %fabs, 0xH7C00
131 %subnormal.class = call i1 @llvm.is.fpclass.f16(half %x, i32 144)
132 %and = and i1 %is.finite, %subnormal.class
136 define i1 @fcmp_isfinite_or_class_subnormal(half %x) {
137 ; CHECK-LABEL: @fcmp_isfinite_or_class_subnormal(
138 ; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]])
139 ; CHECK-NEXT: [[SUBNORMAL_CLASS:%.*]] = fcmp one half [[TMP1]], 0xH7C00
140 ; CHECK-NEXT: ret i1 [[SUBNORMAL_CLASS]]
142 %fabs = call half @llvm.fabs.f16(half %x)
143 %is.finite = fcmp olt half %fabs, 0xH7C00
144 %subnormal.class = call i1 @llvm.is.fpclass.f16(half %x, i32 144)
145 %or = or i1 %is.finite, %subnormal.class
150 define i1 @fcmp_issubnormal_or_class_finite(half %x) {
151 ; CHECK-LABEL: @fcmp_issubnormal_or_class_finite(
152 ; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]])
153 ; CHECK-NEXT: [[OR:%.*]] = fcmp one half [[TMP1]], 0xH7C00
154 ; CHECK-NEXT: ret i1 [[OR]]
156 %fabs = call half @llvm.fabs.f16(half %x)
157 %is.subnormal = fcmp olt half %fabs, 0xH0400
158 %is.finite.class = call i1 @llvm.is.fpclass.f16(half %x, i32 504)
159 %or = or i1 %is.subnormal, %is.finite.class
164 define i1 @class_finite_or_fcmp_issubnormal(half %x) {
165 ; CHECK-LABEL: @class_finite_or_fcmp_issubnormal(
166 ; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]])
167 ; CHECK-NEXT: [[OR:%.*]] = fcmp one half [[TMP1]], 0xH7C00
168 ; CHECK-NEXT: ret i1 [[OR]]
170 %fabs = call half @llvm.fabs.f16(half %x)
171 %is.subnormal = fcmp olt half %fabs, 0xH0400
172 %is.finite.class = call i1 @llvm.is.fpclass.f16(half %x, i32 504)
173 %or = or i1 %is.finite.class, %is.subnormal
178 define i1 @fcmp_issubnormal_and_class_finite(half %x) {
179 ; CHECK-LABEL: @fcmp_issubnormal_and_class_finite(
180 ; CHECK-NEXT: [[AND:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 240)
181 ; CHECK-NEXT: ret i1 [[AND]]
183 %fabs = call half @llvm.fabs.f16(half %x)
184 %is.subnormal = fcmp olt half %fabs, 0xH0400
185 %is.finite.class = call i1 @llvm.is.fpclass.f16(half %x, i32 504)
186 %and = and i1 %is.subnormal, %is.finite.class
190 define i1 @class_inf_or_fcmp_issubnormal(half %x) {
191 ; CHECK-LABEL: @class_inf_or_fcmp_issubnormal(
192 ; CHECK-NEXT: [[OR:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 756)
193 ; CHECK-NEXT: ret i1 [[OR]]
195 %fabs = call half @llvm.fabs.f16(half %x)
196 %is.subnormal = fcmp olt half %fabs, 0xH0400
197 %is.inf.class = call i1 @llvm.is.fpclass.f16(half %x, i32 516)
198 %or = or i1 %is.inf.class, %is.subnormal
203 define <2 x i1> @class_finite_or_fcmp_issubnormal_vector(<2 x half> %x) {
204 ; CHECK-LABEL: @class_finite_or_fcmp_issubnormal_vector(
205 ; CHECK-NEXT: [[TMP1:%.*]] = call <2 x half> @llvm.fabs.v2f16(<2 x half> [[X:%.*]])
206 ; CHECK-NEXT: [[OR:%.*]] = fcmp one <2 x half> [[TMP1]], <half 0xH7C00, half 0xH7C00>
207 ; CHECK-NEXT: ret <2 x i1> [[OR]]
209 %fabs = call <2 x half> @llvm.fabs.v2f16(<2 x half> %x)
210 %is.subnormal = fcmp olt <2 x half> %fabs, <half 0xH0400, half 0xH0400>
211 %is.finite.class = call <2 x i1> @llvm.is.fpclass.v2f16(<2 x half> %x, i32 504)
212 %or = or <2 x i1> %is.finite.class, %is.subnormal
216 define i1 @fcmp_oeq_zero_or_class_normal(half %x) {
217 ; CHECK-LABEL: @fcmp_oeq_zero_or_class_normal(
218 ; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 360)
219 ; CHECK-NEXT: ret i1 [[CLASS]]
221 %oeq.inf = fcmp oeq half %x, 0.0
222 %class = call i1 @llvm.is.fpclass.f16(half %x, i32 264)
223 %or = or i1 %oeq.inf, %class
227 define i1 @fcmp_oeq_zero_or_class_normal_daz(half %x) #1 {
228 ; CHECK-LABEL: @fcmp_oeq_zero_or_class_normal_daz(
229 ; CHECK-NEXT: [[OEQ_INF:%.*]] = fcmp oeq half [[X:%.*]], 0xH0000
230 ; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X]], i32 264)
231 ; CHECK-NEXT: [[OR:%.*]] = or i1 [[OEQ_INF]], [[CLASS]]
232 ; CHECK-NEXT: ret i1 [[OR]]
234 %oeq.inf = fcmp oeq half %x, 0.0
235 %class = call i1 @llvm.is.fpclass.f16(half %x, i32 264)
236 %or = or i1 %oeq.inf, %class
240 define <2 x i1> @fcmp_oeq_zero_or_class_normal_daz_v2f16(<2 x half> %x) #1 {
241 ; CHECK-LABEL: @fcmp_oeq_zero_or_class_normal_daz_v2f16(
242 ; CHECK-NEXT: [[OEQ_INF:%.*]] = fcmp oeq <2 x half> [[X:%.*]], zeroinitializer
243 ; CHECK-NEXT: [[CLASS:%.*]] = call <2 x i1> @llvm.is.fpclass.v2f16(<2 x half> [[X]], i32 264)
244 ; CHECK-NEXT: [[OR:%.*]] = or <2 x i1> [[OEQ_INF]], [[CLASS]]
245 ; CHECK-NEXT: ret <2 x i1> [[OR]]
247 %oeq.inf = fcmp oeq <2 x half> %x, zeroinitializer
248 %class = call <2 x i1> @llvm.is.fpclass.v2f16(<2 x half> %x, i32 264)
249 %or = or <2 x i1> %oeq.inf, %class
253 define i1 @fcmp_oeq_zero_or_class_normal_dynamic(half %x) #2 {
254 ; CHECK-LABEL: @fcmp_oeq_zero_or_class_normal_dynamic(
255 ; CHECK-NEXT: [[OEQ_INF:%.*]] = fcmp oeq half [[X:%.*]], 0xH0000
256 ; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X]], i32 264)
257 ; CHECK-NEXT: [[OR:%.*]] = or i1 [[OEQ_INF]], [[CLASS]]
258 ; CHECK-NEXT: ret i1 [[OR]]
260 %oeq.inf = fcmp oeq half %x, 0.0
261 %class = call i1 @llvm.is.fpclass.f16(half %x, i32 264)
262 %or = or i1 %oeq.inf, %class
266 define <2 x i1> @fcmp_oeq_zero_or_class_normal_dynamic_v2f16(<2 x half> %x) #2 {
267 ; CHECK-LABEL: @fcmp_oeq_zero_or_class_normal_dynamic_v2f16(
268 ; CHECK-NEXT: [[OEQ_INF:%.*]] = fcmp oeq <2 x half> [[X:%.*]], zeroinitializer
269 ; CHECK-NEXT: [[CLASS:%.*]] = call <2 x i1> @llvm.is.fpclass.v2f16(<2 x half> [[X]], i32 264)
270 ; CHECK-NEXT: [[OR:%.*]] = or <2 x i1> [[OEQ_INF]], [[CLASS]]
271 ; CHECK-NEXT: ret <2 x i1> [[OR]]
273 %oeq.inf = fcmp oeq <2 x half> %x, zeroinitializer
274 %class = call <2 x i1> @llvm.is.fpclass.v2f16(<2 x half> %x, i32 264)
275 %or = or <2 x i1> %oeq.inf, %class
279 define i1 @class_normal_or_fcmp_oeq_zero(half %x) {
280 ; CHECK-LABEL: @class_normal_or_fcmp_oeq_zero(
281 ; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 360)
282 ; CHECK-NEXT: ret i1 [[CLASS]]
284 %oeq.inf = fcmp oeq half %x, 0.0
285 %class = call i1 @llvm.is.fpclass.f16(half %x, i32 264)
286 %or = or i1 %oeq.inf, %class
290 define i1 @fcmp_ueq_zero_or_class_normal(half %x) {
291 ; CHECK-LABEL: @fcmp_ueq_zero_or_class_normal(
292 ; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 363)
293 ; CHECK-NEXT: ret i1 [[CLASS]]
295 %ueq.inf = fcmp ueq half %x, 0.0
296 %class = call i1 @llvm.is.fpclass.f16(half %x, i32 264)
297 %or = or i1 %ueq.inf, %class
301 define i1 @class_normal_or_fcmp_ueq_zero(half %x) {
302 ; CHECK-LABEL: @class_normal_or_fcmp_ueq_zero(
303 ; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 363)
304 ; CHECK-NEXT: ret i1 [[CLASS]]
306 %ueq.inf = fcmp ueq half %x, 0.0
307 %class = call i1 @llvm.is.fpclass.f16(half %x, i32 264)
308 %or = or i1 %ueq.inf, %class
312 define i1 @fcmp_one_zero_or_class_normal(half %x) {
313 ; CHECK-LABEL: @fcmp_one_zero_or_class_normal(
314 ; CHECK-NEXT: [[CLASS:%.*]] = fcmp one half [[X:%.*]], 0xH0000
315 ; CHECK-NEXT: ret i1 [[CLASS]]
317 %one.inf = fcmp one half %x, 0.0
318 %class = call i1 @llvm.is.fpclass.f16(half %x, i32 264)
319 %or = or i1 %one.inf, %class
323 define i1 @fcmp_one_zero_or_class_normal_daz(half %x) #1 {
324 ; CHECK-LABEL: @fcmp_one_zero_or_class_normal_daz(
325 ; CHECK-NEXT: [[ONE_INF:%.*]] = fcmp one half [[X:%.*]], 0xH0000
326 ; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X]], i32 264)
327 ; CHECK-NEXT: [[OR:%.*]] = or i1 [[ONE_INF]], [[CLASS]]
328 ; CHECK-NEXT: ret i1 [[OR]]
330 %one.inf = fcmp one half %x, 0.0
331 %class = call i1 @llvm.is.fpclass.f16(half %x, i32 264)
332 %or = or i1 %one.inf, %class
336 define i1 @fcmp_one_zero_or_class_normal_dynamic(half %x) #2 {
337 ; CHECK-LABEL: @fcmp_one_zero_or_class_normal_dynamic(
338 ; CHECK-NEXT: [[ONE_INF:%.*]] = fcmp one half [[X:%.*]], 0xH0000
339 ; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X]], i32 264)
340 ; CHECK-NEXT: [[OR:%.*]] = or i1 [[ONE_INF]], [[CLASS]]
341 ; CHECK-NEXT: ret i1 [[OR]]
343 %one.inf = fcmp one half %x, 0.0
344 %class = call i1 @llvm.is.fpclass.f16(half %x, i32 264)
345 %or = or i1 %one.inf, %class
349 define i1 @class_normal_or_fcmp_one_zero(half %x) {
350 ; CHECK-LABEL: @class_normal_or_fcmp_one_zero(
351 ; CHECK-NEXT: [[CLASS:%.*]] = fcmp one half [[X:%.*]], 0xH0000
352 ; CHECK-NEXT: ret i1 [[CLASS]]
354 %one.inf = fcmp one half %x, 0.0
355 %class = call i1 @llvm.is.fpclass.f16(half %x, i32 264)
356 %or = or i1 %one.inf, %class
360 define i1 @fcmp_une_zero_or_class_normal(half %x) {
361 ; CHECK-LABEL: @fcmp_une_zero_or_class_normal(
362 ; CHECK-NEXT: [[CLASS:%.*]] = fcmp une half [[X:%.*]], 0xH0000
363 ; CHECK-NEXT: ret i1 [[CLASS]]
365 %une.inf = fcmp une half %x, 0.0
366 %class = call i1 @llvm.is.fpclass.f16(half %x, i32 264)
367 %or = or i1 %une.inf, %class
371 define i1 @class_normal_or_fcmp_une_zero(half %x) {
372 ; CHECK-LABEL: @class_normal_or_fcmp_une_zero(
373 ; CHECK-NEXT: [[CLASS:%.*]] = fcmp une half [[X:%.*]], 0xH0000
374 ; CHECK-NEXT: ret i1 [[CLASS]]
376 %une.inf = fcmp une half %x, 0.0
377 %class = call i1 @llvm.is.fpclass.f16(half %x, i32 264)
378 %or = or i1 %une.inf, %class
382 define i1 @class_normal_or_fcmp_une_zero_daz(half %x) #1 {
383 ; CHECK-LABEL: @class_normal_or_fcmp_une_zero_daz(
384 ; CHECK-NEXT: [[UNE_INF:%.*]] = fcmp une half [[X:%.*]], 0xH0000
385 ; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X]], i32 264)
386 ; CHECK-NEXT: [[OR:%.*]] = or i1 [[UNE_INF]], [[CLASS]]
387 ; CHECK-NEXT: ret i1 [[OR]]
389 %une.inf = fcmp une half %x, 0.0
390 %class = call i1 @llvm.is.fpclass.f16(half %x, i32 264)
391 %or = or i1 %une.inf, %class
395 define i1 @class_normal_or_fcmp_une_zero_dynamic(half %x) #2 {
396 ; CHECK-LABEL: @class_normal_or_fcmp_une_zero_dynamic(
397 ; CHECK-NEXT: [[UNE_INF:%.*]] = fcmp une half [[X:%.*]], 0xH0000
398 ; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X]], i32 264)
399 ; CHECK-NEXT: [[OR:%.*]] = or i1 [[UNE_INF]], [[CLASS]]
400 ; CHECK-NEXT: ret i1 [[OR]]
402 %une.inf = fcmp une half %x, 0.0
403 %class = call i1 @llvm.is.fpclass.f16(half %x, i32 264)
404 %or = or i1 %une.inf, %class
408 define i1 @fcmp_oeq_inf_xor_class_normal(half %x) {
409 ; CHECK-LABEL: @fcmp_oeq_inf_xor_class_normal(
410 ; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 776)
411 ; CHECK-NEXT: ret i1 [[CLASS]]
413 %oeq.inf = fcmp oeq half %x, 0xH7C00
414 %class = call i1 @llvm.is.fpclass.f16(half %x, i32 264)
415 %xor = xor i1 %oeq.inf, %class
419 define i1 @class_normal_xor_fcmp_oeq_inf(half %x) {
420 ; CHECK-LABEL: @class_normal_xor_fcmp_oeq_inf(
421 ; CHECK-NEXT: [[CLASS:%.*]] = call i1 @llvm.is.fpclass.f16(half [[X:%.*]], i32 776)
422 ; CHECK-NEXT: ret i1 [[CLASS]]
424 %oeq.inf = fcmp oeq half %x, 0xH7C00
425 %class = call i1 @llvm.is.fpclass.f16(half %x, i32 264)
426 %xor = xor i1 %class, %oeq.inf
431 declare half @llvm.fabs.f16(half) #0
432 declare half @llvm.canonicalize.f16(half) #0
433 declare <2 x half> @llvm.fabs.v2f16(<2 x half>) #0
434 declare i1 @llvm.is.fpclass.f16(half, i32 immarg) #0
435 declare <2 x i1> @llvm.is.fpclass.v2f16(<2 x half>, i32 immarg) #0
437 attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
438 attributes #1 = { "denormal-fp-math"="ieee,preserve-sign" }
439 attributes #2 = { "denormal-fp-math"="ieee,dynamic" }