1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt %s -S -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 | FileCheck %s 3; Check for when one branch implies the value of a successors conditional and 4; it's not simply the same conditional repeated. 5 6define void @test(i32 %length.i, i32 %i) { 7; CHECK-LABEL: @test( 8; CHECK-NEXT: [[IPLUS1:%.*]] = add nsw i32 [[I:%.*]], 1 9; CHECK-NEXT: [[VAR29:%.*]] = icmp slt i32 [[IPLUS1]], [[LENGTH_I:%.*]] 10; CHECK-NEXT: br i1 [[VAR29]], label [[IN_BOUNDS:%.*]], label [[OUT_OF_BOUNDS:%.*]] 11; CHECK: in_bounds: 12; CHECK-NEXT: ret void 13; CHECK: out_of_bounds: 14; CHECK-NEXT: call void @foo(i64 0) 15; CHECK-NEXT: unreachable 16; 17 %iplus1 = add nsw i32 %i, 1 18 %var29 = icmp slt i32 %iplus1, %length.i 19 br i1 %var29, label %next, label %out_of_bounds 20 21next: 22 %var30 = icmp slt i32 %i, %length.i 23 br i1 %var30, label %in_bounds, label %out_of_bounds2 24 25in_bounds: 26 ret void 27 28out_of_bounds: 29 call void @foo(i64 0) 30 unreachable 31 32out_of_bounds2: 33 call void @foo(i64 1) 34 unreachable 35} 36 37; If the add is not nsw, it's not safe to use the fact about i+1 to imply the 38; i condition since it could have overflowed. 39define void @test_neg(i32 %length.i, i32 %i) { 40; CHECK-LABEL: @test_neg( 41; CHECK-NEXT: [[IPLUS1:%.*]] = add i32 [[I:%.*]], 1 42; CHECK-NEXT: [[VAR29:%.*]] = icmp slt i32 [[IPLUS1]], [[LENGTH_I:%.*]] 43; CHECK-NEXT: br i1 [[VAR29]], label [[NEXT:%.*]], label [[OUT_OF_BOUNDS:%.*]] 44; CHECK: next: 45; CHECK-NEXT: [[VAR30:%.*]] = icmp slt i32 [[I]], [[LENGTH_I]] 46; CHECK-NEXT: br i1 [[VAR30]], label [[IN_BOUNDS:%.*]], label [[OUT_OF_BOUNDS2:%.*]] 47; CHECK: in_bounds: 48; CHECK-NEXT: ret void 49; CHECK: out_of_bounds: 50; CHECK-NEXT: call void @foo(i64 0) 51; CHECK-NEXT: unreachable 52; CHECK: out_of_bounds2: 53; CHECK-NEXT: call void @foo(i64 1) 54; CHECK-NEXT: unreachable 55; 56 %iplus1 = add i32 %i, 1 57 %var29 = icmp slt i32 %iplus1, %length.i 58 br i1 %var29, label %next, label %out_of_bounds 59 60next: 61 %var30 = icmp slt i32 %i, %length.i 62 br i1 %var30, label %in_bounds, label %out_of_bounds2 63 64in_bounds: 65 ret void 66 67out_of_bounds: 68 call void @foo(i64 0) 69 unreachable 70 71out_of_bounds2: 72 call void @foo(i64 1) 73 unreachable 74} 75 76 77define void @test2(i32 %length.i, i32 %i) { 78; CHECK-LABEL: @test2( 79; CHECK-NEXT: [[IPLUS100:%.*]] = add nsw i32 [[I:%.*]], 100 80; CHECK-NEXT: [[VAR29:%.*]] = icmp slt i32 [[IPLUS100]], [[LENGTH_I:%.*]] 81; CHECK-NEXT: br i1 [[VAR29]], label [[IN_BOUNDS:%.*]], label [[OUT_OF_BOUNDS:%.*]] 82; CHECK: in_bounds: 83; CHECK-NEXT: ret void 84; CHECK: out_of_bounds: 85; CHECK-NEXT: call void @foo(i64 0) 86; CHECK-NEXT: unreachable 87; 88 %iplus100 = add nsw i32 %i, 100 89 %var29 = icmp slt i32 %iplus100, %length.i 90 br i1 %var29, label %next, label %out_of_bounds 91 92next: 93 %var30 = icmp slt i32 %i, %length.i 94 br i1 %var30, label %in_bounds, label %out_of_bounds2 95 96in_bounds: 97 ret void 98 99out_of_bounds: 100 call void @foo(i64 0) 101 unreachable 102 103out_of_bounds2: 104 call void @foo(i64 1) 105 unreachable 106} 107 108declare void @foo(i64) 109 110