xref: /llvm-project/llvm/test/Transforms/InstCombine/select-safe-transforms.ll (revision 38fffa630ee80163dc65e759392ad29798905679)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3
4declare i1 @gen1()
5
6define i1 @cond_eq_and(i8 %X, i8 %Y, i8 noundef %C) {
7; CHECK-LABEL: @cond_eq_and(
8; CHECK-NEXT:    [[COND:%.*]] = icmp eq i8 [[X:%.*]], [[C:%.*]]
9; CHECK-NEXT:    [[LHS:%.*]] = icmp ult i8 [[X]], [[Y:%.*]]
10; CHECK-NEXT:    [[RES:%.*]] = select i1 [[COND]], i1 [[LHS]], i1 false
11; CHECK-NEXT:    ret i1 [[RES]]
12;
13  %cond = icmp eq i8 %X, %C
14  %lhs = icmp ult i8 %X, %Y
15  %res = select i1 %cond, i1 %lhs, i1 false
16  ret i1 %res
17}
18
19define i1 @cond_eq_and_const(i8 %X, i8 %Y) {
20; CHECK-LABEL: @cond_eq_and_const(
21; CHECK-NEXT:    [[COND:%.*]] = icmp eq i8 [[X:%.*]], 10
22; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i8 [[Y:%.*]], 10
23; CHECK-NEXT:    [[RES:%.*]] = select i1 [[COND]], i1 [[TMP1]], i1 false
24; CHECK-NEXT:    ret i1 [[RES]]
25;
26  %cond = icmp eq i8 %X, 10
27  %lhs = icmp ult i8 %X, %Y
28  %res = select i1 %cond, i1 %lhs, i1 false
29  ret i1 %res
30}
31
32define i1 @cond_eq_or(i8 %X, i8 %Y, i8 noundef %C) {
33; CHECK-LABEL: @cond_eq_or(
34; CHECK-NEXT:    [[COND:%.*]] = icmp ne i8 [[X:%.*]], [[C:%.*]]
35; CHECK-NEXT:    [[LHS:%.*]] = icmp ult i8 [[X]], [[Y:%.*]]
36; CHECK-NEXT:    [[RES:%.*]] = select i1 [[COND]], i1 true, i1 [[LHS]]
37; CHECK-NEXT:    ret i1 [[RES]]
38;
39  %cond = icmp ne i8 %X, %C
40  %lhs = icmp ult i8 %X, %Y
41  %res = select i1 %cond, i1 true, i1 %lhs
42  ret i1 %res
43}
44
45define i1 @cond_eq_or_const(i8 %X, i8 %Y) {
46; CHECK-LABEL: @cond_eq_or_const(
47; CHECK-NEXT:    [[COND:%.*]] = icmp ne i8 [[X:%.*]], 10
48; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i8 [[Y:%.*]], 10
49; CHECK-NEXT:    [[RES:%.*]] = select i1 [[COND]], i1 true, i1 [[TMP1]]
50; CHECK-NEXT:    ret i1 [[RES]]
51;
52  %cond = icmp ne i8 %X, 10
53  %lhs = icmp ult i8 %X, %Y
54  %res = select i1 %cond, i1 true, i1 %lhs
55  ret i1 %res
56}
57
58define i1 @xor_and(i1 %c, i32 %X, i32 %Y) {
59; CHECK-LABEL: @xor_and(
60; CHECK-NEXT:    [[COMP:%.*]] = icmp uge i32 [[X:%.*]], [[Y:%.*]]
61; CHECK-NEXT:    [[NOT_C:%.*]] = xor i1 [[C:%.*]], true
62; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[NOT_C]], i1 true, i1 [[COMP]]
63; CHECK-NEXT:    ret i1 [[SEL]]
64;
65  %comp = icmp ult i32 %X, %Y
66  %sel = select i1 %c, i1 %comp, i1 false
67  %res = xor i1 %sel, true
68  ret i1 %res
69}
70
71define <2 x i1> @xor_and2(<2 x i1> %c, <2 x i32> %X, <2 x i32> %Y) {
72; CHECK-LABEL: @xor_and2(
73; CHECK-NEXT:    [[COMP:%.*]] = icmp uge <2 x i32> [[X:%.*]], [[Y:%.*]]
74; CHECK-NEXT:    [[SEL:%.*]] = select <2 x i1> [[C:%.*]], <2 x i1> [[COMP]], <2 x i1> <i1 false, i1 true>
75; CHECK-NEXT:    ret <2 x i1> [[SEL]]
76;
77  %comp = icmp ult <2 x i32> %X, %Y
78  %sel = select <2 x i1> %c, <2 x i1> %comp, <2 x i1> <i1 true, i1 false>
79  %res = xor <2 x i1> %sel, <i1 true, i1 true>
80  ret <2 x i1> %res
81}
82
83@glb = global i8 0
84
85define <2 x i1> @xor_and3(<2 x i1> %c, <2 x i32> %X, <2 x i32> %Y) {
86; CHECK-LABEL: @xor_and3(
87; CHECK-NEXT:    [[COMP:%.*]] = icmp uge <2 x i32> [[X:%.*]], [[Y:%.*]]
88; CHECK-NEXT:    [[SEL:%.*]] = select <2 x i1> [[C:%.*]], <2 x i1> [[COMP]], <2 x i1> <i1 xor (i1 ptrtoint (ptr @glb to i1), i1 true), i1 true>
89; CHECK-NEXT:    ret <2 x i1> [[SEL]]
90;
91  %comp = icmp ult <2 x i32> %X, %Y
92  %sel = select <2 x i1> %c, <2 x i1> %comp, <2 x i1> <i1 ptrtoint (ptr @glb to i1), i1 false>
93  %res = xor <2 x i1> %sel, <i1 true, i1 true>
94  ret <2 x i1> %res
95}
96
97define i1 @xor_or(i1 %c, i32 %X, i32 %Y) {
98; CHECK-LABEL: @xor_or(
99; CHECK-NEXT:    [[COMP:%.*]] = icmp uge i32 [[X:%.*]], [[Y:%.*]]
100; CHECK-NEXT:    [[NOT_C:%.*]] = xor i1 [[C:%.*]], true
101; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[NOT_C]], i1 [[COMP]], i1 false
102; CHECK-NEXT:    ret i1 [[SEL]]
103;
104  %comp = icmp ult i32 %X, %Y
105  %sel = select i1 %c, i1 true, i1 %comp
106  %res = xor i1 %sel, true
107  ret i1 %res
108}
109
110define <2 x i1> @xor_or2(<2 x i1> %c, <2 x i32> %X, <2 x i32> %Y) {
111; CHECK-LABEL: @xor_or2(
112; CHECK-NEXT:    [[COMP:%.*]] = icmp uge <2 x i32> [[X:%.*]], [[Y:%.*]]
113; CHECK-NEXT:    [[SEL:%.*]] = select <2 x i1> [[C:%.*]], <2 x i1> <i1 false, i1 true>, <2 x i1> [[COMP]]
114; CHECK-NEXT:    ret <2 x i1> [[SEL]]
115;
116  %comp = icmp ult <2 x i32> %X, %Y
117  %sel = select <2 x i1> %c, <2 x i1> <i1 true, i1 false>, <2 x i1> %comp
118  %res = xor <2 x i1> %sel, <i1 true, i1 true>
119  ret <2 x i1> %res
120}
121
122define <2 x i1> @xor_or3(<2 x i1> %c, <2 x i32> %X, <2 x i32> %Y) {
123; CHECK-LABEL: @xor_or3(
124; CHECK-NEXT:    [[COMP:%.*]] = icmp uge <2 x i32> [[X:%.*]], [[Y:%.*]]
125; CHECK-NEXT:    [[SEL:%.*]] = select <2 x i1> [[C:%.*]], <2 x i1> <i1 xor (i1 ptrtoint (ptr @glb to i1), i1 true), i1 true>, <2 x i1> [[COMP]]
126; CHECK-NEXT:    ret <2 x i1> [[SEL]]
127;
128  %comp = icmp ult <2 x i32> %X, %Y
129  %sel = select <2 x i1> %c, <2 x i1> <i1 ptrtoint (ptr @glb to i1), i1 false>, <2 x i1> %comp
130  %res = xor <2 x i1> %sel, <i1 true, i1 true>
131  ret <2 x i1> %res
132}
133
134define i1 @and_orn_cmp_1_logical(i32 %a, i32 %b, i1 %y) {
135; CHECK-LABEL: @and_orn_cmp_1_logical(
136; CHECK-NEXT:    [[X:%.*]] = icmp sgt i32 [[A:%.*]], [[B:%.*]]
137; CHECK-NEXT:    [[AND:%.*]] = select i1 [[X]], i1 [[Y:%.*]], i1 false
138; CHECK-NEXT:    ret i1 [[AND]]
139;
140  %x = icmp sgt i32 %a, %b
141  %x_inv = icmp sle i32 %a, %b
142  %or = select i1 %y, i1 true, i1 %x_inv
143  %and = select i1 %x, i1 %or, i1 false
144  ret i1 %and
145}
146
147; TODO: This should fold the same way as the next test.
148
149define i1 @and_orn_cmp_1_partial_logical(i32 %a, i32 %b, i1 %y) {
150; CHECK-LABEL: @and_orn_cmp_1_partial_logical(
151; CHECK-NEXT:    [[X:%.*]] = icmp sgt i32 [[A:%.*]], [[B:%.*]]
152; CHECK-NEXT:    [[X_INV:%.*]] = icmp sle i32 [[A]], [[B]]
153; CHECK-NEXT:    [[OR:%.*]] = or i1 [[X_INV]], [[Y:%.*]]
154; CHECK-NEXT:    [[AND:%.*]] = select i1 [[X]], i1 [[OR]], i1 false
155; CHECK-NEXT:    ret i1 [[AND]]
156;
157  %x = icmp sgt i32 %a, %b
158  %x_inv = icmp sle i32 %a, %b
159  %or = or i1 %x_inv, %y
160  %and = select i1 %x, i1 %or, i1 false
161  ret i1 %and
162}
163
164define i1 @and_orn_cmp_1_partial_logical_commute(i32 %a, i32 %b) {
165; CHECK-LABEL: @and_orn_cmp_1_partial_logical_commute(
166; CHECK-NEXT:    [[Y:%.*]] = call i1 @gen1()
167; CHECK-NEXT:    [[X:%.*]] = icmp sgt i32 [[A:%.*]], [[B:%.*]]
168; CHECK-NEXT:    [[AND:%.*]] = select i1 [[X]], i1 [[Y]], i1 false
169; CHECK-NEXT:    ret i1 [[AND]]
170;
171  %y = call i1 @gen1() ; thwart complexity-based canonicalization
172  %x = icmp sgt i32 %a, %b
173  %x_inv = icmp sle i32 %a, %b
174  %or = or i1 %y, %x_inv
175  %and = select i1 %x, i1 %or, i1 false
176  ret i1 %and
177}
178
179; TODO: This does not require poison-safe (select) logical-and.
180
181define i1 @andn_or_cmp_2_logical(i16 %a, i16 %b, i1 %y) {
182; CHECK-LABEL: @andn_or_cmp_2_logical(
183; CHECK-NEXT:    [[X_INV:%.*]] = icmp slt i16 [[A:%.*]], [[B:%.*]]
184; CHECK-NEXT:    [[AND:%.*]] = select i1 [[Y:%.*]], i1 [[X_INV]], i1 false
185; CHECK-NEXT:    ret i1 [[AND]]
186;
187  %x = icmp sge i16 %a, %b
188  %x_inv = icmp slt i16 %a, %b
189  %or = select i1 %y, i1 true, i1 %x
190  %and = select i1 %or, i1 %x_inv, i1 false
191  ret i1 %and
192}
193
194define i1 @andn_or_cmp_2_partial_logical(i16 %a, i16 %b, i1 %y) {
195; CHECK-LABEL: @andn_or_cmp_2_partial_logical(
196; CHECK-NEXT:    [[X_INV:%.*]] = icmp slt i16 [[A:%.*]], [[B:%.*]]
197; CHECK-NEXT:    [[AND:%.*]] = and i1 [[Y:%.*]], [[X_INV]]
198; CHECK-NEXT:    ret i1 [[AND]]
199;
200  %x = icmp sge i16 %a, %b
201  %x_inv = icmp slt i16 %a, %b
202  %or = or i1 %x, %y
203  %and = select i1 %or, i1 %x_inv, i1 false
204  ret i1 %and
205}
206
207define i1 @andn_or_cmp_2_partial_logical_commute(i16 %a, i16 %b) {
208; CHECK-LABEL: @andn_or_cmp_2_partial_logical_commute(
209; CHECK-NEXT:    [[Y:%.*]] = call i1 @gen1()
210; CHECK-NEXT:    [[X_INV:%.*]] = icmp slt i16 [[A:%.*]], [[B:%.*]]
211; CHECK-NEXT:    [[AND:%.*]] = and i1 [[Y]], [[X_INV]]
212; CHECK-NEXT:    ret i1 [[AND]]
213;
214  %y = call i1 @gen1() ; thwart complexity-based canonicalization
215  %x = icmp sge i16 %a, %b
216  %x_inv = icmp slt i16 %a, %b
217  %or = or i1 %y, %x
218  %and = select i1 %or, i1 %x_inv, i1 false
219  ret i1 %and
220}
221
222; PR58552 - this would crash trying to replace non-matching types
223
224define <2 x i1> @not_logical_or(i1 %b, <2 x i32> %a) {
225; CHECK-LABEL: @not_logical_or(
226; CHECK-NEXT:    [[COND:%.*]] = icmp ult <2 x i32> [[A:%.*]], splat (i32 3)
227; CHECK-NEXT:    [[IMPLIED:%.*]] = icmp slt <2 x i32> [[A]], splat (i32 -1)
228; CHECK-NEXT:    [[OR:%.*]] = select i1 [[B:%.*]], <2 x i1> splat (i1 true), <2 x i1> [[IMPLIED]]
229; CHECK-NEXT:    [[AND:%.*]] = select <2 x i1> [[COND]], <2 x i1> [[OR]], <2 x i1> zeroinitializer
230; CHECK-NEXT:    ret <2 x i1> [[AND]]
231;
232  %cond = icmp ult <2 x i32> %a, <i32 3, i32 3>
233  %implied = icmp slt <2 x i32> %a, <i32 -1, i32 -1>
234  %or = select i1 %b, <2 x i1> <i1 true, i1 true>, <2 x i1> %implied
235  %and = select <2 x i1> %cond, <2 x i1> %or, <2 x i1> zeroinitializer
236  ret <2 x i1> %and
237}
238
239; This could reduce, but we do not match select-of-vectors with scalar condition as logical-or.
240
241define <2 x i1> @not_logical_or2(i1 %b, <2 x i32> %a) {
242; CHECK-LABEL: @not_logical_or2(
243; CHECK-NEXT:    [[COND:%.*]] = icmp ult <2 x i32> [[A:%.*]], splat (i32 3)
244; CHECK-NEXT:    [[IMPLIED:%.*]] = icmp slt <2 x i32> [[A]], splat (i32 -1)
245; CHECK-NEXT:    [[OR:%.*]] = select i1 [[B:%.*]], <2 x i1> splat (i1 true), <2 x i1> [[IMPLIED]]
246; CHECK-NEXT:    [[AND:%.*]] = select <2 x i1> [[OR]], <2 x i1> [[COND]], <2 x i1> zeroinitializer
247; CHECK-NEXT:    ret <2 x i1> [[AND]]
248;
249  %cond = icmp ult <2 x i32> %a, <i32 3, i32 3>
250  %implied = icmp slt <2 x i32> %a, <i32 -1, i32 -1>
251  %or = select i1 %b, <2 x i1> <i1 true, i1 true>, <2 x i1> %implied
252  %and = select <2 x i1> %or, <2 x i1> %cond, <2 x i1> zeroinitializer
253  ret <2 x i1> %and
254}
255
256define i1 @bools_logical_commute0(i1 %a, i1 %b, i1 %c) {
257; CHECK-LABEL: @bools_logical_commute0(
258; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 [[B:%.*]], i1 [[A:%.*]]
259; CHECK-NEXT:    ret i1 [[OR]]
260;
261  %not = xor i1 %c, -1
262  %and1 = select i1 %not, i1 %a, i1 false
263  %and2 = select i1 %c, i1 %b, i1 false
264  %or = select i1 %and1, i1 true, i1 %and2
265  ret i1 %or
266}
267
268define i1 @bools_logical_commute0_and1(i1 %a, i1 %b, i1 %c) {
269; CHECK-LABEL: @bools_logical_commute0_and1(
270; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 [[B:%.*]], i1 [[A:%.*]]
271; CHECK-NEXT:    ret i1 [[OR]]
272;
273  %not = xor i1 %c, -1
274  %and1 = and i1 %not, %a
275  %and2 = select i1 %c, i1 %b, i1 false
276  %or = select i1 %and1, i1 true, i1 %and2
277  ret i1 %or
278}
279
280define i1 @bools_logical_commute0_and2(i1 %a, i1 %b, i1 %c) {
281; CHECK-LABEL: @bools_logical_commute0_and2(
282; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 [[B:%.*]], i1 [[A:%.*]]
283; CHECK-NEXT:    ret i1 [[OR]]
284;
285  %not = xor i1 %c, -1
286  %and1 = select i1 %not, i1 %a, i1 false
287  %and2 = and i1 %c, %b
288  %or = select i1 %and1, i1 true, i1 %and2
289  ret i1 %or
290}
291
292define i1 @bools_logical_commute0_and1_and2(i1 %a, i1 %b, i1 %c) {
293; CHECK-LABEL: @bools_logical_commute0_and1_and2(
294; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 [[B:%.*]], i1 [[A:%.*]]
295; CHECK-NEXT:    ret i1 [[OR]]
296;
297  %not = xor i1 %c, -1
298  %and1 = and i1 %not, %a
299  %and2 = and i1 %c, %b
300  %or = select i1 %and1, i1 true, i1 %and2
301  ret i1 %or
302}
303
304define i1 @bools_logical_commute1(i1 %a, i1 %b, i1 %c) {
305; CHECK-LABEL: @bools_logical_commute1(
306; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 [[B:%.*]], i1 [[A:%.*]]
307; CHECK-NEXT:    ret i1 [[OR]]
308;
309  %not = xor i1 %c, -1
310  %and1 = select i1 %a, i1 %not, i1 false
311  %and2 = select i1 %c, i1 %b, i1 false
312  %or = select i1 %and1, i1 true, i1 %and2
313  ret i1 %or
314}
315
316define i1 @bools_logical_commute1_and1(i1 %b, i1 %c) {
317; CHECK-LABEL: @bools_logical_commute1_and1(
318; CHECK-NEXT:    [[A:%.*]] = call i1 @gen1()
319; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 [[B:%.*]], i1 [[A]]
320; CHECK-NEXT:    ret i1 [[OR]]
321;
322  %a = call i1 @gen1()
323  %not = xor i1 %c, -1
324  %and1 = and i1 %a, %not
325  %and2 = select i1 %c, i1 %b, i1 false
326  %or = select i1 %and1, i1 true, i1 %and2
327  ret i1 %or
328}
329
330define i1 @bools_logical_commute1_and2(i1 %a, i1 %b, i1 %c) {
331; CHECK-LABEL: @bools_logical_commute1_and2(
332; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 [[B:%.*]], i1 [[A:%.*]]
333; CHECK-NEXT:    ret i1 [[OR]]
334;
335  %not = xor i1 %c, -1
336  %and1 = select i1 %a, i1 %not, i1 false
337  %and2 = and i1 %c, %b
338  %or = select i1 %and1, i1 true, i1 %and2
339  ret i1 %or
340}
341
342define i1 @bools_logical_commute1_and1_and2(i1 %b, i1 %c) {
343; CHECK-LABEL: @bools_logical_commute1_and1_and2(
344; CHECK-NEXT:    [[A:%.*]] = call i1 @gen1()
345; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 [[B:%.*]], i1 [[A]]
346; CHECK-NEXT:    ret i1 [[OR]]
347;
348  %a = call i1 @gen1()
349  %not = xor i1 %c, -1
350  %and1 = and i1 %a, %not
351  %and2 = and i1 %c, %b
352  %or = select i1 %and1, i1 true, i1 %and2
353  ret i1 %or
354}
355
356define <2 x i1> @bools_logical_commute2(<2 x i1> %a, <2 x i1> %b, <2 x i1> %c) {
357; CHECK-LABEL: @bools_logical_commute2(
358; CHECK-NEXT:    [[OR:%.*]] = select <2 x i1> [[C:%.*]], <2 x i1> [[B:%.*]], <2 x i1> [[A:%.*]]
359; CHECK-NEXT:    ret <2 x i1> [[OR]]
360;
361  %not = xor <2 x i1> %c, <i1 -1, i1 -1>
362  %and1 = select <2 x i1> %not, <2 x i1> %a, <2 x i1> <i1 false, i1 false>
363  %and2 = select <2 x i1> %b, <2 x i1> %c, <2 x i1> <i1 false, i1 false>
364  %or = select <2 x i1> %and1, <2 x i1> <i1 true, i1 true>, <2 x i1> %and2
365  ret <2 x i1> %or
366}
367
368define <2 x i1> @bools_logical_commute2_and1(<2 x i1> %a, <2 x i1> %b, <2 x i1> %c) {
369; CHECK-LABEL: @bools_logical_commute2_and1(
370; CHECK-NEXT:    [[OR:%.*]] = select <2 x i1> [[C:%.*]], <2 x i1> [[B:%.*]], <2 x i1> [[A:%.*]]
371; CHECK-NEXT:    ret <2 x i1> [[OR]]
372;
373  %not = xor <2 x i1> %c, <i1 -1, i1 -1>
374  %and1 = and <2 x i1> %not, %a
375  %and2 = select <2 x i1> %b, <2 x i1> %c, <2 x i1> <i1 false, i1 false>
376  %or = select <2 x i1> %and1, <2 x i1> <i1 true, i1 true>, <2 x i1> %and2
377  ret <2 x i1> %or
378}
379
380define <2 x i1> @bools_logical_commute2_and2(<2 x i1> %a, <2 x i1> %b, <2 x i1> %c) {
381; CHECK-LABEL: @bools_logical_commute2_and2(
382; CHECK-NEXT:    [[OR:%.*]] = select <2 x i1> [[C:%.*]], <2 x i1> [[B:%.*]], <2 x i1> [[A:%.*]]
383; CHECK-NEXT:    ret <2 x i1> [[OR]]
384;
385  %not = xor <2 x i1> %c, <i1 -1, i1 -1>
386  %and1 = select <2 x i1> %not, <2 x i1> %a, <2 x i1> <i1 false, i1 false>
387  %and2 = and <2 x i1> %b, %c
388  %or = select <2 x i1> %and1, <2 x i1> <i1 true, i1 true>, <2 x i1> %and2
389  ret <2 x i1> %or
390}
391
392define <2 x i1> @bools_logical_commute2_and1_and2(<2 x i1> %a, <2 x i1> %b, <2 x i1> %c) {
393; CHECK-LABEL: @bools_logical_commute2_and1_and2(
394; CHECK-NEXT:    [[OR:%.*]] = select <2 x i1> [[C:%.*]], <2 x i1> [[B:%.*]], <2 x i1> [[A:%.*]]
395; CHECK-NEXT:    ret <2 x i1> [[OR]]
396;
397  %not = xor <2 x i1> %c, <i1 -1, i1 -1>
398  %and1 = and <2 x i1> %not, %a
399  %and2 = and <2 x i1> %b, %c
400  %or = select <2 x i1> %and1, <2 x i1> <i1 true, i1 true>, <2 x i1> %and2
401  ret <2 x i1> %or
402}
403
404define i1 @bools_logical_commute3(i1 %a, i1 %b, i1 %c) {
405; CHECK-LABEL: @bools_logical_commute3(
406; CHECK-NEXT:    [[TMP1:%.*]] = freeze i1 [[C:%.*]]
407; CHECK-NEXT:    [[OR:%.*]] = select i1 [[TMP1]], i1 [[B:%.*]], i1 [[A:%.*]]
408; CHECK-NEXT:    ret i1 [[OR]]
409;
410  %not = xor i1 %c, -1
411  %and1 = select i1 %a, i1 %not, i1 false
412  %and2 = select i1 %b, i1 %c, i1 false
413  %or = select i1 %and1, i1 true, i1 %and2
414  ret i1 %or
415}
416
417define i1 @bools_logical_commute3_and1(i1 %b, i1 %c) {
418; CHECK-LABEL: @bools_logical_commute3_and1(
419; CHECK-NEXT:    [[A:%.*]] = call i1 @gen1()
420; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 [[B:%.*]], i1 [[A]]
421; CHECK-NEXT:    ret i1 [[OR]]
422;
423  %a = call i1 @gen1()
424  %not = xor i1 %c, -1
425  %and1 = and i1 %a, %not
426  %and2 = select i1 %b, i1 %c, i1 false
427  %or = select i1 %and1, i1 true, i1 %and2
428  ret i1 %or
429}
430
431define i1 @bools_logical_commute3_and2(i1 %a, i1 %b, i1 %c) {
432; CHECK-LABEL: @bools_logical_commute3_and2(
433; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 [[B:%.*]], i1 [[A:%.*]]
434; CHECK-NEXT:    ret i1 [[OR]]
435;
436  %not = xor i1 %c, -1
437  %and1 = select i1 %a, i1 %not, i1 false
438  %and2 = and i1 %b, %c
439  %or = select i1 %and1, i1 true, i1 %and2
440  ret i1 %or
441}
442
443define i1 @bools_logical_commute3_and1_and2(i1 %b, i1 %c) {
444; CHECK-LABEL: @bools_logical_commute3_and1_and2(
445; CHECK-NEXT:    [[A:%.*]] = call i1 @gen1()
446; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 [[B:%.*]], i1 [[A]]
447; CHECK-NEXT:    ret i1 [[OR]]
448;
449  %a = call i1 @gen1()
450  %not = xor i1 %c, -1
451  %and1 = and i1 %a, %not
452  %and2 = and i1 %b, %c
453  %or = select i1 %and1, i1 true, i1 %and2
454  ret i1 %or
455}
456
457define i1 @bools2_logical_commute0(i1 %a, i1 %b, i1 %c) {
458; CHECK-LABEL: @bools2_logical_commute0(
459; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B:%.*]]
460; CHECK-NEXT:    ret i1 [[OR]]
461;
462  %not = xor i1 %c, -1
463  %and1 = select i1 %c, i1 %a, i1 false
464  %and2 = select i1 %not, i1 %b, i1 false
465  %or = select i1 %and1, i1 true, i1 %and2
466  ret i1 %or
467}
468
469define i1 @bools2_logical_commute0_and1(i1 %a, i1 %b, i1 %c) {
470; CHECK-LABEL: @bools2_logical_commute0_and1(
471; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B:%.*]]
472; CHECK-NEXT:    ret i1 [[OR]]
473;
474  %not = xor i1 %c, -1
475  %and1 = and i1 %c, %a
476  %and2 = select i1 %not, i1 %b, i1 false
477  %or = select i1 %and1, i1 true, i1 %and2
478  ret i1 %or
479}
480
481define i1 @bools2_logical_commute0_and2(i1 %a, i1 %b, i1 %c) {
482; CHECK-LABEL: @bools2_logical_commute0_and2(
483; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B:%.*]]
484; CHECK-NEXT:    ret i1 [[OR]]
485;
486  %not = xor i1 %c, -1
487  %and1 = select i1 %c, i1 %a, i1 false
488  %and2 = and i1 %not, %b
489  %or = select i1 %and1, i1 true, i1 %and2
490  ret i1 %or
491}
492
493define i1 @bools2_logical_commute0_and1_and2(i1 %a, i1 %b, i1 %c) {
494; CHECK-LABEL: @bools2_logical_commute0_and1_and2(
495; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B:%.*]]
496; CHECK-NEXT:    ret i1 [[OR]]
497;
498  %not = xor i1 %c, -1
499  %and1 = and i1 %c, %a
500  %and2 = and i1 %not, %b
501  %or = select i1 %and1, i1 true, i1 %and2
502  ret i1 %or
503}
504
505define i1 @bools2_logical_commute1(i1 %a, i1 %b, i1 %c) {
506; CHECK-LABEL: @bools2_logical_commute1(
507; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B:%.*]]
508; CHECK-NEXT:    ret i1 [[OR]]
509;
510  %not = xor i1 %c, -1
511  %and1 = select i1 %a, i1 %c, i1 false
512  %and2 = select i1 %not, i1 %b, i1 false
513  %or = select i1 %and1, i1 true, i1 %and2
514  ret i1 %or
515}
516
517define i1 @bools2_logical_commute1_and1(i1 %a, i1 %b, i1 %c) {
518; CHECK-LABEL: @bools2_logical_commute1_and1(
519; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B:%.*]]
520; CHECK-NEXT:    ret i1 [[OR]]
521;
522  %not = xor i1 %c, -1
523  %and1 = and i1 %a, %c
524  %and2 = select i1 %not, i1 %b, i1 false
525  %or = select i1 %and1, i1 true, i1 %and2
526  ret i1 %or
527}
528
529define i1 @bools2_logical_commute1_and2(i1 %a, i1 %b, i1 %c) {
530; CHECK-LABEL: @bools2_logical_commute1_and2(
531; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B:%.*]]
532; CHECK-NEXT:    ret i1 [[OR]]
533;
534  %not = xor i1 %c, -1
535  %and1 = select i1 %a, i1 %c, i1 false
536  %and2 = and i1 %not, %b
537  %or = select i1 %and1, i1 true, i1 %and2
538  ret i1 %or
539}
540
541define i1 @bools2_logical_commute1_and1_and2(i1 %a, i1 %b, i1 %c) {
542; CHECK-LABEL: @bools2_logical_commute1_and1_and2(
543; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B:%.*]]
544; CHECK-NEXT:    ret i1 [[OR]]
545;
546  %not = xor i1 %c, -1
547  %and1 = and i1 %a, %c
548  %and2 = and i1 %not, %b
549  %or = select i1 %and1, i1 true, i1 %and2
550  ret i1 %or
551}
552
553define i1 @bools2_logical_commute2(i1 %a, i1 %b, i1 %c) {
554; CHECK-LABEL: @bools2_logical_commute2(
555; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B:%.*]]
556; CHECK-NEXT:    ret i1 [[OR]]
557;
558  %not = xor i1 %c, -1
559  %and1 = select i1 %c, i1 %a, i1 false
560  %and2 = select i1 %b, i1 %not, i1 false
561  %or = select i1 %and1, i1 true, i1 %and2
562  ret i1 %or
563}
564
565define i1 @bools2_logical_commute2_and1(i1 %a, i1 %b, i1 %c) {
566; CHECK-LABEL: @bools2_logical_commute2_and1(
567; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B:%.*]]
568; CHECK-NEXT:    ret i1 [[OR]]
569;
570  %not = xor i1 %c, -1
571  %and1 = and i1 %c, %a
572  %and2 = select i1 %b, i1 %not, i1 false
573  %or = select i1 %and1, i1 true, i1 %and2
574  ret i1 %or
575}
576
577define i1 @bools2_logical_commute2_and2(i1 %a, i1 %c) {
578; CHECK-LABEL: @bools2_logical_commute2_and2(
579; CHECK-NEXT:    [[B:%.*]] = call i1 @gen1()
580; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B]]
581; CHECK-NEXT:    ret i1 [[OR]]
582;
583  %b = call i1 @gen1()
584  %not = xor i1 %c, -1
585  %and1 = select i1 %c, i1 %a, i1 false
586  %and2 = and i1 %b, %not
587  %or = select i1 %and1, i1 true, i1 %and2
588  ret i1 %or
589}
590
591define i1 @bools2_logical_commute2_and1_and2(i1 %a, i1 %c) {
592; CHECK-LABEL: @bools2_logical_commute2_and1_and2(
593; CHECK-NEXT:    [[B:%.*]] = call i1 @gen1()
594; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B]]
595; CHECK-NEXT:    ret i1 [[OR]]
596;
597  %b = call i1 @gen1()
598  %not = xor i1 %c, -1
599  %and1 = and i1 %c, %a
600  %and2 = and i1 %b, %not
601  %or = select i1 %and1, i1 true, i1 %and2
602  ret i1 %or
603}
604
605; Freeze 'c' to prevent poison from leaking.
606
607define i1 @bools2_logical_commute3(i1 %a, i1 %b, i1 %c) {
608; CHECK-LABEL: @bools2_logical_commute3(
609; CHECK-NEXT:    [[TMP1:%.*]] = freeze i1 [[C:%.*]]
610; CHECK-NEXT:    [[OR:%.*]] = select i1 [[TMP1]], i1 [[A:%.*]], i1 [[B:%.*]]
611; CHECK-NEXT:    ret i1 [[OR]]
612;
613  %not = xor i1 %c, -1
614  %and1 = select i1 %a, i1 %c, i1 false
615  %and2 = select i1 %b, i1 %not, i1 false
616  %or = select i1 %and1, i1 true, i1 %and2
617  ret i1 %or
618}
619
620; No freeze needed when 'c' is guaranteed not be poison.
621; Intermediate logic folds may already reduce this.
622
623define i1 @bools2_logical_commute3_nopoison(i1 %a, i1 %b, i1 noundef %c) {
624; CHECK-LABEL: @bools2_logical_commute3_nopoison(
625; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B:%.*]]
626; CHECK-NEXT:    ret i1 [[OR]]
627;
628  %not = xor i1 %c, -1
629  %and1 = select i1 %a, i1 %c, i1 false
630  %and2 = select i1 %b, i1 %not, i1 false
631  %or = select i1 %and1, i1 true, i1 %and2
632  ret i1 %or
633}
634
635define i1 @bools2_logical_commute3_and1(i1 %a, i1 %b, i1 %c) {
636; CHECK-LABEL: @bools2_logical_commute3_and1(
637; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B:%.*]]
638; CHECK-NEXT:    ret i1 [[OR]]
639;
640  %not = xor i1 %c, -1
641  %and1 = and i1 %a, %c
642  %and2 = select i1 %b, i1 %not, i1 false
643  %or = select i1 %and1, i1 true, i1 %and2
644  ret i1 %or
645}
646
647define i1 @bools2_logical_commute3_and2(i1 %a, i1 %c) {
648; CHECK-LABEL: @bools2_logical_commute3_and2(
649; CHECK-NEXT:    [[B:%.*]] = call i1 @gen1()
650; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B]]
651; CHECK-NEXT:    ret i1 [[OR]]
652;
653  %b = call i1 @gen1()
654  %not = xor i1 %c, -1
655  %and1 = select i1 %a, i1 %c, i1 false
656  %and2 = and i1 %b, %not
657  %or = select i1 %and1, i1 true, i1 %and2
658  ret i1 %or
659}
660
661define i1 @bools2_logical_commute3_and1_and2(i1 %a, i1 %c) {
662; CHECK-LABEL: @bools2_logical_commute3_and1_and2(
663; CHECK-NEXT:    [[B:%.*]] = call i1 @gen1()
664; CHECK-NEXT:    [[OR:%.*]] = select i1 [[C:%.*]], i1 [[A:%.*]], i1 [[B]]
665; CHECK-NEXT:    ret i1 [[OR]]
666;
667  %b = call i1 @gen1()
668  %not = xor i1 %c, -1
669  %and1 = and i1 %a, %c
670  %and2 = and i1 %b, %not
671  %or = select i1 %and1, i1 true, i1 %and2
672  ret i1 %or
673}
674
675define i1 @orn_and_cmp_1_logical(i37 %a, i37 %b, i1 %y) {
676; CHECK-LABEL: @orn_and_cmp_1_logical(
677; CHECK-NEXT:    [[X_INV:%.*]] = icmp sle i37 [[A:%.*]], [[B:%.*]]
678; CHECK-NEXT:    [[OR:%.*]] = select i1 [[X_INV]], i1 true, i1 [[Y:%.*]]
679; CHECK-NEXT:    ret i1 [[OR]]
680;
681  %x = icmp sgt i37 %a, %b
682  %x_inv = icmp sle i37 %a, %b
683  %and = select i1 %y, i1 %x, i1 false
684  %or = select i1 %x_inv, i1 true, i1 %and
685  ret i1 %or
686}
687
688; TODO: This should fold the same way as the next test.
689
690define i1 @orn_and_cmp_1_partial_logical(i37 %a, i37 %b, i1 %y) {
691; CHECK-LABEL: @orn_and_cmp_1_partial_logical(
692; CHECK-NEXT:    [[X:%.*]] = icmp sgt i37 [[A:%.*]], [[B:%.*]]
693; CHECK-NEXT:    [[X_INV:%.*]] = icmp sle i37 [[A]], [[B]]
694; CHECK-NEXT:    [[AND:%.*]] = and i1 [[X]], [[Y:%.*]]
695; CHECK-NEXT:    [[OR:%.*]] = select i1 [[X_INV]], i1 true, i1 [[AND]]
696; CHECK-NEXT:    ret i1 [[OR]]
697;
698  %x = icmp sgt i37 %a, %b
699  %x_inv = icmp sle i37 %a, %b
700  %and = and i1 %x, %y
701  %or = select i1 %x_inv, i1 true, i1 %and
702  ret i1 %or
703}
704
705define i1 @orn_and_cmp_1_partial_logical_commute(i37 %a, i37 %b) {
706; CHECK-LABEL: @orn_and_cmp_1_partial_logical_commute(
707; CHECK-NEXT:    [[Y:%.*]] = call i1 @gen1()
708; CHECK-NEXT:    [[X_INV:%.*]] = icmp sle i37 [[A:%.*]], [[B:%.*]]
709; CHECK-NEXT:    [[OR:%.*]] = select i1 [[X_INV]], i1 true, i1 [[Y]]
710; CHECK-NEXT:    ret i1 [[OR]]
711;
712  %y = call i1 @gen1() ; thwart complexity-based canonicalization
713  %x = icmp sgt i37 %a, %b
714  %x_inv = icmp sle i37 %a, %b
715  %and = and i1 %y, %x
716  %or = select i1 %x_inv, i1 true, i1 %and
717  ret i1 %or
718}
719
720; TODO: This does not require poison-safe (select) logical-or.
721
722define i1 @orn_and_cmp_2_logical(i16 %a, i16 %b, i1 %y) {
723; CHECK-LABEL: @orn_and_cmp_2_logical(
724; CHECK-NEXT:    [[X_INV:%.*]] = icmp slt i16 [[A:%.*]], [[B:%.*]]
725; CHECK-NEXT:    [[OR:%.*]] = select i1 [[Y:%.*]], i1 true, i1 [[X_INV]]
726; CHECK-NEXT:    ret i1 [[OR]]
727;
728  %x = icmp sge i16 %a, %b
729  %x_inv = icmp slt i16 %a, %b
730  %and = select i1 %y, i1 %x, i1 false
731  %or = select i1 %and, i1 true, i1 %x_inv
732  ret i1 %or
733}
734
735define i1 @orn_and_cmp_2_partial_logical(i16 %a, i16 %b, i1 %y) {
736; CHECK-LABEL: @orn_and_cmp_2_partial_logical(
737; CHECK-NEXT:    [[X_INV:%.*]] = icmp slt i16 [[A:%.*]], [[B:%.*]]
738; CHECK-NEXT:    [[OR:%.*]] = or i1 [[Y:%.*]], [[X_INV]]
739; CHECK-NEXT:    ret i1 [[OR]]
740;
741  %x = icmp sge i16 %a, %b
742  %x_inv = icmp slt i16 %a, %b
743  %and = and i1 %x, %y
744  %or = select i1 %and, i1 true, i1 %x_inv
745  ret i1 %or
746}
747
748define i1 @orn_and_cmp_2_partial_logical_commute(i16 %a, i16 %b) {
749; CHECK-LABEL: @orn_and_cmp_2_partial_logical_commute(
750; CHECK-NEXT:    [[Y:%.*]] = call i1 @gen1()
751; CHECK-NEXT:    [[X_INV:%.*]] = icmp slt i16 [[A:%.*]], [[B:%.*]]
752; CHECK-NEXT:    [[OR:%.*]] = or i1 [[Y]], [[X_INV]]
753; CHECK-NEXT:    ret i1 [[OR]]
754;
755  %y = call i1 @gen1() ; thwart complexity-based canonicalization
756  %x = icmp sge i16 %a, %b
757  %x_inv = icmp slt i16 %a, %b
758  %and = and i1 %y, %x
759  %or = select i1 %and, i1 true, i1 %x_inv
760  ret i1 %or
761}
762
763; PR58552 - this would crash trying to replace non-matching types
764
765define <2 x i1> @not_logical_and(i1 %b, <2 x i32> %a) {
766; CHECK-LABEL: @not_logical_and(
767; CHECK-NEXT:    [[COND:%.*]] = icmp ult <2 x i32> [[A:%.*]], splat (i32 3)
768; CHECK-NEXT:    [[IMPLIED:%.*]] = icmp ugt <2 x i32> [[A]], splat (i32 1)
769; CHECK-NEXT:    [[AND:%.*]] = select i1 [[B:%.*]], <2 x i1> [[COND]], <2 x i1> zeroinitializer
770; CHECK-NEXT:    [[OR:%.*]] = select <2 x i1> [[IMPLIED]], <2 x i1> splat (i1 true), <2 x i1> [[AND]]
771; CHECK-NEXT:    ret <2 x i1> [[OR]]
772;
773  %cond = icmp ult <2 x i32> %a, <i32 3, i32 3>
774  %implied = icmp ugt <2 x i32> %a, <i32 1, i32 1>
775  %and = select i1 %b, <2 x i1> %cond, <2 x i1> zeroinitializer
776  %or = select <2 x i1> %implied, <2 x i1> <i1 true, i1 true>, <2 x i1> %and
777  ret <2 x i1> %or
778}
779
780; This could reduce, but we do not match select-of-vectors with scalar condition as logical-and.
781
782define <2 x i1> @not_logical_and2(i1 %b, <2 x i32> %a) {
783; CHECK-LABEL: @not_logical_and2(
784; CHECK-NEXT:    [[COND:%.*]] = icmp ult <2 x i32> [[A:%.*]], splat (i32 3)
785; CHECK-NEXT:    [[IMPLIED:%.*]] = icmp ugt <2 x i32> [[A]], splat (i32 1)
786; CHECK-NEXT:    [[AND:%.*]] = select i1 [[B:%.*]], <2 x i1> [[COND]], <2 x i1> zeroinitializer
787; CHECK-NEXT:    [[OR:%.*]] = select <2 x i1> [[AND]], <2 x i1> splat (i1 true), <2 x i1> [[IMPLIED]]
788; CHECK-NEXT:    ret <2 x i1> [[OR]]
789;
790  %cond = icmp ult <2 x i32> %a, <i32 3, i32 3>
791  %implied = icmp ugt <2 x i32> %a, <i32 1, i32 1>
792  %and = select i1 %b, <2 x i1> %cond, <2 x i1> zeroinitializer
793  %or = select <2 x i1> %and, <2 x i1> <i1 true, i1 true>, <2 x i1> %implied
794  ret <2 x i1> %or
795}
796