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: [[TMP1:%.*]] = and i1 [[TMP0]], false 1558; CHECK-NEXT: br label [[LOOP:%.*]] 1559; CHECK: loop: 1560; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] 1561; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 1562; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP1]], i32 9) [ "deopt"() ] 1563; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 1564; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 1565; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 1566; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 1567; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 1568; CHECK-NEXT: [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], 200 1569; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 1570; CHECK: exit: 1571; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 1572; CHECK-NEXT: ret i32 [[RESULT]] 1573; 1574loop.preheader: 1575 %length = load i32, i32* %length.ptr, !range !{i32 0, i32 50} 1576 br label %loop 1577 1578loop: 1579 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 1580 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 1581 %within.bounds = icmp ult i32 %i, %length 1582 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 1583 1584 %i.i64 = zext i32 %i to i64 1585 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 1586 %array.i = load i32, i32* %array.i.ptr, align 4 1587 %loop.acc.next = add i32 %loop.acc, %array.i 1588 1589 %i.next = add nuw i32 %i, 1 1590 %continue = icmp slt i32 %i.next, 200 1591 br i1 %continue, label %loop, label %exit 1592 1593exit: 1594 %result = phi i32 [ %loop.acc.next, %loop ] 1595 ret i32 %result 1596} 1597 1598; NE Check (as produced by LFTR) where we can prove Start < End via simple 1599; instruction analysis 1600define i32 @ne_latch_zext(i32* %array, i32 %length, i16 %n16) { 1601; CHECK-LABEL: @ne_latch_zext( 1602; CHECK-NEXT: loop.preheader: 1603; CHECK-NEXT: [[N:%.*]] = zext i16 [[N16:%.*]] to i32 1604; CHECK-NEXT: [[NPLUS1:%.*]] = add nuw nsw i32 [[N]], 1 1605; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[NPLUS1]], [[LENGTH:%.*]] 1606; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]] 1607; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]] 1608; CHECK-NEXT: br label [[LOOP:%.*]] 1609; CHECK: loop: 1610; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] 1611; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] 1612; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1 1613; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I_NEXT]], [[NPLUS1]] 1614; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 1615; CHECK: exit: 1616; CHECK-NEXT: ret i32 0 1617; 1618loop.preheader: 1619 %n = zext i16 %n16 to i32 1620 %nplus1 = add nsw nuw i32 %n, 1 1621 br label %loop 1622 1623loop: 1624 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 1625 %within.bounds = icmp ult i32 %i, %length 1626 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 1627 1628 %i.next = add nsw nuw i32 %i, 1 1629 %continue = icmp ne i32 %i.next, %nplus1 1630 br i1 %continue, label %loop, label %exit 1631 1632exit: 1633 ret i32 0 1634} 1635 1636; Same as previous, but with a pre-increment test since this is easier to match 1637define i32 @ne_latch_zext_preinc(i32* %array, i32 %length, i16 %n16) { 1638; CHECK-LABEL: @ne_latch_zext_preinc( 1639; CHECK-NEXT: loop.preheader: 1640; CHECK-NEXT: [[N:%.*]] = zext i16 [[N16:%.*]] to i32 1641; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], -1 1642; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i32 [[N]], [[TMP0]] 1643; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 0, [[LENGTH]] 1644; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]] 1645; CHECK-NEXT: br label [[LOOP:%.*]] 1646; CHECK: loop: 1647; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] 1648; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ] 1649; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 1650; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I]], [[N]] 1651; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 1652; CHECK: exit: 1653; CHECK-NEXT: ret i32 0 1654; 1655loop.preheader: 1656 %n = zext i16 %n16 to i32 1657 br label %loop 1658 1659loop: 1660 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 1661 %within.bounds = icmp ult i32 %i, %length 1662 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 1663 1664 %i.next = add nuw i32 %i, 1 1665 %continue = icmp ne i32 %i, %n 1666 br i1 %continue, label %loop, label %exit 1667 1668exit: 1669 ret i32 0 1670} 1671 1672; NE Check (as produced by LFTR) where we can prove Start < End via the 1673; condition guarding the loop entry. 1674define i32 @ne_latch_dom_check(i32* %array, i32 %length, i32 %n) { 1675; CHECK-LABEL: @ne_latch_dom_check( 1676; CHECK-NEXT: entry: 1677; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0 1678; CHECK-NEXT: [[NPLUS1:%.*]] = add nuw i32 [[N]], 1 1679; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 1680; CHECK: loop.preheader: 1681; CHECK-NEXT: br label [[LOOP:%.*]] 1682; CHECK: loop: 1683; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 1684; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]] 1685; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ] 1686; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i32 [[I]], 1 1687; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I_NEXT]], [[NPLUS1]] 1688; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 1689; CHECK: exit.loopexit: 1690; CHECK-NEXT: br label [[EXIT]] 1691; CHECK: exit: 1692; CHECK-NEXT: ret i32 0 1693; 1694entry: 1695 %tmp5 = icmp sle i32 %n, 0 1696 %nplus1 = add nuw i32 %n, 1 1697 br i1 %tmp5, label %exit, label %loop.preheader 1698 1699loop.preheader: 1700 br label %loop 1701 1702loop: 1703 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 1704 %within.bounds = icmp ult i32 %i, %length 1705 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 1706 1707 %i.next = add nsw nuw i32 %i, 1 1708 %continue = icmp ne i32 %i.next, %nplus1 1709 br i1 %continue, label %loop, label %exit 1710 1711exit: 1712 ret i32 0 1713} 1714 1715; Same as previous, but easier to match 1716define i32 @ne_latch_dom_check_preinc(i32* %array, i32 %length, i32 %n) { 1717; CHECK-LABEL: @ne_latch_dom_check_preinc( 1718; CHECK-NEXT: entry: 1719; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0 1720; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 1721; CHECK: loop.preheader: 1722; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], -1 1723; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i32 [[N]], [[TMP0]] 1724; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 0, [[LENGTH]] 1725; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]] 1726; CHECK-NEXT: br label [[LOOP:%.*]] 1727; CHECK: loop: 1728; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 1729; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ] 1730; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 1731; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I]], [[N]] 1732; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 1733; CHECK: exit.loopexit: 1734; CHECK-NEXT: br label [[EXIT]] 1735; CHECK: exit: 1736; CHECK-NEXT: ret i32 0 1737; 1738entry: 1739 %tmp5 = icmp sle i32 %n, 0 1740 br i1 %tmp5, label %exit, label %loop.preheader 1741 1742loop.preheader: 1743 br label %loop 1744 1745loop: 1746 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 1747 %within.bounds = icmp ult i32 %i, %length 1748 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 1749 1750 %i.next = add nuw i32 %i, 1 1751 %continue = icmp ne i32 %i, %n 1752 br i1 %continue, label %loop, label %exit 1753 1754exit: 1755 ret i32 0 1756} 1757 1758; Same as previous, except swapped br/cmp 1759define i32 @eq_latch_dom_check_preinc(i32* %array, i32 %length, i32 %n) { 1760; CHECK-LABEL: @eq_latch_dom_check_preinc( 1761; CHECK-NEXT: entry: 1762; CHECK-NEXT: [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0 1763; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 1764; CHECK: loop.preheader: 1765; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], -1 1766; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i32 [[N]], [[TMP0]] 1767; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 0, [[LENGTH]] 1768; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]] 1769; CHECK-NEXT: br label [[LOOP:%.*]] 1770; CHECK: loop: 1771; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 1772; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ] 1773; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 1774; CHECK-NEXT: [[DONE:%.*]] = icmp eq i32 [[I]], [[N]] 1775; CHECK-NEXT: br i1 [[DONE]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP]] 1776; CHECK: exit.loopexit: 1777; CHECK-NEXT: br label [[EXIT]] 1778; CHECK: exit: 1779; CHECK-NEXT: ret i32 0 1780; 1781entry: 1782 %tmp5 = icmp sle i32 %n, 0 1783 br i1 %tmp5, label %exit, label %loop.preheader 1784 1785loop.preheader: 1786 br label %loop 1787 1788loop: 1789 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 1790 %within.bounds = icmp ult i32 %i, %length 1791 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 1792 1793 %i.next = add nuw i32 %i, 1 1794 %done = icmp eq i32 %i, %n 1795 br i1 %done, label %exit, label %loop 1796 1797exit: 1798 ret i32 0 1799} 1800 1801 1802; NE latch - can't prove (end-start) mod step == 0 (i.e. might wrap 1803; around several times or even be infinite) 1804define i32 @neg_ne_latch_mod_step(i32* %array, i32 %length, i16 %n16) { 1805; CHECK-LABEL: @neg_ne_latch_mod_step( 1806; CHECK-NEXT: loop.preheader: 1807; CHECK-NEXT: [[N:%.*]] = zext i16 [[N16:%.*]] to i32 1808; CHECK-NEXT: br label [[LOOP:%.*]] 1809; CHECK: loop: 1810; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] 1811; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]] 1812; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ] 1813; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 3 1814; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I]], [[N]] 1815; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 1816; CHECK: exit: 1817; CHECK-NEXT: ret i32 0 1818; 1819loop.preheader: 1820 %n = zext i16 %n16 to i32 1821 br label %loop 1822 1823loop: 1824 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 1825 %within.bounds = icmp ult i32 %i, %length 1826 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 1827 1828 %i.next = add i32 %i, 3 1829 %continue = icmp ne i32 %i, %n 1830 br i1 %continue, label %loop, label %exit 1831 1832exit: 1833 ret i32 0 1834} 1835 1836; NE latch - TODO: could prove (end-start) mod step == 0 1837define i32 @ne_latch_mod_step(i32* %array, i32 %length) { 1838; CHECK-LABEL: @ne_latch_mod_step( 1839; CHECK-NEXT: loop.preheader: 1840; CHECK-NEXT: br label [[LOOP:%.*]] 1841; CHECK: loop: 1842; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER:%.*]] ] 1843; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]] 1844; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ] 1845; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 2 1846; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I]], 400 1847; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 1848; CHECK: exit: 1849; CHECK-NEXT: ret i32 0 1850; 1851loop.preheader: 1852 br label %loop 1853 1854loop: 1855 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 1856 %within.bounds = icmp ult i32 %i, %length 1857 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 1858 1859 %i.next = add nuw i32 %i, 2 1860 %continue = icmp ne i32 %i, 400 1861 br i1 %continue, label %loop, label %exit 1862 1863exit: 1864 ret i32 0 1865} 1866 1867; NE Latch - but end > start so wraps around and not equivelent to a ult 1868define i32 @neg_ne_latch_swapped_order(i32* %array, i32 %length) { 1869; CHECK-LABEL: @neg_ne_latch_swapped_order( 1870; CHECK-NEXT: loop.preheader: 1871; CHECK-NEXT: br label [[LOOP:%.*]] 1872; CHECK: loop: 1873; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 400, [[LOOP_PREHEADER:%.*]] ] 1874; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]] 1875; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ] 1876; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1 1877; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ne i32 [[I]], 0 1878; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]] 1879; CHECK: exit: 1880; CHECK-NEXT: ret i32 0 1881; 1882loop.preheader: 1883 br label %loop 1884 1885loop: 1886 %i = phi i32 [ %i.next, %loop ], [ 400, %loop.preheader ] 1887 %within.bounds = icmp ult i32 %i, %length 1888 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 1889 1890 %i.next = add i32 %i, 1 1891 %continue = icmp ne i32 %i, 0 1892 br i1 %continue, label %loop, label %exit 1893 1894exit: 1895 ret i32 0 1896} 1897 1898; Negative test, make sure we don't crash on unconditional latches 1899; TODO: there's no reason we shouldn't be able to predicate the 1900; condition for an statically infinite loop. 1901define i32 @unconditional_latch(i32* %a, i32 %length) { 1902; CHECK-LABEL: @unconditional_latch( 1903; CHECK-NEXT: loop.preheader: 1904; CHECK-NEXT: br label [[LOOP:%.*]] 1905; CHECK: loop: 1906; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 400, [[LOOP_PREHEADER:%.*]] ] 1907; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]] 1908; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ] 1909; CHECK-NEXT: store volatile i32 0, i32* [[A:%.*]], align 4 1910; CHECK-NEXT: [[I_NEXT]] = add i32 [[I]], 1 1911; CHECK-NEXT: br label [[LOOP]] 1912; 1913loop.preheader: 1914 br label %loop 1915 1916loop: 1917 %i = phi i32 [ %i.next, %loop ], [ 400, %loop.preheader ] 1918 %within.bounds = icmp ult i32 %i, %length 1919 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 1920 store volatile i32 0, i32* %a 1921 %i.next = add i32 %i, 1 1922 br label %loop 1923} 1924