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