1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -instcombine < %s | FileCheck %s
6 ; Should not be converted to "and", which has different poison semantics.
7 define i1 @logical_and(i1 %a, i1 %b) {
8 ; CHECK-LABEL: @logical_and(
9 ; CHECK-NEXT: [[RES:%.*]] = select i1 [[A:%.*]], i1 [[B:%.*]], i1 false
10 ; CHECK-NEXT: ret i1 [[RES]]
12 %res = select i1 %a, i1 %b, i1 false
16 ; Should not be converted to "or", which has different poison semantics.
17 define i1 @logical_or(i1 %a, i1 %b) {
18 ; CHECK-LABEL: @logical_or(
19 ; CHECK-NEXT: [[RES:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[B:%.*]]
20 ; CHECK-NEXT: ret i1 [[RES]]
22 %res = select i1 %a, i1 true, i1 %b
25 ; Canonicalize to logical and form, even if that requires adding a "not".
26 define i1 @logical_and_not(i1 %a, i1 %b) {
27 ; CHECK-LABEL: @logical_and_not(
28 ; CHECK-NEXT: [[NOT_A:%.*]] = xor i1 [[A:%.*]], true
29 ; CHECK-NEXT: [[RES:%.*]] = select i1 [[NOT_A]], i1 [[B:%.*]], i1 false
30 ; CHECK-NEXT: ret i1 [[RES]]
32 %res = select i1 %a, i1 false, i1 %b
36 ; Canonicalize to logical or form, even if that requires adding a "not".
37 define i1 @logical_or_not(i1 %a, i1 %b) {
38 ; CHECK-LABEL: @logical_or_not(
39 ; CHECK-NEXT: [[NOT_A:%.*]] = xor i1 [[A:%.*]], true
40 ; CHECK-NEXT: [[RES:%.*]] = select i1 [[NOT_A]], i1 true, i1 [[B:%.*]]
41 ; CHECK-NEXT: ret i1 [[RES]]
43 %res = select i1 %a, i1 %b, i1 true
47 ; These are variants where condition or !condition is used to represent true
48 ; or false in one of the select arms. It should be canonicalized to the
51 define i1 @logical_and_cond_reuse(i1 %a, i1 %b) {
52 ; CHECK-LABEL: @logical_and_cond_reuse(
53 ; CHECK-NEXT: [[RES:%.*]] = select i1 [[A:%.*]], i1 [[B:%.*]], i1 false
54 ; CHECK-NEXT: ret i1 [[RES]]
56 %res = select i1 %a, i1 %b, i1 %a
60 define i1 @logical_or_cond_reuse(i1 %a, i1 %b) {
61 ; CHECK-LABEL: @logical_or_cond_reuse(
62 ; CHECK-NEXT: [[RES:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[B:%.*]]
63 ; CHECK-NEXT: ret i1 [[RES]]
65 %res = select i1 %a, i1 %a, i1 %b
69 define i1 @logical_and_not_cond_reuse(i1 %a, i1 %b) {
70 ; CHECK-LABEL: @logical_and_not_cond_reuse(
71 ; CHECK-NEXT: [[A_NOT:%.*]] = xor i1 [[A:%.*]], true
72 ; CHECK-NEXT: [[RES:%.*]] = select i1 [[A_NOT]], i1 true, i1 [[B:%.*]]
73 ; CHECK-NEXT: ret i1 [[RES]]
75 %a.not = xor i1 %a, true
76 %res = select i1 %a, i1 %b, i1 %a.not
80 define i1 @logical_or_not_cond_reuse(i1 %a, i1 %b) {
81 ; CHECK-LABEL: @logical_or_not_cond_reuse(
82 ; CHECK-NEXT: [[A_NOT:%.*]] = xor i1 [[A:%.*]], true
83 ; CHECK-NEXT: [[RES:%.*]] = select i1 [[A_NOT]], i1 [[B:%.*]], i1 false
84 ; CHECK-NEXT: ret i1 [[RES]]
86 %a.not = xor i1 %a, true
87 %res = select i1 %a, i1 %a.not, i1 %b
91 ; Safe to convert to or due to poison implication.
92 define i1 @logical_or_implies(i32 %x) {
93 ; CHECK-LABEL: @logical_or_implies(
94 ; CHECK-NEXT: [[C1:%.*]] = icmp eq i32 [[X:%.*]], 0
95 ; CHECK-NEXT: [[C2:%.*]] = icmp eq i32 [[X]], 42
96 ; CHECK-NEXT: [[RES:%.*]] = or i1 [[C1]], [[C2]]
97 ; CHECK-NEXT: ret i1 [[RES]]
99 %c1 = icmp eq i32 %x, 0
100 %c2 = icmp eq i32 %x, 42
101 %res = select i1 %c1, i1 true, i1 %c2
105 ; Will fold after conversion to or.
106 define i1 @logical_or_implies_folds(i32 %x) {
107 ; CHECK-LABEL: @logical_or_implies_folds(
108 ; CHECK-NEXT: ret i1 true
110 %c1 = icmp slt i32 %x, 0
111 %c2 = icmp sge i32 %x, 0
112 %res = select i1 %c1, i1 true, i1 %c2
116 ; Safe to convert to and due to poison implication.
117 define i1 @logical_and_implies(i32 %x) {
118 ; CHECK-LABEL: @logical_and_implies(
119 ; CHECK-NEXT: [[C1:%.*]] = icmp ne i32 [[X:%.*]], 0
120 ; CHECK-NEXT: [[C2:%.*]] = icmp ne i32 [[X]], 42
121 ; CHECK-NEXT: [[RES:%.*]] = and i1 [[C1]], [[C2]]
122 ; CHECK-NEXT: ret i1 [[RES]]
124 %c1 = icmp ne i32 %x, 0
125 %c2 = icmp ne i32 %x, 42
126 %res = select i1 %c1, i1 %c2, i1 false
130 ; Will fold after conversion to and.
131 define i1 @logical_and_implies_folds(i32 %x) {
132 ; CHECK-LABEL: @logical_and_implies_folds(
133 ; CHECK-NEXT: [[C1:%.*]] = icmp ugt i32 [[X:%.*]], 42
134 ; CHECK-NEXT: ret i1 [[C1]]
136 %c1 = icmp ugt i32 %x, 42
137 %c2 = icmp ne i32 %x, 0
138 %res = select i1 %c1, i1 %c2, i1 false
142 ; Noundef on condition has no effect.
143 define i1 @logical_or_noundef_a(i1 noundef %a, i1 %b) {
144 ; CHECK-LABEL: @logical_or_noundef_a(
145 ; CHECK-NEXT: [[RES:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[B:%.*]]
146 ; CHECK-NEXT: ret i1 [[RES]]
148 %res = select i1 %a, i1 true, i1 %b
152 ; Noundef on false value allows conversion to or.
153 define i1 @logical_or_noundef_b(i1 %a, i1 noundef %b) {
154 ; CHECK-LABEL: @logical_or_noundef_b(
155 ; CHECK-NEXT: [[RES:%.*]] = or i1 [[A:%.*]], [[B:%.*]]
156 ; CHECK-NEXT: ret i1 [[RES]]
158 %res = select i1 %a, i1 true, i1 %b
162 ; Noundef on condition has no effect.
163 define i1 @logical_and_noundef_a(i1 noundef %a, i1 %b) {
164 ; CHECK-LABEL: @logical_and_noundef_a(
165 ; CHECK-NEXT: [[RES:%.*]] = select i1 [[A:%.*]], i1 [[B:%.*]], i1 false
166 ; CHECK-NEXT: ret i1 [[RES]]
168 %res = select i1 %a, i1 %b, i1 false
172 ; Noundef on false value allows conversion to and.
173 define i1 @logical_and_noundef_b(i1 %a, i1 noundef %b) {
174 ; CHECK-LABEL: @logical_and_noundef_b(
175 ; CHECK-NEXT: [[RES:%.*]] = and i1 [[A:%.*]], [[B:%.*]]
176 ; CHECK-NEXT: ret i1 [[RES]]
178 %res = select i1 %a, i1 %b, i1 false
182 ; (!x && !y) || x --> x || !y
184 define i1 @not_not_true(i1 %x, i1 %y) {
185 ; CHECK-LABEL: @not_not_true(
186 ; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true
187 ; CHECK-NEXT: [[R:%.*]] = select i1 [[X:%.*]], i1 true, i1 [[NOTY]]
188 ; CHECK-NEXT: ret i1 [[R]]
190 %notx = xor i1 %x, true
191 %noty = xor i1 %y, true
192 %r = select i1 %notx, i1 %noty, i1 true
196 ; (!x && !y) --> !(x || y)
198 define i1 @not_not_false(i1 %x, i1 %y) {
199 ; CHECK-LABEL: @not_not_false(
200 ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[X:%.*]], i1 true, i1 [[Y:%.*]]
201 ; CHECK-NEXT: [[R:%.*]] = xor i1 [[TMP1]], true
202 ; CHECK-NEXT: ret i1 [[R]]
204 %notx = xor i1 %x, true
205 %noty = xor i1 %y, true
206 %r = select i1 %notx, i1 %noty, i1 false
210 ; (!x || !y) --> !(x && y)
212 define i1 @not_true_not(i1 %x, i1 %y) {
213 ; CHECK-LABEL: @not_true_not(
214 ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[X:%.*]], i1 [[Y:%.*]], i1 false
215 ; CHECK-NEXT: [[R:%.*]] = xor i1 [[TMP1]], true
216 ; CHECK-NEXT: ret i1 [[R]]
218 %notx = xor i1 %x, true
219 %noty = xor i1 %y, true
220 %r = select i1 %notx, i1 true, i1 %noty
224 ; (!!x && !y) --> x && !y
226 define i1 @not_false_not(i1 %x, i1 %y) {
227 ; CHECK-LABEL: @not_false_not(
228 ; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true
229 ; CHECK-NEXT: [[R:%.*]] = select i1 [[X:%.*]], i1 [[NOTY]], i1 false
230 ; CHECK-NEXT: ret i1 [[R]]
232 %notx = xor i1 %x, true
233 %noty = xor i1 %y, true
234 %r = select i1 %notx, i1 false, i1 %noty
238 define i1 @not_not_true_use1(i1 %x, i1 %y) {
239 ; CHECK-LABEL: @not_not_true_use1(
240 ; CHECK-NEXT: [[NOTX:%.*]] = xor i1 [[X:%.*]], true
241 ; CHECK-NEXT: call void @use(i1 [[NOTX]])
242 ; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true
243 ; CHECK-NEXT: [[R:%.*]] = select i1 [[X]], i1 true, i1 [[NOTY]]
244 ; CHECK-NEXT: ret i1 [[R]]
246 %notx = xor i1 %x, true
247 call void @use(i1 %notx)
248 %noty = xor i1 %y, true
249 %r = select i1 %notx, i1 %noty, i1 true
253 define i1 @not_not_false_use1(i1 %x, i1 %y) {
254 ; CHECK-LABEL: @not_not_false_use1(
255 ; CHECK-NEXT: [[NOTX:%.*]] = xor i1 [[X:%.*]], true
256 ; CHECK-NEXT: call void @use(i1 [[NOTX]])
257 ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[X]], i1 true, i1 [[Y:%.*]]
258 ; CHECK-NEXT: [[R:%.*]] = xor i1 [[TMP1]], true
259 ; CHECK-NEXT: ret i1 [[R]]
261 %notx = xor i1 %x, true
262 call void @use(i1 %notx)
263 %noty = xor i1 %y, true
264 %r = select i1 %notx, i1 %noty, i1 false
268 define i1 @not_true_not_use1(i1 %x, i1 %y) {
269 ; CHECK-LABEL: @not_true_not_use1(
270 ; CHECK-NEXT: [[NOTX:%.*]] = xor i1 [[X:%.*]], true
271 ; CHECK-NEXT: call void @use(i1 [[NOTX]])
272 ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[X]], i1 [[Y:%.*]], i1 false
273 ; CHECK-NEXT: [[R:%.*]] = xor i1 [[TMP1]], true
274 ; CHECK-NEXT: ret i1 [[R]]
276 %notx = xor i1 %x, true
277 call void @use(i1 %notx)
278 %noty = xor i1 %y, true
279 %r = select i1 %notx, i1 true, i1 %noty
283 define i1 @not_false_not_use1(i1 %x, i1 %y) {
284 ; CHECK-LABEL: @not_false_not_use1(
285 ; CHECK-NEXT: [[NOTX:%.*]] = xor i1 [[X:%.*]], true
286 ; CHECK-NEXT: call void @use(i1 [[NOTX]])
287 ; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true
288 ; CHECK-NEXT: [[R:%.*]] = select i1 [[X]], i1 [[NOTY]], i1 false
289 ; CHECK-NEXT: ret i1 [[R]]
291 %notx = xor i1 %x, true
292 call void @use(i1 %notx)
293 %noty = xor i1 %y, true
294 %r = select i1 %notx, i1 false, i1 %noty
298 define i1 @not_not_true_use2(i1 %x, i1 %y) {
299 ; CHECK-LABEL: @not_not_true_use2(
300 ; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true
301 ; CHECK-NEXT: call void @use(i1 [[NOTY]])
302 ; CHECK-NEXT: [[R:%.*]] = select i1 [[X:%.*]], i1 true, i1 [[NOTY]]
303 ; CHECK-NEXT: ret i1 [[R]]
305 %notx = xor i1 %x, true
306 %noty = xor i1 %y, true
307 call void @use(i1 %noty)
308 %r = select i1 %notx, i1 %noty, i1 true
312 define i1 @not_not_false_use2(i1 %x, i1 %y) {
313 ; CHECK-LABEL: @not_not_false_use2(
314 ; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true
315 ; CHECK-NEXT: call void @use(i1 [[NOTY]])
316 ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[X:%.*]], i1 true, i1 [[Y]]
317 ; CHECK-NEXT: [[R:%.*]] = xor i1 [[TMP1]], true
318 ; CHECK-NEXT: ret i1 [[R]]
320 %notx = xor i1 %x, true
321 %noty = xor i1 %y, true
322 call void @use(i1 %noty)
323 %r = select i1 %notx, i1 %noty, i1 false
327 define i1 @not_true_not_use2(i1 %x, i1 %y) {
328 ; CHECK-LABEL: @not_true_not_use2(
329 ; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true
330 ; CHECK-NEXT: call void @use(i1 [[NOTY]])
331 ; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[X:%.*]], i1 [[Y]], i1 false
332 ; CHECK-NEXT: [[R:%.*]] = xor i1 [[TMP1]], true
333 ; CHECK-NEXT: ret i1 [[R]]
335 %notx = xor i1 %x, true
336 %noty = xor i1 %y, true
337 call void @use(i1 %noty)
338 %r = select i1 %notx, i1 true, i1 %noty
342 define i1 @not_false_not_use2(i1 %x, i1 %y) {
343 ; CHECK-LABEL: @not_false_not_use2(
344 ; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true
345 ; CHECK-NEXT: call void @use(i1 [[NOTY]])
346 ; CHECK-NEXT: [[R:%.*]] = select i1 [[X:%.*]], i1 [[NOTY]], i1 false
347 ; CHECK-NEXT: ret i1 [[R]]
349 %notx = xor i1 %x, true
350 %noty = xor i1 %y, true
351 call void @use(i1 %noty)
352 %r = select i1 %notx, i1 false, i1 %noty
356 define i1 @not_not_true_use3(i1 %x, i1 %y) {
357 ; CHECK-LABEL: @not_not_true_use3(
358 ; CHECK-NEXT: [[NOTX:%.*]] = xor i1 [[X:%.*]], true
359 ; CHECK-NEXT: call void @use(i1 [[NOTX]])
360 ; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true
361 ; CHECK-NEXT: call void @use(i1 [[NOTY]])
362 ; CHECK-NEXT: [[R:%.*]] = select i1 [[X]], i1 true, i1 [[NOTY]]
363 ; CHECK-NEXT: ret i1 [[R]]
365 %notx = xor i1 %x, true
366 call void @use(i1 %notx)
367 %noty = xor i1 %y, true
368 call void @use(i1 %noty)
369 %r = select i1 %notx, i1 %noty, i1 true
373 define i1 @not_not_false_use3(i1 %x, i1 %y) {
374 ; CHECK-LABEL: @not_not_false_use3(
375 ; CHECK-NEXT: [[NOTX:%.*]] = xor i1 [[X:%.*]], true
376 ; CHECK-NEXT: call void @use(i1 [[NOTX]])
377 ; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true
378 ; CHECK-NEXT: call void @use(i1 [[NOTY]])
379 ; CHECK-NEXT: [[R:%.*]] = select i1 [[NOTX]], i1 [[NOTY]], i1 false
380 ; CHECK-NEXT: ret i1 [[R]]
382 %notx = xor i1 %x, true
383 call void @use(i1 %notx)
384 %noty = xor i1 %y, true
385 call void @use(i1 %noty)
386 %r = select i1 %notx, i1 %noty, i1 false
390 define i1 @not_true_not_use3(i1 %x, i1 %y) {
391 ; CHECK-LABEL: @not_true_not_use3(
392 ; CHECK-NEXT: [[NOTX:%.*]] = xor i1 [[X:%.*]], true
393 ; CHECK-NEXT: call void @use(i1 [[NOTX]])
394 ; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true
395 ; CHECK-NEXT: call void @use(i1 [[NOTY]])
396 ; CHECK-NEXT: [[R:%.*]] = select i1 [[NOTX]], i1 true, i1 [[NOTY]]
397 ; CHECK-NEXT: ret i1 [[R]]
399 %notx = xor i1 %x, true
400 call void @use(i1 %notx)
401 %noty = xor i1 %y, true
402 call void @use(i1 %noty)
403 %r = select i1 %notx, i1 true, i1 %noty
407 define i1 @not_false_not_use3(i1 %x, i1 %y) {
408 ; CHECK-LABEL: @not_false_not_use3(
409 ; CHECK-NEXT: [[NOTX:%.*]] = xor i1 [[X:%.*]], true
410 ; CHECK-NEXT: call void @use(i1 [[NOTX]])
411 ; CHECK-NEXT: [[NOTY:%.*]] = xor i1 [[Y:%.*]], true
412 ; CHECK-NEXT: call void @use(i1 [[NOTY]])
413 ; CHECK-NEXT: [[R:%.*]] = select i1 [[X]], i1 [[NOTY]], i1 false
414 ; CHECK-NEXT: ret i1 [[R]]
416 %notx = xor i1 %x, true
417 call void @use(i1 %notx)
418 %noty = xor i1 %y, true
419 call void @use(i1 %noty)
420 %r = select i1 %notx, i1 false, i1 %noty
424 ; https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=35399
426 @g1 = external global i16
427 @g2 = external global i16
429 define i1 @demorgan_select_infloop1(i1 %L) {
430 ; CHECK-LABEL: @demorgan_select_infloop1(
431 ; CHECK-NEXT: [[NOT_L:%.*]] = xor i1 [[L:%.*]], true
432 ; CHECK-NEXT: [[C15:%.*]] = select i1 [[NOT_L]], i1 xor (i1 and (i1 icmp eq (i16* getelementptr inbounds (i16, i16* @g2, i64 1), i16* @g1), i1 icmp ne (i16* getelementptr inbounds (i16, i16* @g2, i64 1), i16* @g1)), i1 true), i1 false
433 ; CHECK-NEXT: ret i1 [[C15]]
435 %not.L = xor i1 %L, true
436 %C15 = select i1 %not.L, i1 xor (i1 and (i1 icmp eq (i16* getelementptr inbounds (i16, i16* @g2, i64 1), i16* @g1), i1 icmp ne (i16* getelementptr inbounds (i16, i16* @g2, i64 1), i16* @g1)), i1 true), i1 false
441 define i1 @demorgan_select_infloop2(i1 %L) {
442 ; CHECK-LABEL: @demorgan_select_infloop2(
443 ; CHECK-NEXT: [[NOT_L:%.*]] = xor i1 [[L:%.*]], true
444 ; CHECK-NEXT: [[C15:%.*]] = select i1 [[NOT_L]], i1 true, i1 xor (i1 and (i1 icmp eq (i16* getelementptr inbounds (i16, i16* @g2, i64 1), i16* @g1), i1 icmp ne (i16* getelementptr inbounds (i16, i16* @g2, i64 1), i16* @g1)), i1 true)
445 ; CHECK-NEXT: ret i1 [[C15]]
447 %not.L = xor i1 %L, true
448 %C15 = select i1 %not.L, i1 true, i1 xor (i1 and (i1 icmp eq (i16* getelementptr inbounds (i16, i16* @g2, i64 1), i16* @g1), i1 icmp ne (i16* getelementptr inbounds (i16, i16* @g2, i64 1), i16* @g1)), i1 true)