1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -S -early-cse -earlycse-debug-hash | FileCheck %s
3 ; RUN: opt < %s -S -basicaa -early-cse-memssa | FileCheck %s
5 define void @test1(float %A, float %B, float* %PA, float* %PB) {
7 ; CHECK-NEXT: [[C:%.*]] = fadd float [[A:%.*]], [[B:%.*]]
8 ; CHECK-NEXT: store float [[C]], float* [[PA:%.*]]
9 ; CHECK-NEXT: store float [[C]], float* [[PB:%.*]]
10 ; CHECK-NEXT: ret void
12 %C = fadd float %A, %B
13 store float %C, float* %PA
14 %D = fadd float %B, %A
15 store float %D, float* %PB
19 define void @test2(float %A, float %B, i1* %PA, i1* %PB) {
20 ; CHECK-LABEL: @test2(
21 ; CHECK-NEXT: [[C:%.*]] = fcmp oeq float [[A:%.*]], [[B:%.*]]
22 ; CHECK-NEXT: store i1 [[C]], i1* [[PA:%.*]]
23 ; CHECK-NEXT: store i1 [[C]], i1* [[PB:%.*]]
24 ; CHECK-NEXT: ret void
26 %C = fcmp oeq float %A, %B
28 %D = fcmp oeq float %B, %A
33 define void @test3(float %A, float %B, i1* %PA, i1* %PB) {
34 ; CHECK-LABEL: @test3(
35 ; CHECK-NEXT: [[C:%.*]] = fcmp uge float [[A:%.*]], [[B:%.*]]
36 ; CHECK-NEXT: store i1 [[C]], i1* [[PA:%.*]]
37 ; CHECK-NEXT: store i1 [[C]], i1* [[PB:%.*]]
38 ; CHECK-NEXT: ret void
40 %C = fcmp uge float %A, %B
42 %D = fcmp ule float %B, %A
47 define void @test4(i32 %A, i32 %B, i1* %PA, i1* %PB) {
48 ; CHECK-LABEL: @test4(
49 ; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
50 ; CHECK-NEXT: store i1 [[C]], i1* [[PA:%.*]]
51 ; CHECK-NEXT: store i1 [[C]], i1* [[PB:%.*]]
52 ; CHECK-NEXT: ret void
54 %C = icmp eq i32 %A, %B
56 %D = icmp eq i32 %B, %A
61 define void @test5(i32 %A, i32 %B, i1* %PA, i1* %PB) {
62 ; CHECK-LABEL: @test5(
63 ; CHECK-NEXT: [[C:%.*]] = icmp sgt i32 [[A:%.*]], [[B:%.*]]
64 ; CHECK-NEXT: store i1 [[C]], i1* [[PA:%.*]]
65 ; CHECK-NEXT: store i1 [[C]], i1* [[PB:%.*]]
66 ; CHECK-NEXT: ret void
68 %C = icmp sgt i32 %A, %B
70 %D = icmp slt i32 %B, %A
75 ; Test degenerate case of commuted compare of identical comparands.
77 define void @test6(float %f, i1* %p1, i1* %p2) {
78 ; CHECK-LABEL: @test6(
79 ; CHECK-NEXT: [[C1:%.*]] = fcmp ult float [[F:%.*]], [[F]]
80 ; CHECK-NEXT: store i1 [[C1]], i1* [[P1:%.*]]
81 ; CHECK-NEXT: store i1 [[C1]], i1* [[P2:%.*]]
82 ; CHECK-NEXT: ret void
84 %c1 = fcmp ult float %f, %f
85 %c2 = fcmp ugt float %f, %f
91 ; Min/max operands may be commuted in the compare and select.
93 define i8 @smin_commute(i8 %a, i8 %b) {
94 ; CHECK-LABEL: @smin_commute(
95 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i8 [[A:%.*]], [[B:%.*]]
96 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i8 [[B]], [[A]]
97 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]]
98 ; CHECK-NEXT: [[R:%.*]] = mul i8 [[M1]], [[M1]]
99 ; CHECK-NEXT: ret i8 [[R]]
101 %cmp1 = icmp slt i8 %a, %b
102 %cmp2 = icmp slt i8 %b, %a
103 %m1 = select i1 %cmp1, i8 %a, i8 %b
104 %m2 = select i1 %cmp2, i8 %b, i8 %a
109 ; Min/max can also have a swapped predicate and select operands.
111 define i1 @smin_swapped(i8 %a, i8 %b) {
112 ; CHECK-LABEL: @smin_swapped(
113 ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i8 [[A:%.*]], [[B:%.*]]
114 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i8 [[A]], [[B]]
115 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[B]], i8 [[A]]
116 ; CHECK-NEXT: ret i1 true
118 %cmp1 = icmp sgt i8 %a, %b
119 %cmp2 = icmp slt i8 %a, %b
120 %m1 = select i1 %cmp1, i8 %b, i8 %a
121 %m2 = select i1 %cmp2, i8 %a, i8 %b
122 %r = icmp eq i8 %m2, %m1
126 ; Min/max can also have an inverted predicate and select operands.
128 define i1 @smin_inverted(i8 %a, i8 %b) {
129 ; CHECK-LABEL: @smin_inverted(
130 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i8 [[A:%.*]], [[B:%.*]]
131 ; CHECK-NEXT: [[CMP2:%.*]] = xor i1 [[CMP1]], true
132 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]]
133 ; CHECK-NEXT: ret i1 true
135 %cmp1 = icmp slt i8 %a, %b
136 %cmp2 = xor i1 %cmp1, -1
137 %m1 = select i1 %cmp1, i8 %a, i8 %b
138 %m2 = select i1 %cmp2, i8 %b, i8 %a
139 %r = icmp eq i8 %m1, %m2
143 define i8 @smax_commute(i8 %a, i8 %b) {
144 ; CHECK-LABEL: @smax_commute(
145 ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i8 [[A:%.*]], [[B:%.*]]
146 ; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i8 [[B]], [[A]]
147 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]]
148 ; CHECK-NEXT: ret i8 0
150 %cmp1 = icmp sgt i8 %a, %b
151 %cmp2 = icmp sgt i8 %b, %a
152 %m1 = select i1 %cmp1, i8 %a, i8 %b
153 %m2 = select i1 %cmp2, i8 %b, i8 %a
154 %r = urem i8 %m2, %m1
158 define i8 @smax_swapped(i8 %a, i8 %b) {
159 ; CHECK-LABEL: @smax_swapped(
160 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i8 [[A:%.*]], [[B:%.*]]
161 ; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i8 [[A]], [[B]]
162 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[B]], i8 [[A]]
163 ; CHECK-NEXT: ret i8 1
165 %cmp1 = icmp slt i8 %a, %b
166 %cmp2 = icmp sgt i8 %a, %b
167 %m1 = select i1 %cmp1, i8 %b, i8 %a
168 %m2 = select i1 %cmp2, i8 %a, i8 %b
169 %r = sdiv i8 %m1, %m2
173 define i1 @smax_inverted(i8 %a, i8 %b) {
174 ; CHECK-LABEL: @smax_inverted(
175 ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i8 [[A:%.*]], [[B:%.*]]
176 ; CHECK-NEXT: [[CMP2:%.*]] = xor i1 [[CMP1]], true
177 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]]
178 ; CHECK-NEXT: ret i1 true
180 %cmp1 = icmp sgt i8 %a, %b
181 %cmp2 = xor i1 %cmp1, -1
182 %m1 = select i1 %cmp1, i8 %a, i8 %b
183 %m2 = select i1 %cmp2, i8 %b, i8 %a
184 %r = icmp eq i8 %m1, %m2
188 define i8 @umin_commute(i8 %a, i8 %b) {
189 ; CHECK-LABEL: @umin_commute(
190 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i8 [[A:%.*]], [[B:%.*]]
191 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i8 [[B]], [[A]]
192 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]]
193 ; CHECK-NEXT: ret i8 0
195 %cmp1 = icmp ult i8 %a, %b
196 %cmp2 = icmp ult i8 %b, %a
197 %m1 = select i1 %cmp1, i8 %a, i8 %b
198 %m2 = select i1 %cmp2, i8 %b, i8 %a
203 ; Choose a vector type just to show that works.
205 define <2 x i8> @umin_swapped(<2 x i8> %a, <2 x i8> %b) {
206 ; CHECK-LABEL: @umin_swapped(
207 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt <2 x i8> [[A:%.*]], [[B:%.*]]
208 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ult <2 x i8> [[A]], [[B]]
209 ; CHECK-NEXT: [[M1:%.*]] = select <2 x i1> [[CMP1]], <2 x i8> [[B]], <2 x i8> [[A]]
210 ; CHECK-NEXT: ret <2 x i8> zeroinitializer
212 %cmp1 = icmp ugt <2 x i8> %a, %b
213 %cmp2 = icmp ult <2 x i8> %a, %b
214 %m1 = select <2 x i1> %cmp1, <2 x i8> %b, <2 x i8> %a
215 %m2 = select <2 x i1> %cmp2, <2 x i8> %a, <2 x i8> %b
216 %r = sub <2 x i8> %m2, %m1
220 define i1 @umin_inverted(i8 %a, i8 %b) {
221 ; CHECK-LABEL: @umin_inverted(
222 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i8 [[A:%.*]], [[B:%.*]]
223 ; CHECK-NEXT: [[CMP2:%.*]] = xor i1 [[CMP1]], true
224 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]]
225 ; CHECK-NEXT: ret i1 true
227 %cmp1 = icmp ult i8 %a, %b
228 %cmp2 = xor i1 %cmp1, -1
229 %m1 = select i1 %cmp1, i8 %a, i8 %b
230 %m2 = select i1 %cmp2, i8 %b, i8 %a
231 %r = icmp eq i8 %m1, %m2
235 define i8 @umax_commute(i8 %a, i8 %b) {
236 ; CHECK-LABEL: @umax_commute(
237 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i8 [[A:%.*]], [[B:%.*]]
238 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i8 [[B]], [[A]]
239 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]]
240 ; CHECK-NEXT: ret i8 1
242 %cmp1 = icmp ugt i8 %a, %b
243 %cmp2 = icmp ugt i8 %b, %a
244 %m1 = select i1 %cmp1, i8 %a, i8 %b
245 %m2 = select i1 %cmp2, i8 %b, i8 %a
246 %r = udiv i8 %m1, %m2
250 define i8 @umax_swapped(i8 %a, i8 %b) {
251 ; CHECK-LABEL: @umax_swapped(
252 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i8 [[A:%.*]], [[B:%.*]]
253 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i8 [[A]], [[B]]
254 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[B]], i8 [[A]]
255 ; CHECK-NEXT: [[R:%.*]] = add i8 [[M1]], [[M1]]
256 ; CHECK-NEXT: ret i8 [[R]]
258 %cmp1 = icmp ult i8 %a, %b
259 %cmp2 = icmp ugt i8 %a, %b
260 %m1 = select i1 %cmp1, i8 %b, i8 %a
261 %m2 = select i1 %cmp2, i8 %a, i8 %b
266 define i1 @umax_inverted(i8 %a, i8 %b) {
267 ; CHECK-LABEL: @umax_inverted(
268 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i8 [[A:%.*]], [[B:%.*]]
269 ; CHECK-NEXT: [[CMP2:%.*]] = xor i1 [[CMP1]], true
270 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]]
271 ; CHECK-NEXT: ret i1 true
273 %cmp1 = icmp ugt i8 %a, %b
274 %cmp2 = xor i1 %cmp1, -1
275 %m1 = select i1 %cmp1, i8 %a, i8 %b
276 %m2 = select i1 %cmp2, i8 %b, i8 %a
277 %r = icmp eq i8 %m1, %m2
281 ; Min/max may exist with non-canonical operands. Value tracking can match those.
283 define i8 @smax_nsw(i8 %a, i8 %b) {
284 ; CHECK-LABEL: @smax_nsw(
285 ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i8 [[A:%.*]], [[B:%.*]]
286 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i8 [[A]], [[B]]
287 ; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i8 [[SUB]], 0
288 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 0, i8 [[SUB]]
289 ; CHECK-NEXT: ret i8 0
291 %sub = sub nsw i8 %a, %b
292 %cmp1 = icmp slt i8 %a, %b
293 %cmp2 = icmp sgt i8 %sub, 0
294 %m1 = select i1 %cmp1, i8 0, i8 %sub
295 %m2 = select i1 %cmp2, i8 %sub, i8 0
300 define i8 @abs_swapped(i8 %a) {
301 ; CHECK-LABEL: @abs_swapped(
302 ; CHECK-NEXT: [[NEG:%.*]] = sub i8 0, [[A:%.*]]
303 ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i8 [[A]], 0
304 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i8 [[A]], 0
305 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[NEG]]
306 ; CHECK-NEXT: ret i8 [[M1]]
309 %cmp1 = icmp sgt i8 %a, 0
310 %cmp2 = icmp slt i8 %a, 0
311 %m1 = select i1 %cmp1, i8 %a, i8 %neg
312 %m2 = select i1 %cmp2, i8 %neg, i8 %a
317 define i8 @abs_inverted(i8 %a) {
318 ; CHECK-LABEL: @abs_inverted(
319 ; CHECK-NEXT: [[NEG:%.*]] = sub i8 0, [[A:%.*]]
320 ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i8 [[A]], 0
321 ; CHECK-NEXT: [[CMP2:%.*]] = xor i1 [[CMP1]], true
322 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[NEG]]
323 ; CHECK-NEXT: ret i8 [[M1]]
326 %cmp1 = icmp sgt i8 %a, 0
327 %cmp2 = xor i1 %cmp1, -1
328 %m1 = select i1 %cmp1, i8 %a, i8 %neg
329 %m2 = select i1 %cmp2, i8 %neg, i8 %a
334 define i8 @nabs_swapped(i8 %a) {
335 ; CHECK-LABEL: @nabs_swapped(
336 ; CHECK-NEXT: [[NEG:%.*]] = sub i8 0, [[A:%.*]]
337 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i8 [[A]], 0
338 ; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i8 [[A]], 0
339 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[NEG]]
340 ; CHECK-NEXT: ret i8 0
343 %cmp1 = icmp slt i8 %a, 0
344 %cmp2 = icmp sgt i8 %a, 0
345 %m1 = select i1 %cmp1, i8 %a, i8 %neg
346 %m2 = select i1 %cmp2, i8 %neg, i8 %a
351 define i8 @nabs_inverted(i8 %a) {
352 ; CHECK-LABEL: @nabs_inverted(
353 ; CHECK-NEXT: [[NEG:%.*]] = sub i8 0, [[A:%.*]]
354 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i8 [[A]], 0
355 ; CHECK-NEXT: [[CMP2:%.*]] = xor i1 [[CMP1]], true
356 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[NEG]]
357 ; CHECK-NEXT: ret i8 0
360 %cmp1 = icmp slt i8 %a, 0
361 %cmp2 = xor i1 %cmp1, -1
362 %m1 = select i1 %cmp1, i8 %a, i8 %neg
363 %m2 = select i1 %cmp2, i8 %neg, i8 %a
368 ; These two tests make sure we still consider it a match when the RHS of the
369 ; compares are different.
370 define i8 @abs_different_constants(i8 %a) {
371 ; CHECK-LABEL: @abs_different_constants(
372 ; CHECK-NEXT: [[NEG:%.*]] = sub i8 0, [[A:%.*]]
373 ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i8 [[A]], -1
374 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i8 [[A]], 0
375 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[NEG]]
376 ; CHECK-NEXT: ret i8 [[M1]]
379 %cmp1 = icmp sgt i8 %a, -1
380 %cmp2 = icmp slt i8 %a, 0
381 %m1 = select i1 %cmp1, i8 %a, i8 %neg
382 %m2 = select i1 %cmp2, i8 %neg, i8 %a
387 define i8 @nabs_different_constants(i8 %a) {
388 ; CHECK-LABEL: @nabs_different_constants(
389 ; CHECK-NEXT: [[NEG:%.*]] = sub i8 0, [[A:%.*]]
390 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i8 [[A]], 0
391 ; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i8 [[A]], -1
392 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[NEG]]
393 ; CHECK-NEXT: ret i8 0
396 %cmp1 = icmp slt i8 %a, 0
397 %cmp2 = icmp sgt i8 %a, -1
398 %m1 = select i1 %cmp1, i8 %a, i8 %neg
399 %m2 = select i1 %cmp2, i8 %neg, i8 %a
404 ; https://bugs.llvm.org/show_bug.cgi?id=41101
405 ; Detect equivalence of selects with commuted operands: 'not' cond.
407 define i32 @select_not_cond(i1 %cond, i32 %t, i32 %f) {
408 ; CHECK-LABEL: @select_not_cond(
409 ; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[COND:%.*]], true
410 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]]
411 ; CHECK-NEXT: ret i32 0
413 %not = xor i1 %cond, -1
414 %m1 = select i1 %cond, i32 %t, i32 %f
415 %m2 = select i1 %not, i32 %f, i32 %t
416 %r = xor i32 %m2, %m1
420 ; Detect equivalence of selects with commuted operands: 'not' cond with vector select.
422 define <2 x double> @select_not_cond_commute_vec(<2 x i1> %cond, <2 x double> %t, <2 x double> %f) {
423 ; CHECK-LABEL: @select_not_cond_commute_vec(
424 ; CHECK-NEXT: [[NOT:%.*]] = xor <2 x i1> [[COND:%.*]], <i1 true, i1 true>
425 ; CHECK-NEXT: [[M1:%.*]] = select <2 x i1> [[COND]], <2 x double> [[T:%.*]], <2 x double> [[F:%.*]]
426 ; CHECK-NEXT: ret <2 x double> <double 1.000000e+00, double 1.000000e+00>
428 %not = xor <2 x i1> %cond, <i1 -1, i1 -1>
429 %m1 = select <2 x i1> %cond, <2 x double> %t, <2 x double> %f
430 %m2 = select <2 x i1> %not, <2 x double> %f, <2 x double> %t
431 %r = fdiv nnan <2 x double> %m1, %m2
435 ; Negative test - select ops must be commuted.
437 define i32 @select_not_cond_wrong_select_ops(i1 %cond, i32 %t, i32 %f) {
438 ; CHECK-LABEL: @select_not_cond_wrong_select_ops(
439 ; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[COND:%.*]], true
440 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]]
441 ; CHECK-NEXT: [[M2:%.*]] = select i1 [[NOT]], i32 [[T]], i32 [[F]]
442 ; CHECK-NEXT: [[R:%.*]] = xor i32 [[M2]], [[M1]]
443 ; CHECK-NEXT: ret i32 [[R]]
445 %not = xor i1 %cond, -1
446 %m1 = select i1 %cond, i32 %t, i32 %f
447 %m2 = select i1 %not, i32 %t, i32 %f
448 %r = xor i32 %m2, %m1
452 ; Negative test - not a 'not'.
454 define i32 @select_not_cond_wrong_cond(i1 %cond, i32 %t, i32 %f) {
455 ; CHECK-LABEL: @select_not_cond_wrong_cond(
456 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND:%.*]], i32 [[T:%.*]], i32 [[F:%.*]]
457 ; CHECK-NEXT: [[M2:%.*]] = select i1 [[COND]], i32 [[F]], i32 [[T]]
458 ; CHECK-NEXT: [[R:%.*]] = xor i32 [[M2]], [[M1]]
459 ; CHECK-NEXT: ret i32 [[R]]
461 %not = xor i1 %cond, -2
462 %m1 = select i1 %cond, i32 %t, i32 %f
463 %m2 = select i1 %not, i32 %f, i32 %t
464 %r = xor i32 %m2, %m1
468 ; Detect equivalence of selects with commuted operands: inverted pred with fcmps.
470 define i32 @select_invert_pred_cond(float %x, i32 %t, i32 %f) {
471 ; CHECK-LABEL: @select_invert_pred_cond(
472 ; CHECK-NEXT: [[COND:%.*]] = fcmp ueq float [[X:%.*]], 4.200000e+01
473 ; CHECK-NEXT: [[INVCOND:%.*]] = fcmp one float [[X]], 4.200000e+01
474 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]]
475 ; CHECK-NEXT: ret i32 0
477 %cond = fcmp ueq float %x, 42.0
478 %invcond = fcmp one float %x, 42.0
479 %m1 = select i1 %cond, i32 %t, i32 %f
480 %m2 = select i1 %invcond, i32 %f, i32 %t
481 %r = xor i32 %m2, %m1
485 ; Detect equivalence of selects with commuted operands: inverted pred with icmps and vectors.
487 define <2 x i32> @select_invert_pred_cond_commute_vec(<2 x i8> %x, <2 x i32> %t, <2 x i32> %f) {
488 ; CHECK-LABEL: @select_invert_pred_cond_commute_vec(
489 ; CHECK-NEXT: [[COND:%.*]] = icmp sgt <2 x i8> [[X:%.*]], <i8 42, i8 -1>
490 ; CHECK-NEXT: [[INVCOND:%.*]] = icmp sle <2 x i8> [[X]], <i8 42, i8 -1>
491 ; CHECK-NEXT: [[M1:%.*]] = select <2 x i1> [[COND]], <2 x i32> [[T:%.*]], <2 x i32> [[F:%.*]]
492 ; CHECK-NEXT: ret <2 x i32> zeroinitializer
494 %cond = icmp sgt <2 x i8> %x, <i8 42, i8 -1>
495 %invcond = icmp sle <2 x i8> %x, <i8 42, i8 -1>
496 %m1 = select <2 x i1> %cond, <2 x i32> %t, <2 x i32> %f
497 %m2 = select <2 x i1> %invcond, <2 x i32> %f, <2 x i32> %t
498 %r = xor <2 x i32> %m1, %m2
502 ; Negative test - select ops must be commuted.
504 define i32 @select_invert_pred_wrong_select_ops(float %x, i32 %t, i32 %f) {
505 ; CHECK-LABEL: @select_invert_pred_wrong_select_ops(
506 ; CHECK-NEXT: [[COND:%.*]] = fcmp ueq float [[X:%.*]], 4.200000e+01
507 ; CHECK-NEXT: [[INVCOND:%.*]] = fcmp one float [[X]], 4.200000e+01
508 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[F:%.*]], i32 [[T:%.*]]
509 ; CHECK-NEXT: [[M2:%.*]] = select i1 [[INVCOND]], i32 [[F]], i32 [[T]]
510 ; CHECK-NEXT: [[R:%.*]] = xor i32 [[M2]], [[M1]]
511 ; CHECK-NEXT: ret i32 [[R]]
513 %cond = fcmp ueq float %x, 42.0
514 %invcond = fcmp one float %x, 42.0
515 %m1 = select i1 %cond, i32 %f, i32 %t
516 %m2 = select i1 %invcond, i32 %f, i32 %t
517 %r = xor i32 %m2, %m1
521 ; Negative test - not an inverted predicate.
523 define i32 @select_invert_pred_wrong_cond(float %x, i32 %t, i32 %f) {
524 ; CHECK-LABEL: @select_invert_pred_wrong_cond(
525 ; CHECK-NEXT: [[COND:%.*]] = fcmp ueq float [[X:%.*]], 4.200000e+01
526 ; CHECK-NEXT: [[INVCOND:%.*]] = fcmp une float [[X]], 4.200000e+01
527 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]]
528 ; CHECK-NEXT: [[M2:%.*]] = select i1 [[INVCOND]], i32 [[F]], i32 [[T]]
529 ; CHECK-NEXT: [[R:%.*]] = xor i32 [[M2]], [[M1]]
530 ; CHECK-NEXT: ret i32 [[R]]
532 %cond = fcmp ueq float %x, 42.0
533 %invcond = fcmp une float %x, 42.0
534 %m1 = select i1 %cond, i32 %t, i32 %f
535 %m2 = select i1 %invcond, i32 %f, i32 %t
536 %r = xor i32 %m2, %m1
540 ; Negative test - cmp ops must match.
542 define i32 @select_invert_pred_wrong_cmp_ops(float %x, i32 %t, i32 %f) {
543 ; CHECK-LABEL: @select_invert_pred_wrong_cmp_ops(
544 ; CHECK-NEXT: [[COND:%.*]] = fcmp ueq float [[X:%.*]], 4.200000e+01
545 ; CHECK-NEXT: [[INVCOND:%.*]] = fcmp one float [[X]], 4.300000e+01
546 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]]
547 ; CHECK-NEXT: [[M2:%.*]] = select i1 [[INVCOND]], i32 [[F]], i32 [[T]]
548 ; CHECK-NEXT: [[R:%.*]] = xor i32 [[M2]], [[M1]]
549 ; CHECK-NEXT: ret i32 [[R]]
551 %cond = fcmp ueq float %x, 42.0
552 %invcond = fcmp one float %x, 43.0
553 %m1 = select i1 %cond, i32 %t, i32 %f
554 %m2 = select i1 %invcond, i32 %f, i32 %t
555 %r = xor i32 %m2, %m1
559 ; If we have both an inverted predicate and a 'not' op, recognize the double-negation.
561 define i32 @select_not_invert_pred_cond(i8 %x, i32 %t, i32 %f) {
562 ; CHECK-LABEL: @select_not_invert_pred_cond(
563 ; CHECK-NEXT: [[COND:%.*]] = icmp ugt i8 [[X:%.*]], 42
564 ; CHECK-NEXT: [[INVCOND:%.*]] = icmp ule i8 [[X]], 42
565 ; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[INVCOND]], true
566 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]]
567 ; CHECK-NEXT: ret i32 0
569 %cond = icmp ugt i8 %x, 42
570 %invcond = icmp ule i8 %x, 42
571 %not = xor i1 %invcond, -1
572 %m1 = select i1 %cond, i32 %t, i32 %f
573 %m2 = select i1 %not, i32 %t, i32 %f
574 %r = sub i32 %m1, %m2
578 ; If we have both an inverted predicate and a 'not' op, recognize the double-negation.
580 define i32 @select_not_invert_pred_cond_commute(i8 %x, i8 %y, i32 %t, i32 %f) {
581 ; CHECK-LABEL: @select_not_invert_pred_cond_commute(
582 ; CHECK-NEXT: [[INVCOND:%.*]] = icmp ule i8 [[X:%.*]], [[Y:%.*]]
583 ; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[INVCOND]], true
584 ; CHECK-NEXT: [[M2:%.*]] = select i1 [[NOT]], i32 [[T:%.*]], i32 [[F:%.*]]
585 ; CHECK-NEXT: [[COND:%.*]] = icmp ugt i8 [[X]], [[Y]]
586 ; CHECK-NEXT: ret i32 0
588 %invcond = icmp ule i8 %x, %y
589 %not = xor i1 %invcond, -1
590 %m2 = select i1 %not, i32 %t, i32 %f
591 %cond = icmp ugt i8 %x, %y
592 %m1 = select i1 %cond, i32 %t, i32 %f
593 %r = sub i32 %m2, %m1
597 ; Negative test - not an inverted predicate.
599 define i32 @select_not_invert_pred_cond_wrong_pred(i8 %x, i8 %y, i32 %t, i32 %f) {
600 ; CHECK-LABEL: @select_not_invert_pred_cond_wrong_pred(
601 ; CHECK-NEXT: [[INVCOND:%.*]] = icmp ult i8 [[X:%.*]], [[Y:%.*]]
602 ; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[INVCOND]], true
603 ; CHECK-NEXT: [[M2:%.*]] = select i1 [[NOT]], i32 [[T:%.*]], i32 [[F:%.*]]
604 ; CHECK-NEXT: [[COND:%.*]] = icmp ugt i8 [[X]], [[Y]]
605 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[T]], i32 [[F]]
606 ; CHECK-NEXT: [[R:%.*]] = sub i32 [[M2]], [[M1]]
607 ; CHECK-NEXT: ret i32 [[R]]
609 %invcond = icmp ult i8 %x, %y
610 %not = xor i1 %invcond, -1
611 %m2 = select i1 %not, i32 %t, i32 %f
612 %cond = icmp ugt i8 %x, %y
613 %m1 = select i1 %cond, i32 %t, i32 %f
614 %r = sub i32 %m2, %m1
618 ; Negative test - cmp ops must match.
620 define i32 @select_not_invert_pred_cond_wrong_cmp_op(i8 %x, i8 %y, i32 %t, i32 %f) {
621 ; CHECK-LABEL: @select_not_invert_pred_cond_wrong_cmp_op(
622 ; CHECK-NEXT: [[INVCOND:%.*]] = icmp ule i8 [[X:%.*]], 42
623 ; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[INVCOND]], true
624 ; CHECK-NEXT: [[M2:%.*]] = select i1 [[NOT]], i32 [[T:%.*]], i32 [[F:%.*]]
625 ; CHECK-NEXT: [[COND:%.*]] = icmp ugt i8 [[X]], [[Y:%.*]]
626 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[T]], i32 [[F]]
627 ; CHECK-NEXT: [[R:%.*]] = sub i32 [[M2]], [[M1]]
628 ; CHECK-NEXT: ret i32 [[R]]
630 %invcond = icmp ule i8 %x, 42
631 %not = xor i1 %invcond, -1
632 %m2 = select i1 %not, i32 %t, i32 %f
633 %cond = icmp ugt i8 %x, %y
634 %m1 = select i1 %cond, i32 %t, i32 %f
635 %r = sub i32 %m2, %m1
639 ; Negative test - select ops must be same (and not commuted).
641 define i32 @select_not_invert_pred_cond_wrong_select_op(i8 %x, i8 %y, i32 %t, i32 %f) {
642 ; CHECK-LABEL: @select_not_invert_pred_cond_wrong_select_op(
643 ; CHECK-NEXT: [[INVCOND:%.*]] = icmp ule i8 [[X:%.*]], [[Y:%.*]]
644 ; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[INVCOND]], true
645 ; CHECK-NEXT: [[M2:%.*]] = select i1 [[NOT]], i32 [[T:%.*]], i32 [[F:%.*]]
646 ; CHECK-NEXT: [[COND:%.*]] = icmp ugt i8 [[X]], [[Y]]
647 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[F]], i32 [[T]]
648 ; CHECK-NEXT: [[R:%.*]] = sub i32 [[M2]], [[M1]]
649 ; CHECK-NEXT: ret i32 [[R]]
651 %invcond = icmp ule i8 %x, %y
652 %not = xor i1 %invcond, -1
653 %m2 = select i1 %not, i32 %t, i32 %f
654 %cond = icmp ugt i8 %x, %y
655 %m1 = select i1 %cond, i32 %f, i32 %t
656 %r = sub i32 %m2, %m1
661 ; This test is a reproducer for a bug involving inverted min/max selects
662 ; hashing differently but comparing as equal. It exhibits such a pair of
663 ; values, and we run this test with -earlycse-debug-hash which would catch
664 ; the disagreement and fail if it regressed. This test also includes a
665 ; negation of each negation to check for the same issue one level deeper.
666 define void @not_not_min(i32* %px, i32* %py, i32* %pout) {
667 ; CHECK-LABEL: @not_not_min(
668 ; CHECK-NEXT: [[X:%.*]] = load volatile i32, i32* [[PX:%.*]]
669 ; CHECK-NEXT: [[Y:%.*]] = load volatile i32, i32* [[PY:%.*]]
670 ; CHECK-NEXT: [[CMPA:%.*]] = icmp slt i32 [[X]], [[Y]]
671 ; CHECK-NEXT: [[CMPB:%.*]] = xor i1 [[CMPA]], true
672 ; CHECK-NEXT: [[RA:%.*]] = select i1 [[CMPA]], i32 [[X]], i32 [[Y]]
673 ; CHECK-NEXT: store volatile i32 [[RA]], i32* [[POUT:%.*]]
674 ; CHECK-NEXT: store volatile i32 [[RA]], i32* [[POUT]]
675 ; CHECK-NEXT: store volatile i32 [[RA]], i32* [[POUT]]
676 ; CHECK-NEXT: ret void
678 %x = load volatile i32, i32* %px
679 %y = load volatile i32, i32* %py
680 %cmpa = icmp slt i32 %x, %y
681 %cmpb = xor i1 %cmpa, -1
682 %cmpc = xor i1 %cmpb, -1
683 %ra = select i1 %cmpa, i32 %x, i32 %y
684 %rb = select i1 %cmpb, i32 %y, i32 %x
685 %rc = select i1 %cmpc, i32 %x, i32 %y
686 store volatile i32 %ra, i32* %pout
687 store volatile i32 %rb, i32* %pout
688 store volatile i32 %rc, i32* %pout