1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -loop-predication < %s 2>&1 | FileCheck %s 3; RUN: opt -S -passes='require<scalar-evolution>,loop(loop-predication)' < %s 2>&1 | FileCheck %s 4 5declare void @llvm.experimental.guard(i1, ...) 6 7define i32 @unsigned_loop_0_to_n_ult_check(i32* %array, i32 %length, i32 %n) { 8; CHECK-LABEL: @unsigned_loop_0_to_n_ult_check( 9; CHECK-NEXT: entry: 10; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0 11; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 12; CHECK: loop.preheader: 13; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH:%.*]] 14; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]] 15; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]] 16; CHECK-NEXT: br label [[LOOP:%.*]] 17; CHECK: loop: 18; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 19; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 20; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] 21; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 22; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 23; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 24; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 25; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 26; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]] 27; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 28; CHECK: exit.loopexit: 29; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 30; CHECK-NEXT: br label [[EXIT]] 31; CHECK: exit: 32; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 33; CHECK-NEXT: ret i32 [[RESULT]] 34; 35entry: 36 %tmp5 = icmp eq i32 %n, 0 37 br i1 %tmp5, label %exit, label %loop.preheader 38 39loop.preheader: 40 br label %loop 41 42loop: 43 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 44 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 45 %within.bounds = icmp ult i32 %i, %length 46 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 47 48 %i.i64 = zext i32 %i to i64 49 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 50 %array.i = load i32, i32* %array.i.ptr, align 4 51 %loop.acc.next = add i32 %loop.acc, %array.i 52 53 %i.next = add nuw i32 %i, 1 54 %continue = icmp ult i32 %i.next, %n 55 br i1 %continue, label %loop, label %exit 56 57exit: 58 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 59 ret i32 %result 60} 61 62define i32 @unsigned_loop_0_to_n_ule_latch_ult_check(i32* %array, i32 %length, i32 %n) { 63; CHECK-LABEL: @unsigned_loop_0_to_n_ule_latch_ult_check( 64; CHECK-NEXT: entry: 65; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0 66; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 67; CHECK: loop.preheader: 68; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[N]], [[LENGTH:%.*]] 69; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]] 70; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]] 71; CHECK-NEXT: br label [[LOOP:%.*]] 72; CHECK: loop: 73; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 74; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 75; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] 76; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 77; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 78; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 79; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 80; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 81; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ule i32 [[I_NEXT]], [[N]] 82; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 83; CHECK: exit.loopexit: 84; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 85; CHECK-NEXT: br label [[EXIT]] 86; CHECK: exit: 87; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 88; CHECK-NEXT: ret i32 [[RESULT]] 89; 90entry: 91 %tmp5 = icmp eq i32 %n, 0 92 br i1 %tmp5, label %exit, label %loop.preheader 93 94loop.preheader: 95 br label %loop 96 97loop: 98 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 99 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 100 %within.bounds = icmp ult i32 %i, %length 101 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 102 103 %i.i64 = zext i32 %i to i64 104 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 105 %array.i = load i32, i32* %array.i.ptr, align 4 106 %loop.acc.next = add i32 %loop.acc, %array.i 107 108 %i.next = add nuw i32 %i, 1 109 %continue = icmp ule i32 %i.next, %n 110 br i1 %continue, label %loop, label %exit 111 112exit: 113 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 114 ret i32 %result 115} 116 117define i32 @unsigned_loop_0_to_n_ugt_check(i32* %array, i32 %length, i32 %n) { 118; CHECK-LABEL: @unsigned_loop_0_to_n_ugt_check( 119; CHECK-NEXT: entry: 120; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0 121; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 122; CHECK: loop.preheader: 123; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH:%.*]] 124; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]] 125; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]] 126; CHECK-NEXT: br label [[LOOP:%.*]] 127; CHECK: loop: 128; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 129; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 130; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] 131; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 132; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 133; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 134; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 135; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 136; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]] 137; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 138; CHECK: exit.loopexit: 139; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 140; CHECK-NEXT: br label [[EXIT]] 141; CHECK: exit: 142; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 143; CHECK-NEXT: ret i32 [[RESULT]] 144; 145entry: 146 %tmp5 = icmp eq i32 %n, 0 147 br i1 %tmp5, label %exit, label %loop.preheader 148 149loop.preheader: 150 br label %loop 151 152loop: 153 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 154 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 155 %within.bounds = icmp ugt i32 %length, %i 156 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 157 158 %i.i64 = zext i32 %i to i64 159 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 160 %array.i = load i32, i32* %array.i.ptr, align 4 161 %loop.acc.next = add i32 %loop.acc, %array.i 162 163 %i.next = add nuw i32 %i, 1 164 %continue = icmp ult i32 %i.next, %n 165 br i1 %continue, label %loop, label %exit 166 167exit: 168 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 169 ret i32 %result 170} 171 172define i32 @signed_loop_0_to_n_ult_check(i32* %array, i32 %length, i32 %n) { 173; CHECK-LABEL: @signed_loop_0_to_n_ult_check( 174; CHECK-NEXT: entry: 175; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0 176; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 177; CHECK: loop.preheader: 178; CHECK-NEXT: [[TMP0:%.*]] = icmp sle i32 [[N]], [[LENGTH:%.*]] 179; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]] 180; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]] 181; CHECK-NEXT: br label [[LOOP:%.*]] 182; CHECK: loop: 183; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 184; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 185; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] 186; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 187; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 188; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 189; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 190; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 191; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]] 192; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 193; CHECK: exit.loopexit: 194; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 195; CHECK-NEXT: br label [[EXIT]] 196; CHECK: exit: 197; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 198; CHECK-NEXT: ret i32 [[RESULT]] 199; 200entry: 201 %tmp5 = icmp sle i32 %n, 0 202 br i1 %tmp5, label %exit, label %loop.preheader 203 204loop.preheader: 205 br label %loop 206 207loop: 208 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 209 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 210 %within.bounds = icmp ult i32 %i, %length 211 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 212 213 %i.i64 = zext i32 %i to i64 214 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 215 %array.i = load i32, i32* %array.i.ptr, align 4 216 %loop.acc.next = add i32 %loop.acc, %array.i 217 218 %i.next = add nuw i32 %i, 1 219 %continue = icmp slt i32 %i.next, %n 220 br i1 %continue, label %loop, label %exit 221 222exit: 223 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 224 ret i32 %result 225} 226 227define i32 @signed_loop_0_to_n_ult_check_length_range_known(i32* %array, i32* %length.ptr, i32 %n) { 228; CHECK-LABEL: @signed_loop_0_to_n_ult_check_length_range_known( 229; CHECK-NEXT: entry: 230; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0 231; CHECK-NEXT: [[LENGTH:%.*]] = load i32, i32* [[LENGTH_PTR:%.*]], !range !0 232; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 233; CHECK: loop.preheader: 234; CHECK-NEXT: [[TMP0:%.*]] = icmp sle i32 [[N]], [[LENGTH]] 235; CHECK-NEXT: [[TMP1:%.*]] = and i1 true, [[TMP0]] 236; CHECK-NEXT: br label [[LOOP:%.*]] 237; CHECK: loop: 238; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 239; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 240; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP1]], i32 9) [ "deopt"() ] 241; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 242; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 243; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 244; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 245; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 246; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]] 247; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 248; CHECK: exit.loopexit: 249; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 250; CHECK-NEXT: br label [[EXIT]] 251; CHECK: exit: 252; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 253; CHECK-NEXT: ret i32 [[RESULT]] 254; 255entry: 256 %tmp5 = icmp sle i32 %n, 0 257 %length = load i32, i32* %length.ptr, !range !{i32 1, i32 2147483648} 258 br i1 %tmp5, label %exit, label %loop.preheader 259 260loop.preheader: 261 br label %loop 262 263loop: 264 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 265 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 266 %within.bounds = icmp ult i32 %i, %length 267 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 268 269 %i.i64 = zext i32 %i to i64 270 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 271 %array.i = load i32, i32* %array.i.ptr, align 4 272 %loop.acc.next = add i32 %loop.acc, %array.i 273 274 %i.next = add nuw i32 %i, 1 275 %continue = icmp slt i32 %i.next, %n 276 br i1 %continue, label %loop, label %exit 277 278exit: 279 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 280 ret i32 %result 281} 282 283define i32 @signed_loop_0_to_n_inverse_latch_predicate(i32* %array, i32 %length, i32 %n) { 284; CHECK-LABEL: @signed_loop_0_to_n_inverse_latch_predicate( 285; CHECK-NEXT: entry: 286; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0 287; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 288; CHECK: loop.preheader: 289; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[N]], [[LENGTH:%.*]] 290; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]] 291; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]] 292; CHECK-NEXT: br label [[LOOP:%.*]] 293; CHECK: loop: 294; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 295; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 296; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] 297; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 298; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 299; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 300; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 301; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 302; CHECK-NEXT: [[CONTINUE:%.*]] = icmp sgt i32 [[I_NEXT]], [[N]] 303; CHECK-NEXT: br i1 [[CONTINUE]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP]] 304; CHECK: exit.loopexit: 305; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 306; CHECK-NEXT: br label [[EXIT]] 307; CHECK: exit: 308; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 309; CHECK-NEXT: ret i32 [[RESULT]] 310; 311entry: 312 %tmp5 = icmp sle i32 %n, 0 313 br i1 %tmp5, label %exit, label %loop.preheader 314 315loop.preheader: 316 br label %loop 317 318loop: 319 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 320 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 321 %within.bounds = icmp ult i32 %i, %length 322 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 323 324 %i.i64 = zext i32 %i to i64 325 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 326 %array.i = load i32, i32* %array.i.ptr, align 4 327 %loop.acc.next = add i32 %loop.acc, %array.i 328 329 %i.next = add nuw i32 %i, 1 330 %continue = icmp sgt i32 %i.next, %n 331 br i1 %continue, label %exit, label %loop 332 333exit: 334 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 335 ret i32 %result 336} 337 338define i32 @signed_loop_0_to_n_sle_latch_ult_check(i32* %array, i32 %length, i32 %n) { 339; CHECK-LABEL: @signed_loop_0_to_n_sle_latch_ult_check( 340; CHECK-NEXT: entry: 341; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0 342; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 343; CHECK: loop.preheader: 344; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[N]], [[LENGTH:%.*]] 345; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]] 346; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]] 347; CHECK-NEXT: br label [[LOOP:%.*]] 348; CHECK: loop: 349; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 350; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 351; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] 352; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 353; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 354; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 355; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 356; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 357; CHECK-NEXT: [[CONTINUE:%.*]] = icmp sle i32 [[I_NEXT]], [[N]] 358; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 359; CHECK: exit.loopexit: 360; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 361; CHECK-NEXT: br label [[EXIT]] 362; CHECK: exit: 363; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 364; CHECK-NEXT: ret i32 [[RESULT]] 365; 366entry: 367 %tmp5 = icmp sle i32 %n, 0 368 br i1 %tmp5, label %exit, label %loop.preheader 369 370loop.preheader: 371 br label %loop 372 373loop: 374 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 375 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 376 %within.bounds = icmp ult i32 %i, %length 377 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 378 379 %i.i64 = zext i32 %i to i64 380 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 381 %array.i = load i32, i32* %array.i.ptr, align 4 382 %loop.acc.next = add i32 %loop.acc, %array.i 383 384 %i.next = add nuw i32 %i, 1 385 %continue = icmp sle i32 %i.next, %n 386 br i1 %continue, label %loop, label %exit 387 388exit: 389 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 390 ret i32 %result 391} 392 393define i32 @signed_loop_0_to_n_preincrement_latch_check(i32* %array, i32 %length, i32 %n) { 394; CHECK-LABEL: @signed_loop_0_to_n_preincrement_latch_check( 395; CHECK-NEXT: entry: 396; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0 397; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 398; CHECK: loop.preheader: 399; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], -1 400; CHECK-NEXT: [[TMP1:%.*]] = icmp sle i32 [[N]], [[TMP0]] 401; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 0, [[LENGTH]] 402; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]] 403; CHECK-NEXT: br label [[LOOP:%.*]] 404; CHECK: loop: 405; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 406; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 407; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ] 408; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 409; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 410; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 411; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 412; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1 413; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I]], [[N]] 414; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 415; CHECK: exit.loopexit: 416; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 417; CHECK-NEXT: br label [[EXIT]] 418; CHECK: exit: 419; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 420; CHECK-NEXT: ret i32 [[RESULT]] 421; 422entry: 423 %tmp5 = icmp sle i32 %n, 0 424 br i1 %tmp5, label %exit, label %loop.preheader 425 426loop.preheader: 427 br label %loop 428 429loop: 430 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 431 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 432 %within.bounds = icmp ult i32 %i, %length 433 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 434 435 %i.i64 = zext i32 %i to i64 436 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 437 %array.i = load i32, i32* %array.i.ptr, align 4 438 %loop.acc.next = add i32 %loop.acc, %array.i 439 440 %i.next = add i32 %i, 1 441 %continue = icmp slt i32 %i, %n 442 br i1 %continue, label %loop, label %exit 443 444exit: 445 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 446 ret i32 %result 447} 448 449define i32 @signed_loop_0_to_n_preincrement_latch_check_postincrement_guard_check(i32* %array, i32 %length, i32 %n) { 450; CHECK-LABEL: @signed_loop_0_to_n_preincrement_latch_check_postincrement_guard_check( 451; CHECK-NEXT: entry: 452; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0 453; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 454; CHECK: loop.preheader: 455; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], -2 456; CHECK-NEXT: [[TMP1:%.*]] = icmp sle i32 [[N]], [[TMP0]] 457; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 1, [[LENGTH]] 458; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]] 459; CHECK-NEXT: br label [[LOOP:%.*]] 460; CHECK: loop: 461; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 462; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 463; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1 464; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ] 465; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 466; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 467; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 468; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 469; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I]], [[N]] 470; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 471; CHECK: exit.loopexit: 472; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 473; CHECK-NEXT: br label [[EXIT]] 474; CHECK: exit: 475; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 476; CHECK-NEXT: ret i32 [[RESULT]] 477; 478entry: 479 %tmp5 = icmp sle i32 %n, 0 480 br i1 %tmp5, label %exit, label %loop.preheader 481 482loop.preheader: 483 br label %loop 484 485loop: 486 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 487 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 488 489 %i.next = add i32 %i, 1 490 %within.bounds = icmp ult i32 %i.next, %length 491 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 492 493 %i.i64 = zext i32 %i to i64 494 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 495 %array.i = load i32, i32* %array.i.ptr, align 4 496 %loop.acc.next = add i32 %loop.acc, %array.i 497 498 %continue = icmp slt i32 %i, %n 499 br i1 %continue, label %loop, label %exit 500 501exit: 502 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 503 ret i32 %result 504} 505 506define i32 @signed_loop_0_to_n_sle_latch_offset_ult_check(i32* %array, i32 %length, i32 %n) { 507; CHECK-LABEL: @signed_loop_0_to_n_sle_latch_offset_ult_check( 508; CHECK-NEXT: entry: 509; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0 510; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 511; CHECK: loop.preheader: 512; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], -1 513; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[N]], [[TMP0]] 514; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 1, [[LENGTH]] 515; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]] 516; CHECK-NEXT: br label [[LOOP:%.*]] 517; CHECK: loop: 518; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 519; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 520; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ] 521; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 522; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 523; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 524; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 525; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1 526; CHECK-NEXT: [[CONTINUE:%.*]] = icmp sle i32 [[I_NEXT]], [[N]] 527; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 528; CHECK: exit.loopexit: 529; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 530; CHECK-NEXT: br label [[EXIT]] 531; CHECK: exit: 532; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 533; CHECK-NEXT: ret i32 [[RESULT]] 534; 535entry: 536 %tmp5 = icmp sle i32 %n, 0 537 br i1 %tmp5, label %exit, label %loop.preheader 538 539loop.preheader: 540 br label %loop 541 542loop: 543 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 544 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 545 %i.offset = add i32 %i, 1 546 %within.bounds = icmp ult i32 %i.offset, %length 547 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 548 549 %i.i64 = zext i32 %i to i64 550 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 551 %array.i = load i32, i32* %array.i.ptr, align 4 552 %loop.acc.next = add i32 %loop.acc, %array.i 553 554 %i.next = add i32 %i, 1 555 %continue = icmp sle i32 %i.next, %n 556 br i1 %continue, label %loop, label %exit 557 558exit: 559 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 560 ret i32 %result 561} 562 563define i32 @signed_loop_0_to_n_offset_sle_latch_offset_ult_check(i32* %array, i32 %length, i32 %n) { 564; CHECK-LABEL: @signed_loop_0_to_n_offset_sle_latch_offset_ult_check( 565; CHECK-NEXT: entry: 566; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0 567; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 568; CHECK: loop.preheader: 569; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[N]], [[LENGTH:%.*]] 570; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 1, [[LENGTH]] 571; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]] 572; CHECK-NEXT: br label [[LOOP:%.*]] 573; CHECK: loop: 574; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 575; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 576; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] 577; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 578; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 579; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 580; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 581; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1 582; CHECK-NEXT: [[I_NEXT_OFFSET:%.*]] = add i32 [[I_NEXT]], 1 583; CHECK-NEXT: [[CONTINUE:%.*]] = icmp sle i32 [[I_NEXT_OFFSET]], [[N]] 584; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 585; CHECK: exit.loopexit: 586; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 587; CHECK-NEXT: br label [[EXIT]] 588; CHECK: exit: 589; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 590; CHECK-NEXT: ret i32 [[RESULT]] 591; 592entry: 593 %tmp5 = icmp sle i32 %n, 0 594 br i1 %tmp5, label %exit, label %loop.preheader 595 596loop.preheader: 597 br label %loop 598 599loop: 600 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 601 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 602 %i.offset = add i32 %i, 1 603 %within.bounds = icmp ult i32 %i.offset, %length 604 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 605 606 %i.i64 = zext i32 %i to i64 607 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 608 %array.i = load i32, i32* %array.i.ptr, align 4 609 %loop.acc.next = add i32 %loop.acc, %array.i 610 611 %i.next = add i32 %i, 1 612 %i.next.offset = add i32 %i.next, 1 613 %continue = icmp sle i32 %i.next.offset, %n 614 br i1 %continue, label %loop, label %exit 615 616exit: 617 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 618 ret i32 %result 619} 620 621define i32 @unsupported_latch_pred_loop_0_to_n(i32* %array, i32 %length, i32 %n) { 622; CHECK-LABEL: @unsupported_latch_pred_loop_0_to_n( 623; CHECK-NEXT: entry: 624; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0 625; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 626; CHECK: loop.preheader: 627; CHECK-NEXT: br label [[LOOP:%.*]] 628; CHECK: loop: 629; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 630; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 631; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]] 632; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ] 633; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 634; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 635; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 636; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 637; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], 1 638; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I_NEXT]], [[N]] 639; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 640; CHECK: exit.loopexit: 641; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 642; CHECK-NEXT: br label [[EXIT]] 643; CHECK: exit: 644; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 645; CHECK-NEXT: ret i32 [[RESULT]] 646; 647entry: 648 %tmp5 = icmp sle i32 %n, 0 649 br i1 %tmp5, label %exit, label %loop.preheader 650 651loop.preheader: 652 br label %loop 653 654loop: 655 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 656 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 657 %within.bounds = icmp ult i32 %i, %length 658 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 659 660 %i.i64 = zext i32 %i to i64 661 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 662 %array.i = load i32, i32* %array.i.ptr, align 4 663 %loop.acc.next = add i32 %loop.acc, %array.i 664 665 %i.next = add nsw i32 %i, 1 666 %continue = icmp ne i32 %i.next, %n 667 br i1 %continue, label %loop, label %exit 668 669exit: 670 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 671 ret i32 %result 672} 673 674define i32 @signed_loop_0_to_n_unsupported_iv_step(i32* %array, i32 %length, i32 %n) { 675; CHECK-LABEL: @signed_loop_0_to_n_unsupported_iv_step( 676; CHECK-NEXT: entry: 677; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0 678; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 679; CHECK: loop.preheader: 680; CHECK-NEXT: br label [[LOOP:%.*]] 681; CHECK: loop: 682; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 683; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 684; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]] 685; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ] 686; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 687; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 688; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 689; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 690; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], 2 691; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]] 692; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 693; CHECK: exit.loopexit: 694; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 695; CHECK-NEXT: br label [[EXIT]] 696; CHECK: exit: 697; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 698; CHECK-NEXT: ret i32 [[RESULT]] 699; 700entry: 701 %tmp5 = icmp sle i32 %n, 0 702 br i1 %tmp5, label %exit, label %loop.preheader 703 704loop.preheader: 705 br label %loop 706 707loop: 708 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 709 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 710 %within.bounds = icmp ult i32 %i, %length 711 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 712 713 %i.i64 = zext i32 %i to i64 714 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 715 %array.i = load i32, i32* %array.i.ptr, align 4 716 %loop.acc.next = add i32 %loop.acc, %array.i 717 718 %i.next = add nsw i32 %i, 2 719 %continue = icmp slt i32 %i.next, %n 720 br i1 %continue, label %loop, label %exit 721 722exit: 723 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 724 ret i32 %result 725} 726 727define i32 @signed_loop_0_to_n_equal_iv_range_check(i32* %array, i32 %length, i32 %n) { 728; CHECK-LABEL: @signed_loop_0_to_n_equal_iv_range_check( 729; CHECK-NEXT: entry: 730; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0 731; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 732; CHECK: loop.preheader: 733; CHECK-NEXT: [[TMP0:%.*]] = icmp sle i32 [[N]], [[LENGTH:%.*]] 734; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]] 735; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]] 736; CHECK-NEXT: br label [[LOOP:%.*]] 737; CHECK: loop: 738; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 739; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 740; CHECK-NEXT: [[J:%.*]] = phi i32 [ [[J_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 741; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] 742; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 743; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 744; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 745; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 746; CHECK-NEXT: [[J_NEXT]] = add nsw i32 [[J]], 1 747; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], 1 748; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]] 749; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 750; CHECK: exit.loopexit: 751; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 752; CHECK-NEXT: br label [[EXIT]] 753; CHECK: exit: 754; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 755; CHECK-NEXT: ret i32 [[RESULT]] 756; 757entry: 758 %tmp5 = icmp sle i32 %n, 0 759 br i1 %tmp5, label %exit, label %loop.preheader 760 761loop.preheader: 762 br label %loop 763 764loop: 765 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 766 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 767 %j = phi i32 [ %j.next, %loop ], [ 0, %loop.preheader ] 768 769 %within.bounds = icmp ult i32 %j, %length 770 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 771 772 %i.i64 = zext i32 %i to i64 773 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 774 %array.i = load i32, i32* %array.i.ptr, align 4 775 %loop.acc.next = add i32 %loop.acc, %array.i 776 777 %j.next = add nsw i32 %j, 1 778 %i.next = add nsw i32 %i, 1 779 %continue = icmp slt i32 %i.next, %n 780 br i1 %continue, label %loop, label %exit 781 782exit: 783 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 784 ret i32 %result 785} 786 787define i32 @signed_loop_start_to_n_offset_iv_range_check(i32* %array, i32 %start.i, 788; CHECK-LABEL: @signed_loop_start_to_n_offset_iv_range_check( 789; CHECK-NEXT: entry: 790; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0 791; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 792; CHECK: loop.preheader: 793; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], [[START_I:%.*]] 794; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[TMP0]], [[START_J:%.*]] 795; CHECK-NEXT: [[TMP2:%.*]] = icmp sle i32 [[N]], [[TMP1]] 796; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i32 [[START_J]], [[LENGTH]] 797; CHECK-NEXT: [[TMP4:%.*]] = and i1 [[TMP3]], [[TMP2]] 798; CHECK-NEXT: br label [[LOOP:%.*]] 799; CHECK: loop: 800; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 801; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[START_I]], [[LOOP_PREHEADER]] ] 802; CHECK-NEXT: [[J:%.*]] = phi i32 [ [[J_NEXT:%.*]], [[LOOP]] ], [ [[START_J]], [[LOOP_PREHEADER]] ] 803; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP4]], i32 9) [ "deopt"() ] 804; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 805; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 806; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 807; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 808; CHECK-NEXT: [[J_NEXT]] = add i32 [[J]], 1 809; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1 810; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]] 811; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 812; CHECK: exit.loopexit: 813; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 814; CHECK-NEXT: br label [[EXIT]] 815; CHECK: exit: 816; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 817; CHECK-NEXT: ret i32 [[RESULT]] 818; 819 i32 %start.j, i32 %length, 820 i32 %n) { 821entry: 822 %tmp5 = icmp sle i32 %n, 0 823 br i1 %tmp5, label %exit, label %loop.preheader 824 825loop.preheader: 826 br label %loop 827 828loop: 829 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 830 %i = phi i32 [ %i.next, %loop ], [ %start.i, %loop.preheader ] 831 %j = phi i32 [ %j.next, %loop ], [ %start.j, %loop.preheader ] 832 833 %within.bounds = icmp ult i32 %j, %length 834 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 835 836 %i.i64 = zext i32 %i to i64 837 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 838 %array.i = load i32, i32* %array.i.ptr, align 4 839 %loop.acc.next = add i32 %loop.acc, %array.i 840 841 %j.next = add i32 %j, 1 842 %i.next = add i32 %i, 1 843 %continue = icmp slt i32 %i.next, %n 844 br i1 %continue, label %loop, label %exit 845 846exit: 847 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 848 ret i32 %result 849} 850 851define i32 @signed_loop_0_to_n_different_iv_types(i32* %array, i16 %length, i32 %n) { 852; CHECK-LABEL: @signed_loop_0_to_n_different_iv_types( 853; CHECK-NEXT: entry: 854; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0 855; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 856; CHECK: loop.preheader: 857; CHECK-NEXT: br label [[LOOP:%.*]] 858; CHECK: loop: 859; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 860; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 861; CHECK-NEXT: [[J:%.*]] = phi i16 [ [[J_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 862; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i16 [[J]], [[LENGTH:%.*]] 863; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ] 864; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 865; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 866; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 867; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 868; CHECK-NEXT: [[J_NEXT]] = add i16 [[J]], 1 869; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1 870; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]] 871; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 872; CHECK: exit.loopexit: 873; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 874; CHECK-NEXT: br label [[EXIT]] 875; CHECK: exit: 876; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 877; CHECK-NEXT: ret i32 [[RESULT]] 878; 879entry: 880 %tmp5 = icmp sle i32 %n, 0 881 br i1 %tmp5, label %exit, label %loop.preheader 882 883loop.preheader: 884 br label %loop 885 886loop: 887 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 888 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 889 %j = phi i16 [ %j.next, %loop ], [ 0, %loop.preheader ] 890 891 %within.bounds = icmp ult i16 %j, %length 892 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 893 894 %i.i64 = zext i32 %i to i64 895 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 896 %array.i = load i32, i32* %array.i.ptr, align 4 897 %loop.acc.next = add i32 %loop.acc, %array.i 898 899 %j.next = add i16 %j, 1 900 %i.next = add i32 %i, 1 901 %continue = icmp slt i32 %i.next, %n 902 br i1 %continue, label %loop, label %exit 903 904exit: 905 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 906 ret i32 %result 907} 908 909define i32 @signed_loop_0_to_n_different_iv_strides(i32* %array, i32 %length, i32 %n) { 910; CHECK-LABEL: @signed_loop_0_to_n_different_iv_strides( 911; CHECK-NEXT: entry: 912; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0 913; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 914; CHECK: loop.preheader: 915; CHECK-NEXT: br label [[LOOP:%.*]] 916; CHECK: loop: 917; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 918; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 919; CHECK-NEXT: [[J:%.*]] = phi i32 [ [[J_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 920; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[J]], [[LENGTH:%.*]] 921; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ] 922; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 923; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 924; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 925; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 926; CHECK-NEXT: [[J_NEXT]] = add nsw i32 [[J]], 2 927; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], 1 928; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]] 929; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 930; CHECK: exit.loopexit: 931; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 932; CHECK-NEXT: br label [[EXIT]] 933; CHECK: exit: 934; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 935; CHECK-NEXT: ret i32 [[RESULT]] 936; 937entry: 938 %tmp5 = icmp sle i32 %n, 0 939 br i1 %tmp5, label %exit, label %loop.preheader 940 941loop.preheader: 942 br label %loop 943 944loop: 945 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 946 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 947 %j = phi i32 [ %j.next, %loop ], [ 0, %loop.preheader ] 948 949 %within.bounds = icmp ult i32 %j, %length 950 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 951 952 %i.i64 = zext i32 %i to i64 953 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 954 %array.i = load i32, i32* %array.i.ptr, align 4 955 %loop.acc.next = add i32 %loop.acc, %array.i 956 957 %j.next = add nsw i32 %j, 2 958 %i.next = add nsw i32 %i, 1 959 %continue = icmp slt i32 %i.next, %n 960 br i1 %continue, label %loop, label %exit 961 962exit: 963 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 964 ret i32 %result 965} 966 967define i32 @two_range_checks(i32* %array.1, i32 %length.1, 968; CHECK-LABEL: @two_range_checks( 969; CHECK-NEXT: entry: 970; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0 971; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 972; CHECK: loop.preheader: 973; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH_2:%.*]] 974; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH_2]] 975; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]] 976; CHECK-NEXT: [[TMP3:%.*]] = icmp ule i32 [[N]], [[LENGTH_1:%.*]] 977; CHECK-NEXT: [[TMP4:%.*]] = icmp ult i32 0, [[LENGTH_1]] 978; CHECK-NEXT: [[TMP5:%.*]] = and i1 [[TMP4]], [[TMP3]] 979; CHECK-NEXT: [[TMP6:%.*]] = and i1 [[TMP2]], [[TMP5]] 980; CHECK-NEXT: br label [[LOOP:%.*]] 981; CHECK: loop: 982; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 983; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 984; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP6]], i32 9) [ "deopt"() ] 985; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 986; CHECK-NEXT: [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_1:%.*]], i64 [[I_I64]] 987; CHECK-NEXT: [[ARRAY_1_I:%.*]] = load i32, i32* [[ARRAY_1_I_PTR]], align 4 988; CHECK-NEXT: [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]] 989; CHECK-NEXT: [[ARRAY_2_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_2:%.*]], i64 [[I_I64]] 990; CHECK-NEXT: [[ARRAY_2_I:%.*]] = load i32, i32* [[ARRAY_2_I_PTR]], align 4 991; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_1]], [[ARRAY_2_I]] 992; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 993; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]] 994; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 995; CHECK: exit.loopexit: 996; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 997; CHECK-NEXT: br label [[EXIT]] 998; CHECK: exit: 999; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 1000; CHECK-NEXT: ret i32 [[RESULT]] 1001; 1002 i32* %array.2, i32 %length.2, i32 %n) { 1003entry: 1004 %tmp5 = icmp eq i32 %n, 0 1005 br i1 %tmp5, label %exit, label %loop.preheader 1006 1007loop.preheader: 1008 br label %loop 1009 1010loop: 1011 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 1012 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 1013 %within.bounds.1 = icmp ult i32 %i, %length.1 1014 %within.bounds.2 = icmp ult i32 %i, %length.2 1015 %within.bounds = and i1 %within.bounds.1, %within.bounds.2 1016 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 1017 1018 %i.i64 = zext i32 %i to i64 1019 %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64 1020 %array.1.i = load i32, i32* %array.1.i.ptr, align 4 1021 %loop.acc.1 = add i32 %loop.acc, %array.1.i 1022 1023 %array.2.i.ptr = getelementptr inbounds i32, i32* %array.2, i64 %i.i64 1024 %array.2.i = load i32, i32* %array.2.i.ptr, align 4 1025 %loop.acc.next = add i32 %loop.acc.1, %array.2.i 1026 1027 %i.next = add nuw i32 %i, 1 1028 %continue = icmp ult i32 %i.next, %n 1029 br i1 %continue, label %loop, label %exit 1030 1031exit: 1032 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 1033 ret i32 %result 1034} 1035 1036define i32 @three_range_checks(i32* %array.1, i32 %length.1, 1037; CHECK-LABEL: @three_range_checks( 1038; CHECK-NEXT: entry: 1039; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0 1040; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 1041; CHECK: loop.preheader: 1042; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH_3:%.*]] 1043; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH_3]] 1044; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]] 1045; CHECK-NEXT: [[TMP3:%.*]] = icmp ule i32 [[N]], [[LENGTH_2:%.*]] 1046; CHECK-NEXT: [[TMP4:%.*]] = icmp ult i32 0, [[LENGTH_2]] 1047; CHECK-NEXT: [[TMP5:%.*]] = and i1 [[TMP4]], [[TMP3]] 1048; CHECK-NEXT: [[TMP6:%.*]] = icmp ule i32 [[N]], [[LENGTH_1:%.*]] 1049; CHECK-NEXT: [[TMP7:%.*]] = icmp ult i32 0, [[LENGTH_1]] 1050; CHECK-NEXT: [[TMP8:%.*]] = and i1 [[TMP7]], [[TMP6]] 1051; CHECK-NEXT: [[TMP9:%.*]] = and i1 [[TMP2]], [[TMP5]] 1052; CHECK-NEXT: [[TMP10:%.*]] = and i1 [[TMP9]], [[TMP8]] 1053; CHECK-NEXT: br label [[LOOP:%.*]] 1054; CHECK: loop: 1055; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 1056; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 1057; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP10]], i32 9) [ "deopt"() ] 1058; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 1059; CHECK-NEXT: [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_1:%.*]], i64 [[I_I64]] 1060; CHECK-NEXT: [[ARRAY_1_I:%.*]] = load i32, i32* [[ARRAY_1_I_PTR]], align 4 1061; CHECK-NEXT: [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]] 1062; CHECK-NEXT: [[ARRAY_2_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_2:%.*]], i64 [[I_I64]] 1063; CHECK-NEXT: [[ARRAY_2_I:%.*]] = load i32, i32* [[ARRAY_2_I_PTR]], align 4 1064; CHECK-NEXT: [[LOOP_ACC_2:%.*]] = add i32 [[LOOP_ACC_1]], [[ARRAY_2_I]] 1065; CHECK-NEXT: [[ARRAY_3_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_3:%.*]], i64 [[I_I64]] 1066; CHECK-NEXT: [[ARRAY_3_I:%.*]] = load i32, i32* [[ARRAY_3_I_PTR]], align 4 1067; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_2]], [[ARRAY_3_I]] 1068; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 1069; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]] 1070; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 1071; CHECK: exit.loopexit: 1072; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 1073; CHECK-NEXT: br label [[EXIT]] 1074; CHECK: exit: 1075; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 1076; CHECK-NEXT: ret i32 [[RESULT]] 1077; 1078 i32* %array.2, i32 %length.2, 1079 i32* %array.3, i32 %length.3, i32 %n) { 1080entry: 1081 %tmp5 = icmp eq i32 %n, 0 1082 br i1 %tmp5, label %exit, label %loop.preheader 1083 1084loop.preheader: 1085 br label %loop 1086 1087loop: 1088 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 1089 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 1090 %within.bounds.1 = icmp ult i32 %i, %length.1 1091 %within.bounds.2 = icmp ult i32 %i, %length.2 1092 %within.bounds.3 = icmp ult i32 %i, %length.3 1093 %within.bounds.1.and.2 = and i1 %within.bounds.1, %within.bounds.2 1094 %within.bounds = and i1 %within.bounds.1.and.2, %within.bounds.3 1095 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 1096 1097 %i.i64 = zext i32 %i to i64 1098 %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64 1099 %array.1.i = load i32, i32* %array.1.i.ptr, align 4 1100 %loop.acc.1 = add i32 %loop.acc, %array.1.i 1101 1102 %array.2.i.ptr = getelementptr inbounds i32, i32* %array.2, i64 %i.i64 1103 %array.2.i = load i32, i32* %array.2.i.ptr, align 4 1104 %loop.acc.2 = add i32 %loop.acc.1, %array.2.i 1105 1106 %array.3.i.ptr = getelementptr inbounds i32, i32* %array.3, i64 %i.i64 1107 %array.3.i = load i32, i32* %array.3.i.ptr, align 4 1108 %loop.acc.next = add i32 %loop.acc.2, %array.3.i 1109 1110 %i.next = add nuw i32 %i, 1 1111 %continue = icmp ult i32 %i.next, %n 1112 br i1 %continue, label %loop, label %exit 1113 1114exit: 1115 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 1116 ret i32 %result 1117} 1118 1119define i32 @three_guards(i32* %array.1, i32 %length.1, 1120; CHECK-LABEL: @three_guards( 1121; CHECK-NEXT: entry: 1122; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0 1123; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 1124; CHECK: loop.preheader: 1125; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH_1:%.*]] 1126; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH_1]] 1127; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]] 1128; CHECK-NEXT: [[TMP3:%.*]] = icmp ule i32 [[N]], [[LENGTH_2:%.*]] 1129; CHECK-NEXT: [[TMP4:%.*]] = icmp ult i32 0, [[LENGTH_2]] 1130; CHECK-NEXT: [[TMP5:%.*]] = and i1 [[TMP4]], [[TMP3]] 1131; CHECK-NEXT: [[TMP6:%.*]] = icmp ule i32 [[N]], [[LENGTH_3:%.*]] 1132; CHECK-NEXT: [[TMP7:%.*]] = icmp ult i32 0, [[LENGTH_3]] 1133; CHECK-NEXT: [[TMP8:%.*]] = and i1 [[TMP7]], [[TMP6]] 1134; CHECK-NEXT: br label [[LOOP:%.*]] 1135; CHECK: loop: 1136; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 1137; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 1138; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] 1139; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 1140; CHECK-NEXT: [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_1:%.*]], i64 [[I_I64]] 1141; CHECK-NEXT: [[ARRAY_1_I:%.*]] = load i32, i32* [[ARRAY_1_I_PTR]], align 4 1142; CHECK-NEXT: [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]] 1143; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP5]], i32 9) [ "deopt"() ] 1144; CHECK-NEXT: [[ARRAY_2_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_2:%.*]], i64 [[I_I64]] 1145; CHECK-NEXT: [[ARRAY_2_I:%.*]] = load i32, i32* [[ARRAY_2_I_PTR]], align 4 1146; CHECK-NEXT: [[LOOP_ACC_2:%.*]] = add i32 [[LOOP_ACC_1]], [[ARRAY_2_I]] 1147; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP8]], i32 9) [ "deopt"() ] 1148; CHECK-NEXT: [[ARRAY_3_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_3:%.*]], i64 [[I_I64]] 1149; CHECK-NEXT: [[ARRAY_3_I:%.*]] = load i32, i32* [[ARRAY_3_I_PTR]], align 4 1150; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_2]], [[ARRAY_3_I]] 1151; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 1152; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]] 1153; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 1154; CHECK: exit.loopexit: 1155; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 1156; CHECK-NEXT: br label [[EXIT]] 1157; CHECK: exit: 1158; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 1159; CHECK-NEXT: ret i32 [[RESULT]] 1160; 1161 i32* %array.2, i32 %length.2, 1162 i32* %array.3, i32 %length.3, i32 %n) { 1163entry: 1164 %tmp5 = icmp eq i32 %n, 0 1165 br i1 %tmp5, label %exit, label %loop.preheader 1166 1167loop.preheader: 1168 br label %loop 1169 1170loop: 1171 1172 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 1173 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 1174 1175 %within.bounds.1 = icmp ult i32 %i, %length.1 1176 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds.1, i32 9) [ "deopt"() ] 1177 1178 %i.i64 = zext i32 %i to i64 1179 %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64 1180 %array.1.i = load i32, i32* %array.1.i.ptr, align 4 1181 %loop.acc.1 = add i32 %loop.acc, %array.1.i 1182 1183 %within.bounds.2 = icmp ult i32 %i, %length.2 1184 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds.2, i32 9) [ "deopt"() ] 1185 1186 %array.2.i.ptr = getelementptr inbounds i32, i32* %array.2, i64 %i.i64 1187 %array.2.i = load i32, i32* %array.2.i.ptr, align 4 1188 %loop.acc.2 = add i32 %loop.acc.1, %array.2.i 1189 1190 %within.bounds.3 = icmp ult i32 %i, %length.3 1191 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds.3, i32 9) [ "deopt"() ] 1192 1193 %array.3.i.ptr = getelementptr inbounds i32, i32* %array.3, i64 %i.i64 1194 %array.3.i = load i32, i32* %array.3.i.ptr, align 4 1195 %loop.acc.next = add i32 %loop.acc.2, %array.3.i 1196 1197 %i.next = add nuw i32 %i, 1 1198 %continue = icmp ult i32 %i.next, %n 1199 br i1 %continue, label %loop, label %exit 1200 1201exit: 1202 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 1203 ret i32 %result 1204} 1205 1206define i32 @unsigned_loop_0_to_n_unrelated_condition(i32* %array, i32 %length, i32 %n, i32 %x) { 1207; CHECK-LABEL: @unsigned_loop_0_to_n_unrelated_condition( 1208; CHECK-NEXT: entry: 1209; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0 1210; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 1211; CHECK: loop.preheader: 1212; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH:%.*]] 1213; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]] 1214; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]] 1215; CHECK-NEXT: br label [[LOOP:%.*]] 1216; CHECK: loop: 1217; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 1218; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 1219; CHECK-NEXT: [[UNRELATED_COND:%.*]] = icmp ult i32 [[X:%.*]], [[LENGTH]] 1220; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[UNRELATED_COND]], [[TMP2]] 1221; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ] 1222; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 1223; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 1224; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 1225; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 1226; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 1227; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]] 1228; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 1229; CHECK: exit.loopexit: 1230; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 1231; CHECK-NEXT: br label [[EXIT]] 1232; CHECK: exit: 1233; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 1234; CHECK-NEXT: ret i32 [[RESULT]] 1235; 1236entry: 1237 %tmp5 = icmp eq i32 %n, 0 1238 br i1 %tmp5, label %exit, label %loop.preheader 1239 1240loop.preheader: 1241 br label %loop 1242 1243loop: 1244 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 1245 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 1246 %within.bounds = icmp ult i32 %i, %length 1247 %unrelated.cond = icmp ult i32 %x, %length 1248 %guard.cond = and i1 %within.bounds, %unrelated.cond 1249 call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ] 1250 1251 %i.i64 = zext i32 %i to i64 1252 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 1253 %array.i = load i32, i32* %array.i.ptr, align 4 1254 %loop.acc.next = add i32 %loop.acc, %array.i 1255 1256 %i.next = add nuw i32 %i, 1 1257 %continue = icmp ult i32 %i.next, %n 1258 br i1 %continue, label %loop, label %exit 1259 1260exit: 1261 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 1262 ret i32 %result 1263} 1264 1265; Don't change the guard condition if there were no widened subconditions 1266define i32 @test_no_widened_conditions(i32* %array, i32 %length, i32 %n, i32 %x1, i32 %x2, i32 %x3) { 1267; CHECK-LABEL: @test_no_widened_conditions( 1268; CHECK-NEXT: entry: 1269; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0 1270; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 1271; CHECK: loop.preheader: 1272; CHECK-NEXT: br label [[LOOP:%.*]] 1273; CHECK: loop: 1274; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 1275; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 1276; CHECK-NEXT: [[UNRELATED_COND_1:%.*]] = icmp eq i32 [[X1:%.*]], [[I]] 1277; CHECK-NEXT: [[UNRELATED_COND_2:%.*]] = icmp eq i32 [[X2:%.*]], [[I]] 1278; CHECK-NEXT: [[UNRELATED_COND_3:%.*]] = icmp eq i32 [[X3:%.*]], [[I]] 1279; CHECK-NEXT: [[UNRELATED_COND_AND_1:%.*]] = and i1 [[UNRELATED_COND_1]], [[UNRELATED_COND_2]] 1280; CHECK-NEXT: [[GUARD_COND:%.*]] = and i1 [[UNRELATED_COND_AND_1]], [[UNRELATED_COND_3]] 1281; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[GUARD_COND]], i32 9) [ "deopt"() ] 1282; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 1283; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 1284; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 1285; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 1286; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 1287; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]] 1288; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 1289; CHECK: exit.loopexit: 1290; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 1291; CHECK-NEXT: br label [[EXIT]] 1292; CHECK: exit: 1293; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 1294; CHECK-NEXT: ret i32 [[RESULT]] 1295; 1296entry: 1297 %tmp5 = icmp eq i32 %n, 0 1298 br i1 %tmp5, label %exit, label %loop.preheader 1299 1300loop.preheader: 1301 br label %loop 1302 1303loop: 1304 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 1305 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 1306 %unrelated.cond.1 = icmp eq i32 %x1, %i 1307 %unrelated.cond.2 = icmp eq i32 %x2, %i 1308 %unrelated.cond.3 = icmp eq i32 %x3, %i 1309 %unrelated.cond.and.1 = and i1 %unrelated.cond.1, %unrelated.cond.2 1310 %guard.cond = and i1 %unrelated.cond.and.1, %unrelated.cond.3 1311 1312 call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ] 1313 1314 %i.i64 = zext i32 %i to i64 1315 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 1316 %array.i = load i32, i32* %array.i.ptr, align 4 1317 %loop.acc.next = add i32 %loop.acc, %array.i 1318 1319 %i.next = add nuw i32 %i, 1 1320 %continue = icmp ult i32 %i.next, %n 1321 br i1 %continue, label %loop, label %exit 1322 1323exit: 1324 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 1325 ret i32 %result 1326} 1327 1328define i32 @signed_loop_start_to_n_loop_variant_bound(i32* %array, i32 %x, i32 %start, i32 %n) { 1329; CHECK-LABEL: @signed_loop_start_to_n_loop_variant_bound( 1330; CHECK-NEXT: entry: 1331; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0 1332; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 1333; CHECK: loop.preheader: 1334; CHECK-NEXT: br label [[LOOP:%.*]] 1335; CHECK: loop: 1336; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 1337; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[START:%.*]], [[LOOP_PREHEADER]] ] 1338; CHECK-NEXT: [[BOUND:%.*]] = add i32 [[I]], [[X:%.*]] 1339; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[BOUND]] 1340; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ] 1341; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 1342; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 1343; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 1344; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 1345; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], 1 1346; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]] 1347; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 1348; CHECK: exit.loopexit: 1349; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 1350; CHECK-NEXT: br label [[EXIT]] 1351; CHECK: exit: 1352; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 1353; CHECK-NEXT: ret i32 [[RESULT]] 1354; 1355entry: 1356 %tmp5 = icmp sle i32 %n, 0 1357 br i1 %tmp5, label %exit, label %loop.preheader 1358 1359loop.preheader: 1360 br label %loop 1361 1362loop: 1363 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 1364 %i = phi i32 [ %i.next, %loop ], [ %start, %loop.preheader ] 1365 %bound = add i32 %i, %x 1366 %within.bounds = icmp ult i32 %i, %bound 1367 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 1368 1369 %i.i64 = zext i32 %i to i64 1370 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 1371 %array.i = load i32, i32* %array.i.ptr, align 4 1372 %loop.acc.next = add i32 %loop.acc, %array.i 1373 1374 %i.next = add nsw i32 %i, 1 1375 %continue = icmp slt i32 %i.next, %n 1376 br i1 %continue, label %loop, label %exit 1377 1378exit: 1379 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 1380 ret i32 %result 1381} 1382 1383define i32 @signed_loop_start_to_n_non_monotonic_predicate(i32* %array, i32 %x, i32 %start, i32 %n) { 1384; CHECK-LABEL: @signed_loop_start_to_n_non_monotonic_predicate( 1385; CHECK-NEXT: entry: 1386; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0 1387; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 1388; CHECK: loop.preheader: 1389; CHECK-NEXT: br label [[LOOP:%.*]] 1390; CHECK: loop: 1391; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 1392; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[START:%.*]], [[LOOP_PREHEADER]] ] 1393; CHECK-NEXT: [[GUARD_COND:%.*]] = icmp eq i32 [[I]], [[X:%.*]] 1394; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[GUARD_COND]], i32 9) [ "deopt"() ] 1395; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 1396; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 1397; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 1398; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 1399; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], 1 1400; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]] 1401; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 1402; CHECK: exit.loopexit: 1403; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 1404; CHECK-NEXT: br label [[EXIT]] 1405; CHECK: exit: 1406; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 1407; CHECK-NEXT: ret i32 [[RESULT]] 1408; 1409entry: 1410 %tmp5 = icmp sle i32 %n, 0 1411 br i1 %tmp5, label %exit, label %loop.preheader 1412 1413loop.preheader: 1414 br label %loop 1415 1416loop: 1417 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 1418 %i = phi i32 [ %i.next, %loop ], [ %start, %loop.preheader ] 1419 %guard.cond = icmp eq i32 %i, %x 1420 call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ] 1421 1422 %i.i64 = zext i32 %i to i64 1423 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 1424 %array.i = load i32, i32* %array.i.ptr, align 4 1425 %loop.acc.next = add i32 %loop.acc, %array.i 1426 1427 %i.next = add nsw i32 %i, 1 1428 %continue = icmp slt i32 %i.next, %n 1429 br i1 %continue, label %loop, label %exit 1430 1431exit: 1432 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 1433 ret i32 %result 1434} 1435 1436define i32 @unsigned_loop_0_to_n_hoist_length(i32* %array, i16 %length.i16, i32 %n) { 1437; CHECK-LABEL: @unsigned_loop_0_to_n_hoist_length( 1438; CHECK-NEXT: entry: 1439; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0 1440; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 1441; CHECK: loop.preheader: 1442; CHECK-NEXT: [[TMP0:%.*]] = zext i16 [[LENGTH_I16:%.*]] to i32 1443; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i32 [[N]], [[TMP0]] 1444; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 0, [[TMP0]] 1445; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]] 1446; CHECK-NEXT: br label [[LOOP:%.*]] 1447; CHECK: loop: 1448; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 1449; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 1450; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ] 1451; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 1452; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 1453; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 1454; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 1455; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 1456; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]] 1457; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 1458; CHECK: exit.loopexit: 1459; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 1460; CHECK-NEXT: br label [[EXIT]] 1461; CHECK: exit: 1462; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 1463; CHECK-NEXT: ret i32 [[RESULT]] 1464; 1465entry: 1466 %tmp5 = icmp eq i32 %n, 0 1467 br i1 %tmp5, label %exit, label %loop.preheader 1468 1469loop.preheader: 1470 br label %loop 1471 1472loop: 1473 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 1474 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 1475 %length = zext i16 %length.i16 to i32 1476 %within.bounds = icmp ult i32 %i, %length 1477 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 1478 1479 %i.i64 = zext i32 %i to i64 1480 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 1481 %array.i = load i32, i32* %array.i.ptr, align 4 1482 %loop.acc.next = add i32 %loop.acc, %array.i 1483 1484 %i.next = add nuw i32 %i, 1 1485 %continue = icmp ult i32 %i.next, %n 1486 br i1 %continue, label %loop, label %exit 1487 1488exit: 1489 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 1490 ret i32 %result 1491} 1492 1493define i32 @unsigned_loop_0_to_n_cant_hoist_length(i32* %array, i32 %length, i32 %divider, i32 %n) { 1494; CHECK-LABEL: @unsigned_loop_0_to_n_cant_hoist_length( 1495; CHECK-NEXT: entry: 1496; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0 1497; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 1498; CHECK: loop.preheader: 1499; CHECK-NEXT: br label [[LOOP:%.*]] 1500; CHECK: loop: 1501; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 1502; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 1503; CHECK-NEXT: [[LENGTH_UDIV:%.*]] = udiv i32 [[LENGTH:%.*]], [[DIVIDER:%.*]] 1504; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH_UDIV]] 1505; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH_UDIV]] 1506; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]] 1507; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] 1508; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 1509; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 1510; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 1511; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 1512; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 1513; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]] 1514; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 1515; CHECK: exit.loopexit: 1516; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 1517; CHECK-NEXT: br label [[EXIT]] 1518; CHECK: exit: 1519; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 1520; CHECK-NEXT: ret i32 [[RESULT]] 1521; 1522entry: 1523 %tmp5 = icmp eq i32 %n, 0 1524 br i1 %tmp5, label %exit, label %loop.preheader 1525 1526loop.preheader: 1527 br label %loop 1528 1529loop: 1530 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 1531 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 1532 %length.udiv = udiv i32 %length, %divider 1533 %within.bounds = icmp ult i32 %i, %length.udiv 1534 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 1535 1536 %i.i64 = zext i32 %i to i64 1537 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 1538 %array.i = load i32, i32* %array.i.ptr, align 4 1539 %loop.acc.next = add i32 %loop.acc, %array.i 1540 1541 %i.next = add nuw i32 %i, 1 1542 %continue = icmp ult i32 %i.next, %n 1543 br i1 %continue, label %loop, label %exit 1544 1545exit: 1546 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 1547 ret i32 %result 1548} 1549 1550 1551; This is a case where the length information tells us that the guard 1552; must trigger on some iteration. 1553define i32 @provably_taken(i32* %array, i32* %length.ptr) { 1554; CHECK-LABEL: @provably_taken( 1555; CHECK-NEXT: loop.preheader: 1556; CHECK-NEXT: [[LENGTH:%.*]] = load i32, i32* [[LENGTH_PTR:%.*]], !range !1 1557; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 0, [[LENGTH]] 1558; CHECK-NEXT: [[TMP1:%.*]] = and i1 [[TMP0]], false 1559; CHECK-NEXT: br label [[LOOP:%.*]] 1560; CHECK: loop: 1561; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] 1562; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 1563; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP1]], i32 9) [ "deopt"() ] 1564; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 1565; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 1566; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 1567; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 1568; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 1569; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], 200 1570; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 1571; CHECK: exit: 1572; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 1573; CHECK-NEXT: ret i32 [[RESULT]] 1574; 1575loop.preheader: 1576 %length = load i32, i32* %length.ptr, !range !{i32 0, i32 50} 1577 br label %loop 1578 1579loop: 1580 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 1581 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 1582 %within.bounds = icmp ult i32 %i, %length 1583 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 1584 1585 %i.i64 = zext i32 %i to i64 1586 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 1587 %array.i = load i32, i32* %array.i.ptr, align 4 1588 %loop.acc.next = add i32 %loop.acc, %array.i 1589 1590 %i.next = add nuw i32 %i, 1 1591 %continue = icmp slt i32 %i.next, 200 1592 br i1 %continue, label %loop, label %exit 1593 1594exit: 1595 %result = phi i32 [ %loop.acc.next, %loop ] 1596 ret i32 %result 1597} 1598 1599; NE Check (as produced by LFTR) where we can prove Start < End via simple 1600; instruction analysis 1601define i32 @ne_latch_zext(i32* %array, i32 %length, i16 %n16) { 1602; CHECK-LABEL: @ne_latch_zext( 1603; CHECK-NEXT: loop.preheader: 1604; CHECK-NEXT: [[N:%.*]] = zext i16 [[N16:%.*]] to i32 1605; CHECK-NEXT: [[NPLUS1:%.*]] = add nuw nsw i32 [[N]], 1 1606; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[NPLUS1]], [[LENGTH:%.*]] 1607; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]] 1608; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]] 1609; CHECK-NEXT: br label [[LOOP:%.*]] 1610; CHECK: loop: 1611; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] 1612; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] 1613; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1 1614; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I_NEXT]], [[NPLUS1]] 1615; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 1616; CHECK: exit: 1617; CHECK-NEXT: ret i32 0 1618; 1619loop.preheader: 1620 %n = zext i16 %n16 to i32 1621 %nplus1 = add nsw nuw i32 %n, 1 1622 br label %loop 1623 1624loop: 1625 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 1626 %within.bounds = icmp ult i32 %i, %length 1627 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 1628 1629 %i.next = add nsw nuw i32 %i, 1 1630 %continue = icmp ne i32 %i.next, %nplus1 1631 br i1 %continue, label %loop, label %exit 1632 1633exit: 1634 ret i32 0 1635} 1636 1637; Same as previous, but with a pre-increment test since this is easier to match 1638define i32 @ne_latch_zext_preinc(i32* %array, i32 %length, i16 %n16) { 1639; CHECK-LABEL: @ne_latch_zext_preinc( 1640; CHECK-NEXT: loop.preheader: 1641; CHECK-NEXT: [[N:%.*]] = zext i16 [[N16:%.*]] to i32 1642; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], -1 1643; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i32 [[N]], [[TMP0]] 1644; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 0, [[LENGTH]] 1645; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]] 1646; CHECK-NEXT: br label [[LOOP:%.*]] 1647; CHECK: loop: 1648; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] 1649; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ] 1650; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 1651; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I]], [[N]] 1652; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 1653; CHECK: exit: 1654; CHECK-NEXT: ret i32 0 1655; 1656loop.preheader: 1657 %n = zext i16 %n16 to i32 1658 br label %loop 1659 1660loop: 1661 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 1662 %within.bounds = icmp ult i32 %i, %length 1663 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 1664 1665 %i.next = add nuw i32 %i, 1 1666 %continue = icmp ne i32 %i, %n 1667 br i1 %continue, label %loop, label %exit 1668 1669exit: 1670 ret i32 0 1671} 1672 1673; NE Check (as produced by LFTR) where we can prove Start < End via the 1674; condition guarding the loop entry. 1675define i32 @ne_latch_dom_check(i32* %array, i32 %length, i32 %n) { 1676; CHECK-LABEL: @ne_latch_dom_check( 1677; CHECK-NEXT: entry: 1678; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0 1679; CHECK-NEXT: [[NPLUS1:%.*]] = add nuw i32 [[N]], 1 1680; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 1681; CHECK: loop.preheader: 1682; CHECK-NEXT: br label [[LOOP:%.*]] 1683; CHECK: loop: 1684; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 1685; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]] 1686; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ] 1687; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1 1688; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I_NEXT]], [[NPLUS1]] 1689; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 1690; CHECK: exit.loopexit: 1691; CHECK-NEXT: br label [[EXIT]] 1692; CHECK: exit: 1693; CHECK-NEXT: ret i32 0 1694; 1695entry: 1696 %tmp5 = icmp sle i32 %n, 0 1697 %nplus1 = add nuw i32 %n, 1 1698 br i1 %tmp5, label %exit, label %loop.preheader 1699 1700loop.preheader: 1701 br label %loop 1702 1703loop: 1704 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 1705 %within.bounds = icmp ult i32 %i, %length 1706 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 1707 1708 %i.next = add nsw nuw i32 %i, 1 1709 %continue = icmp ne i32 %i.next, %nplus1 1710 br i1 %continue, label %loop, label %exit 1711 1712exit: 1713 ret i32 0 1714} 1715 1716; Same as previous, but easier to match 1717define i32 @ne_latch_dom_check_preinc(i32* %array, i32 %length, i32 %n) { 1718; CHECK-LABEL: @ne_latch_dom_check_preinc( 1719; CHECK-NEXT: entry: 1720; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0 1721; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 1722; CHECK: loop.preheader: 1723; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], -1 1724; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i32 [[N]], [[TMP0]] 1725; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 0, [[LENGTH]] 1726; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]] 1727; CHECK-NEXT: br label [[LOOP:%.*]] 1728; CHECK: loop: 1729; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 1730; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ] 1731; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 1732; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I]], [[N]] 1733; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 1734; CHECK: exit.loopexit: 1735; CHECK-NEXT: br label [[EXIT]] 1736; CHECK: exit: 1737; CHECK-NEXT: ret i32 0 1738; 1739entry: 1740 %tmp5 = icmp sle i32 %n, 0 1741 br i1 %tmp5, label %exit, label %loop.preheader 1742 1743loop.preheader: 1744 br label %loop 1745 1746loop: 1747 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 1748 %within.bounds = icmp ult i32 %i, %length 1749 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 1750 1751 %i.next = add nuw i32 %i, 1 1752 %continue = icmp ne i32 %i, %n 1753 br i1 %continue, label %loop, label %exit 1754 1755exit: 1756 ret i32 0 1757} 1758 1759; Same as previous, except swapped br/cmp 1760define i32 @eq_latch_dom_check_preinc(i32* %array, i32 %length, i32 %n) { 1761; CHECK-LABEL: @eq_latch_dom_check_preinc( 1762; CHECK-NEXT: entry: 1763; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0 1764; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 1765; CHECK: loop.preheader: 1766; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], -1 1767; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i32 [[N]], [[TMP0]] 1768; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 0, [[LENGTH]] 1769; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]] 1770; CHECK-NEXT: br label [[LOOP:%.*]] 1771; CHECK: loop: 1772; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 1773; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ] 1774; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 1775; CHECK-NEXT: [[DONE:%.*]] = icmp eq i32 [[I]], [[N]] 1776; CHECK-NEXT: br i1 [[DONE]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP]] 1777; CHECK: exit.loopexit: 1778; CHECK-NEXT: br label [[EXIT]] 1779; CHECK: exit: 1780; CHECK-NEXT: ret i32 0 1781; 1782entry: 1783 %tmp5 = icmp sle i32 %n, 0 1784 br i1 %tmp5, label %exit, label %loop.preheader 1785 1786loop.preheader: 1787 br label %loop 1788 1789loop: 1790 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 1791 %within.bounds = icmp ult i32 %i, %length 1792 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 1793 1794 %i.next = add nuw i32 %i, 1 1795 %done = icmp eq i32 %i, %n 1796 br i1 %done, label %exit, label %loop 1797 1798exit: 1799 ret i32 0 1800} 1801 1802 1803; NE latch - can't prove (end-start) mod step == 0 (i.e. might wrap 1804; around several times or even be infinite) 1805define i32 @neg_ne_latch_mod_step(i32* %array, i32 %length, i16 %n16) { 1806; CHECK-LABEL: @neg_ne_latch_mod_step( 1807; CHECK-NEXT: loop.preheader: 1808; CHECK-NEXT: [[N:%.*]] = zext i16 [[N16:%.*]] to i32 1809; CHECK-NEXT: br label [[LOOP:%.*]] 1810; CHECK: loop: 1811; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] 1812; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]] 1813; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ] 1814; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 3 1815; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I]], [[N]] 1816; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 1817; CHECK: exit: 1818; CHECK-NEXT: ret i32 0 1819; 1820loop.preheader: 1821 %n = zext i16 %n16 to i32 1822 br label %loop 1823 1824loop: 1825 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 1826 %within.bounds = icmp ult i32 %i, %length 1827 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 1828 1829 %i.next = add i32 %i, 3 1830 %continue = icmp ne i32 %i, %n 1831 br i1 %continue, label %loop, label %exit 1832 1833exit: 1834 ret i32 0 1835} 1836 1837; NE latch - TODO: could prove (end-start) mod step == 0 1838define i32 @ne_latch_mod_step(i32* %array, i32 %length) { 1839; CHECK-LABEL: @ne_latch_mod_step( 1840; CHECK-NEXT: loop.preheader: 1841; CHECK-NEXT: br label [[LOOP:%.*]] 1842; CHECK: loop: 1843; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] 1844; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]] 1845; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ] 1846; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 2 1847; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I]], 400 1848; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 1849; CHECK: exit: 1850; CHECK-NEXT: ret i32 0 1851; 1852loop.preheader: 1853 br label %loop 1854 1855loop: 1856 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 1857 %within.bounds = icmp ult i32 %i, %length 1858 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 1859 1860 %i.next = add nuw i32 %i, 2 1861 %continue = icmp ne i32 %i, 400 1862 br i1 %continue, label %loop, label %exit 1863 1864exit: 1865 ret i32 0 1866} 1867 1868; NE Latch - but end > start so wraps around and not equivelent to a ult 1869define i32 @neg_ne_latch_swapped_order(i32* %array, i32 %length) { 1870; CHECK-LABEL: @neg_ne_latch_swapped_order( 1871; CHECK-NEXT: loop.preheader: 1872; CHECK-NEXT: br label [[LOOP:%.*]] 1873; CHECK: loop: 1874; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 400, [[LOOP_PREHEADER:%.*]] ] 1875; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]] 1876; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ] 1877; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1 1878; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I]], 0 1879; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 1880; CHECK: exit: 1881; CHECK-NEXT: ret i32 0 1882; 1883loop.preheader: 1884 br label %loop 1885 1886loop: 1887 %i = phi i32 [ %i.next, %loop ], [ 400, %loop.preheader ] 1888 %within.bounds = icmp ult i32 %i, %length 1889 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 1890 1891 %i.next = add i32 %i, 1 1892 %continue = icmp ne i32 %i, 0 1893 br i1 %continue, label %loop, label %exit 1894 1895exit: 1896 ret i32 0 1897} 1898 1899; Negative test, make sure we don't crash on unconditional latches 1900; TODO: there's no reason we shouldn't be able to predicate the 1901; condition for an statically infinite loop. 1902define i32 @unconditional_latch(i32* %a, i32 %length) { 1903; CHECK-LABEL: @unconditional_latch( 1904; CHECK-NEXT: loop.preheader: 1905; CHECK-NEXT: br label [[LOOP:%.*]] 1906; CHECK: loop: 1907; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 400, [[LOOP_PREHEADER:%.*]] ] 1908; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]] 1909; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ] 1910; CHECK-NEXT: store volatile i32 0, i32* [[A:%.*]] 1911; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1 1912; CHECK-NEXT: br label [[LOOP]] 1913; 1914loop.preheader: 1915 br label %loop 1916 1917loop: 1918 %i = phi i32 [ %i.next, %loop ], [ 400, %loop.preheader ] 1919 %within.bounds = icmp ult i32 %i, %length 1920 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 1921 store volatile i32 0, i32* %a 1922 %i.next = add i32 %i, 1 1923 br label %loop 1924} 1925