; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -passes=ipsccp -S | FileCheck %s declare void @use(i1) define void @f1(i32 %a, i32 %b) { ; CHECK-LABEL: @f1( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[A_255:%.*]] = and i32 [[A:%.*]], 255 ; CHECK-NEXT: [[A_2:%.*]] = add nuw nsw i32 [[A_255]], 20 ; CHECK-NEXT: [[BC:%.*]] = icmp ugt i32 [[B:%.*]], [[A_2]] ; CHECK-NEXT: br i1 [[BC]], label [[TRUE:%.*]], label [[FALSE:%.*]] ; CHECK: true: ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: [[C_1:%.*]] = icmp eq i32 [[B]], 21 ; CHECK-NEXT: call void @use(i1 [[C_1]]) ; CHECK-NEXT: [[C_2:%.*]] = icmp ugt i32 [[B]], 21 ; CHECK-NEXT: call void @use(i1 [[C_2]]) ; CHECK-NEXT: [[C_3:%.*]] = icmp ugt i32 [[B]], 255 ; CHECK-NEXT: call void @use(i1 [[C_3]]) ; CHECK-NEXT: ret void ; CHECK: false: ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: [[C_4:%.*]] = icmp eq i32 [[B]], 21 ; CHECK-NEXT: call void @use(i1 [[C_4]]) ; CHECK-NEXT: [[C_5:%.*]] = icmp eq i32 [[B]], 275 ; CHECK-NEXT: call void @use(i1 [[C_5]]) ; CHECK-NEXT: ret void ; entry: %a.255 = and i32 %a, 255 %a.2 = add i32 %a.255, 20 %bc = icmp ugt i32 %b, %a.2 br i1 %bc, label %true, label %false true: ; %b in [21, 0) ; Conditions below are false. %f.1 = icmp eq i32 %b, 0 call void @use(i1 %f.1) %f.2 = icmp eq i32 %b, 20 call void @use(i1 %f.2) %f.3 = icmp ult i32 %b, 20 call void @use(i1 %f.3) ; Conditions below are true. %t.1 = icmp ugt i32 %b, 5 call void @use(i1 %t.1) %t.2 = icmp ne i32 %b, 20 call void @use(i1 %t.2) ; Conditions below cannot be simplified. %c.1 = icmp eq i32 %b, 21 call void @use(i1 %c.1) %c.2 = icmp ugt i32 %b, 21 call void @use(i1 %c.2) %c.3 = icmp ugt i32 %b, 255 call void @use(i1 %c.3) ret void false: ;%b in [0, 276) ; Conditions below are false; %f.4 = icmp eq i32 %b, 276 call void @use(i1 %f.4) %f.5 = icmp ugt i32 %b, 275 call void @use(i1 %f.5) ; Conditions below are true; %t.3 = icmp ne i32 %b, 276 call void @use(i1 %t.3) %t.4 = icmp ule i32 %b, 275 call void @use(i1 %t.4) ; Conditions below cannot be simplified. %c.4 = icmp eq i32 %b, 21 call void @use(i1 %c.4) %c.5 = icmp eq i32 %b, 275 call void @use(i1 %c.5) ret void } define void @f2_ptr(ptr %a, ptr %b) { ; CHECK-LABEL: @f2_ptr( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[BC:%.*]] = icmp eq ptr [[A:%.*]], null ; CHECK-NEXT: br i1 [[BC]], label [[TRUE:%.*]], label [[FALSE:%.*]] ; CHECK: true: ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: [[C_1:%.*]] = icmp eq ptr null, [[B:%.*]] ; CHECK-NEXT: call void @use(i1 [[C_1]]) ; CHECK-NEXT: ret void ; CHECK: false: ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: [[C_2:%.*]] = icmp eq ptr [[A]], [[B]] ; CHECK-NEXT: call void @use(i1 [[C_2]]) ; CHECK-NEXT: ret void ; entry: %bc = icmp eq ptr %a, null br i1 %bc, label %true, label %false true: ; %a == 0 %f.1 = icmp ne ptr %a, null call void @use(i1 %f.1) %t.1 = icmp eq ptr %a, null call void @use(i1 %t.1) %c.1 = icmp eq ptr %a, %b call void @use(i1 %c.1) ret void false: ; %a != 0 %f.2 = icmp eq ptr %a, null call void @use(i1 %f.2) %t.2 = icmp ne ptr %a, null call void @use(i1 %t.2) %c.2 = icmp eq ptr %a, %b call void @use(i1 %c.2) ret void } define ptr @f3(ptr %a, ptr %b, i1 %c) { ; CHECK-LABEL: @f3( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[C_1:%.*]] = icmp eq ptr [[A:%.*]], null ; CHECK-NEXT: br i1 [[C_1]], label [[TRUE:%.*]], label [[FALSE:%.*]] ; CHECK: true: ; CHECK-NEXT: br i1 [[C:%.*]], label [[TRUE_2:%.*]], label [[FALSE_2:%.*]] ; CHECK: true.2: ; CHECK-NEXT: br label [[EXIT_2:%.*]] ; CHECK: false.2: ; CHECK-NEXT: br label [[EXIT_2]] ; CHECK: exit.2: ; CHECK-NEXT: [[P:%.*]] = phi ptr [ null, [[TRUE_2]] ], [ [[B:%.*]], [[FALSE_2]] ] ; CHECK-NEXT: ret ptr [[P]] ; CHECK: false: ; CHECK-NEXT: ret ptr null ; entry: %c.1 = icmp eq ptr %a, null br i1 %c.1, label %true, label %false true: br i1 %c, label %true.2, label %false.2 true.2: br label %exit.2 false.2: br label %exit.2 exit.2: %p = phi ptr [ %a, %true.2 ], [ %b, %false.2 ] ret ptr %p false: ret ptr null } define i32 @f5(i64 %sz) { ; CHECK-LABEL: @f5( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 4088, [[SZ:%.*]] ; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_END:%.*]] ; CHECK: cond.true: ; CHECK-NEXT: [[DIV:%.*]] = udiv i64 4088, [[SZ]] ; CHECK-NEXT: br label [[COND_END]] ; CHECK: cond.end: ; CHECK-NEXT: [[COND:%.*]] = phi i64 [ [[DIV]], [[COND_TRUE]] ], [ 1, [[ENTRY:%.*]] ] ; CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[COND]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] ; entry: %cmp = icmp ugt i64 4088, %sz br i1 %cmp, label %cond.true, label %cond.end cond.true: ; preds = %entry %div = udiv i64 4088, %sz br label %cond.end cond.end: ; preds = %entry, %cond.true %cond = phi i64 [ %div, %cond.true ], [ 1, %entry ] %conv = trunc i64 %cond to i32 ret i32 %conv } define void @f6(i32 %b) { ; CHECK-LABEL: @f6( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[C_1:%.*]] = icmp ugt i32 [[B:%.*]], 20 ; CHECK-NEXT: br i1 [[C_1]], label [[TRUE:%.*]], label [[FALSE:%.*]] ; CHECK: true: ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: ret void ; CHECK: false: ; CHECK-NEXT: ret void ; entry: %a = add i32 10, 10 %c.1 = icmp ugt i32 %b, %a br i1 %c.1, label %true, label %false true: %c.2 = icmp eq i32 %a, 20 call void @use(i1 %c.2) ret void false: ret void } ; Test with 2 unrelated nested conditions. define void @f7_nested_conds(ptr %a, i32 %b) { ; CHECK-LABEL: @f7_nested_conds( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[A_V:%.*]] = load i32, ptr [[A:%.*]], align 4 ; CHECK-NEXT: [[C_1:%.*]] = icmp ne i32 [[A_V]], 0 ; CHECK-NEXT: br i1 [[C_1]], label [[TRUE:%.*]], label [[FALSE:%.*]] ; CHECK: false: ; CHECK-NEXT: br label [[TRUE_2:%.*]] ; CHECK: true.2: ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: ret void ; CHECK: true: ; CHECK-NEXT: store i32 [[B:%.*]], ptr [[A]], align 4 ; CHECK-NEXT: ret void ; entry: %a.v = load i32, ptr %a %c.1 = icmp ne i32 %a.v, 0 br i1 %c.1, label %true, label %false false: %c.2 = icmp ult i32 %a.v, 3 br i1 %c.2, label %true.2, label %true true.2: %c.3 = icmp eq i32 %a.v, 0 call void @use(i1 %c.3) ret void true: store i32 %b, ptr %a ret void } ; Test with 2 related nested conditions (%b > [20, 276) && %b < 255). define void @f8_nested_conds(i32 %a, i32 %b) { ; CHECK-LABEL: @f8_nested_conds( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[A_255:%.*]] = and i32 [[A:%.*]], 255 ; CHECK-NEXT: [[A_2:%.*]] = add nuw nsw i32 [[A_255]], 20 ; CHECK-NEXT: [[BC_1:%.*]] = icmp ugt i32 [[B:%.*]], [[A_2]] ; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]] ; CHECK: true: ; CHECK-NEXT: [[BC_2:%.*]] = icmp ult i32 [[B]], 255 ; CHECK-NEXT: br i1 [[BC_2]], label [[TRUE_2:%.*]], label [[FALSE_2:%.*]] ; CHECK: true.2: ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: [[C_1:%.*]] = icmp eq i32 [[B]], 21 ; CHECK-NEXT: call void @use(i1 [[C_1]]) ; CHECK-NEXT: [[C_2:%.*]] = icmp ugt i32 [[B]], 21 ; CHECK-NEXT: call void @use(i1 [[C_2]]) ; CHECK-NEXT: [[C_3:%.*]] = icmp ugt i32 [[B]], 34 ; CHECK-NEXT: call void @use(i1 [[C_3]]) ; CHECK-NEXT: ret void ; CHECK: false.2: ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: [[C_4:%.*]] = icmp eq i32 [[B]], 255 ; CHECK-NEXT: call void @use(i1 [[C_4]]) ; CHECK-NEXT: [[C_5:%.*]] = icmp ne i32 [[B]], 275 ; CHECK-NEXT: call void @use(i1 [[C_5]]) ; CHECK-NEXT: ret void ; CHECK: false: ; CHECK-NEXT: ret void ; entry: %a.255 = and i32 %a, 255 %a.2 = add i32 %a.255, 20 %bc.1 = icmp ugt i32 %b, %a.2 br i1 %bc.1, label %true, label %false true: ; %b in [21, 0) %bc.2 = icmp ult i32 %b, 255 br i1 %bc.2, label %true.2, label %false.2 true.2: ; %b in [21, 255) ; Conditions below are false. %f.1 = icmp eq i32 %b, 0 call void @use(i1 %f.1) %f.2 = icmp eq i32 %b, 20 call void @use(i1 %f.2) %f.3 = icmp ult i32 %b, 20 call void @use(i1 %f.3) %f.4 = icmp eq i32 %b, 255 call void @use(i1 %f.4) %f.5 = icmp ugt i32 %b, 255 call void @use(i1 %f.5) ; Conditions below are true. %t.1 = icmp ugt i32 %b, 5 call void @use(i1 %t.1) %t.2 = icmp ne i32 %b, 20 call void @use(i1 %t.2) %t.3 = icmp ult i32 %b, 255 call void @use(i1 %t.3) %t.4 = icmp ne i32 %b, 300 call void @use(i1 %t.4) ; Conditions below cannot be simplified. %c.1 = icmp eq i32 %b, 21 call void @use(i1 %c.1) %c.2 = icmp ugt i32 %b, 21 call void @use(i1 %c.2) %c.3 = icmp ugt i32 %b, 34 call void @use(i1 %c.3) ret void false.2: ;%b in [255, 0) ; Conditions below are false; %f.6 = icmp eq i32 %b, 254 call void @use(i1 %f.6) %f.7 = icmp ult i32 %b, 255 call void @use(i1 %f.7) ; Conditions below are true; %t.5 = icmp ne i32 %b, 254 call void @use(i1 %t.5) %t.6 = icmp uge i32 %b, 255 call void @use(i1 %t.6) ; Conditions below cannot be simplified. %c.4 = icmp eq i32 %b, 255 call void @use(i1 %c.4) %c.5 = icmp ne i32 %b, 275 call void @use(i1 %c.5) ret void false: ret void } ; Test with with nested conditions where the second conditions is more limiting than the first one. define void @f9_nested_conds(i32 %a, i32 %b) { ; CHECK-LABEL: @f9_nested_conds( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[BC_1:%.*]] = icmp ugt i32 [[B:%.*]], 10 ; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]] ; CHECK: true: ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: [[C_1:%.*]] = icmp eq i32 [[B]], 11 ; CHECK-NEXT: call void @use(i1 [[C_1]]) ; CHECK-NEXT: [[C_2:%.*]] = icmp ugt i32 [[B]], 11 ; CHECK-NEXT: call void @use(i1 [[C_2]]) ; CHECK-NEXT: [[BC_2:%.*]] = icmp ugt i32 [[B]], 20 ; CHECK-NEXT: br i1 [[BC_2]], label [[TRUE_2:%.*]], label [[FALSE_2:%.*]] ; CHECK: true.2: ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: [[C_3:%.*]] = icmp eq i32 [[B]], 21 ; CHECK-NEXT: call void @use(i1 [[C_3]]) ; CHECK-NEXT: [[C_4:%.*]] = icmp ugt i32 [[B]], 21 ; CHECK-NEXT: call void @use(i1 [[C_4]]) ; CHECK-NEXT: [[C_5:%.*]] = icmp ugt i32 [[B]], 34 ; CHECK-NEXT: call void @use(i1 [[C_5]]) ; CHECK-NEXT: ret void ; CHECK: false.2: ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: [[C_6:%.*]] = icmp eq i32 [[B]], 11 ; CHECK-NEXT: call void @use(i1 [[C_6]]) ; CHECK-NEXT: [[C_7:%.*]] = icmp ne i32 [[B]], 15 ; CHECK-NEXT: call void @use(i1 [[C_7]]) ; CHECK-NEXT: ret void ; CHECK: false: ; CHECK-NEXT: ret void ; entry: %bc.1 = icmp ugt i32 %b, 10 br i1 %bc.1, label %true, label %false true: ; %b in [11, 0) ; Conditions below are false. %f.1 = icmp eq i32 %b, 0 call void @use(i1 %f.1) %f.2 = icmp eq i32 %b, 10 call void @use(i1 %f.2) ; Conditions below are true. %t.1 = icmp ugt i32 %b, 5 call void @use(i1 %t.1) %t.2 = icmp ne i32 %b, 10 call void @use(i1 %t.2) ; Conditions below cannot be simplified. %c.1 = icmp eq i32 %b, 11 call void @use(i1 %c.1) %c.2 = icmp ugt i32 %b, 11 call void @use(i1 %c.2) %bc.2 = icmp ugt i32 %b, 20 br i1 %bc.2, label %true.2, label %false.2 true.2: ; %b in [21, 0) ; Conditions below are false. %f.3 = icmp eq i32 %b, 11 call void @use(i1 %f.3) %f.4 = icmp eq i32 %b, 20 call void @use(i1 %f.4) ; Conditions below are true. %t.3 = icmp ugt i32 %b, 11 call void @use(i1 %t.3) %t.4 = icmp ne i32 %b, 20 call void @use(i1 %t.4) ; Conditions below cannot be simplified. %c.3 = icmp eq i32 %b, 21 call void @use(i1 %c.3) %c.4 = icmp ugt i32 %b, 21 call void @use(i1 %c.4) %c.5 = icmp ugt i32 %b, 34 call void @use(i1 %c.5) ret void false.2: ;%b in [11, 21) ; Conditions below are false; %f.5 = icmp eq i32 %b, 21 call void @use(i1 %f.5) %f.6 = icmp ugt i32 %b, 21 call void @use(i1 %f.6) %f.7 = icmp ne i32 %b, 5 call void @use(i1 %f.7) ; Conditions below are true; %t.5 = icmp ne i32 %b, 21 call void @use(i1 %t.5) %t.6 = icmp ult i32 %b, 21 call void @use(i1 %t.6) %t.7 = icmp ne i32 %b, 5 call void @use(i1 %t.7) ; Conditions below cannot be simplified. %c.6 = icmp eq i32 %b, 11 call void @use(i1 %c.6) %c.7 = icmp ne i32 %b, 15 call void @use(i1 %c.7) ret void false: ret void } ; Test with with nested conditions where the second conditions is more limiting than the first one. define void @f10_cond_does_not_restrict_range(i32 %a, i32 %b) { ; CHECK-LABEL: @f10_cond_does_not_restrict_range( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[B_255:%.*]] = and i32 [[B:%.*]], 255 ; CHECK-NEXT: br label [[TRUE:%.*]] ; CHECK: true: ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: [[C_1:%.*]] = icmp eq i32 [[B_255]], 11 ; CHECK-NEXT: call void @use(i1 [[C_1]]) ; CHECK-NEXT: [[C_2:%.*]] = icmp ugt i32 [[B_255]], 30 ; CHECK-NEXT: call void @use(i1 [[C_2]]) ; CHECK-NEXT: ret void ; entry: %b.255 = and i32 %b, 255 %bc.1 = icmp ult i32 %b.255, 300 br i1 %bc.1, label %true, label %false true: ; %b in [0, 256) ; Conditions below are false. %f.1 = icmp eq i32 %b.255, 256 call void @use(i1 %f.1) %f.2 = icmp eq i32 %b.255, 300 call void @use(i1 %f.2) ; Conditions below are true. %t.1 = icmp ult i32 %b.255, 256 call void @use(i1 %t.1) %t.2 = icmp ult i32 %b.255, 300 call void @use(i1 %t.2) %t.3 = icmp ne i32 %b.255, 256 call void @use(i1 %t.3) %t.4 = icmp ne i32 %b.255, 300 call void @use(i1 %t.4) ; Conditions below cannot be simplified. %c.1 = icmp eq i32 %b.255, 11 call void @use(i1 %c.1) %c.2 = icmp ugt i32 %b.255, 30 call void @use(i1 %c.2) ret void false: ret void } define void @f11_contradiction(i32 %a, i32 %b) { ; CHECK-LABEL: @f11_contradiction( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[BC_1:%.*]] = icmp eq i32 [[B:%.*]], 10 ; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]] ; CHECK: true: ; CHECK-NEXT: br label [[FALSE]] ; CHECK: false: ; CHECK-NEXT: ret void ; entry: %bc.1 = icmp eq i32 %b, 10 br i1 %bc.1, label %true, label %false true: ; %b in [10, 11) %bc.2 = icmp eq i32 %b, 20 br i1 %bc.2, label %true.2, label %false true.2: %f.1 = icmp eq i32 %b, 256 call void @use(i1 %f.1) %f.2 = icmp ne i32 %b, 300 call void @use(i1 %f.2) ret void false: ret void } define void @f12_float(float %b) { ; CHECK-LABEL: @f12_float( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[BC_1:%.*]] = fcmp olt float 1.000000e+00, [[B:%.*]] ; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]] ; CHECK: true: ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: ret void ; CHECK: false: ; CHECK-NEXT: ret void ; entry: %a = fadd float 0.0, 1.0 %bc.1 = fcmp olt float %a, %b br i1 %bc.1, label %true, label %false true: ; %b in [10, 11) %f.1 = fcmp one float %a, 1.0 call void @use(i1 %f.1) %t.1 = fcmp oeq float %a, 1.0 call void @use(i1 %t.1) ret void false: ret void } @A = global i32 17 @B = global i32 17 define void @f13_constexpr1() { ; CHECK-LABEL: @f13_constexpr1( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[BC_1:%.*]] = icmp eq i32 add (i32 ptrtoint (ptr @A to i32), i32 10), 55 ; CHECK-NEXT: br i1 [[BC_1]], label [[TRUE:%.*]], label [[FALSE:%.*]] ; CHECK: true: ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: ret void ; CHECK: false: ; CHECK-NEXT: ret void ; entry: %a = add i32 ptrtoint (ptr @A to i32), 10 %bc.1 = icmp eq i32 %a, 55 br i1 %bc.1, label %true, label %false true: ; %b in [10, 11) %f.1 = icmp eq i32 %a, 10 call void @use(i1 %f.1) %f.2 = icmp eq i32 %a, 55 call void @use(i1 %f.2) ret void false: ret void } ; TODO: can we fold the compares in the true block? define void @f14_constexpr2() { ; CHECK-LABEL: @f14_constexpr2( ; CHECK-NEXT: entry: ; CHECK-NEXT: br i1 icmp eq (i32 ptrtoint (ptr @A to i32), i32 ptrtoint (ptr @B to i32)), label [[TRUE:%.*]], label [[FALSE:%.*]] ; CHECK: true: ; CHECK-NEXT: call void @use(i1 icmp ne (i32 ptrtoint (ptr @B to i32), i32 ptrtoint (ptr @A to i32))) ; CHECK-NEXT: call void @use(i1 icmp eq (i32 ptrtoint (ptr @B to i32), i32 ptrtoint (ptr @A to i32))) ; CHECK-NEXT: ret void ; CHECK: false: ; CHECK-NEXT: ret void ; entry: %a = add i32 ptrtoint (ptr @A to i32), 0 %b = add i32 ptrtoint (ptr @B to i32), 0 %bc.1 = icmp eq i32 %a, %b br i1 %bc.1, label %true, label %false true: ; %b in [10, 11) %f.1 = icmp ne i32 %a, %b call void @use(i1 %f.1) %f.2 = icmp eq i32 %a, %b call void @use(i1 %f.2) ret void false: ret void } define void @loop_1() { ; CHECK-LABEL: @loop_1( ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[FOR_COND:%.*]] ; CHECK: for.cond: ; CHECK-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC27:%.*]], [[FOR_COND_CLEANUP13:%.*]] ] ; CHECK-NEXT: [[CMP9:%.*]] = icmp sle i32 [[I_0]], 3 ; CHECK-NEXT: br i1 [[CMP9]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP:%.*]] ; CHECK: for.cond.cleanup: ; CHECK-NEXT: ret void ; CHECK: for.body: ; CHECK-NEXT: br label [[FOR_COND11:%.*]] ; CHECK: for.cond11: ; CHECK-NEXT: br label [[FOR_COND_CLEANUP13]] ; CHECK: for.cond.cleanup13: ; CHECK-NEXT: [[INC27]] = add nsw i32 [[I_0]], 1 ; CHECK-NEXT: br label [[FOR_COND]] ; entry: br label %for.cond for.cond: ; preds = %for.cond.cleanup13, %if.then %i.0 = phi i32 [ 0, %entry ], [ %inc27, %for.cond.cleanup13 ] %cmp9 = icmp sle i32 %i.0, 3 br i1 %cmp9, label %for.body, label %for.cond.cleanup for.cond.cleanup: ; preds = %for.cond ret void for.body: ; preds = %for.cond br label %for.cond11 for.cond11: ; preds = %arrayctor.cont21, %for.body br label %for.cond.cleanup13 for.cond.cleanup13: ; preds = %for.cond11 %inc27 = add nsw i32 %i.0, 1 br label %for.cond } define void @loop() { ; CHECK-LABEL: @loop( ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[FOR_COND:%.*]] ; CHECK: for.cond: ; CHECK-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC27:%.*]], [[FOR_COND_CLEANUP13:%.*]] ] ; CHECK-NEXT: [[CMP9:%.*]] = icmp sle i32 [[I_0]], 3 ; CHECK-NEXT: br i1 [[CMP9]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP:%.*]] ; CHECK: for.cond.cleanup: ; CHECK-NEXT: ret void ; CHECK: for.body: ; CHECK-NEXT: br label [[FOR_COND11:%.*]] ; CHECK: for.cond11: ; CHECK-NEXT: [[J_0:%.*]] = phi i32 [ 0, [[FOR_BODY]] ], [ [[INC:%.*]], [[FOR_BODY14:%.*]] ] ; CHECK-NEXT: [[CMP12:%.*]] = icmp slt i32 [[J_0]], 2 ; CHECK-NEXT: br i1 [[CMP12]], label [[FOR_BODY14]], label [[FOR_COND_CLEANUP13]] ; CHECK: for.cond.cleanup13: ; CHECK-NEXT: [[INC27]] = add nsw i32 [[I_0]], 1 ; CHECK-NEXT: br label [[FOR_COND]] ; CHECK: for.body14: ; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[J_0]], 1 ; CHECK-NEXT: br label [[FOR_COND11]] ; entry: br label %for.cond for.cond: ; preds = %for.cond.cleanup13, %if.then %i.0 = phi i32 [ 0, %entry ], [ %inc27, %for.cond.cleanup13 ] %cmp9 = icmp sle i32 %i.0, 3 br i1 %cmp9, label %for.body, label %for.cond.cleanup for.cond.cleanup: ; preds = %for.cond ret void for.body: ; preds = %for.cond br label %for.cond11 for.cond11: ; preds = %arrayctor.cont21, %for.body %j.0 = phi i32 [ 0, %for.body ], [ %inc, %for.body14 ] %cmp12 = icmp slt i32 %j.0, 2 br i1 %cmp12, label %for.body14, label %for.cond.cleanup13 for.cond.cleanup13: ; preds = %for.cond11 %inc27 = add nsw i32 %i.0, 1 br label %for.cond for.body14: %inc = add nsw i32 %j.0, 1 br label %for.cond11 } define i32 @udiv_1(i64 %sz) { ; CHECK-LABEL: @udiv_1( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 4088, [[SZ:%.*]] ; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_END:%.*]] ; CHECK: cond.true: ; CHECK-NEXT: [[DIV:%.*]] = udiv i64 4088, [[SZ]] ; CHECK-NEXT: br label [[COND_END]] ; CHECK: cond.end: ; CHECK-NEXT: [[COND:%.*]] = phi i64 [ [[DIV]], [[COND_TRUE]] ], [ 1, [[ENTRY:%.*]] ] ; CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[COND]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] ; entry: %cmp = icmp ugt i64 4088, %sz br i1 %cmp, label %cond.true, label %cond.end cond.true: ; preds = %entry %div = udiv i64 4088, %sz br label %cond.end cond.end: ; preds = %entry, %cond.true %cond = phi i64 [ %div, %cond.true ], [ 1, %entry ] %conv = trunc i64 %cond to i32 ret i32 %conv } ; Same as @udiv_1, but with the condition switched. define i32 @udiv_2(i64 %sz) { ; CHECK-LABEL: @udiv_2( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[SZ:%.*]], 4088 ; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_END:%.*]] ; CHECK: cond.true: ; CHECK-NEXT: br label [[COND_END]] ; CHECK: cond.end: ; CHECK-NEXT: [[COND:%.*]] = phi i64 [ 0, [[COND_TRUE]] ], [ 1, [[ENTRY:%.*]] ] ; CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[COND]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] ; entry: %cmp = icmp ugt i64 %sz, 4088 br i1 %cmp, label %cond.true, label %cond.end cond.true: ; preds = %entry %div = udiv i64 4088, %sz br label %cond.end cond.end: ; preds = %entry, %cond.true %cond = phi i64 [ %div, %cond.true ], [ 1, %entry ] %conv = trunc i64 %cond to i32 ret i32 %conv } define void @f16_conditions_and(i32 %a, i32 %b) { ; CHECK-LABEL: @f16_conditions_and( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[LT:%.*]] = icmp ult i32 [[A:%.*]], 100 ; CHECK-NEXT: [[GT:%.*]] = icmp ugt i32 [[A]], 20 ; CHECK-NEXT: [[BC:%.*]] = and i1 [[LT]], [[GT]] ; CHECK-NEXT: br i1 [[BC]], label [[TRUE:%.*]], label [[FALSE:%.*]] ; CHECK: true: ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: [[C_1:%.*]] = icmp eq i32 [[A]], 21 ; CHECK-NEXT: call void @use(i1 [[C_1]]) ; CHECK-NEXT: [[C_2:%.*]] = icmp ugt i32 [[A]], 21 ; CHECK-NEXT: call void @use(i1 [[C_2]]) ; CHECK-NEXT: [[C_3:%.*]] = icmp ugt i32 [[A]], 50 ; CHECK-NEXT: call void @use(i1 [[C_3]]) ; CHECK-NEXT: ret void ; CHECK: false: ; CHECK-NEXT: [[F_4:%.*]] = icmp eq i32 [[A]], 50 ; CHECK-NEXT: call void @use(i1 [[F_4]]) ; CHECK-NEXT: [[T_3:%.*]] = icmp ne i32 [[A]], 50 ; CHECK-NEXT: call void @use(i1 [[T_3]]) ; CHECK-NEXT: [[C_4:%.*]] = icmp eq i32 [[A]], 10 ; CHECK-NEXT: call void @use(i1 [[C_4]]) ; CHECK-NEXT: [[C_5:%.*]] = icmp eq i32 [[B:%.*]], 100 ; CHECK-NEXT: call void @use(i1 [[C_5]]) ; CHECK-NEXT: ret void ; entry: %lt = icmp ult i32 %a, 100 %gt = icmp ugt i32 %a, 20 %bc = and i1 %lt, %gt br i1 %bc, label %true, label %false true: ; %a in [21, 100) ; Conditions below are false. %f.1 = icmp eq i32 %a, 0 call void @use(i1 %f.1) %f.2 = icmp eq i32 %a, 20 call void @use(i1 %f.2) %f.3 = icmp ugt i32 %a, 100 call void @use(i1 %f.3) ; Conditions below are true. %t.1 = icmp ult i32 %a, 100 call void @use(i1 %t.1) %t.2 = icmp ne i32 %a, 20 call void @use(i1 %t.2) ; Conditions below cannot be simplified. %c.1 = icmp eq i32 %a, 21 call void @use(i1 %c.1) %c.2 = icmp ugt i32 %a, 21 call void @use(i1 %c.2) %c.3 = icmp ugt i32 %a, 50 call void @use(i1 %c.3) ret void false: ; TODO: Currently there is no conditional range info in the false branch for branch conditions with an AND. ; %a should be in in [100, 21) ; Conditions below are false; %f.4 = icmp eq i32 %a, 50 call void @use(i1 %f.4) ; Conditions below are true; %t.3 = icmp ne i32 %a, 50 call void @use(i1 %t.3) ; Conditions below cannot be simplified. %c.4 = icmp eq i32 %a, 10 call void @use(i1 %c.4) %c.5 = icmp eq i32 %b, 100 call void @use(i1 %c.5) ret void } define void @f16_conditions_and_logical(i32 %a, i32 %b) { ; CHECK-LABEL: @f16_conditions_and_logical( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[LT:%.*]] = icmp ult i32 [[A:%.*]], 100 ; CHECK-NEXT: [[GT:%.*]] = icmp ugt i32 [[A]], 20 ; CHECK-NEXT: [[BC:%.*]] = select i1 [[LT]], i1 [[GT]], i1 false ; CHECK-NEXT: br i1 [[BC]], label [[TRUE:%.*]], label [[FALSE:%.*]] ; CHECK: true: ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: [[C_1:%.*]] = icmp eq i32 [[A]], 21 ; CHECK-NEXT: call void @use(i1 [[C_1]]) ; CHECK-NEXT: [[C_2:%.*]] = icmp ugt i32 [[A]], 21 ; CHECK-NEXT: call void @use(i1 [[C_2]]) ; CHECK-NEXT: [[C_3:%.*]] = icmp ugt i32 [[A]], 50 ; CHECK-NEXT: call void @use(i1 [[C_3]]) ; CHECK-NEXT: ret void ; CHECK: false: ; CHECK-NEXT: [[F_4:%.*]] = icmp eq i32 [[A]], 50 ; CHECK-NEXT: call void @use(i1 [[F_4]]) ; CHECK-NEXT: [[T_3:%.*]] = icmp ne i32 [[A]], 50 ; CHECK-NEXT: call void @use(i1 [[T_3]]) ; CHECK-NEXT: [[C_4:%.*]] = icmp eq i32 [[A]], 10 ; CHECK-NEXT: call void @use(i1 [[C_4]]) ; CHECK-NEXT: [[C_5:%.*]] = icmp eq i32 [[B:%.*]], 100 ; CHECK-NEXT: call void @use(i1 [[C_5]]) ; CHECK-NEXT: ret void ; entry: %lt = icmp ult i32 %a, 100 %gt = icmp ugt i32 %a, 20 %bc = select i1 %lt, i1 %gt, i1 false br i1 %bc, label %true, label %false true: ; %a in [21, 100) ; Conditions below are false. %f.1 = icmp eq i32 %a, 0 call void @use(i1 %f.1) %f.2 = icmp eq i32 %a, 20 call void @use(i1 %f.2) %f.3 = icmp ugt i32 %a, 100 call void @use(i1 %f.3) ; Conditions below are true. %t.1 = icmp ult i32 %a, 100 call void @use(i1 %t.1) %t.2 = icmp ne i32 %a, 20 call void @use(i1 %t.2) ; Conditions below cannot be simplified. %c.1 = icmp eq i32 %a, 21 call void @use(i1 %c.1) %c.2 = icmp ugt i32 %a, 21 call void @use(i1 %c.2) %c.3 = icmp ugt i32 %a, 50 call void @use(i1 %c.3) ret void false: ; TODO: Currently there is no conditional range info in the false branch for branch conditions with an AND. ; %a should be in in [100, 21) ; Conditions below are false; %f.4 = icmp eq i32 %a, 50 call void @use(i1 %f.4) ; Conditions below are true; %t.3 = icmp ne i32 %a, 50 call void @use(i1 %t.3) ; Conditions below cannot be simplified. %c.4 = icmp eq i32 %a, 10 call void @use(i1 %c.4) %c.5 = icmp eq i32 %b, 100 call void @use(i1 %c.5) ret void } define void @f17_conditions_or(i32 %a, i32 %b) { ; CHECK-LABEL: @f17_conditions_or( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[GT:%.*]] = icmp uge i32 [[A:%.*]], 100 ; CHECK-NEXT: [[LT:%.*]] = icmp ule i32 [[A]], 20 ; CHECK-NEXT: [[BC:%.*]] = or i1 [[LT]], [[GT]] ; CHECK-NEXT: br i1 [[BC]], label [[TRUE:%.*]], label [[FALSE:%.*]] ; CHECK: false: ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: [[C_1:%.*]] = icmp eq i32 [[A]], 21 ; CHECK-NEXT: call void @use(i1 [[C_1]]) ; CHECK-NEXT: [[C_2:%.*]] = icmp ugt i32 [[A]], 21 ; CHECK-NEXT: call void @use(i1 [[C_2]]) ; CHECK-NEXT: [[C_3:%.*]] = icmp ugt i32 [[A]], 50 ; CHECK-NEXT: call void @use(i1 [[C_3]]) ; CHECK-NEXT: ret void ; CHECK: true: ; CHECK-NEXT: [[F_4:%.*]] = icmp eq i32 [[A]], 50 ; CHECK-NEXT: call void @use(i1 [[F_4]]) ; CHECK-NEXT: [[T_3:%.*]] = icmp ne i32 [[A]], 50 ; CHECK-NEXT: call void @use(i1 [[T_3]]) ; CHECK-NEXT: [[C_4:%.*]] = icmp eq i32 [[A]], 10 ; CHECK-NEXT: call void @use(i1 [[C_4]]) ; CHECK-NEXT: [[C_5:%.*]] = icmp eq i32 [[B:%.*]], 100 ; CHECK-NEXT: call void @use(i1 [[C_5]]) ; CHECK-NEXT: ret void ; entry: %gt = icmp uge i32 %a, 100 %lt = icmp ule i32 %a, 20 %bc = or i1 %lt, %gt br i1 %bc, label %true, label %false false: ; %a in [21, 100) ; Conditions below are false. %f.1 = icmp eq i32 %a, 0 call void @use(i1 %f.1) %f.2 = icmp eq i32 %a, 20 call void @use(i1 %f.2) %f.3 = icmp ugt i32 %a, 100 call void @use(i1 %f.3) ; Conditions below are true. %t.1 = icmp ult i32 %a, 100 call void @use(i1 %t.1) %t.2 = icmp ne i32 %a, 20 call void @use(i1 %t.2) ; Conditions below cannot be simplified. %c.1 = icmp eq i32 %a, 21 call void @use(i1 %c.1) %c.2 = icmp ugt i32 %a, 21 call void @use(i1 %c.2) %c.3 = icmp ugt i32 %a, 50 call void @use(i1 %c.3) ret void true: ; TODO: Currently there is no conditional range info in the false branch for branch conditions with an AND. ; %a should be in in [100, 21) ; Conditions below are false; %f.4 = icmp eq i32 %a, 50 call void @use(i1 %f.4) ; Conditions below are true; %t.3 = icmp ne i32 %a, 50 call void @use(i1 %t.3) ; Conditions below cannot be simplified. %c.4 = icmp eq i32 %a, 10 call void @use(i1 %c.4) %c.5 = icmp eq i32 %b, 100 call void @use(i1 %c.5) ret void } define void @f17_conditions_or_logical(i32 %a, i32 %b) { ; CHECK-LABEL: @f17_conditions_or_logical( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[GT:%.*]] = icmp uge i32 [[A:%.*]], 100 ; CHECK-NEXT: [[LT:%.*]] = icmp ule i32 [[A]], 20 ; CHECK-NEXT: [[BC:%.*]] = select i1 [[LT]], i1 true, i1 [[GT]] ; CHECK-NEXT: br i1 [[BC]], label [[TRUE:%.*]], label [[FALSE:%.*]] ; CHECK: false: ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: [[C_1:%.*]] = icmp eq i32 [[A]], 21 ; CHECK-NEXT: call void @use(i1 [[C_1]]) ; CHECK-NEXT: [[C_2:%.*]] = icmp ugt i32 [[A]], 21 ; CHECK-NEXT: call void @use(i1 [[C_2]]) ; CHECK-NEXT: [[C_3:%.*]] = icmp ugt i32 [[A]], 50 ; CHECK-NEXT: call void @use(i1 [[C_3]]) ; CHECK-NEXT: ret void ; CHECK: true: ; CHECK-NEXT: [[F_4:%.*]] = icmp eq i32 [[A]], 50 ; CHECK-NEXT: call void @use(i1 [[F_4]]) ; CHECK-NEXT: [[T_3:%.*]] = icmp ne i32 [[A]], 50 ; CHECK-NEXT: call void @use(i1 [[T_3]]) ; CHECK-NEXT: [[C_4:%.*]] = icmp eq i32 [[A]], 10 ; CHECK-NEXT: call void @use(i1 [[C_4]]) ; CHECK-NEXT: [[C_5:%.*]] = icmp eq i32 [[B:%.*]], 100 ; CHECK-NEXT: call void @use(i1 [[C_5]]) ; CHECK-NEXT: ret void ; entry: %gt = icmp uge i32 %a, 100 %lt = icmp ule i32 %a, 20 %bc = select i1 %lt, i1 true, i1 %gt br i1 %bc, label %true, label %false false: ; %a in [21, 100) ; Conditions below are false. %f.1 = icmp eq i32 %a, 0 call void @use(i1 %f.1) %f.2 = icmp eq i32 %a, 20 call void @use(i1 %f.2) %f.3 = icmp ugt i32 %a, 100 call void @use(i1 %f.3) ; Conditions below are true. %t.1 = icmp ult i32 %a, 100 call void @use(i1 %t.1) %t.2 = icmp ne i32 %a, 20 call void @use(i1 %t.2) ; Conditions below cannot be simplified. %c.1 = icmp eq i32 %a, 21 call void @use(i1 %c.1) %c.2 = icmp ugt i32 %a, 21 call void @use(i1 %c.2) %c.3 = icmp ugt i32 %a, 50 call void @use(i1 %c.3) ret void true: ; TODO: Currently there is no conditional range info in the false branch for branch conditions with an AND. ; %a should be in in [100, 21) ; Conditions below are false; %f.4 = icmp eq i32 %a, 50 call void @use(i1 %f.4) ; Conditions below are true; %t.3 = icmp ne i32 %a, 50 call void @use(i1 %t.3) ; Conditions below cannot be simplified. %c.4 = icmp eq i32 %a, 10 call void @use(i1 %c.4) %c.5 = icmp eq i32 %b, 100 call void @use(i1 %c.5) ret void } define void @f18_conditions_chained_and(i32 %a, i32 %b) { ; CHECK-LABEL: @f18_conditions_chained_and( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[LT:%.*]] = icmp ult i32 [[A:%.*]], 100 ; CHECK-NEXT: [[GT:%.*]] = icmp ugt i32 [[A]], 20 ; CHECK-NEXT: [[BC:%.*]] = and i1 [[LT]], [[GT]] ; CHECK-NEXT: [[B_LT:%.*]] = icmp ult i32 [[B:%.*]], 50 ; CHECK-NEXT: [[BC_2:%.*]] = and i1 [[BC]], [[B_LT]] ; CHECK-NEXT: br i1 [[BC_2]], label [[TRUE:%.*]], label [[FALSE:%.*]] ; CHECK: true: ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: [[C_1:%.*]] = icmp eq i32 [[A]], 21 ; CHECK-NEXT: call void @use(i1 [[C_1]]) ; CHECK-NEXT: [[C_2:%.*]] = icmp ugt i32 [[A]], 21 ; CHECK-NEXT: call void @use(i1 [[C_2]]) ; CHECK-NEXT: [[C_3:%.*]] = icmp ugt i32 [[A]], 50 ; CHECK-NEXT: call void @use(i1 [[C_3]]) ; CHECK-NEXT: [[C_4:%.*]] = icmp eq i32 [[B]], 0 ; CHECK-NEXT: call void @use(i1 [[C_4]]) ; CHECK-NEXT: [[C_5:%.*]] = icmp eq i32 [[B]], 20 ; CHECK-NEXT: call void @use(i1 [[C_5]]) ; CHECK-NEXT: ret void ; CHECK: false: ; CHECK-NEXT: [[F_5:%.*]] = icmp eq i32 [[A]], 50 ; CHECK-NEXT: call void @use(i1 [[F_5]]) ; CHECK-NEXT: [[T_3:%.*]] = icmp ne i32 [[A]], 50 ; CHECK-NEXT: call void @use(i1 [[T_3]]) ; CHECK-NEXT: [[C_6:%.*]] = icmp eq i32 [[A]], 10 ; CHECK-NEXT: call void @use(i1 [[C_6]]) ; CHECK-NEXT: [[C_7:%.*]] = icmp eq i32 [[B]], 100 ; CHECK-NEXT: call void @use(i1 [[C_7]]) ; CHECK-NEXT: ret void ; entry: %lt = icmp ult i32 %a, 100 %gt = icmp ugt i32 %a, 20 %bc = and i1 %lt, %gt %b.lt = icmp ult i32 %b, 50 %bc.2 = and i1 %bc, %b.lt br i1 %bc.2, label %true, label %false true: ; %a in [21, 100) ; Conditions below are false. %f.1 = icmp eq i32 %a, 0 call void @use(i1 %f.1) %f.2 = icmp eq i32 %a, 20 call void @use(i1 %f.2) %f.3 = icmp ugt i32 %a, 100 call void @use(i1 %f.3) %f.4 = icmp ugt i32 %b, 100 call void @use(i1 %f.4) ; Conditions below are true. %t.1 = icmp ult i32 %a, 100 call void @use(i1 %t.1) %t.2 = icmp ne i32 %a, 20 call void @use(i1 %t.2) ; Conditions below cannot be simplified. %c.1 = icmp eq i32 %a, 21 call void @use(i1 %c.1) %c.2 = icmp ugt i32 %a, 21 call void @use(i1 %c.2) %c.3 = icmp ugt i32 %a, 50 call void @use(i1 %c.3) %c.4 = icmp eq i32 %b, 0 call void @use(i1 %c.4) %c.5 = icmp eq i32 %b, 20 call void @use(i1 %c.5) ret void false: ; Conditions below are false; %f.5 = icmp eq i32 %a, 50 call void @use(i1 %f.5) ; Conditions below are true; %t.3 = icmp ne i32 %a, 50 call void @use(i1 %t.3) ; Conditions below cannot be simplified. %c.6 = icmp eq i32 %a, 10 call void @use(i1 %c.6) %c.7 = icmp eq i32 %b, 100 call void @use(i1 %c.7) ret void } define void @f19_conditions_chained_and_nested_and(i32 %a, i32 %b) { ; CHECK-LABEL: @f19_conditions_chained_and_nested_and( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[LT_A:%.*]] = icmp ult i32 [[A:%.*]], 100 ; CHECK-NEXT: [[LT_B:%.*]] = icmp ult i32 [[B:%.*]], 1000 ; CHECK-NEXT: [[BC:%.*]] = and i1 [[LT_A]], [[LT_B]] ; CHECK-NEXT: br i1 [[BC]], label [[TRUE:%.*]], label [[FALSE:%.*]] ; CHECK: true: ; CHECK-NEXT: [[GT_A:%.*]] = icmp ugt i32 [[A]], 30 ; CHECK-NEXT: [[GT_B:%.*]] = icmp ugt i32 [[B]], 300 ; CHECK-NEXT: [[BC_2:%.*]] = and i1 [[GT_A]], [[GT_B]] ; CHECK-NEXT: br i1 [[BC_2]], label [[TRUE_2:%.*]], label [[FALSE]] ; CHECK: true.2: ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: [[C_1:%.*]] = icmp eq i32 [[A]], 31 ; CHECK-NEXT: call void @use(i1 [[C_1]]) ; CHECK-NEXT: [[C_2:%.*]] = icmp ugt i32 [[A]], 31 ; CHECK-NEXT: call void @use(i1 [[C_2]]) ; CHECK-NEXT: [[C_3:%.*]] = icmp ugt i32 [[A]], 50 ; CHECK-NEXT: call void @use(i1 [[C_3]]) ; CHECK-NEXT: [[C_4:%.*]] = icmp eq i32 [[B]], 301 ; CHECK-NEXT: call void @use(i1 [[C_4]]) ; CHECK-NEXT: [[C_5:%.*]] = icmp ugt i32 [[B]], 301 ; CHECK-NEXT: call void @use(i1 [[C_5]]) ; CHECK-NEXT: [[C_6:%.*]] = icmp ugt i32 [[B]], 500 ; CHECK-NEXT: call void @use(i1 [[C_6]]) ; CHECK-NEXT: ret void ; CHECK: false: ; CHECK-NEXT: ret void ; entry: %lt.a = icmp ult i32 %a, 100 %lt.b = icmp ult i32 %b, 1000 %bc = and i1 %lt.a, %lt.b br i1 %bc, label %true, label %false true: %gt.a = icmp ugt i32 %a, 30 %gt.b = icmp ugt i32 %b, 300 %bc.2 = and i1 %gt.a, %gt.b br i1 %bc.2, label %true.2, label %false true.2: ; Conditions below are false. %f.1 = icmp eq i32 %a, 0 call void @use(i1 %f.1) %f.2 = icmp eq i32 %a, 20 call void @use(i1 %f.2) %f.3 = icmp ugt i32 %a, 100 call void @use(i1 %f.3) %f.4 = icmp eq i32 %b, 0 call void @use(i1 %f.4) %f.5 = icmp eq i32 %b, 300 call void @use(i1 %f.5) %f.6 = icmp ugt i32 %b, 1000 call void @use(i1 %f.6) ; Conditions below are true. %t.1 = icmp ult i32 %a, 100 call void @use(i1 %t.1) %t.2 = icmp ne i32 %a, 20 call void @use(i1 %t.2) %t.3 = icmp ult i32 %b, 1000 call void @use(i1 %t.3) %t.4 = icmp ne i32 %b, 300 call void @use(i1 %t.4) ; Conditions below cannot be simplified. %c.1 = icmp eq i32 %a, 31 call void @use(i1 %c.1) %c.2 = icmp ugt i32 %a, 31 call void @use(i1 %c.2) %c.3 = icmp ugt i32 %a, 50 call void @use(i1 %c.3) %c.4 = icmp eq i32 %b, 301 call void @use(i1 %c.4) %c.5 = icmp ugt i32 %b, 301 call void @use(i1 %c.5) %c.6 = icmp ugt i32 %b, 500 call void @use(i1 %c.6) ret void false: ret void } declare i64 @get_i64() declare i1 @cond() define void @f20_ne_0_nuked_by_and(i32 %arg) local_unnamed_addr #0 { ; CHECK-LABEL: @f20_ne_0_nuked_by_and( ; CHECK-NEXT: bb11: ; CHECK-NEXT: br label [[BB122:%.*]] ; CHECK: bb122: ; CHECK-NEXT: [[TMP123:%.*]] = phi i32 [ 256, [[BB11:%.*]] ], [ [[TMP136:%.*]], [[BB135:%.*]] ] ; CHECK-NEXT: [[TMP127:%.*]] = call i64 @get_i64() ; CHECK-NEXT: [[TMP128:%.*]] = trunc i64 [[TMP127]] to i32 ; CHECK-NEXT: [[TMP131:%.*]] = icmp ne i32 [[TMP128]], 0 ; CHECK-NEXT: [[TMP132:%.*]] = icmp sgt i32 [[TMP123]], [[TMP128]] ; CHECK-NEXT: [[TMP133:%.*]] = and i1 [[TMP131]], [[TMP132]] ; CHECK-NEXT: br i1 [[TMP133]], label [[BB134:%.*]], label [[BB135]] ; CHECK: bb134: ; CHECK-NEXT: br label [[BB135]] ; CHECK: bb135: ; CHECK-NEXT: [[TMP136]] = phi i32 [ [[TMP123]], [[BB122]] ], [ [[TMP128]], [[BB134]] ] ; CHECK-NEXT: [[BC:%.*]] = call i1 @cond() ; CHECK-NEXT: br i1 [[BC]], label [[BB139:%.*]], label [[BB122]] ; CHECK: bb139: ; CHECK-NEXT: call void @use(i1 false) ; CHECK-NEXT: ret void ; bb11: ; preds = %bb1 br label %bb122 bb122: ; preds = %bb135, %bb120 %tmp123 = phi i32 [ 256, %bb11 ], [ %tmp136, %bb135 ] %tmp127 = call i64 @get_i64() %tmp128 = trunc i64 %tmp127 to i32 %tmp131 = icmp ne i32 %tmp128, 0 %tmp132 = icmp sgt i32 %tmp123, %tmp128 %tmp133 = and i1 %tmp131, %tmp132 br i1 %tmp133, label %bb134, label %bb135 bb134: ; preds = %bb122 br label %bb135 bb135: ; preds = %bb134, %bb122 %tmp136 = phi i32 [ %tmp123, %bb122 ], [ %tmp128, %bb134 ] %bc = call i1 @cond() br i1 %bc, label %bb139, label %bb122 bb139: ; preds = %bb135 %tmp140 = icmp eq i32 %tmp136, 0 call void @use(i1 %tmp140) ret void bb142: ; preds = %bb139 ret void } define i32 @equal_not_constant(ptr noundef %p, ptr noundef %q) { ; CHECK-LABEL: @equal_not_constant( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr [[P:%.*]], null ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] ; CHECK: if.then: ; CHECK-NEXT: [[CMP_THEN:%.*]] = icmp eq ptr [[P]], [[Q:%.*]] ; CHECK-NEXT: br i1 [[CMP_THEN]], label [[IF_THEN1:%.*]], label [[IF_END]] ; CHECK: if.then1: ; CHECK-NEXT: call void @use(i1 true) ; CHECK-NEXT: br label [[IF_END]] ; CHECK: if.end: ; CHECK-NEXT: ret i32 0 ; entry: %cmp = icmp ne ptr %p, null br i1 %cmp, label %if.then, label %if.end if.then: ; preds = %entry %cmp.then = icmp eq ptr %p, %q br i1 %cmp.then, label %if.then1, label %if.end if.then1: ; preds = %if.then %cmp.then1 = icmp ne ptr %q, null call void @use(i1 %cmp.then1) br label %if.end if.end: ret i32 0 } define i32 @not_equal_not_constant(ptr noundef %p, ptr noundef %q) { ; CHECK-LABEL: @not_equal_not_constant( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[CMP:%.*]] = icmp ne ptr [[P:%.*]], null ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] ; CHECK: if.then: ; CHECK-NEXT: [[CMP_THEN:%.*]] = icmp ne ptr [[P]], [[Q:%.*]] ; CHECK-NEXT: br i1 [[CMP_THEN]], label [[IF_THEN1:%.*]], label [[IF_END]] ; CHECK: if.then1: ; CHECK-NEXT: [[CMP_THEN1:%.*]] = icmp ne ptr [[Q]], null ; CHECK-NEXT: call void @use(i1 [[CMP_THEN1]]) ; CHECK-NEXT: br label [[IF_END]] ; CHECK: if.end: ; CHECK-NEXT: ret i32 0 ; entry: %cmp = icmp ne ptr %p, null br i1 %cmp, label %if.then, label %if.end if.then: ; preds = %entry %cmp.then = icmp ne ptr %p, %q br i1 %cmp.then, label %if.then1, label %if.end if.then1: ; preds = %if.then %cmp.then1 = icmp ne ptr %q, null call void @use(i1 %cmp.then1) br label %if.end if.end: ret i32 0 } define i1 @ptr_icmp_data_layout() { ; CHECK-LABEL: @ptr_icmp_data_layout( ; CHECK-NEXT: ret i1 false ; %a.end = getelementptr i32, ptr @A, i64 1 %cmp = icmp eq ptr %a.end, @A ret i1 %cmp }