1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 2; RUN: opt -S -passes=constraint-elimination < %s | FileCheck %s 3 4define void @multiple_pow2(i64 %count) { 5; CHECK-LABEL: define void @multiple_pow2( 6; CHECK-SAME: i64 [[COUNT:%.*]]) { 7; CHECK-NEXT: entry: 8; CHECK-NEXT: [[END:%.*]] = shl i64 [[COUNT]], 2 9; CHECK-NEXT: br label [[LOOP:%.*]] 10; CHECK: loop: 11; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ], [ 0, [[ENTRY:%.*]] ] 12; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 4 13; CHECK-NEXT: [[CMP_I_NOT:%.*]] = icmp eq i64 [[IV]], [[END]] 14; CHECK-NEXT: br i1 [[CMP_I_NOT]], label [[EXIT:%.*]], label [[LOOP_LATCH]] 15; CHECK: loop.latch: 16; CHECK-NEXT: br i1 true, label [[LOOP]], label [[EXIT]] 17; CHECK: exit: 18; CHECK-NEXT: ret void 19; 20entry: 21 %end = shl i64 %count, 2 22 br label %loop 23 24loop: 25 %iv = phi i64 [ %iv.next, %loop.latch ], [ 0, %entry ] 26 %iv.next = add i64 %iv, 4 27 %cmp.i.not = icmp eq i64 %iv, %end 28 br i1 %cmp.i.not, label %exit, label %loop.latch 29 30loop.latch: 31 %cmp2.i.i = icmp ult i64 %iv, %end 32 br i1 %cmp2.i.i, label %loop, label %exit 33 34exit: 35 ret void 36} 37 38define void @multiple_pow2_larger_than_needed(i64 %count) { 39; CHECK-LABEL: define void @multiple_pow2_larger_than_needed( 40; CHECK-SAME: i64 [[COUNT:%.*]]) { 41; CHECK-NEXT: entry: 42; CHECK-NEXT: [[END:%.*]] = shl i64 [[COUNT]], 3 43; CHECK-NEXT: br label [[LOOP:%.*]] 44; CHECK: loop: 45; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ], [ 0, [[ENTRY:%.*]] ] 46; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 4 47; CHECK-NEXT: [[CMP_I_NOT:%.*]] = icmp eq i64 [[IV]], [[END]] 48; CHECK-NEXT: br i1 [[CMP_I_NOT]], label [[EXIT:%.*]], label [[LOOP_LATCH]] 49; CHECK: loop.latch: 50; CHECK-NEXT: br i1 true, label [[LOOP]], label [[EXIT]] 51; CHECK: exit: 52; CHECK-NEXT: ret void 53; 54entry: 55 %end = shl i64 %count, 3 56 br label %loop 57 58loop: 59 %iv = phi i64 [ %iv.next, %loop.latch ], [ 0, %entry ] 60 %iv.next = add i64 %iv, 4 61 %cmp.i.not = icmp eq i64 %iv, %end 62 br i1 %cmp.i.not, label %exit, label %loop.latch 63 64loop.latch: 65 %cmp2.i.i = icmp ult i64 %iv, %end 66 br i1 %cmp2.i.i, label %loop, label %exit 67 68exit: 69 ret void 70} 71 72define void @multiple_pow2_too_small(i64 %count) { 73; CHECK-LABEL: define void @multiple_pow2_too_small( 74; CHECK-SAME: i64 [[COUNT:%.*]]) { 75; CHECK-NEXT: entry: 76; CHECK-NEXT: [[END:%.*]] = shl i64 [[COUNT]], 1 77; CHECK-NEXT: br label [[LOOP:%.*]] 78; CHECK: loop: 79; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ], [ 0, [[ENTRY:%.*]] ] 80; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 4 81; CHECK-NEXT: [[CMP_I_NOT:%.*]] = icmp eq i64 [[IV]], [[END]] 82; CHECK-NEXT: br i1 [[CMP_I_NOT]], label [[EXIT:%.*]], label [[LOOP_LATCH]] 83; CHECK: loop.latch: 84; CHECK-NEXT: [[CMP2_I_I:%.*]] = icmp ult i64 [[IV]], [[END]] 85; CHECK-NEXT: br i1 [[CMP2_I_I]], label [[LOOP]], label [[EXIT]] 86; CHECK: exit: 87; CHECK-NEXT: ret void 88; 89entry: 90 %end = shl i64 %count, 1 91 br label %loop 92 93loop: 94 %iv = phi i64 [ %iv.next, %loop.latch ], [ 0, %entry ] 95 %iv.next = add i64 %iv, 4 96 %cmp.i.not = icmp eq i64 %iv, %end 97 br i1 %cmp.i.not, label %exit, label %loop.latch 98 99loop.latch: 100 %cmp2.i.i = icmp ult i64 %iv, %end 101 br i1 %cmp2.i.i, label %loop, label %exit 102 103exit: 104 ret void 105} 106 107define void @multiple_pow2_start_offset(i64 %count) { 108; CHECK-LABEL: define void @multiple_pow2_start_offset( 109; CHECK-SAME: i64 [[COUNT:%.*]]) { 110; CHECK-NEXT: entry: 111; CHECK-NEXT: [[END:%.*]] = shl i64 [[COUNT]], 2 112; CHECK-NEXT: [[PRECOND:%.*]] = icmp ugt i64 [[END]], 4 113; CHECK-NEXT: br i1 [[PRECOND]], label [[LOOP:%.*]], label [[EXIT:%.*]] 114; CHECK: loop: 115; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ], [ 4, [[ENTRY:%.*]] ] 116; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 4 117; CHECK-NEXT: [[CMP_I_NOT:%.*]] = icmp eq i64 [[IV]], [[END]] 118; CHECK-NEXT: br i1 [[CMP_I_NOT]], label [[EXIT]], label [[LOOP_LATCH]] 119; CHECK: loop.latch: 120; CHECK-NEXT: br i1 true, label [[LOOP]], label [[EXIT]] 121; CHECK: exit: 122; CHECK-NEXT: ret void 123; 124entry: 125 %end = shl i64 %count, 2 126 %precond = icmp ugt i64 %end, 4 127 br i1 %precond, label %loop, label %exit 128 129loop: 130 %iv = phi i64 [ %iv.next, %loop.latch ], [ 4, %entry ] 131 %iv.next = add i64 %iv, 4 132 %cmp.i.not = icmp eq i64 %iv, %end 133 br i1 %cmp.i.not, label %exit, label %loop.latch 134 135loop.latch: 136 %cmp2.i.i = icmp ult i64 %iv, %end 137 br i1 %cmp2.i.i, label %loop, label %exit 138 139exit: 140 ret void 141} 142 143define void @multiple_pow2_wrong_start_offset(i64 %count) { 144; CHECK-LABEL: define void @multiple_pow2_wrong_start_offset( 145; CHECK-SAME: i64 [[COUNT:%.*]]) { 146; CHECK-NEXT: entry: 147; CHECK-NEXT: [[END:%.*]] = shl i64 [[COUNT]], 2 148; CHECK-NEXT: [[PRECOND:%.*]] = icmp ugt i64 [[END]], 1 149; CHECK-NEXT: br i1 [[PRECOND]], label [[LOOP:%.*]], label [[EXIT:%.*]] 150; CHECK: loop: 151; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ], [ 1, [[ENTRY:%.*]] ] 152; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 4 153; CHECK-NEXT: [[CMP_I_NOT:%.*]] = icmp eq i64 [[IV]], [[END]] 154; CHECK-NEXT: br i1 [[CMP_I_NOT]], label [[EXIT]], label [[LOOP_LATCH]] 155; CHECK: loop.latch: 156; CHECK-NEXT: [[CMP2_I_I:%.*]] = icmp ult i64 [[IV]], [[END]] 157; CHECK-NEXT: br i1 [[CMP2_I_I]], label [[LOOP]], label [[EXIT]] 158; CHECK: exit: 159; CHECK-NEXT: ret void 160; 161entry: 162 %end = shl i64 %count, 2 163 %precond = icmp ugt i64 %end, 1 164 br i1 %precond, label %loop, label %exit 165 166loop: 167 %iv = phi i64 [ %iv.next, %loop.latch ], [ 1, %entry ] 168 %iv.next = add i64 %iv, 4 169 %cmp.i.not = icmp eq i64 %iv, %end 170 br i1 %cmp.i.not, label %exit, label %loop.latch 171 172loop.latch: 173 %cmp2.i.i = icmp ult i64 %iv, %end 174 br i1 %cmp2.i.i, label %loop, label %exit 175 176exit: 177 ret void 178} 179 180define void @multiple_pow2_start_offset_dynamic(i64 %count) { 181; CHECK-LABEL: define void @multiple_pow2_start_offset_dynamic( 182; CHECK-SAME: i64 [[COUNT:%.*]]) { 183; CHECK-NEXT: entry: 184; CHECK-NEXT: [[SHL:%.*]] = shl i64 [[COUNT]], 2 185; CHECK-NEXT: [[END:%.*]] = add i64 [[SHL]], 1 186; CHECK-NEXT: [[PRECOND:%.*]] = icmp ne i64 [[END]], 0 187; CHECK-NEXT: br i1 [[PRECOND]], label [[LOOP:%.*]], label [[EXIT:%.*]] 188; CHECK: loop: 189; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ], [ 1, [[ENTRY:%.*]] ] 190; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 4 191; CHECK-NEXT: [[CMP_I_NOT:%.*]] = icmp eq i64 [[IV]], [[END]] 192; CHECK-NEXT: br i1 [[CMP_I_NOT]], label [[EXIT]], label [[LOOP_LATCH]] 193; CHECK: loop.latch: 194; CHECK-NEXT: br i1 true, label [[LOOP]], label [[EXIT]] 195; CHECK: exit: 196; CHECK-NEXT: ret void 197; 198entry: 199 %shl = shl i64 %count, 2 200 %end = add i64 %shl, 1 201 %precond = icmp ne i64 %end, 0 202 br i1 %precond, label %loop, label %exit 203 204loop: 205 %iv = phi i64 [ %iv.next, %loop.latch ], [ 1, %entry ] 206 %iv.next = add i64 %iv, 4 207 %cmp.i.not = icmp eq i64 %iv, %end 208 br i1 %cmp.i.not, label %exit, label %loop.latch 209 210loop.latch: 211 %cmp2.i.i = icmp ult i64 %iv, %end 212 br i1 %cmp2.i.i, label %loop, label %exit 213 214exit: 215 ret void 216} 217 218define void @multiple_non_pow2_nuw(i64 %count) { 219; CHECK-LABEL: define void @multiple_non_pow2_nuw( 220; CHECK-SAME: i64 [[COUNT:%.*]]) { 221; CHECK-NEXT: entry: 222; CHECK-NEXT: [[END:%.*]] = mul nuw i64 [[COUNT]], 3 223; CHECK-NEXT: br label [[LOOP:%.*]] 224; CHECK: loop: 225; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ], [ 0, [[ENTRY:%.*]] ] 226; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 3 227; CHECK-NEXT: [[CMP_I_NOT:%.*]] = icmp eq i64 [[IV]], [[END]] 228; CHECK-NEXT: br i1 [[CMP_I_NOT]], label [[EXIT:%.*]], label [[LOOP_LATCH]] 229; CHECK: loop.latch: 230; CHECK-NEXT: br i1 true, label [[LOOP]], label [[EXIT]] 231; CHECK: exit: 232; CHECK-NEXT: ret void 233; 234entry: 235 %end = mul nuw i64 %count, 3 236 br label %loop 237 238loop: 239 %iv = phi i64 [ %iv.next, %loop.latch ], [ 0, %entry ] 240 %iv.next = add i64 %iv, 3 241 %cmp.i.not = icmp eq i64 %iv, %end 242 br i1 %cmp.i.not, label %exit, label %loop.latch 243 244loop.latch: 245 %cmp2.i.i = icmp ult i64 %iv, %end 246 br i1 %cmp2.i.i, label %loop, label %exit 247 248exit: 249 ret void 250} 251 252define void @multiple_non_pow2_missing_nuw(i64 %count) { 253; CHECK-LABEL: define void @multiple_non_pow2_missing_nuw( 254; CHECK-SAME: i64 [[COUNT:%.*]]) { 255; CHECK-NEXT: entry: 256; CHECK-NEXT: [[END:%.*]] = mul i64 [[COUNT]], 3 257; CHECK-NEXT: br label [[LOOP:%.*]] 258; CHECK: loop: 259; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ], [ 0, [[ENTRY:%.*]] ] 260; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], 3 261; CHECK-NEXT: [[CMP_I_NOT:%.*]] = icmp eq i64 [[IV]], [[END]] 262; CHECK-NEXT: br i1 [[CMP_I_NOT]], label [[EXIT:%.*]], label [[LOOP_LATCH]] 263; CHECK: loop.latch: 264; CHECK-NEXT: [[CMP2_I_I:%.*]] = icmp ult i64 [[IV]], [[END]] 265; CHECK-NEXT: br i1 [[CMP2_I_I]], label [[LOOP]], label [[EXIT]] 266; CHECK: exit: 267; CHECK-NEXT: ret void 268; 269entry: 270 %end = mul i64 %count, 3 271 br label %loop 272 273loop: 274 %iv = phi i64 [ %iv.next, %loop.latch ], [ 0, %entry ] 275 %iv.next = add i64 %iv, 3 276 %cmp.i.not = icmp eq i64 %iv, %end 277 br i1 %cmp.i.not, label %exit, label %loop.latch 278 279loop.latch: 280 %cmp2.i.i = icmp ult i64 %iv, %end 281 br i1 %cmp2.i.i, label %loop, label %exit 282 283exit: 284 ret void 285} 286