1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s 3 4declare void @use(i1) 5 6define void @loop_iv_cond_variable_bound(i32 %n) { 7; CHECK-LABEL: @loop_iv_cond_variable_bound( 8; CHECK-NEXT: entry: 9; CHECK-NEXT: br label [[LOOP:%.*]] 10; CHECK: loop: 11; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] 12; CHECK-NEXT: [[T_1:%.*]] = icmp ule i32 [[IV]], [[N:%.*]] 13; CHECK-NEXT: call void @use(i1 [[T_1]]) 14; CHECK-NEXT: [[T_2:%.*]] = icmp sge i32 [[IV]], 0 15; CHECK-NEXT: call void @use(i1 [[T_2]]) 16; CHECK-NEXT: [[T_3:%.*]] = icmp sge i32 [[IV]], -1 17; CHECK-NEXT: call void @use(i1 [[T_3]]) 18; CHECK-NEXT: [[C_1:%.*]] = icmp ult i32 [[IV]], [[N]] 19; CHECK-NEXT: call void @use(i1 [[C_1]]) 20; CHECK-NEXT: [[C_2:%.*]] = icmp ugt i32 [[IV]], 1 21; CHECK-NEXT: call void @use(i1 [[C_2]]) 22; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[IV]], [[N]] 23; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 24; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]] 25; CHECK: exit: 26; CHECK-NEXT: ret void 27; 28entry: 29 br label %loop 30 31loop: 32 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] 33 %t.1 = icmp ule i32 %iv, %n 34 call void @use(i1 %t.1) 35 %t.2 = icmp sge i32 %iv, 0 36 call void @use(i1 %t.2) 37 %t.3 = icmp sge i32 %iv, -1 38 call void @use(i1 %t.3) 39 40 %c.1 = icmp ult i32 %iv, %n 41 call void @use(i1 %c.1) 42 %c.2 = icmp ugt i32 %iv, 1 43 call void @use(i1 %c.2) 44 45 %cmp = icmp ult i32 %iv, %n 46 %iv.next = add nuw nsw i32 %iv, 1 47 br i1 %cmp, label %loop, label %exit 48 49exit: 50 ret void 51} 52 53define void @loop_iv_cond_constant_bound() { 54; CHECK-LABEL: @loop_iv_cond_constant_bound( 55; CHECK-NEXT: entry: 56; CHECK-NEXT: br label [[LOOP:%.*]] 57; CHECK: loop: 58; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] 59; CHECK-NEXT: [[T_1:%.*]] = icmp ule i32 [[IV]], 2 60; CHECK-NEXT: call void @use(i1 [[T_1]]) 61; CHECK-NEXT: [[T_2:%.*]] = icmp sge i32 [[IV]], 0 62; CHECK-NEXT: call void @use(i1 [[T_2]]) 63; CHECK-NEXT: [[T_3:%.*]] = icmp sge i32 [[IV]], -1 64; CHECK-NEXT: call void @use(i1 [[T_3]]) 65; CHECK-NEXT: [[C_1:%.*]] = icmp ult i32 [[IV]], 2 66; CHECK-NEXT: call void @use(i1 [[C_1]]) 67; CHECK-NEXT: [[C_2:%.*]] = icmp ugt i32 [[IV]], 1 68; CHECK-NEXT: call void @use(i1 [[C_2]]) 69; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[IV]], 2 70; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 71; CHECK-NEXT: br i1 [[CMP]], label [[LOOP]], label [[EXIT:%.*]] 72; CHECK: exit: 73; CHECK-NEXT: ret void 74; 75entry: 76 br label %loop 77 78loop: 79 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] 80 %t.1 = icmp ule i32 %iv, 2 81 call void @use(i1 %t.1) 82 %t.2 = icmp sge i32 %iv, 0 83 call void @use(i1 %t.2) 84 %t.3 = icmp sge i32 %iv, -1 85 call void @use(i1 %t.3) 86 87 %c.1 = icmp ult i32 %iv, 2 88 call void @use(i1 %c.1) 89 %c.2 = icmp ugt i32 %iv, 1 90 call void @use(i1 %c.2) 91 92 %cmp = icmp ult i32 %iv, 2 93 %iv.next = add nuw nsw i32 %iv, 1 94 br i1 %cmp, label %loop, label %exit 95 96exit: 97 ret void 98} 99 100declare void @clobber() 101 102define void @eq_exit_check_constant_int() { 103; CHECK-LABEL: @eq_exit_check_constant_int( 104; CHECK-NEXT: entry: 105; CHECK-NEXT: br label [[LOOP:%.*]] 106; CHECK: loop: 107; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 1, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] 108; CHECK-NEXT: [[IV_NEXT]] = add nuw i64 [[IV]], 1 109; CHECK-NEXT: call void @clobber() 110; CHECK-NEXT: [[C:%.*]] = icmp eq i64 [[IV]], 2 111; CHECK-NEXT: br i1 [[C]], label [[EXIT:%.*]], label [[LOOP]] 112; CHECK: exit: 113; CHECK-NEXT: ret void 114; 115entry: 116 br label %loop 117 118loop: 119 %iv = phi i64 [ 1, %entry], [ %iv.next, %loop ] 120 %iv.next = add nuw i64 %iv, 1 121 call void @clobber() 122 %c = icmp eq i64 %iv, 2 123 br i1 %c, label %exit, label %loop 124 125exit: 126 ret void 127} 128 129define void @eq_exit_check_variable(i64 %N) { 130; CHECK-LABEL: @eq_exit_check_variable( 131; CHECK-NEXT: entry: 132; CHECK-NEXT: [[PRECOND:%.*]] = icmp eq i64 [[N:%.*]], 0 133; CHECK-NEXT: br i1 [[PRECOND]], label [[EXIT:%.*]], label [[LOOP:%.*]] 134; CHECK: loop: 135; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 1, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] 136; CHECK-NEXT: [[IV_NEXT]] = add nuw i64 [[IV]], 1 137; CHECK-NEXT: call void @clobber() 138; CHECK-NEXT: [[EXITCOND86_NOT_I_I:%.*]] = icmp eq i64 [[IV]], [[N]] 139; CHECK-NEXT: br i1 [[EXITCOND86_NOT_I_I]], label [[EXIT]], label [[LOOP]] 140; CHECK: exit: 141; CHECK-NEXT: ret void 142; 143entry: 144 %precond = icmp eq i64 %N, 0 145 br i1 %precond, label %exit, label %loop 146 147loop: 148 %iv = phi i64 [ 1, %entry ], [ %iv.next, %loop ] 149 %iv.next = add nuw i64 %iv, 1 150 call void @clobber() 151 %exitcond86.not.i.i = icmp eq i64 %iv, %N 152 br i1 %exitcond86.not.i.i, label %exit, label %loop 153 154exit: 155 ret void 156} 157 158define void @eq_exit_check_constant_ptr(ptr %start) { 159; CHECK-LABEL: @eq_exit_check_constant_ptr( 160; CHECK-NEXT: entry: 161; CHECK-NEXT: [[UPPER:%.*]] = getelementptr inbounds i8, ptr [[START:%.*]], i8 2 162; CHECK-NEXT: br label [[LOOP:%.*]] 163; CHECK: loop: 164; CHECK-NEXT: [[IV:%.*]] = phi ptr [ [[START]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] 165; CHECK-NEXT: [[IV_NEXT]] = getelementptr inbounds i8, ptr [[IV]], i8 1 166; CHECK-NEXT: call void @clobber() 167; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[IV]], [[UPPER]] 168; CHECK-NEXT: br i1 [[C]], label [[EXIT:%.*]], label [[LOOP]] 169; CHECK: exit: 170; CHECK-NEXT: ret void 171; 172entry: 173 %upper = getelementptr inbounds i8, ptr %start, i8 2 174 br label %loop 175 176loop: 177 %iv = phi ptr [ %start, %entry], [ %iv.next, %loop ] 178 %iv.next = getelementptr inbounds i8, ptr %iv, i8 1 179 call void @clobber() 180 %c = icmp eq ptr %iv, %upper 181 br i1 %c, label %exit, label %loop 182 183exit: 184 ret void 185} 186