xref: /llvm-project/llvm/test/Transforms/InstCombine/fcmp-special.ll (revision d9a5aa8e2d755643cf4e7fa86aa831ed226fe54d)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3
4define i1 @oeq_self(double %arg) {
5; CHECK-LABEL: @oeq_self(
6; CHECK-NEXT:    [[TMP:%.*]] = fcmp ord double [[ARG:%.*]], 0.000000e+00
7; CHECK-NEXT:    ret i1 [[TMP]]
8;
9  %tmp = fcmp oeq double %arg, %arg
10  ret i1 %tmp
11}
12
13; PR1111 - https://bugs.llvm.org/show_bug.cgi?id=1111
14
15define i1 @une_self(double %x) {
16; CHECK-LABEL: @une_self(
17; CHECK-NEXT:    [[TMP:%.*]] = fcmp uno double [[X:%.*]], 0.000000e+00
18; CHECK-NEXT:    ret i1 [[TMP]]
19;
20  %tmp = fcmp une double %x, %x
21  ret i1 %tmp
22}
23
24; When just checking for a NaN (ORD/UNO), canonicalize constants.
25; Float/double are alternated for additional coverage.
26
27define i1 @ord_zero(float %x) {
28; CHECK-LABEL: @ord_zero(
29; CHECK-NEXT:    [[F:%.*]] = fcmp ord float [[X:%.*]], 0.000000e+00
30; CHECK-NEXT:    ret i1 [[F]]
31;
32  %f = fcmp ord float %x, 0.0
33  ret i1 %f
34}
35
36define i1 @ord_nonzero(double %x) {
37; CHECK-LABEL: @ord_nonzero(
38; CHECK-NEXT:    [[F:%.*]] = fcmp ord double [[X:%.*]], 0.000000e+00
39; CHECK-NEXT:    ret i1 [[F]]
40;
41  %f = fcmp ord double %x, 3.0
42  ret i1 %f
43}
44
45define i1 @ord_self(float %x) {
46; CHECK-LABEL: @ord_self(
47; CHECK-NEXT:    [[F:%.*]] = fcmp ord float [[X:%.*]], 0.000000e+00
48; CHECK-NEXT:    ret i1 [[F]]
49;
50  %f = fcmp ord float %x, %x
51  ret i1 %f
52}
53
54define i1 @uno_zero(double %x) {
55; CHECK-LABEL: @uno_zero(
56; CHECK-NEXT:    [[F:%.*]] = fcmp uno double [[X:%.*]], 0.000000e+00
57; CHECK-NEXT:    ret i1 [[F]]
58;
59  %f = fcmp uno double %x, 0.0
60  ret i1 %f
61}
62
63define i1 @uno_nonzero(float %x) {
64; CHECK-LABEL: @uno_nonzero(
65; CHECK-NEXT:    [[F:%.*]] = fcmp uno float [[X:%.*]], 0.000000e+00
66; CHECK-NEXT:    ret i1 [[F]]
67;
68  %f = fcmp uno float %x, 3.0
69  ret i1 %f
70}
71
72define i1 @uno_self(double %x) {
73; CHECK-LABEL: @uno_self(
74; CHECK-NEXT:    [[F:%.*]] = fcmp uno double [[X:%.*]], 0.000000e+00
75; CHECK-NEXT:    ret i1 [[F]]
76;
77  %f = fcmp uno double %x, %x
78  ret i1 %f
79}
80
81define <2 x i1> @ord_zero_vec(<2 x double> %x) {
82; CHECK-LABEL: @ord_zero_vec(
83; CHECK-NEXT:    [[F:%.*]] = fcmp ord <2 x double> [[X:%.*]], zeroinitializer
84; CHECK-NEXT:    ret <2 x i1> [[F]]
85;
86  %f = fcmp ord <2 x double> %x, zeroinitializer
87  ret <2 x i1> %f
88}
89
90define <2 x i1> @ord_nonzero_vec(<2 x float> %x) {
91; CHECK-LABEL: @ord_nonzero_vec(
92; CHECK-NEXT:    [[F:%.*]] = fcmp ord <2 x float> [[X:%.*]], zeroinitializer
93; CHECK-NEXT:    ret <2 x i1> [[F]]
94;
95  %f = fcmp ord <2 x float> %x, <float 3.0, float 5.0>
96  ret <2 x i1> %f
97}
98
99define <2 x i1> @ord_self_vec(<2 x double> %x) {
100; CHECK-LABEL: @ord_self_vec(
101; CHECK-NEXT:    [[F:%.*]] = fcmp ord <2 x double> [[X:%.*]], zeroinitializer
102; CHECK-NEXT:    ret <2 x i1> [[F]]
103;
104  %f = fcmp ord <2 x double> %x, %x
105  ret <2 x i1> %f
106}
107
108define <2 x i1> @uno_zero_vec(<2 x float> %x) {
109; CHECK-LABEL: @uno_zero_vec(
110; CHECK-NEXT:    [[F:%.*]] = fcmp uno <2 x float> [[X:%.*]], zeroinitializer
111; CHECK-NEXT:    ret <2 x i1> [[F]]
112;
113  %f = fcmp uno <2 x float> %x, zeroinitializer
114  ret <2 x i1> %f
115}
116
117define <2 x i1> @uno_nonzero_vec(<2 x double> %x) {
118; CHECK-LABEL: @uno_nonzero_vec(
119; CHECK-NEXT:    [[F:%.*]] = fcmp uno <2 x double> [[X:%.*]], zeroinitializer
120; CHECK-NEXT:    ret <2 x i1> [[F]]
121;
122  %f = fcmp uno <2 x double> %x, <double 3.0, double 5.0>
123  ret <2 x i1> %f
124}
125
126define <2 x i1> @uno_self_vec(<2 x float> %x) {
127; CHECK-LABEL: @uno_self_vec(
128; CHECK-NEXT:    [[F:%.*]] = fcmp uno <2 x float> [[X:%.*]], zeroinitializer
129; CHECK-NEXT:    ret <2 x i1> [[F]]
130;
131  %f = fcmp uno <2 x float> %x, %x
132  ret <2 x i1> %f
133}
134
135; If a scalar constant is NaN in any of the above tests, it would have been eliminated by InstSimplify.
136; If a vector has a NaN element, we don't do anything with it.
137
138define <2 x i1> @uno_vec_with_nan(<2 x double> %x) {
139; CHECK-LABEL: @uno_vec_with_nan(
140; CHECK-NEXT:    [[F:%.*]] = fcmp uno <2 x double> [[X:%.*]], <double 3.000000e+00, double 0x7FF00000FFFFFFFF>
141; CHECK-NEXT:    ret <2 x i1> [[F]]
142;
143  %f = fcmp uno <2 x double> %x, <double 3.0, double 0x7FF00000FFFFFFFF>
144  ret <2 x i1> %f
145}
146
147define <2 x i1> @uno_vec_with_poison(<2 x double> %x) {
148; CHECK-LABEL: @uno_vec_with_poison(
149; CHECK-NEXT:    [[F:%.*]] = fcmp uno <2 x double> [[X:%.*]], zeroinitializer
150; CHECK-NEXT:    ret <2 x i1> [[F]]
151;
152  %f = fcmp uno <2 x double> %x, <double 3.0, double poison>
153  ret <2 x i1> %f
154}
155
156define <2 x i1> @ord_vec_with_poison(<2 x double> %x) {
157; CHECK-LABEL: @ord_vec_with_poison(
158; CHECK-NEXT:    [[F:%.*]] = fcmp ord <2 x double> [[X:%.*]], <double 0.000000e+00, double poison>
159; CHECK-NEXT:    ret <2 x i1> [[F]]
160;
161  %f = fcmp ord <2 x double> %x, <double 0.0, double poison>
162  ret <2 x i1> %f
163}
164
165; TODO: This could be handled in InstSimplify.
166
167define i1 @nnan_ops_to_fcmp_ord(float %x, float %y) {
168; CHECK-LABEL: @nnan_ops_to_fcmp_ord(
169; CHECK-NEXT:    ret i1 true
170;
171  %mul = fmul nnan float %x, %y
172  %div = fdiv nnan float %x, %y
173  %cmp = fcmp ord float %mul, %div
174  ret i1 %cmp
175}
176
177; TODO: This could be handled in InstSimplify.
178
179define i1 @nnan_ops_to_fcmp_uno(float %x, float %y) {
180; CHECK-LABEL: @nnan_ops_to_fcmp_uno(
181; CHECK-NEXT:    ret i1 false
182;
183  %mul = fmul nnan float %x, %y
184  %div = fdiv nnan float %x, %y
185  %cmp = fcmp uno float %mul, %div
186  ret i1 %cmp
187}
188
189; TODO: For any predicate/type/FMF, comparison to -0.0 is the same as comparison to +0.0.
190
191define i1 @negative_zero_oeq(float %x) {
192; CHECK-LABEL: @negative_zero_oeq(
193; CHECK-NEXT:    [[R:%.*]] = fcmp oeq float [[X:%.*]], 0.000000e+00
194; CHECK-NEXT:    ret i1 [[R]]
195;
196  %r = fcmp oeq float %x, -0.0
197  ret i1 %r
198}
199
200define i1 @negative_zero_oge(double %x) {
201; CHECK-LABEL: @negative_zero_oge(
202; CHECK-NEXT:    [[R:%.*]] = fcmp nnan oge double [[X:%.*]], 0.000000e+00
203; CHECK-NEXT:    ret i1 [[R]]
204;
205  %r = fcmp nnan oge double %x, -0.0
206  ret i1 %r
207}
208
209define i1 @negative_zero_uge(half %x) {
210; CHECK-LABEL: @negative_zero_uge(
211; CHECK-NEXT:    [[R:%.*]] = fcmp fast uge half [[X:%.*]], 0xH0000
212; CHECK-NEXT:    ret i1 [[R]]
213;
214  %r = fcmp fast uge half %x, -0.0
215  ret i1 %r
216}
217
218define <2 x i1> @negative_zero_olt_vec(<2 x float> %x) {
219; CHECK-LABEL: @negative_zero_olt_vec(
220; CHECK-NEXT:    [[R:%.*]] = fcmp reassoc ninf olt <2 x float> [[X:%.*]], zeroinitializer
221; CHECK-NEXT:    ret <2 x i1> [[R]]
222;
223  %r = fcmp reassoc ninf olt <2 x float> %x, <float -0.0, float -0.0>
224  ret <2 x i1> %r
225}
226
227define <2 x i1> @negative_zero_une_vec_poison(<2 x double> %x) {
228; CHECK-LABEL: @negative_zero_une_vec_poison(
229; CHECK-NEXT:    [[R:%.*]] = fcmp nnan une <2 x double> [[X:%.*]], zeroinitializer
230; CHECK-NEXT:    ret <2 x i1> [[R]]
231;
232  %r = fcmp nnan une <2 x double> %x, <double -0.0, double poison>
233  ret <2 x i1> %r
234}
235
236define <2 x i1> @negative_zero_ule_vec_mixed(<2 x float> %x) {
237; CHECK-LABEL: @negative_zero_ule_vec_mixed(
238; CHECK-NEXT:    [[R:%.*]] = fcmp ule <2 x float> [[X:%.*]], zeroinitializer
239; CHECK-NEXT:    ret <2 x i1> [[R]]
240;
241  %r = fcmp ule <2 x float> %x, <float 0.0, float -0.0>
242  ret <2 x i1> %r
243}
244
245