[ARM] Better OR's for MVE compares
[llvm-core.git] / test / Transforms / EarlyCSE / commute.ll
blob0c8639b5e732b754832772699129c158afad34a5
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) {
6 ; CHECK-LABEL: @test1(
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
16   ret void
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
27   store i1 %C, i1* %PA
28   %D = fcmp oeq float %B, %A
29   store i1 %D, i1* %PB
30   ret void
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
41   store i1 %C, i1* %PA
42   %D = fcmp ule float %B, %A
43   store i1 %D, i1* %PB
44   ret void
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
55   store i1 %C, i1* %PA
56   %D = icmp eq i32 %B, %A
57   store i1 %D, i1* %PB
58   ret void
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
69   store i1 %C, i1* %PA
70   %D = icmp slt i32 %B, %A
71   store i1 %D, i1* %PB
72   ret void
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
86   store i1 %c1, i1* %p1
87   store i1 %c2, i1* %p2
88   ret void
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
105   %r = mul i8 %m1, %m2
106   ret i8 %r
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
123   ret i1 %r
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
140   ret i1 %r
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
155   ret i8 %r
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
170   ret i8 %r
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
185   ret i1 %r
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
199   %r = sub i8 %m2, %m1
200   ret i8 %r
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
217   ret <2 x i8> %r
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
232   ret i1 %r
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
247   ret i8 %r
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
262   %r = add i8 %m2, %m1
263   ret i8 %r
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
278   ret i1 %r
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
296   %r = sub i8 %m2, %m1
297   ret i8 %r
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]]
308   %neg = sub i8 0, %a
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
313   %r = or i8 %m2, %m1
314   ret i8 %r
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]]
325   %neg = sub i8 0, %a
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
330   %r = or i8 %m2, %m1
331   ret i8 %r
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
342   %neg = sub i8 0, %a
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
347   %r = xor i8 %m2, %m1
348   ret i8 %r
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
359   %neg = sub i8 0, %a
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
364   %r = xor i8 %m2, %m1
365   ret i8 %r
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]]
378   %neg = sub i8 0, %a
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
383   %r = or i8 %m2, %m1
384   ret i8 %r
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
395   %neg = sub i8 0, %a
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
400   %r = xor i8 %m2, %m1
401   ret i8 %r
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
417   ret i32 %r
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
432   ret <2 x double> %r
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
449   ret i32 %r
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
465   ret i32 %r
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
482   ret i32 %r
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
499   ret <2 x i32> %r
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
518   ret i32 %r
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
537   ret i32 %r
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
556   ret i32 %r
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
575   ret i32 %r
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
594   ret i32 %r
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
615   ret i32 %r
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
636   ret i32 %r
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
657   ret i32 %r
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
690   ret void