1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -passes=instcombine %s | FileCheck %s
4 ; --------------------------------------------------------------------
5 ; (@canonicalize(x) == @canonicalize(y)) is equivalent to to (x == y)
6 ; --------------------------------------------------------------------
8 define i1 @canonicalize_oeq_canonicalize_f32(float %x, float %y) {
9 ; CHECK-LABEL: @canonicalize_oeq_canonicalize_f32(
10 ; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[X:%.*]], [[Y:%.*]]
11 ; CHECK-NEXT: ret i1 [[CMP]]
13 %canon.x = call float @llvm.canonicalize.f32(float %x)
14 %canon.y = call float @llvm.canonicalize.f32(float %y)
15 %cmp = fcmp oeq float %canon.x, %canon.y
19 define i1 @canonicalize_oeq_canonicalize_f32_flags(float %x, float %y) {
20 ; CHECK-LABEL: @canonicalize_oeq_canonicalize_f32_flags(
21 ; CHECK-NEXT: [[CMP:%.*]] = fcmp nsz oeq float [[X:%.*]], [[Y:%.*]]
22 ; CHECK-NEXT: ret i1 [[CMP]]
24 %canon.x = call float @llvm.canonicalize.f32(float %x)
25 %canon.y = call float @llvm.canonicalize.f32(float %y)
26 %cmp = fcmp nsz oeq float %canon.x, %canon.y
30 define <2 x i1> @canonicalize_oeq_canonicalize_v2f32(<2 x float> %x, <2 x float> %y) {
31 ; CHECK-LABEL: @canonicalize_oeq_canonicalize_v2f32(
32 ; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq <2 x float> [[X:%.*]], [[Y:%.*]]
33 ; CHECK-NEXT: ret <2 x i1> [[CMP]]
35 %canon.x = call <2 x float> @llvm.canonicalize.v2f32(<2 x float> %x)
36 %canon.y = call <2 x float> @llvm.canonicalize.v2f32(<2 x float> %y)
37 %cmp = fcmp oeq <2 x float> %canon.x, %canon.y
41 define i1 @canonicalize_ueq_canonicalize_f32(float %x, float %y) {
42 ; CHECK-LABEL: @canonicalize_ueq_canonicalize_f32(
43 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ueq float [[X:%.*]], [[Y:%.*]]
44 ; CHECK-NEXT: ret i1 [[CMP]]
46 %canon.x = call float @llvm.canonicalize.f32(float %x)
47 %canon.y = call float @llvm.canonicalize.f32(float %y)
48 %cmp = fcmp ueq float %canon.x, %canon.y
52 define <2 x i1> @canonicalize_ueq_canonicalize_v2f32(<2 x float> %x, <2 x float> %y) {
53 ; CHECK-LABEL: @canonicalize_ueq_canonicalize_v2f32(
54 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ueq <2 x float> [[X:%.*]], [[Y:%.*]]
55 ; CHECK-NEXT: ret <2 x i1> [[CMP]]
57 %canon.x = call <2 x float> @llvm.canonicalize.v2f32(<2 x float> %x)
58 %canon.y = call <2 x float> @llvm.canonicalize.v2f32(<2 x float> %y)
59 %cmp = fcmp ueq <2 x float> %canon.x, %canon.y
63 define i1 @canonicalize_one_canonicalize_f32(float %x, float %y) {
64 ; CHECK-LABEL: @canonicalize_one_canonicalize_f32(
65 ; CHECK-NEXT: [[CMP:%.*]] = fcmp one float [[X:%.*]], [[Y:%.*]]
66 ; CHECK-NEXT: ret i1 [[CMP]]
68 %canon.x = call float @llvm.canonicalize.f32(float %x)
69 %canon.y = call float @llvm.canonicalize.f32(float %y)
70 %cmp = fcmp one float %canon.x, %canon.y
74 define <2 x i1> @canonicalize_one_canonicalize_v2f32(<2 x float> %x, <2 x float> %y) {
75 ; CHECK-LABEL: @canonicalize_one_canonicalize_v2f32(
76 ; CHECK-NEXT: [[CMP:%.*]] = fcmp one <2 x float> [[X:%.*]], [[Y:%.*]]
77 ; CHECK-NEXT: ret <2 x i1> [[CMP]]
79 %canon.x = call <2 x float> @llvm.canonicalize.v2f32(<2 x float> %x)
80 %canon.y = call <2 x float> @llvm.canonicalize.v2f32(<2 x float> %y)
81 %cmp = fcmp one <2 x float> %canon.x, %canon.y
85 define i1 @canonicalize_une_canonicalize_f32(float %x, float %y) {
86 ; CHECK-LABEL: @canonicalize_une_canonicalize_f32(
87 ; CHECK-NEXT: [[CMP:%.*]] = fcmp une float [[X:%.*]], [[Y:%.*]]
88 ; CHECK-NEXT: ret i1 [[CMP]]
90 %canon.x = call float @llvm.canonicalize.f32(float %x)
91 %canon.y = call float @llvm.canonicalize.f32(float %y)
92 %cmp = fcmp une float %canon.x, %canon.y
96 define <2 x i1> @canonicalize_une_canonicalize_v2f32(<2 x float> %x, <2 x float> %y) {
97 ; CHECK-LABEL: @canonicalize_une_canonicalize_v2f32(
98 ; CHECK-NEXT: [[CMP:%.*]] = fcmp une <2 x float> [[X:%.*]], [[Y:%.*]]
99 ; CHECK-NEXT: ret <2 x i1> [[CMP]]
101 %canon.x = call <2 x float> @llvm.canonicalize.v2f32(<2 x float> %x)
102 %canon.y = call <2 x float> @llvm.canonicalize.v2f32(<2 x float> %y)
103 %cmp = fcmp une <2 x float> %canon.x, %canon.y
107 define i1 @canonicalize_ogt_canonicalize_f32(float %x, float %y) {
108 ; CHECK-LABEL: @canonicalize_ogt_canonicalize_f32(
109 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[X:%.*]], [[Y:%.*]]
110 ; CHECK-NEXT: ret i1 [[CMP]]
112 %canon.x = call float @llvm.canonicalize.f32(float %x)
113 %canon.y = call float @llvm.canonicalize.f32(float %y)
114 %cmp = fcmp ogt float %canon.x, %canon.y
118 define i1 @canonicalize_oge_canonicalize_f32(float %x, float %y) {
119 ; CHECK-LABEL: @canonicalize_oge_canonicalize_f32(
120 ; CHECK-NEXT: [[CMP:%.*]] = fcmp oge float [[X:%.*]], [[Y:%.*]]
121 ; CHECK-NEXT: ret i1 [[CMP]]
123 %canon.x = call float @llvm.canonicalize.f32(float %x)
124 %canon.y = call float @llvm.canonicalize.f32(float %y)
125 %cmp = fcmp oge float %canon.x, %canon.y
129 define i1 @canonicalize_olt_canonicalize_f32(float %x, float %y) {
130 ; CHECK-LABEL: @canonicalize_olt_canonicalize_f32(
131 ; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[X:%.*]], [[Y:%.*]]
132 ; CHECK-NEXT: ret i1 [[CMP]]
134 %canon.x = call float @llvm.canonicalize.f32(float %x)
135 %canon.y = call float @llvm.canonicalize.f32(float %y)
136 %cmp = fcmp olt float %canon.x, %canon.y
140 define i1 @canonicalize_ole_canonicalize_f32(float %x, float %y) {
141 ; CHECK-LABEL: @canonicalize_ole_canonicalize_f32(
142 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ole float [[X:%.*]], [[Y:%.*]]
143 ; CHECK-NEXT: ret i1 [[CMP]]
145 %canon.x = call float @llvm.canonicalize.f32(float %x)
146 %canon.y = call float @llvm.canonicalize.f32(float %y)
147 %cmp = fcmp ole float %canon.x, %canon.y
151 define i1 @canonicalize_ord_canonicalize_f32(float %x, float %y) {
152 ; CHECK-LABEL: @canonicalize_ord_canonicalize_f32(
153 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ord float [[X:%.*]], [[Y:%.*]]
154 ; CHECK-NEXT: ret i1 [[CMP]]
156 %canon.x = call float @llvm.canonicalize.f32(float %x)
157 %canon.y = call float @llvm.canonicalize.f32(float %y)
158 %cmp = fcmp ord float %canon.x, %canon.y
162 define i1 @canonicalize_ugt_canonicalize_f32(float %x, float %y) {
163 ; CHECK-LABEL: @canonicalize_ugt_canonicalize_f32(
164 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ugt float [[X:%.*]], [[Y:%.*]]
165 ; CHECK-NEXT: ret i1 [[CMP]]
167 %canon.x = call float @llvm.canonicalize.f32(float %x)
168 %canon.y = call float @llvm.canonicalize.f32(float %y)
169 %cmp = fcmp ugt float %canon.x, %canon.y
173 define i1 @canonicalize_uge_canonicalize_f32(float %x, float %y) {
174 ; CHECK-LABEL: @canonicalize_uge_canonicalize_f32(
175 ; CHECK-NEXT: [[CMP:%.*]] = fcmp uge float [[X:%.*]], [[Y:%.*]]
176 ; CHECK-NEXT: ret i1 [[CMP]]
178 %canon.x = call float @llvm.canonicalize.f32(float %x)
179 %canon.y = call float @llvm.canonicalize.f32(float %y)
180 %cmp = fcmp uge float %canon.x, %canon.y
184 define i1 @canonicalize_ult_canonicalize_f32(float %x, float %y) {
185 ; CHECK-LABEL: @canonicalize_ult_canonicalize_f32(
186 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ult float [[X:%.*]], [[Y:%.*]]
187 ; CHECK-NEXT: ret i1 [[CMP]]
189 %canon.x = call float @llvm.canonicalize.f32(float %x)
190 %canon.y = call float @llvm.canonicalize.f32(float %y)
191 %cmp = fcmp ult float %canon.x, %canon.y
195 define i1 @canonicalize_ule_canonicalize_f32(float %x, float %y) {
196 ; CHECK-LABEL: @canonicalize_ule_canonicalize_f32(
197 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ule float [[X:%.*]], [[Y:%.*]]
198 ; CHECK-NEXT: ret i1 [[CMP]]
200 %canon.x = call float @llvm.canonicalize.f32(float %x)
201 %canon.y = call float @llvm.canonicalize.f32(float %y)
202 %cmp = fcmp ule float %canon.x, %canon.y
206 define i1 @canonicalize_uno_canonicalize_f32(float %x, float %y) {
207 ; CHECK-LABEL: @canonicalize_uno_canonicalize_f32(
208 ; CHECK-NEXT: [[CMP:%.*]] = fcmp uno float [[X:%.*]], [[Y:%.*]]
209 ; CHECK-NEXT: ret i1 [[CMP]]
211 %canon.x = call float @llvm.canonicalize.f32(float %x)
212 %canon.y = call float @llvm.canonicalize.f32(float %y)
213 %cmp = fcmp uno float %canon.x, %canon.y
217 define i1 @canonicalize_oeq_y_f32() {
218 ; CHECK-LABEL: @canonicalize_oeq_y_f32(
219 ; CHECK-NEXT: [[X:%.*]] = call float @gen_f32()
220 ; CHECK-NEXT: [[Y:%.*]] = call float @gen_f32()
221 ; CHECK-NEXT: [[CANON_X:%.*]] = call float @llvm.canonicalize.f32(float [[X]])
222 ; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[CANON_X]], [[Y]]
223 ; CHECK-NEXT: ret i1 [[CMP]]
225 %x = call float @gen_f32()
226 %y = call float @gen_f32()
227 %canon.x = call float @llvm.canonicalize.f32(float %x)
228 %cmp = fcmp oeq float %canon.x, %y
232 define i1 @canonicalize_oeq_y_commute_f32() {
233 ; CHECK-LABEL: @canonicalize_oeq_y_commute_f32(
234 ; CHECK-NEXT: [[X:%.*]] = call float @gen_f32()
235 ; CHECK-NEXT: [[Y:%.*]] = call float @gen_f32()
236 ; CHECK-NEXT: [[CANON_Y:%.*]] = call float @llvm.canonicalize.f32(float [[Y]])
237 ; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq float [[X]], [[CANON_Y]]
238 ; CHECK-NEXT: ret i1 [[CMP]]
240 %x = call float @gen_f32()
241 %y = call float @gen_f32()
242 %canon.y = call float @llvm.canonicalize.f32(float %y)
243 %cmp = fcmp oeq float %x, %canon.y
247 ; --------------------------------------------------------------------
248 ; (@canonicalize(x) == x) is equivalent to (x == x)
249 ; --------------------------------------------------------------------
251 define i1 @canonicalize_oeq_arg_f32(float %x) {
252 ; CHECK-LABEL: @canonicalize_oeq_arg_f32(
253 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ord float [[X:%.*]], 0.000000e+00
254 ; CHECK-NEXT: ret i1 [[CMP]]
256 %canon.x = call float @llvm.canonicalize.f32(float %x)
257 %cmp = fcmp oeq float %canon.x, %x
261 define i1 @canonicalize_oeq_arg_f32_flags(float %x) {
262 ; CHECK-LABEL: @canonicalize_oeq_arg_f32_flags(
263 ; CHECK-NEXT: [[CMP:%.*]] = fcmp nsz ord float [[X:%.*]], 0.000000e+00
264 ; CHECK-NEXT: ret i1 [[CMP]]
266 %canon.x = call float @llvm.canonicalize.f32(float %x)
267 %cmp = fcmp nsz oeq float %canon.x, %x
271 declare float @gen_f32()
272 declare <2 x float> @gen_v2f32()
274 define i1 @canonicalize_oeq_arg_f32_commute() {
275 ; CHECK-LABEL: @canonicalize_oeq_arg_f32_commute(
276 ; CHECK-NEXT: [[X:%.*]] = call float @gen_f32()
277 ; CHECK-NEXT: [[CMP:%.*]] = fcmp nsz ord float [[X]], 0.000000e+00
278 ; CHECK-NEXT: ret i1 [[CMP]]
280 %x = call float @gen_f32() ; thwart complexity-based canonicalization
281 %canon.x = call float @llvm.canonicalize.f32(float %x)
282 %cmp = fcmp nsz oeq float %x, %canon.x
286 define <2 x i1> @canonicalize_oeq_arg_v2f32(<2 x float> %x) {
287 ; CHECK-LABEL: @canonicalize_oeq_arg_v2f32(
288 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ord <2 x float> [[X:%.*]], zeroinitializer
289 ; CHECK-NEXT: ret <2 x i1> [[CMP]]
291 %canon.x = call <2 x float> @llvm.canonicalize.v2f32(<2 x float> %x)
292 %cmp = fcmp oeq <2 x float> %canon.x, %x
296 define <2 x i1> @canonicalize_oeq_arg_v2f32_commute() {
297 ; CHECK-LABEL: @canonicalize_oeq_arg_v2f32_commute(
298 ; CHECK-NEXT: [[X:%.*]] = call <2 x float> @gen_v2f32()
299 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ord <2 x float> [[X]], zeroinitializer
300 ; CHECK-NEXT: ret <2 x i1> [[CMP]]
302 %x = call <2 x float> @gen_v2f32() ; thwart complexity-based canonicalization
303 %canon.x = call <2 x float> @llvm.canonicalize.v2f32(<2 x float> %x)
304 %cmp = fcmp oeq <2 x float> %x, %canon.x
308 define i1 @canonicalize_ueq_arg_f32(float %x) {
309 ; CHECK-LABEL: @canonicalize_ueq_arg_f32(
310 ; CHECK-NEXT: ret i1 true
312 %canon.x = call float @llvm.canonicalize.f32(float %x)
313 %cmp = fcmp ueq float %canon.x, %x
317 define <2 x i1> @canonicalize_ueq_arg_v2f32(<2 x float> %x) {
318 ; CHECK-LABEL: @canonicalize_ueq_arg_v2f32(
319 ; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
321 %canon.x = call <2 x float> @llvm.canonicalize.v2f32(<2 x float> %x)
322 %cmp = fcmp ueq <2 x float> %canon.x, %x
326 define i1 @canonicalize_one_arg_f32(float %x) {
327 ; CHECK-LABEL: @canonicalize_one_arg_f32(
328 ; CHECK-NEXT: ret i1 false
330 %canon.x = call float @llvm.canonicalize.f32(float %x)
331 %cmp = fcmp one float %canon.x, %x
335 define <2 x i1> @canonicalize_one_arg_v2f32(<2 x float> %x) {
336 ; CHECK-LABEL: @canonicalize_one_arg_v2f32(
337 ; CHECK-NEXT: ret <2 x i1> zeroinitializer
339 %canon.x = call <2 x float> @llvm.canonicalize.v2f32(<2 x float> %x)
340 %cmp = fcmp one <2 x float> %canon.x, %x
344 define i1 @canonicalize_une_arg_f32(float %x) {
345 ; CHECK-LABEL: @canonicalize_une_arg_f32(
346 ; CHECK-NEXT: [[CMP:%.*]] = fcmp uno float [[X:%.*]], 0.000000e+00
347 ; CHECK-NEXT: ret i1 [[CMP]]
349 %canon.x = call float @llvm.canonicalize.f32(float %x)
350 %cmp = fcmp une float %canon.x, %x
354 define <2 x i1> @canonicalize_une_arg_v2f32(<2 x float> %x) {
355 ; CHECK-LABEL: @canonicalize_une_arg_v2f32(
356 ; CHECK-NEXT: [[CMP:%.*]] = fcmp uno <2 x float> [[X:%.*]], zeroinitializer
357 ; CHECK-NEXT: ret <2 x i1> [[CMP]]
359 %canon.x = call <2 x float> @llvm.canonicalize.v2f32(<2 x float> %x)
360 %cmp = fcmp une <2 x float> %canon.x, %x
364 define i1 @canonicalize_ogt_arg_f32(float %x) {
365 ; CHECK-LABEL: @canonicalize_ogt_arg_f32(
366 ; CHECK-NEXT: ret i1 false
368 %canon.x = call float @llvm.canonicalize.f32(float %x)
369 %cmp = fcmp ogt float %canon.x, %x
373 define i1 @canonicalize_oge_arg_f32(float %x) {
374 ; CHECK-LABEL: @canonicalize_oge_arg_f32(
375 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ord float [[X:%.*]], 0.000000e+00
376 ; CHECK-NEXT: ret i1 [[CMP]]
378 %canon.x = call float @llvm.canonicalize.f32(float %x)
379 %cmp = fcmp oge float %canon.x, %x
383 define i1 @canonicalize_olt_arg_f32(float %x) {
384 ; CHECK-LABEL: @canonicalize_olt_arg_f32(
385 ; CHECK-NEXT: ret i1 false
387 %canon.x = call float @llvm.canonicalize.f32(float %x)
388 %cmp = fcmp olt float %canon.x, %x
392 define i1 @canonicalize_ole_arg_f32(float %x) {
393 ; CHECK-LABEL: @canonicalize_ole_arg_f32(
394 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ord float [[X:%.*]], 0.000000e+00
395 ; CHECK-NEXT: ret i1 [[CMP]]
397 %canon.x = call float @llvm.canonicalize.f32(float %x)
398 %cmp = fcmp ole float %canon.x, %x
402 define i1 @canonicalize_ord_arg_f32(float %x) {
403 ; CHECK-LABEL: @canonicalize_ord_arg_f32(
404 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ord float [[X:%.*]], 0.000000e+00
405 ; CHECK-NEXT: ret i1 [[CMP]]
407 %canon.x = call float @llvm.canonicalize.f32(float %x)
408 %cmp = fcmp ord float %canon.x, %x
412 define i1 @canonicalize_ugt_arg_f32(float %x) {
413 ; CHECK-LABEL: @canonicalize_ugt_arg_f32(
414 ; CHECK-NEXT: [[CMP:%.*]] = fcmp uno float [[X:%.*]], 0.000000e+00
415 ; CHECK-NEXT: ret i1 [[CMP]]
417 %canon.x = call float @llvm.canonicalize.f32(float %x)
418 %cmp = fcmp ugt float %canon.x, %x
422 define i1 @canonicalize_uge_arg_f32(float %x) {
423 ; CHECK-LABEL: @canonicalize_uge_arg_f32(
424 ; CHECK-NEXT: ret i1 true
426 %canon.x = call float @llvm.canonicalize.f32(float %x)
427 %cmp = fcmp uge float %canon.x, %x
431 define i1 @canonicalize_ult_arg_f32(float %x) {
432 ; CHECK-LABEL: @canonicalize_ult_arg_f32(
433 ; CHECK-NEXT: [[CMP:%.*]] = fcmp uno float [[X:%.*]], 0.000000e+00
434 ; CHECK-NEXT: ret i1 [[CMP]]
436 %canon.x = call float @llvm.canonicalize.f32(float %x)
437 %cmp = fcmp ult float %canon.x, %x
441 define i1 @canonicalize_ule_arg_f32(float %x) {
442 ; CHECK-LABEL: @canonicalize_ule_arg_f32(
443 ; CHECK-NEXT: ret i1 true
445 %canon.x = call float @llvm.canonicalize.f32(float %x)
446 %cmp = fcmp ule float %canon.x, %x
450 define i1 @canonicalize_uno_arg_f32(float %x) {
451 ; CHECK-LABEL: @canonicalize_uno_arg_f32(
452 ; CHECK-NEXT: [[CMP:%.*]] = fcmp uno float [[X:%.*]], 0.000000e+00
453 ; CHECK-NEXT: ret i1 [[CMP]]
455 %canon.x = call float @llvm.canonicalize.f32(float %x)
456 %cmp = fcmp uno float %canon.x, %x
460 ; --------------------------------------------------------------------
462 ; --------------------------------------------------------------------
464 ; Regression test checking that the vector version of llvm.canonicalize works.
465 define <2 x i1> @vec_canonicalize_with_fpclass(<2 x float> %x) {
466 ; CHECK-LABEL: @vec_canonicalize_with_fpclass(
467 ; CHECK-NEXT: ret <2 x i1> zeroinitializer
469 %canon = call <2 x float> @llvm.canonicalize.v2f32(<2 x float> %x)
470 %fpclass = call <2 x i1> @llvm.is.fpclass.v2f32(<2 x float> %canon, i32 1)
471 ret <2 x i1> %fpclass
474 declare float @llvm.canonicalize.f32(float)
475 declare <2 x float> @llvm.canonicalize.v2f32(<2 x float>)
476 declare <2 x i1> @llvm.is.fpclass.v2f32(<2 x float>, i32 immarg)