1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
4 define i1 @test_second_and_condition_implied_by_first(i8 %x) {
5 ; CHECK-LABEL: @test_second_and_condition_implied_by_first(
7 ; CHECK-NEXT: [[C_1:%.*]] = icmp ugt i8 [[X:%.*]], 10
8 ; CHECK-NEXT: [[T_1:%.*]] = icmp ugt i8 [[X]], 5
9 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[C_1]], true
10 ; CHECK-NEXT: br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]]
12 ; CHECK-NEXT: ret i1 false
14 ; CHECK-NEXT: ret i1 true
17 %c.1 = icmp ugt i8 %x, 10
18 %t.1 = icmp ugt i8 %x, 5
19 %and = and i1 %c.1, %t.1
20 br i1 %and, label %then, label %else
29 define i1 @test_first_and_condition_implied_by_second_ops(i8 %x) {
30 ; CHECK-LABEL: @test_first_and_condition_implied_by_second_ops(
32 ; CHECK-NEXT: [[C_1:%.*]] = icmp ugt i8 [[X:%.*]], 10
33 ; CHECK-NEXT: [[T_1:%.*]] = icmp ugt i8 [[X]], 5
34 ; CHECK-NEXT: [[AND:%.*]] = and i1 true, [[C_1]]
35 ; CHECK-NEXT: br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]]
37 ; CHECK-NEXT: ret i1 false
39 ; CHECK-NEXT: ret i1 true
42 %c.1 = icmp ugt i8 %x, 10
43 %t.1 = icmp ugt i8 %x, 5
44 %and = and i1 %t.1, %c.1
45 br i1 %and, label %then, label %else
54 define i1 @test_second_and_condition_implied_by_first_select_form(i8 %x) {
55 ; CHECK-LABEL: @test_second_and_condition_implied_by_first_select_form(
57 ; CHECK-NEXT: [[C_1:%.*]] = icmp ugt i8 [[X:%.*]], 10
58 ; CHECK-NEXT: [[T_1:%.*]] = icmp ugt i8 [[X]], 5
59 ; CHECK-NEXT: [[AND:%.*]] = select i1 [[C_1]], i1 true, i1 false
60 ; CHECK-NEXT: br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]]
62 ; CHECK-NEXT: ret i1 false
64 ; CHECK-NEXT: ret i1 true
67 %c.1 = icmp ugt i8 %x, 10
68 %t.1 = icmp ugt i8 %x, 5
69 %and = select i1 %c.1, i1 %t.1, i1 false
70 br i1 %and, label %then, label %else
79 define i1 @test_first_and_condition_implied_by_second_select_form(i8 %x) {
80 ; CHECK-LABEL: @test_first_and_condition_implied_by_second_select_form(
82 ; CHECK-NEXT: [[C_1:%.*]] = icmp ugt i8 [[X:%.*]], 10
83 ; CHECK-NEXT: [[T_1:%.*]] = icmp ugt i8 [[X]], 5
84 ; CHECK-NEXT: [[AND:%.*]] = select i1 [[T_1]], i1 [[C_1]], i1 false
85 ; CHECK-NEXT: br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]]
87 ; CHECK-NEXT: ret i1 false
89 ; CHECK-NEXT: ret i1 true
92 %c.1 = icmp ugt i8 %x, 10
93 %t.1 = icmp ugt i8 %x, 5
94 %and = select i1 %t.1, i1 %c.1, i1 false
95 br i1 %and, label %then, label %else
104 define i1 @test_same_cond_for_and(i8 %x) {
105 ; CHECK-LABEL: @test_same_cond_for_and(
107 ; CHECK-NEXT: [[C_1:%.*]] = icmp ugt i8 [[X:%.*]], 10
108 ; CHECK-NEXT: [[AND:%.*]] = and i1 true, [[C_1]]
109 ; CHECK-NEXT: br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]]
111 ; CHECK-NEXT: ret i1 false
113 ; CHECK-NEXT: ret i1 true
116 %c.1 = icmp ugt i8 %x, 10
117 %and = and i1 %c.1, %c.1
118 br i1 %and, label %then, label %else
127 define i1 @test_same_cond_for_and_select_form(i8 %x) {
128 ; CHECK-LABEL: @test_same_cond_for_and_select_form(
130 ; CHECK-NEXT: [[C_1:%.*]] = icmp ugt i8 [[X:%.*]], 10
131 ; CHECK-NEXT: [[AND:%.*]] = select i1 [[C_1]], i1 [[C_1]], i1 false
132 ; CHECK-NEXT: br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]]
134 ; CHECK-NEXT: ret i1 false
136 ; CHECK-NEXT: ret i1 true
139 %c.1 = icmp ugt i8 %x, 10
140 %and = select i1 %c.1, i1 %c.1, i1 false
141 br i1 %and, label %then, label %else
150 define i1 @test_second_and_condition_not_implied_by_first(i8 %x) {
151 ; CHECK-LABEL: @test_second_and_condition_not_implied_by_first(
153 ; CHECK-NEXT: [[C_1:%.*]] = icmp ugt i8 [[X:%.*]], 10
154 ; CHECK-NEXT: [[C_2:%.*]] = icmp ugt i8 [[X]], 5
155 ; CHECK-NEXT: [[AND:%.*]] = and i1 true, [[C_1]]
156 ; CHECK-NEXT: br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]]
158 ; CHECK-NEXT: ret i1 false
160 ; CHECK-NEXT: ret i1 true
163 %c.1 = icmp ugt i8 %x, 10
164 %c.2 = icmp ugt i8 %x, 5
165 %and = and i1 %c.2, %c.1
166 br i1 %and, label %then, label %else
175 define i1 @test_remove_variables(i1 %c, ptr %A, i64 %B, ptr %C) {
176 ; CHECK-LABEL: @test_remove_variables(
178 ; CHECK-NEXT: br i1 [[C:%.*]], label [[THEN_1:%.*]], label [[EXIT:%.*]]
180 ; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[C:%.*]], align 8
181 ; CHECK-NEXT: [[C_1:%.*]] = icmp ult ptr [[TMP0]], [[A:%.*]]
182 ; CHECK-NEXT: br i1 [[C_1]], label [[THEN_2:%.*]], label [[ELSE_2:%.*]]
184 ; CHECK-NEXT: [[C_3:%.*]] = icmp sgt i64 [[B:%.*]], 0
185 ; CHECK-NEXT: [[AND:%.*]] = and i1 true, [[C_3]]
186 ; CHECK-NEXT: ret i1 [[AND]]
188 ; CHECK-NEXT: ret i1 false
190 ; CHECK-NEXT: ret i1 true
193 br i1 %c, label %then.1, label %exit
196 %0 = load ptr, ptr %C, align 8
197 %c.1 = icmp ult ptr %0, %A
198 br i1 %c.1, label %then.2, label %else.2
201 %c.2 = icmp ne ptr %A, null
202 %c.3 = icmp sgt i64 %B, 0
203 %and = and i1 %c.2, %c.3
210 %t = icmp eq ptr null, null
214 define i1 @test_and_op_0_simplified(i32 %v) {
215 ; CHECK-LABEL: @test_and_op_0_simplified(
217 ; CHECK-NEXT: [[C_1:%.*]] = icmp sgt i32 [[V:%.*]], 0
218 ; CHECK-NEXT: [[AND:%.*]] = and i1 false, [[C_1]]
219 ; CHECK-NEXT: ret i1 [[AND]]
222 %c.1 = icmp sgt i32 %v, 0
223 %t.1 = icmp sgt i32 0, 0
224 %and = and i1 %t.1, %c.1
228 define i1 @test_and_op_1_simplified(i32 %v) {
229 ; CHECK-LABEL: @test_and_op_1_simplified(
231 ; CHECK-NEXT: [[C_1:%.*]] = icmp sgt i32 [[V:%.*]], 0
232 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[C_1]], false
233 ; CHECK-NEXT: ret i1 [[AND]]
236 %c.1 = icmp sgt i32 %v, 0
237 %t.1 = icmp sgt i32 0, 0
238 %and = and i1 %c.1, %t.1
242 define i1 @and_select_not_used_for_branch(i32 %x, i32 %y,i32 %z) {
243 ; CHECK-LABEL: @and_select_not_used_for_branch(
245 ; CHECK-NEXT: [[C_1:%.*]] = icmp ne i32 [[X:%.*]], 0
246 ; CHECK-NEXT: [[C_2:%.*]] = icmp ne i32 [[Y:%.*]], 0
247 ; CHECK-NEXT: [[C_3:%.*]] = icmp eq i32 [[X]], 16
248 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[C_2]], [[C_3]]
249 ; CHECK-NEXT: br i1 [[AND]], label [[THEN:%.*]], label [[EXIT:%.*]]
251 ; CHECK-NEXT: [[C_4:%.*]] = icmp eq i32 [[Z:%.*]], 0
252 ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[C_4]], i1 true, i1 false
253 ; CHECK-NEXT: br label [[EXIT]]
255 ; CHECK-NEXT: [[RES:%.*]] = phi i1 [ [[C_1]], [[ENTRY:%.*]] ], [ [[SEL]], [[THEN]] ]
256 ; CHECK-NEXT: ret i1 [[RES]]
259 %c.1 = icmp ne i32 %x, 0
260 %c.2 = icmp ne i32 %y, 0
261 %c.3 = icmp eq i32 %x, 16
262 %and = and i1 %c.2, %c.3
263 br i1 %and, label %then, label %exit
266 %c.4 = icmp eq i32 %z, 0
267 %sel = select i1 %c.4, i1 %c.1, i1 false
271 %res = phi i1 [ %c.1, %entry ], [ %sel, %then ]
275 define i1 @and_select_scope_limited(i32 %x, i32 %y, i32 %z) {
276 ; CHECK-LABEL: @and_select_scope_limited(
278 ; CHECK-NEXT: [[C_1:%.*]] = icmp ne i32 [[X:%.*]], 0
279 ; CHECK-NEXT: [[C_2:%.*]] = icmp ne i32 [[Y:%.*]], 0
280 ; CHECK-NEXT: [[C_3:%.*]] = icmp eq i32 [[X]], 16
281 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[C_2]], [[C_3]]
282 ; CHECK-NEXT: br i1 [[AND]], label [[THEN:%.*]], label [[EXIT:%.*]]
284 ; CHECK-NEXT: [[C_4:%.*]] = icmp eq i32 [[Z:%.*]], 0
285 ; CHECK-NEXT: [[SEL:%.*]] = select i1 [[C_4]], i1 true, i1 false
286 ; CHECK-NEXT: br i1 [[SEL]], label [[T_1:%.*]], label [[EXIT]]
288 ; CHECK-NEXT: ret i1 true
290 ; CHECK-NEXT: [[RES:%.*]] = phi i1 [ [[C_1]], [[ENTRY:%.*]] ], [ [[SEL]], [[THEN]] ]
291 ; CHECK-NEXT: ret i1 [[RES]]
294 %c.1 = icmp ne i32 %x, 0
295 %c.2 = icmp ne i32 %y, 0
296 %c.3 = icmp eq i32 %x, 16
297 %and = and i1 %c.2, %c.3
298 br i1 %and, label %then, label %exit
301 %c.4 = icmp eq i32 %z, 0
302 %sel = select i1 %c.4, i1 %c.1, i1 false
303 br i1 %sel, label %t.1, label %exit
309 %res = phi i1 [ %c.1, %entry ], [ %sel, %then ]
313 declare void @use(ptr)
315 define void @test_monotonic_ptr_iv_inc_1_eq_to_uge(ptr %start, i16 %len) {
316 ; CHECK-LABEL: @test_monotonic_ptr_iv_inc_1_eq_to_uge(
318 ; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i32, ptr [[START:%.*]], i16 [[LEN:%.*]]
319 ; CHECK-NEXT: br label [[LOOP_PH:%.*]]
321 ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
322 ; CHECK: loop.header:
323 ; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[START]], [[LOOP_PH]] ], [ [[PTR_IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
324 ; CHECK-NEXT: [[LEN_NEG:%.*]] = icmp sgt i16 [[LEN]], 0
325 ; CHECK-NEXT: [[C:%.*]] = icmp ne ptr [[PTR_IV]], [[UPPER]]
326 ; CHECK-NEXT: [[AND_0:%.*]] = and i1 [[LEN_NEG]], [[C]]
327 ; CHECK-NEXT: br i1 [[AND_0]], label [[FOR_BODY:%.*]], label [[EXIT:%.*]]
329 ; CHECK-NEXT: [[T_1:%.*]] = icmp uge ptr [[PTR_IV]], [[START]]
330 ; CHECK-NEXT: [[T_2:%.*]] = icmp ult ptr [[PTR_IV]], [[UPPER]]
331 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[T_1]], [[T_2]]
332 ; CHECK-NEXT: br i1 [[AND]], label [[LOOP_LATCH]], label [[EXIT]]
334 ; CHECK-NEXT: call void @use(ptr [[PTR_IV]])
335 ; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr inbounds i32, ptr [[PTR_IV]], i16 1
336 ; CHECK-NEXT: br label [[LOOP_HEADER]]
338 ; CHECK-NEXT: ret void
341 %upper = getelementptr inbounds i32, ptr %start, i16 %len
345 br label %loop.header
348 %ptr.iv = phi ptr [ %start, %loop.ph ], [ %ptr.iv.next, %loop.latch ]
349 %len.neg = icmp sgt i16 %len, 0
350 %c = icmp ne ptr %ptr.iv, %upper
351 %and.0 = and i1 %len.neg, %c
352 br i1 %and.0, label %for.body, label %exit
355 %t.1 = icmp uge ptr %ptr.iv, %start
356 %t.2 = icmp ult ptr %ptr.iv, %upper
357 %and = and i1 %t.1, %t.2
358 br i1 %and, label %loop.latch, label %exit
361 call void @use(ptr %ptr.iv)
362 %ptr.iv.next = getelementptr inbounds i32, ptr %ptr.iv, i16 1
363 br label %loop.header
369 define i1 @test_and_used_in_false_branch(i8 %x) {
370 ; CHECK-LABEL: @test_and_used_in_false_branch(
372 ; CHECK-NEXT: [[C_1:%.*]] = icmp ugt i8 [[X:%.*]], 10
373 ; CHECK-NEXT: [[T_1:%.*]] = icmp ugt i8 [[X]], 5
374 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[C_1]], true
375 ; CHECK-NEXT: br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]]
377 ; CHECK-NEXT: ret i1 true
379 ; CHECK-NEXT: ret i1 [[T_1]]
383 %c.1 = icmp ugt i8 %x, 10
384 %t.1 = icmp ugt i8 %x, 5
385 %and = and i1 %c.1, %t.1
386 br i1 %and, label %then, label %else
395 define i1 @test_or_used_in_false_branch(i8 %x) {
396 ; CHECK-LABEL: @test_or_used_in_false_branch(
398 ; CHECK-NEXT: [[C_1:%.*]] = icmp ule i8 [[X:%.*]], 10
399 ; CHECK-NEXT: [[T_1:%.*]] = icmp ule i8 [[X]], 5
400 ; CHECK-NEXT: [[AND:%.*]] = or i1 [[C_1]], false
401 ; CHECK-NEXT: br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]]
403 ; CHECK-NEXT: ret i1 [[T_1]]
405 ; CHECK-NEXT: ret i1 false
409 %c.1 = icmp ule i8 %x, 10
410 %t.1 = icmp ule i8 %x, 5
411 %and = or i1 %c.1, %t.1
412 br i1 %and, label %then, label %else
421 define i1 @test_or_used_in_false_branch2(i8 %x) {
422 ; CHECK-LABEL: @test_or_used_in_false_branch2(
424 ; CHECK-NEXT: [[C_1:%.*]] = icmp ugt i8 [[X:%.*]], 10
425 ; CHECK-NEXT: [[T_1:%.*]] = icmp ugt i8 [[X]], 5
426 ; CHECK-NEXT: [[AND:%.*]] = or i1 false, [[T_1]]
427 ; CHECK-NEXT: br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]]
429 ; CHECK-NEXT: ret i1 [[T_1]]
431 ; CHECK-NEXT: ret i1 false
435 %c.1 = icmp ugt i8 %x, 10
436 %t.1 = icmp ugt i8 %x, 5
437 %and = or i1 %c.1, %t.1
438 br i1 %and, label %then, label %else
447 define i1 @and_select_first_implies_second_may_be_poison(ptr noundef %A, ptr noundef %B) {
448 ; CHECK-LABEL: @and_select_first_implies_second_may_be_poison(
450 ; CHECK-NEXT: [[C_1:%.*]] = icmp ne ptr [[A:%.*]], [[B:%.*]]
451 ; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds ptr, ptr [[B]], i64 -1
452 ; CHECK-NEXT: [[C_2:%.*]] = icmp ugt ptr [[GEP]], [[A]]
453 ; CHECK-NEXT: [[AND:%.*]] = select i1 [[C_2]], i1 true, i1 false
454 ; CHECK-NEXT: ret i1 [[AND]]
457 %c.1 = icmp ne ptr %A, %B
458 %gep = getelementptr inbounds ptr, ptr %B, i64 -1
459 %c.2 = icmp ugt ptr %gep, %A
460 %and = select i1 %c.2, i1 %c.1, i1 false
464 define i1 @and_select_second_implies_first_may_be_poison(ptr noundef %A, ptr noundef %B) {
465 ; CHECK-LABEL: @and_select_second_implies_first_may_be_poison(
467 ; CHECK-NEXT: [[C_1:%.*]] = icmp ne ptr [[A:%.*]], [[B:%.*]]
468 ; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds ptr, ptr [[B]], i64 -1
469 ; CHECK-NEXT: [[C_2:%.*]] = icmp ugt ptr [[GEP]], [[A]]
470 ; CHECK-NEXT: [[AND:%.*]] = select i1 [[C_1]], i1 [[C_2]], i1 false
471 ; CHECK-NEXT: ret i1 [[AND]]
474 %c.1 = icmp ne ptr %A, %B
475 %gep = getelementptr inbounds ptr, ptr %B, i64 -1
476 %c.2 = icmp ugt ptr %gep, %A
477 %and = select i1 %c.1, i1 %c.2, i1 false
481 define i1 @and_select_second_implies_first_guaranteed_not_poison(ptr noundef %A, ptr noundef %B) {
482 ; CHECK-LABEL: @and_select_second_implies_first_guaranteed_not_poison(
484 ; CHECK-NEXT: [[C_1:%.*]] = icmp ne ptr [[A:%.*]], [[B:%.*]]
485 ; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds ptr, ptr [[B]], i64 -1
486 ; CHECK-NEXT: [[C_2:%.*]] = icmp ugt ptr [[GEP]], [[A]]
487 ; CHECK-NEXT: call void @no_noundef(i1 [[C_2]])
488 ; CHECK-NEXT: [[AND:%.*]] = select i1 [[C_1]], i1 [[C_2]], i1 false
489 ; CHECK-NEXT: ret i1 [[AND]]
492 %c.1 = icmp ne ptr %A, %B
493 %gep = getelementptr inbounds ptr, ptr %B, i64 -1
494 %c.2 = icmp ugt ptr %gep, %A
495 call void @no_noundef(i1 %c.2)
496 %and = select i1 %c.1, i1 %c.2, i1 false
500 declare void @no_noundef(i1 noundef)