1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -S -early-cse | 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 ; Min/max operands may be commuted in the compare and select.
77 define i8 @smin_commute(i8 %a, i8 %b) {
78 ; CHECK-LABEL: @smin_commute(
79 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i8 [[A:%.*]], [[B:%.*]]
80 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i8 [[B]], [[A]]
81 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]]
82 ; CHECK-NEXT: [[R:%.*]] = mul i8 [[M1]], [[M1]]
83 ; CHECK-NEXT: ret i8 [[R]]
85 %cmp1 = icmp slt i8 %a, %b
86 %cmp2 = icmp slt i8 %b, %a
87 %m1 = select i1 %cmp1, i8 %a, i8 %b
88 %m2 = select i1 %cmp2, i8 %b, i8 %a
93 ; Min/max can also have a swapped predicate and select operands.
95 define i1 @smin_swapped(i8 %a, i8 %b) {
96 ; CHECK-LABEL: @smin_swapped(
97 ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i8 [[A:%.*]], [[B:%.*]]
98 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i8 [[A]], [[B]]
99 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[B]], i8 [[A]]
100 ; CHECK-NEXT: ret i1 true
102 %cmp1 = icmp sgt i8 %a, %b
103 %cmp2 = icmp slt i8 %a, %b
104 %m1 = select i1 %cmp1, i8 %b, i8 %a
105 %m2 = select i1 %cmp2, i8 %a, i8 %b
106 %r = icmp eq i8 %m2, %m1
110 define i8 @smax_commute(i8 %a, i8 %b) {
111 ; CHECK-LABEL: @smax_commute(
112 ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i8 [[A:%.*]], [[B:%.*]]
113 ; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i8 [[B]], [[A]]
114 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]]
115 ; CHECK-NEXT: ret i8 0
117 %cmp1 = icmp sgt i8 %a, %b
118 %cmp2 = icmp sgt i8 %b, %a
119 %m1 = select i1 %cmp1, i8 %a, i8 %b
120 %m2 = select i1 %cmp2, i8 %b, i8 %a
121 %r = urem i8 %m2, %m1
125 define i8 @smax_swapped(i8 %a, i8 %b) {
126 ; CHECK-LABEL: @smax_swapped(
127 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i8 [[A:%.*]], [[B:%.*]]
128 ; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i8 [[A]], [[B]]
129 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[B]], i8 [[A]]
130 ; CHECK-NEXT: ret i8 1
132 %cmp1 = icmp slt i8 %a, %b
133 %cmp2 = icmp sgt i8 %a, %b
134 %m1 = select i1 %cmp1, i8 %b, i8 %a
135 %m2 = select i1 %cmp2, i8 %a, i8 %b
136 %r = sdiv i8 %m1, %m2
140 define i8 @umin_commute(i8 %a, i8 %b) {
141 ; CHECK-LABEL: @umin_commute(
142 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i8 [[A:%.*]], [[B:%.*]]
143 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i8 [[B]], [[A]]
144 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]]
145 ; CHECK-NEXT: ret i8 0
147 %cmp1 = icmp ult i8 %a, %b
148 %cmp2 = icmp ult i8 %b, %a
149 %m1 = select i1 %cmp1, i8 %a, i8 %b
150 %m2 = select i1 %cmp2, i8 %b, i8 %a
155 ; Choose a vector type just to show that works.
157 define <2 x i8> @umin_swapped(<2 x i8> %a, <2 x i8> %b) {
158 ; CHECK-LABEL: @umin_swapped(
159 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt <2 x i8> [[A:%.*]], [[B:%.*]]
160 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ult <2 x i8> [[A]], [[B]]
161 ; CHECK-NEXT: [[M1:%.*]] = select <2 x i1> [[CMP1]], <2 x i8> [[B]], <2 x i8> [[A]]
162 ; CHECK-NEXT: ret <2 x i8> zeroinitializer
164 %cmp1 = icmp ugt <2 x i8> %a, %b
165 %cmp2 = icmp ult <2 x i8> %a, %b
166 %m1 = select <2 x i1> %cmp1, <2 x i8> %b, <2 x i8> %a
167 %m2 = select <2 x i1> %cmp2, <2 x i8> %a, <2 x i8> %b
168 %r = sub <2 x i8> %m2, %m1
172 define i8 @umax_commute(i8 %a, i8 %b) {
173 ; CHECK-LABEL: @umax_commute(
174 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i8 [[A:%.*]], [[B:%.*]]
175 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i8 [[B]], [[A]]
176 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[B]]
177 ; CHECK-NEXT: ret i8 1
179 %cmp1 = icmp ugt i8 %a, %b
180 %cmp2 = icmp ugt i8 %b, %a
181 %m1 = select i1 %cmp1, i8 %a, i8 %b
182 %m2 = select i1 %cmp2, i8 %b, i8 %a
183 %r = udiv i8 %m1, %m2
187 define i8 @umax_swapped(i8 %a, i8 %b) {
188 ; CHECK-LABEL: @umax_swapped(
189 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i8 [[A:%.*]], [[B:%.*]]
190 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i8 [[A]], [[B]]
191 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[B]], i8 [[A]]
192 ; CHECK-NEXT: [[R:%.*]] = add i8 [[M1]], [[M1]]
193 ; CHECK-NEXT: ret i8 [[R]]
195 %cmp1 = icmp ult i8 %a, %b
196 %cmp2 = icmp ugt i8 %a, %b
197 %m1 = select i1 %cmp1, i8 %b, i8 %a
198 %m2 = select i1 %cmp2, i8 %a, i8 %b
203 ; Min/max may exist with non-canonical operands. Value tracking can match those.
205 define i8 @smax_nsw(i8 %a, i8 %b) {
206 ; CHECK-LABEL: @smax_nsw(
207 ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i8 [[A:%.*]], [[B:%.*]]
208 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i8 [[A]], [[B]]
209 ; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i8 [[SUB]], 0
210 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 0, i8 [[SUB]]
211 ; CHECK-NEXT: ret i8 0
213 %sub = sub nsw i8 %a, %b
214 %cmp1 = icmp slt i8 %a, %b
215 %cmp2 = icmp sgt i8 %sub, 0
216 %m1 = select i1 %cmp1, i8 0, i8 %sub
217 %m2 = select i1 %cmp2, i8 %sub, i8 0
222 define i8 @abs_swapped(i8 %a) {
223 ; CHECK-LABEL: @abs_swapped(
224 ; CHECK-NEXT: [[NEG:%.*]] = sub i8 0, [[A:%.*]]
225 ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i8 [[A]], 0
226 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i8 [[A]], 0
227 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[NEG]]
228 ; CHECK-NEXT: ret i8 [[M1]]
231 %cmp1 = icmp sgt i8 %a, 0
232 %cmp2 = icmp slt i8 %a, 0
233 %m1 = select i1 %cmp1, i8 %a, i8 %neg
234 %m2 = select i1 %cmp2, i8 %neg, i8 %a
239 define i8 @nabs_swapped(i8 %a) {
240 ; CHECK-LABEL: @nabs_swapped(
241 ; CHECK-NEXT: [[NEG:%.*]] = sub i8 0, [[A:%.*]]
242 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i8 [[A]], 0
243 ; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i8 [[A]], 0
244 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[NEG]]
245 ; CHECK-NEXT: ret i8 0
248 %cmp1 = icmp slt i8 %a, 0
249 %cmp2 = icmp sgt i8 %a, 0
250 %m1 = select i1 %cmp1, i8 %a, i8 %neg
251 %m2 = select i1 %cmp2, i8 %neg, i8 %a
256 ; These two tests make sure we still consider it a match when the RHS of the
257 ; compares are different.
258 define i8 @abs_different_constants(i8 %a) {
259 ; CHECK-LABEL: @abs_different_constants(
260 ; CHECK-NEXT: [[NEG:%.*]] = sub i8 0, [[A:%.*]]
261 ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i8 [[A]], -1
262 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i8 [[A]], 0
263 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[NEG]]
264 ; CHECK-NEXT: ret i8 [[M1]]
267 %cmp1 = icmp sgt i8 %a, -1
268 %cmp2 = icmp slt i8 %a, 0
269 %m1 = select i1 %cmp1, i8 %a, i8 %neg
270 %m2 = select i1 %cmp2, i8 %neg, i8 %a
275 define i8 @nabs_different_constants(i8 %a) {
276 ; CHECK-LABEL: @nabs_different_constants(
277 ; CHECK-NEXT: [[NEG:%.*]] = sub i8 0, [[A:%.*]]
278 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i8 [[A]], 0
279 ; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i8 [[A]], -1
280 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 [[A]], i8 [[NEG]]
281 ; CHECK-NEXT: ret i8 0
284 %cmp1 = icmp slt i8 %a, 0
285 %cmp2 = icmp sgt i8 %a, -1
286 %m1 = select i1 %cmp1, i8 %a, i8 %neg
287 %m2 = select i1 %cmp2, i8 %neg, i8 %a
292 ; https://bugs.llvm.org/show_bug.cgi?id=41101
293 ; Detect equivalence of selects with commuted operands: 'not' cond.
295 define i32 @select_not_cond(i1 %cond, i32 %t, i32 %f) {
296 ; CHECK-LABEL: @select_not_cond(
297 ; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[COND:%.*]], true
298 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]]
299 ; CHECK-NEXT: ret i32 0
301 %not = xor i1 %cond, -1
302 %m1 = select i1 %cond, i32 %t, i32 %f
303 %m2 = select i1 %not, i32 %f, i32 %t
304 %r = xor i32 %m2, %m1
308 ; Detect equivalence of selects with commuted operands: 'not' cond with vector select.
310 define <2 x double> @select_not_cond_commute_vec(<2 x i1> %cond, <2 x double> %t, <2 x double> %f) {
311 ; CHECK-LABEL: @select_not_cond_commute_vec(
312 ; CHECK-NEXT: [[NOT:%.*]] = xor <2 x i1> [[COND:%.*]], <i1 true, i1 true>
313 ; CHECK-NEXT: [[M1:%.*]] = select <2 x i1> [[COND]], <2 x double> [[T:%.*]], <2 x double> [[F:%.*]]
314 ; CHECK-NEXT: ret <2 x double> <double 1.000000e+00, double 1.000000e+00>
316 %not = xor <2 x i1> %cond, <i1 -1, i1 -1>
317 %m1 = select <2 x i1> %cond, <2 x double> %t, <2 x double> %f
318 %m2 = select <2 x i1> %not, <2 x double> %f, <2 x double> %t
319 %r = fdiv nnan <2 x double> %m1, %m2
323 ; Negative test - select ops must be commuted.
325 define i32 @select_not_cond_wrong_select_ops(i1 %cond, i32 %t, i32 %f) {
326 ; CHECK-LABEL: @select_not_cond_wrong_select_ops(
327 ; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[COND:%.*]], true
328 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]]
329 ; CHECK-NEXT: [[M2:%.*]] = select i1 [[NOT]], i32 [[T]], i32 [[F]]
330 ; CHECK-NEXT: [[R:%.*]] = xor i32 [[M2]], [[M1]]
331 ; CHECK-NEXT: ret i32 [[R]]
333 %not = xor i1 %cond, -1
334 %m1 = select i1 %cond, i32 %t, i32 %f
335 %m2 = select i1 %not, i32 %t, i32 %f
336 %r = xor i32 %m2, %m1
340 ; Negative test - not a 'not'.
342 define i32 @select_not_cond_wrong_cond(i1 %cond, i32 %t, i32 %f) {
343 ; CHECK-LABEL: @select_not_cond_wrong_cond(
344 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND:%.*]], i32 [[T:%.*]], i32 [[F:%.*]]
345 ; CHECK-NEXT: [[M2:%.*]] = select i1 [[COND]], i32 [[F]], i32 [[T]]
346 ; CHECK-NEXT: [[R:%.*]] = xor i32 [[M2]], [[M1]]
347 ; CHECK-NEXT: ret i32 [[R]]
349 %not = xor i1 %cond, -2
350 %m1 = select i1 %cond, i32 %t, i32 %f
351 %m2 = select i1 %not, i32 %f, i32 %t
352 %r = xor i32 %m2, %m1
356 ; Detect equivalence of selects with commuted operands: inverted pred with fcmps.
358 define i32 @select_invert_pred_cond(float %x, i32 %t, i32 %f) {
359 ; CHECK-LABEL: @select_invert_pred_cond(
360 ; CHECK-NEXT: [[COND:%.*]] = fcmp ueq float [[X:%.*]], 4.200000e+01
361 ; CHECK-NEXT: [[INVCOND:%.*]] = fcmp one float [[X]], 4.200000e+01
362 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]]
363 ; CHECK-NEXT: ret i32 0
365 %cond = fcmp ueq float %x, 42.0
366 %invcond = fcmp one float %x, 42.0
367 %m1 = select i1 %cond, i32 %t, i32 %f
368 %m2 = select i1 %invcond, i32 %f, i32 %t
369 %r = xor i32 %m2, %m1
373 ; Detect equivalence of selects with commuted operands: inverted pred with icmps and vectors.
375 define <2 x i32> @select_invert_pred_cond_commute_vec(<2 x i8> %x, <2 x i32> %t, <2 x i32> %f) {
376 ; CHECK-LABEL: @select_invert_pred_cond_commute_vec(
377 ; CHECK-NEXT: [[COND:%.*]] = icmp sgt <2 x i8> [[X:%.*]], <i8 42, i8 -1>
378 ; CHECK-NEXT: [[INVCOND:%.*]] = icmp sle <2 x i8> [[X]], <i8 42, i8 -1>
379 ; CHECK-NEXT: [[M1:%.*]] = select <2 x i1> [[COND]], <2 x i32> [[T:%.*]], <2 x i32> [[F:%.*]]
380 ; CHECK-NEXT: ret <2 x i32> zeroinitializer
382 %cond = icmp sgt <2 x i8> %x, <i8 42, i8 -1>
383 %invcond = icmp sle <2 x i8> %x, <i8 42, i8 -1>
384 %m1 = select <2 x i1> %cond, <2 x i32> %t, <2 x i32> %f
385 %m2 = select <2 x i1> %invcond, <2 x i32> %f, <2 x i32> %t
386 %r = xor <2 x i32> %m1, %m2
390 ; Negative test - select ops must be commuted.
392 define i32 @select_invert_pred_wrong_select_ops(float %x, i32 %t, i32 %f) {
393 ; CHECK-LABEL: @select_invert_pred_wrong_select_ops(
394 ; CHECK-NEXT: [[COND:%.*]] = fcmp ueq float [[X:%.*]], 4.200000e+01
395 ; CHECK-NEXT: [[INVCOND:%.*]] = fcmp one float [[X]], 4.200000e+01
396 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[F:%.*]], i32 [[T:%.*]]
397 ; CHECK-NEXT: [[M2:%.*]] = select i1 [[INVCOND]], i32 [[F]], i32 [[T]]
398 ; CHECK-NEXT: [[R:%.*]] = xor i32 [[M2]], [[M1]]
399 ; CHECK-NEXT: ret i32 [[R]]
401 %cond = fcmp ueq float %x, 42.0
402 %invcond = fcmp one float %x, 42.0
403 %m1 = select i1 %cond, i32 %f, i32 %t
404 %m2 = select i1 %invcond, i32 %f, i32 %t
405 %r = xor i32 %m2, %m1
409 ; Negative test - not an inverted predicate.
411 define i32 @select_invert_pred_wrong_cond(float %x, i32 %t, i32 %f) {
412 ; CHECK-LABEL: @select_invert_pred_wrong_cond(
413 ; CHECK-NEXT: [[COND:%.*]] = fcmp ueq float [[X:%.*]], 4.200000e+01
414 ; CHECK-NEXT: [[INVCOND:%.*]] = fcmp une float [[X]], 4.200000e+01
415 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]]
416 ; CHECK-NEXT: [[M2:%.*]] = select i1 [[INVCOND]], i32 [[F]], i32 [[T]]
417 ; CHECK-NEXT: [[R:%.*]] = xor i32 [[M2]], [[M1]]
418 ; CHECK-NEXT: ret i32 [[R]]
420 %cond = fcmp ueq float %x, 42.0
421 %invcond = fcmp une float %x, 42.0
422 %m1 = select i1 %cond, i32 %t, i32 %f
423 %m2 = select i1 %invcond, i32 %f, i32 %t
424 %r = xor i32 %m2, %m1
428 ; Negative test - cmp ops must match.
430 define i32 @select_invert_pred_wrong_cmp_ops(float %x, i32 %t, i32 %f) {
431 ; CHECK-LABEL: @select_invert_pred_wrong_cmp_ops(
432 ; CHECK-NEXT: [[COND:%.*]] = fcmp ueq float [[X:%.*]], 4.200000e+01
433 ; CHECK-NEXT: [[INVCOND:%.*]] = fcmp one float [[X]], 4.300000e+01
434 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]]
435 ; CHECK-NEXT: [[M2:%.*]] = select i1 [[INVCOND]], i32 [[F]], i32 [[T]]
436 ; CHECK-NEXT: [[R:%.*]] = xor i32 [[M2]], [[M1]]
437 ; CHECK-NEXT: ret i32 [[R]]
439 %cond = fcmp ueq float %x, 42.0
440 %invcond = fcmp one float %x, 43.0
441 %m1 = select i1 %cond, i32 %t, i32 %f
442 %m2 = select i1 %invcond, i32 %f, i32 %t
443 %r = xor i32 %m2, %m1
447 ; If we have both an inverted predicate and a 'not' op, recognize the double-negation.
449 define i32 @select_not_invert_pred_cond(i8 %x, i32 %t, i32 %f) {
450 ; CHECK-LABEL: @select_not_invert_pred_cond(
451 ; CHECK-NEXT: [[COND:%.*]] = icmp ugt i8 [[X:%.*]], 42
452 ; CHECK-NEXT: [[INVCOND:%.*]] = icmp ule i8 [[X]], 42
453 ; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[INVCOND]], true
454 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[T:%.*]], i32 [[F:%.*]]
455 ; CHECK-NEXT: ret i32 0
457 %cond = icmp ugt i8 %x, 42
458 %invcond = icmp ule i8 %x, 42
459 %not = xor i1 %invcond, -1
460 %m1 = select i1 %cond, i32 %t, i32 %f
461 %m2 = select i1 %not, i32 %t, i32 %f
462 %r = sub i32 %m1, %m2
466 ; If we have both an inverted predicate and a 'not' op, recognize the double-negation.
468 define i32 @select_not_invert_pred_cond_commute(i8 %x, i8 %y, i32 %t, i32 %f) {
469 ; CHECK-LABEL: @select_not_invert_pred_cond_commute(
470 ; CHECK-NEXT: [[INVCOND:%.*]] = icmp ule i8 [[X:%.*]], [[Y:%.*]]
471 ; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[INVCOND]], true
472 ; CHECK-NEXT: [[M2:%.*]] = select i1 [[NOT]], i32 [[T:%.*]], i32 [[F:%.*]]
473 ; CHECK-NEXT: [[COND:%.*]] = icmp ugt i8 [[X]], [[Y]]
474 ; CHECK-NEXT: ret i32 0
476 %invcond = icmp ule i8 %x, %y
477 %not = xor i1 %invcond, -1
478 %m2 = select i1 %not, i32 %t, i32 %f
479 %cond = icmp ugt i8 %x, %y
480 %m1 = select i1 %cond, i32 %t, i32 %f
481 %r = sub i32 %m2, %m1
485 ; Negative test - not an inverted predicate.
487 define i32 @select_not_invert_pred_cond_wrong_pred(i8 %x, i8 %y, i32 %t, i32 %f) {
488 ; CHECK-LABEL: @select_not_invert_pred_cond_wrong_pred(
489 ; CHECK-NEXT: [[INVCOND:%.*]] = icmp ult i8 [[X:%.*]], [[Y:%.*]]
490 ; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[INVCOND]], true
491 ; CHECK-NEXT: [[M2:%.*]] = select i1 [[NOT]], i32 [[T:%.*]], i32 [[F:%.*]]
492 ; CHECK-NEXT: [[COND:%.*]] = icmp ugt i8 [[X]], [[Y]]
493 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[T]], i32 [[F]]
494 ; CHECK-NEXT: [[R:%.*]] = sub i32 [[M2]], [[M1]]
495 ; CHECK-NEXT: ret i32 [[R]]
497 %invcond = icmp ult i8 %x, %y
498 %not = xor i1 %invcond, -1
499 %m2 = select i1 %not, i32 %t, i32 %f
500 %cond = icmp ugt i8 %x, %y
501 %m1 = select i1 %cond, i32 %t, i32 %f
502 %r = sub i32 %m2, %m1
506 ; Negative test - cmp ops must match.
508 define i32 @select_not_invert_pred_cond_wrong_cmp_op(i8 %x, i8 %y, i32 %t, i32 %f) {
509 ; CHECK-LABEL: @select_not_invert_pred_cond_wrong_cmp_op(
510 ; CHECK-NEXT: [[INVCOND:%.*]] = icmp ule i8 [[X:%.*]], 42
511 ; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[INVCOND]], true
512 ; CHECK-NEXT: [[M2:%.*]] = select i1 [[NOT]], i32 [[T:%.*]], i32 [[F:%.*]]
513 ; CHECK-NEXT: [[COND:%.*]] = icmp ugt i8 [[X]], [[Y:%.*]]
514 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[T]], i32 [[F]]
515 ; CHECK-NEXT: [[R:%.*]] = sub i32 [[M2]], [[M1]]
516 ; CHECK-NEXT: ret i32 [[R]]
518 %invcond = icmp ule i8 %x, 42
519 %not = xor i1 %invcond, -1
520 %m2 = select i1 %not, i32 %t, i32 %f
521 %cond = icmp ugt i8 %x, %y
522 %m1 = select i1 %cond, i32 %t, i32 %f
523 %r = sub i32 %m2, %m1
527 ; Negative test - select ops must be same (and not commuted).
529 define i32 @select_not_invert_pred_cond_wrong_select_op(i8 %x, i8 %y, i32 %t, i32 %f) {
530 ; CHECK-LABEL: @select_not_invert_pred_cond_wrong_select_op(
531 ; CHECK-NEXT: [[INVCOND:%.*]] = icmp ule i8 [[X:%.*]], [[Y:%.*]]
532 ; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[INVCOND]], true
533 ; CHECK-NEXT: [[M2:%.*]] = select i1 [[NOT]], i32 [[T:%.*]], i32 [[F:%.*]]
534 ; CHECK-NEXT: [[COND:%.*]] = icmp ugt i8 [[X]], [[Y]]
535 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[COND]], i32 [[F]], i32 [[T]]
536 ; CHECK-NEXT: [[R:%.*]] = sub i32 [[M2]], [[M1]]
537 ; CHECK-NEXT: ret i32 [[R]]
539 %invcond = icmp ule i8 %x, %y
540 %not = xor i1 %invcond, -1
541 %m2 = select i1 %not, i32 %t, i32 %f
542 %cond = icmp ugt i8 %x, %y
543 %m1 = select i1 %cond, i32 %f, i32 %t
544 %r = sub i32 %m2, %m1