1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3 2; RUN: opt -p constraint-elimination -S %s | FileCheck %s 3 4declare void @use(i1) 5 6define void @start_value_of_inner_add_rec_is_add_rec_condition_can_be_simplified(i32 noundef %len) { 7; CHECK-LABEL: define void @start_value_of_inner_add_rec_is_add_rec_condition_can_be_simplified( 8; CHECK-SAME: i32 noundef [[LEN:%.*]]) { 9; CHECK-NEXT: entry: 10; CHECK-NEXT: br label [[OUTER_HEADER:%.*]] 11; CHECK: outer.header: 12; CHECK-NEXT: [[I_0:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[OUTER_LATCH:%.*]] ] 13; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[I_0]], [[LEN]] 14; CHECK-NEXT: br i1 [[CMP]], label [[INNER_HEADER:%.*]], label [[EXIT:%.*]] 15; CHECK: inner.header: 16; CHECK-NEXT: [[K_0:%.*]] = phi i32 [ [[I_0]], [[OUTER_HEADER]] ], [ [[K_INC:%.*]], [[INNER_LATCH:%.*]] ] 17; CHECK-NEXT: [[CMP2_NOT:%.*]] = icmp eq i32 [[K_0]], [[LEN]] 18; CHECK-NEXT: br i1 [[CMP2_NOT]], label [[OUTER_LATCH]], label [[INNER_LATCH]] 19; CHECK: inner.latch: 20; CHECK-NEXT: call void @use(i1 true) 21; CHECK-NEXT: [[K_INC]] = add i32 [[K_0]], 1 22; CHECK-NEXT: br label [[INNER_HEADER]] 23; CHECK: outer.latch: 24; CHECK-NEXT: [[I_INC]] = add i32 [[I_0]], 1 25; CHECK-NEXT: br label [[OUTER_HEADER]] 26; CHECK: exit: 27; CHECK-NEXT: ret void 28; 29entry: 30 br label %outer.header 31 32outer.header: 33 %i.0 = phi i32 [ 1, %entry ], [ %i.inc, %outer.latch ] 34 %cmp = icmp ult i32 %i.0, %len 35 br i1 %cmp, label %inner.header, label %exit 36 37inner.header: 38 %k.0 = phi i32 [ %i.0, %outer.header ], [ %k.inc, %inner.latch ] 39 %cmp2.not = icmp eq i32 %k.0, %len 40 br i1 %cmp2.not, label %outer.latch, label %inner.latch 41 42inner.latch: 43 %cmp.not.i = icmp ult i32 %k.0, %len 44 call void @use(i1 %cmp.not.i) 45 %k.inc = add i32 %k.0, 1 46 br label %inner.header 47 48outer.latch: 49 %i.inc = add i32 %i.0, 1 50 br label %outer.header 51 52exit: 53 ret void 54} 55 56define void @start_value_of_inner_add_rec_is_add_rec_condition_cannot_be_simplified(i32 noundef %len) { 57; CHECK-LABEL: define void @start_value_of_inner_add_rec_is_add_rec_condition_cannot_be_simplified( 58; CHECK-SAME: i32 noundef [[LEN:%.*]]) { 59; CHECK-NEXT: entry: 60; CHECK-NEXT: br label [[OUTER_HEADER:%.*]] 61; CHECK: outer.header: 62; CHECK-NEXT: [[I_0:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[OUTER_LATCH:%.*]] ] 63; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[I_0]], [[LEN]] 64; CHECK-NEXT: br i1 [[CMP]], label [[INNER_HEADER:%.*]], label [[EXIT:%.*]] 65; CHECK: inner.header: 66; CHECK-NEXT: [[K_0:%.*]] = phi i32 [ [[I_0]], [[OUTER_HEADER]] ], [ [[K_INC:%.*]], [[INNER_LATCH:%.*]] ] 67; CHECK-NEXT: [[CMP2_NOT:%.*]] = icmp eq i32 [[K_0]], [[LEN]] 68; CHECK-NEXT: br i1 [[CMP2_NOT]], label [[OUTER_LATCH]], label [[INNER_LATCH]] 69; CHECK: inner.latch: 70; CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp ult i32 [[K_0]], 3 71; CHECK-NEXT: call void @use(i1 [[CMP_NOT_I]]) 72; CHECK-NEXT: [[K_INC]] = add i32 [[K_0]], 1 73; CHECK-NEXT: br label [[INNER_HEADER]] 74; CHECK: outer.latch: 75; CHECK-NEXT: [[I_INC]] = add i32 [[I_0]], 1 76; CHECK-NEXT: br label [[OUTER_HEADER]] 77; CHECK: exit: 78; CHECK-NEXT: ret void 79; 80entry: 81 br label %outer.header 82 83outer.header: 84 %i.0 = phi i32 [ 1, %entry ], [ %i.inc, %outer.latch ] 85 %cmp = icmp ult i32 %i.0, %len 86 br i1 %cmp, label %inner.header, label %exit 87 88inner.header: 89 %k.0 = phi i32 [ %i.0, %outer.header ], [ %k.inc, %inner.latch ] 90 %cmp2.not = icmp eq i32 %k.0, %len 91 br i1 %cmp2.not, label %outer.latch, label %inner.latch 92 93inner.latch: 94 %cmp.not.i = icmp ult i32 %k.0, 3 95 call void @use(i1 %cmp.not.i) 96 %k.inc = add i32 %k.0, 1 97 br label %inner.header 98 99outer.latch: 100 %i.inc = add i32 %i.0, 1 101 br label %outer.header 102 103exit: 104 ret void 105} 106define void @inner_add_rec_decreasing(i32 noundef %len) { 107; CHECK-LABEL: define void @inner_add_rec_decreasing( 108; CHECK-SAME: i32 noundef [[LEN:%.*]]) { 109; CHECK-NEXT: entry: 110; CHECK-NEXT: br label [[OUTER_HEADER:%.*]] 111; CHECK: outer.header: 112; CHECK-NEXT: [[I_0:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[OUTER_LATCH:%.*]] ] 113; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[I_0]], [[LEN]] 114; CHECK-NEXT: br i1 [[CMP]], label [[INNER_HEADER:%.*]], label [[EXIT:%.*]] 115; CHECK: inner.header: 116; CHECK-NEXT: [[K_0:%.*]] = phi i32 [ [[I_0]], [[OUTER_HEADER]] ], [ [[K_DEC:%.*]], [[INNER_LATCH:%.*]] ] 117; CHECK-NEXT: [[CMP2_NOT:%.*]] = icmp eq i32 [[K_0]], 0 118; CHECK-NEXT: br i1 [[CMP2_NOT]], label [[OUTER_LATCH]], label [[INNER_LATCH]] 119; CHECK: inner.latch: 120; CHECK-NEXT: call void @use(i1 true) 121; CHECK-NEXT: [[K_DEC]] = add i32 [[K_0]], -1 122; CHECK-NEXT: br label [[INNER_HEADER]] 123; CHECK: outer.latch: 124; CHECK-NEXT: [[I_INC]] = add i32 [[I_0]], 1 125; CHECK-NEXT: br label [[OUTER_HEADER]] 126; CHECK: exit: 127; CHECK-NEXT: ret void 128; 129entry: 130 br label %outer.header 131 132outer.header: 133 %i.0 = phi i32 [ 1, %entry ], [ %i.inc, %outer.latch ] 134 %cmp = icmp ult i32 %i.0, %len 135 br i1 %cmp, label %inner.header, label %exit 136 137inner.header: 138 %k.0 = phi i32 [ %i.0, %outer.header ], [ %k.dec, %inner.latch ] 139 %cmp2.not = icmp eq i32 %k.0, 0 140 br i1 %cmp2.not, label %outer.latch, label %inner.latch 141 142inner.latch: 143 %cmp.not.i = icmp ult i32 %k.0, %len 144 call void @use(i1 %cmp.not.i) 145 %k.dec = add i32 %k.0, -1 146 br label %inner.header 147 148outer.latch: 149 %i.inc = add i32 %i.0, 1 150 br label %outer.header 151 152exit: 153 ret void 154} 155