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