Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / InstSimplify / logic-of-fcmps.ll
blob3a8bf53b32cab0799c6676488b931b19c463efcf
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
4 ; Cycle through commuted variants where one operand of fcmp ord/uno is
5 ; known not-a-NAN and the other is repeated in the logically-connected fcmp.
7 declare float @llvm.fabs.f32(float)
8 declare void @llvm.assume(i1 noundef)
10 define i1 @ord1(float %x, float %y) {
11 ; CHECK-LABEL: @ord1(
12 ; CHECK-NEXT:    [[CMP2:%.*]] = fcmp ord float [[X:%.*]], [[Y:%.*]]
13 ; CHECK-NEXT:    ret i1 [[CMP2]]
15   %cmp1 = fcmp ord float 0.0, %x
16   %cmp2 = fcmp ord float %x, %y
17   %r = and i1 %cmp1, %cmp2
18   ret i1 %r
21 define i1 @ord1_assume(float %x, float %y, float %not.nan) {
22 ; CHECK-LABEL: @ord1_assume(
23 ; CHECK-NEXT:    [[ORD:%.*]] = fcmp ord float [[NOT_NAN:%.*]], 0.000000e+00
24 ; CHECK-NEXT:    call void @llvm.assume(i1 [[ORD]])
25 ; CHECK-NEXT:    [[CMP2:%.*]] = fcmp ord float [[X:%.*]], [[Y:%.*]]
26 ; CHECK-NEXT:    ret i1 [[CMP2]]
28   %ord = fcmp ord float %not.nan, 0.0
29   call void @llvm.assume(i1 %ord)
30   %cmp1 = fcmp ord float %not.nan, %x
31   %cmp2 = fcmp ord float %x, %y
32   %r = and i1 %cmp1, %cmp2
33   ret i1 %r
36 define i1 @ord2(double %x, double %y) {
37 ; CHECK-LABEL: @ord2(
38 ; CHECK-NEXT:    [[CMP2:%.*]] = fcmp ord double [[Y:%.*]], [[X:%.*]]
39 ; CHECK-NEXT:    ret i1 [[CMP2]]
41   %cmp1 = fcmp ord double 42.0, %x
42   %cmp2 = fcmp ord double %y, %x
43   %r = and i1 %cmp1, %cmp2
44   ret i1 %r
47 define <2 x i1> @ord3(<2 x float> %x, <2 x float> %y) {
48 ; CHECK-LABEL: @ord3(
49 ; CHECK-NEXT:    [[CMP2:%.*]] = fcmp ord <2 x float> [[X:%.*]], [[Y:%.*]]
50 ; CHECK-NEXT:    ret <2 x i1> [[CMP2]]
52   %cmp1 = fcmp ord <2 x float> %x, zeroinitializer
53   %cmp2 = fcmp ord <2 x float> %x, %y
54   %r = and <2 x i1> %cmp1, %cmp2
55   ret <2 x i1> %r
58 define i1 @ord3_assume(float %x, float %y, float %not.nan) {
59 ; CHECK-LABEL: @ord3_assume(
60 ; CHECK-NEXT:    [[ORD:%.*]] = fcmp ord float [[NOT_NAN:%.*]], 0.000000e+00
61 ; CHECK-NEXT:    call void @llvm.assume(i1 [[ORD]])
62 ; CHECK-NEXT:    [[CMP2:%.*]] = fcmp ord float [[X:%.*]], [[Y:%.*]]
63 ; CHECK-NEXT:    ret i1 [[CMP2]]
65   %ord = fcmp ord float %not.nan, 0.0
66   call void @llvm.assume(i1 %ord)
67   %cmp1 = fcmp ord float %x, %not.nan
68   %cmp2 = fcmp ord float %x, %y
69   %r = and i1 %cmp1, %cmp2
70   ret i1 %r
73 define <2 x i1> @ord4(<2 x double> %x, <2 x double> %y) {
74 ; CHECK-LABEL: @ord4(
75 ; CHECK-NEXT:    [[CMP2:%.*]] = fcmp ord <2 x double> [[Y:%.*]], [[X:%.*]]
76 ; CHECK-NEXT:    ret <2 x i1> [[CMP2]]
78   %cmp1 = fcmp ord <2 x double> %x, <double 42.0, double 42.0>
79   %cmp2 = fcmp ord <2 x double> %y, %x
80   %r = and <2 x i1> %cmp1, %cmp2
81   ret <2 x i1> %r
84 define i1 @ord5(float %x, float %y) {
85 ; CHECK-LABEL: @ord5(
86 ; CHECK-NEXT:    [[CMP1:%.*]] = fcmp ord float [[X:%.*]], [[Y:%.*]]
87 ; CHECK-NEXT:    ret i1 [[CMP1]]
89   %nnan = fdiv nnan float %x, %y
90   %cmp1 = fcmp ord float %x, %y
91   %cmp2 = fcmp ord float %nnan, %x
92   %r = and i1 %cmp1, %cmp2
93   ret i1 %r
96 define i1 @ord5_assume(float %x, float %y, float %nnan) {
97 ; CHECK-LABEL: @ord5_assume(
98 ; CHECK-NEXT:    [[ORD:%.*]] = fcmp ord float [[NNAN:%.*]], 0.000000e+00
99 ; CHECK-NEXT:    call void @llvm.assume(i1 [[ORD]])
100 ; CHECK-NEXT:    [[CMP1:%.*]] = fcmp ord float [[X:%.*]], [[Y:%.*]]
101 ; CHECK-NEXT:    ret i1 [[CMP1]]
103   %ord = fcmp ord float %nnan, 0.0
104   call void @llvm.assume(i1 %ord)
105   %cmp1 = fcmp ord float %x, %y
106   %cmp2 = fcmp ord float %nnan, %x
107   %r = and i1 %cmp1, %cmp2
108   ret i1 %r
111 define i1 @ord6(double %x, double %y) {
112 ; CHECK-LABEL: @ord6(
113 ; CHECK-NEXT:    [[CMP1:%.*]] = fcmp ord double [[Y:%.*]], [[X:%.*]]
114 ; CHECK-NEXT:    ret i1 [[CMP1]]
116   %cmp1 = fcmp ord double %y, %x
117   %cmp2 = fcmp ord double 42.0, %x
118   %r = and i1 %cmp1, %cmp2
119   ret i1 %r
122 define i1 @ord6_assume(double %x, double %y, double %not.nan) {
123 ; CHECK-LABEL: @ord6_assume(
124 ; CHECK-NEXT:    [[ORD:%.*]] = fcmp ord double [[NOT_NAN:%.*]], 0.000000e+00
125 ; CHECK-NEXT:    call void @llvm.assume(i1 [[ORD]])
126 ; CHECK-NEXT:    [[CMP1:%.*]] = fcmp ord double [[Y:%.*]], [[X:%.*]]
127 ; CHECK-NEXT:    ret i1 [[CMP1]]
129   %ord = fcmp ord double %not.nan, 0.0
130   call void @llvm.assume(i1 %ord)
131   %cmp1 = fcmp ord double %y, %x
132   %cmp2 = fcmp ord double %not.nan, %x
133   %r = and i1 %cmp1, %cmp2
134   ret i1 %r
137 define <2 x i1> @ord7(<2 x float> %x, <2 x float> %y) {
138 ; CHECK-LABEL: @ord7(
139 ; CHECK-NEXT:    [[CMP1:%.*]] = fcmp ord <2 x float> [[X:%.*]], [[Y:%.*]]
140 ; CHECK-NEXT:    ret <2 x i1> [[CMP1]]
142   %cmp1 = fcmp ord <2 x float> %x, %y
143   %cmp2 = fcmp ord <2 x float> %x, zeroinitializer
144   %r = and <2 x i1> %cmp1, %cmp2
145   ret <2 x i1> %r
148 define i1 @ord7_assume(float %x, float %y, float %not.nan) {
149 ; CHECK-LABEL: @ord7_assume(
150 ; CHECK-NEXT:    [[ORD:%.*]] = fcmp ord float [[NOT_NAN:%.*]], 0.000000e+00
151 ; CHECK-NEXT:    call void @llvm.assume(i1 [[ORD]])
152 ; CHECK-NEXT:    [[CMP1:%.*]] = fcmp ord float [[X:%.*]], [[Y:%.*]]
153 ; CHECK-NEXT:    ret i1 [[CMP1]]
155   %ord = fcmp ord float %not.nan, 0.0
156   call void @llvm.assume(i1 %ord)
157   %cmp1 = fcmp ord float %x, %y
158   %cmp2 = fcmp ord float %x, %not.nan
159   %r = and i1 %cmp1, %cmp2
160   ret i1 %r
163 define <2 x i1> @ord8(<2 x double> %x, <2 x double> %y) {
164 ; CHECK-LABEL: @ord8(
165 ; CHECK-NEXT:    [[CMP1:%.*]] = fcmp ord <2 x double> [[Y:%.*]], [[X:%.*]]
166 ; CHECK-NEXT:    ret <2 x i1> [[CMP1]]
168   %cmp1 = fcmp ord <2 x double> %y, %x
169   %cmp2 = fcmp ord <2 x double> %x, <double 0.0, double 42.0>
170   %r = and <2 x i1> %cmp1, %cmp2
171   ret <2 x i1> %r
174 define i1 @uno1(float %x, float %y) {
175 ; CHECK-LABEL: @uno1(
176 ; CHECK-NEXT:    [[CMP2:%.*]] = fcmp uno float [[X:%.*]], [[Y:%.*]]
177 ; CHECK-NEXT:    ret i1 [[CMP2]]
179   %cmp1 = fcmp uno float 0.0, %x
180   %cmp2 = fcmp uno float %x, %y
181   %r = or i1 %cmp1, %cmp2
182   ret i1 %r
185 define i1 @uno2(double %x, double %y) {
186 ; CHECK-LABEL: @uno2(
187 ; CHECK-NEXT:    [[CMP2:%.*]] = fcmp uno double [[Y:%.*]], [[X:%.*]]
188 ; CHECK-NEXT:    ret i1 [[CMP2]]
190   %cmp1 = fcmp uno double 42.0, %x
191   %cmp2 = fcmp uno double %y, %x
192   %r = or i1 %cmp1, %cmp2
193   ret i1 %r
196 define <2 x i1> @uno3(<2 x float> %x, <2 x float> %y) {
197 ; CHECK-LABEL: @uno3(
198 ; CHECK-NEXT:    [[CMP2:%.*]] = fcmp uno <2 x float> [[X:%.*]], [[Y:%.*]]
199 ; CHECK-NEXT:    ret <2 x i1> [[CMP2]]
201   %cmp1 = fcmp uno <2 x float> %x, zeroinitializer
202   %cmp2 = fcmp uno <2 x float> %x, %y
203   %r = or <2 x i1> %cmp1, %cmp2
204   ret <2 x i1> %r
207 define <2 x i1> @uno4(<2 x double> %x, <2 x double> %y) {
208 ; CHECK-LABEL: @uno4(
209 ; CHECK-NEXT:    [[CMP2:%.*]] = fcmp uno <2 x double> [[Y:%.*]], [[X:%.*]]
210 ; CHECK-NEXT:    ret <2 x i1> [[CMP2]]
212   %cmp1 = fcmp uno <2 x double> %x, <double 42.0, double 42.0>
213   %cmp2 = fcmp uno <2 x double> %y, %x
214   %r = or <2 x i1> %cmp1, %cmp2
215   ret <2 x i1> %r
218 define i1 @uno5(float %x, float %y) {
219 ; CHECK-LABEL: @uno5(
220 ; CHECK-NEXT:    [[CMP1:%.*]] = fcmp uno float [[X:%.*]], [[Y:%.*]]
221 ; CHECK-NEXT:    ret i1 [[CMP1]]
223   %cmp1 = fcmp uno float %x, %y
224   %cmp2 = fcmp uno float 0.0, %x
225   %r = or i1 %cmp1, %cmp2
226   ret i1 %r
229 define i1 @uno6(double %x, double %y) {
230 ; CHECK-LABEL: @uno6(
231 ; CHECK-NEXT:    [[CMP1:%.*]] = fcmp uno double [[Y:%.*]], [[X:%.*]]
232 ; CHECK-NEXT:    ret i1 [[CMP1]]
234   %cmp1 = fcmp uno double %y, %x
235   %cmp2 = fcmp uno double 42.0, %x
236   %r = or i1 %cmp1, %cmp2
237   ret i1 %r
240 define <2 x i1> @uno7(<2 x float> %x, <2 x float> %y) {
241 ; CHECK-LABEL: @uno7(
242 ; CHECK-NEXT:    [[CMP1:%.*]] = fcmp uno <2 x float> [[X:%.*]], [[Y:%.*]]
243 ; CHECK-NEXT:    ret <2 x i1> [[CMP1]]
245   %nnan = fdiv nnan <2 x float> %x, %y
246   %cmp1 = fcmp uno <2 x float> %x, %y
247   %cmp2 = fcmp uno <2 x float> %x, %nnan
248   %r = or <2 x i1> %cmp1, %cmp2
249   ret <2 x i1> %r
252 define <2 x i1> @uno8(<2 x double> %x, <2 x double> %y) {
253 ; CHECK-LABEL: @uno8(
254 ; CHECK-NEXT:    [[CMP1:%.*]] = fcmp uno <2 x double> [[Y:%.*]], [[X:%.*]]
255 ; CHECK-NEXT:    ret <2 x i1> [[CMP1]]
257   %cmp1 = fcmp uno <2 x double> %y, %x
258   %cmp2 = fcmp uno <2 x double> %x, <double 0x7ff0000000000000, double 42.0>
259   %r = or <2 x i1> %cmp1, %cmp2
260   ret <2 x i1> %r
263 define i1 @olt_implies_ord(float %x, float %y) {
264 ; CHECK-LABEL: @olt_implies_ord(
265 ; CHECK-NEXT:    [[OLT:%.*]] = fcmp olt float [[X:%.*]], [[Y:%.*]]
266 ; CHECK-NEXT:    ret i1 [[OLT]]
268   %ord = fcmp ord float %x, 0.000000e+00
269   %olt = fcmp olt float %x, %y
270   %ret = and i1 %olt, %ord
271   ret i1 %ret
274 define i1 @olt_implies_ord_commuted1(float %x, float %y) {
275 ; CHECK-LABEL: @olt_implies_ord_commuted1(
276 ; CHECK-NEXT:    [[OLT:%.*]] = fcmp olt float [[Y:%.*]], [[X:%.*]]
277 ; CHECK-NEXT:    ret i1 [[OLT]]
279   %ord = fcmp ord float %x, 0.000000e+00
280   %olt = fcmp olt float %y, %x
281   %ret = and i1 %olt, %ord
282   ret i1 %ret
285 define i1 @olt_implies_ord_commuted2(float %x, float %y) {
286 ; CHECK-LABEL: @olt_implies_ord_commuted2(
287 ; CHECK-NEXT:    [[OLT:%.*]] = fcmp olt float [[X:%.*]], [[Y:%.*]]
288 ; CHECK-NEXT:    ret i1 [[OLT]]
290   %ord = fcmp ord float %x, 0.000000e+00
291   %olt = fcmp olt float %x, %y
292   %ret = and i1 %ord, %olt
293   ret i1 %ret
296 define i1 @olt_implies_ord_commuted3(float %x, float %y) {
297 ; CHECK-LABEL: @olt_implies_ord_commuted3(
298 ; CHECK-NEXT:    [[OLT:%.*]] = fcmp olt float [[Y:%.*]], [[X:%.*]]
299 ; CHECK-NEXT:    ret i1 [[OLT]]
301   %ord = fcmp ord float %x, 0.000000e+00
302   %olt = fcmp olt float %y, %x
303   %ret = and i1 %ord, %olt
304   ret i1 %ret
307 define <2 x i1> @olt_implies_ord_vec(<2 x float> %x, <2 x float> %y) {
308 ; CHECK-LABEL: @olt_implies_ord_vec(
309 ; CHECK-NEXT:    [[OLT:%.*]] = fcmp olt <2 x float> [[X:%.*]], [[Y:%.*]]
310 ; CHECK-NEXT:    ret <2 x i1> [[OLT]]
312   %ord = fcmp ord <2 x float> %x, zeroinitializer
313   %olt = fcmp olt <2 x float> %x, %y
314   %ret = and <2 x i1> %ord, %olt
315   ret <2 x i1> %ret
318 define i1 @ord_implies_ord(float %x, float %y) {
319 ; CHECK-LABEL: @ord_implies_ord(
320 ; CHECK-NEXT:    [[ORD2:%.*]] = fcmp ord float [[X:%.*]], [[Y:%.*]]
321 ; CHECK-NEXT:    ret i1 [[ORD2]]
323   %ord = fcmp ord float %x, 0.000000e+00
324   %ord2 = fcmp ord float %x, %y
325   %ret = and i1 %ord, %ord2
326   ret i1 %ret
329 define i1 @olt_implies_uno(float %x, float %y) {
330 ; CHECK-LABEL: @olt_implies_uno(
331 ; CHECK-NEXT:    ret i1 false
333   %uno = fcmp uno float %x, 0.000000e+00
334   %olt = fcmp olt float %x, %y
335   %ret = and i1 %olt, %uno
336   ret i1 %ret
339 define i1 @ult_implies_uno(float %x, float %y) {
340 ; CHECK-LABEL: @ult_implies_uno(
341 ; CHECK-NEXT:    [[ULT:%.*]] = fcmp ult float [[X:%.*]], [[Y:%.*]]
342 ; CHECK-NEXT:    ret i1 [[ULT]]
344   %uno = fcmp uno float %x, 0.000000e+00
345   %ult = fcmp ult float %x, %y
346   %ret = or i1 %ult, %uno
347   ret i1 %ret
350 define i1 @uno_implies_uno(float %x, float %y) {
351 ; CHECK-LABEL: @uno_implies_uno(
352 ; CHECK-NEXT:    [[UNO2:%.*]] = fcmp uno float [[X:%.*]], [[Y:%.*]]
353 ; CHECK-NEXT:    ret i1 [[UNO2]]
355   %uno = fcmp uno float %x, 0.000000e+00
356   %uno2 = fcmp uno float %x, %y
357   %ret = or i1 %uno, %uno2
358   ret i1 %ret
361 define i1 @ult_implies_ord(float %x, float %y) {
362 ; CHECK-LABEL: @ult_implies_ord(
363 ; CHECK-NEXT:    ret i1 true
365   %ord = fcmp ord float %x, 0.000000e+00
366   %ult = fcmp ult float %x, %y
367   %ret = or i1 %ult, %ord
368   ret i1 %ret
371 ; TODO: %cmp1 is false implies %cmp3 is true
372 define float @test_ord_implies_uno(float %x) {
373 ; CHECK-LABEL: @test_ord_implies_uno(
374 ; CHECK-NEXT:    [[CMP1:%.*]] = fcmp ord float [[X:%.*]], 0.000000e+00
375 ; CHECK-NEXT:    [[CMP2:%.*]] = fcmp olt float [[X]], 0.000000e+00
376 ; CHECK-NEXT:    [[CMP3:%.*]] = fcmp uno float [[X]], 0.000000e+00
377 ; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[CMP1]], i1 [[CMP2]], i1 [[CMP3]]
378 ; CHECK-NEXT:    [[RET:%.*]] = select i1 [[SEL]], float 0.000000e+00, float [[X]]
379 ; CHECK-NEXT:    ret float [[RET]]
381   %cmp1 = fcmp ord float %x, 0.000000e+00
382   %cmp2 = fcmp olt float %x, 0.000000e+00
383   %cmp3 = fcmp uno float %x, 0.000000e+00
384   %sel = select i1 %cmp1, i1 %cmp2, i1 %cmp3
385   %ret = select i1 %sel, float 0.000000e+00, float %x
386   ret float %ret
389 ; Negative tests
391 define i1 @olt_implies_ord_fail(float %x, float %y, float %z) {
392 ; CHECK-LABEL: @olt_implies_ord_fail(
393 ; CHECK-NEXT:    [[ORD:%.*]] = fcmp ord float [[X:%.*]], [[Z:%.*]]
394 ; CHECK-NEXT:    [[OLT:%.*]] = fcmp olt float [[X]], [[Y:%.*]]
395 ; CHECK-NEXT:    [[RET:%.*]] = and i1 [[OLT]], [[ORD]]
396 ; CHECK-NEXT:    ret i1 [[RET]]
398   %ord = fcmp ord float %x, %z
399   %olt = fcmp olt float %x, %y
400   %ret = and i1 %olt, %ord
401   ret i1 %ret
404 define i1 @ult_implies_uno_and(float %x, float %y) {
405 ; CHECK-LABEL: @ult_implies_uno_and(
406 ; CHECK-NEXT:    [[UNO:%.*]] = fcmp uno float [[X:%.*]], 0.000000e+00
407 ; CHECK-NEXT:    [[ULT:%.*]] = fcmp ult float [[X]], [[Y:%.*]]
408 ; CHECK-NEXT:    [[RET:%.*]] = and i1 [[ULT]], [[UNO]]
409 ; CHECK-NEXT:    ret i1 [[RET]]
411   %uno = fcmp uno float %x, 0.000000e+00
412   %ult = fcmp ult float %x, %y
413   %ret = and i1 %ult, %uno
414   ret i1 %ret
417 define i1 @olt_implies_olt_fail(float %x, float %y) {
418 ; CHECK-LABEL: @olt_implies_olt_fail(
419 ; CHECK-NEXT:    [[OLT:%.*]] = fcmp olt float [[X:%.*]], 0.000000e+00
420 ; CHECK-NEXT:    [[OLT2:%.*]] = fcmp olt float [[X]], [[Y:%.*]]
421 ; CHECK-NEXT:    [[RET:%.*]] = and i1 [[OLT]], [[OLT2]]
422 ; CHECK-NEXT:    ret i1 [[RET]]
424   %olt = fcmp olt float %x, 0.000000e+00
425   %olt2 = fcmp olt float %x, %y
426   %ret = and i1 %olt, %olt2
427   ret i1 %ret