1; RUN: opt -S -loop-predication < %s 2>&1 | FileCheck %s 2; RUN: opt -S -passes='require<scalar-evolution>,loop(loop-predication)' < %s 2>&1 | FileCheck %s 3 4declare void @llvm.experimental.guard(i1, ...) 5 6define i32 @unsigned_loop_0_to_n_ult_check(i32* %array, i32 %length, i32 %n) { 7; CHECK-LABEL: @unsigned_loop_0_to_n_ult_check 8entry: 9 %tmp5 = icmp eq i32 %n, 0 10 br i1 %tmp5, label %exit, label %loop.preheader 11 12loop.preheader: 13; CHECK: loop.preheader: 14; CHECK: [[limit_check:[^ ]+]] = icmp ule i32 %n, %length 15; CHECK-NEXT: [[first_iteration_check:[^ ]+]] = icmp ult i32 0, %length 16; CHECK-NEXT: [[wide_cond:[^ ]+]] = and i1 [[first_iteration_check]], [[limit_check]] 17; CHECK-NEXT: br label %loop 18 br label %loop 19 20loop: 21; CHECK: loop: 22; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ] 23 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 24 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 25 %within.bounds = icmp ult i32 %i, %length 26 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 27 28 %i.i64 = zext i32 %i to i64 29 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 30 %array.i = load i32, i32* %array.i.ptr, align 4 31 %loop.acc.next = add i32 %loop.acc, %array.i 32 33 %i.next = add nuw i32 %i, 1 34 %continue = icmp ult i32 %i.next, %n 35 br i1 %continue, label %loop, label %exit 36 37exit: 38 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 39 ret i32 %result 40} 41 42define i32 @unsigned_loop_0_to_n_ule_latch_ult_check(i32* %array, i32 %length, i32 %n) { 43; CHECK-LABEL: @unsigned_loop_0_to_n_ule_latch_ult_check 44entry: 45 %tmp5 = icmp eq i32 %n, 0 46 br i1 %tmp5, label %exit, label %loop.preheader 47 48loop.preheader: 49; CHECK: loop.preheader: 50; CHECK: [[limit_check:[^ ]+]] = icmp ult i32 %n, %length 51; CHECK-NEXT: [[first_iteration_check:[^ ]+]] = icmp ult i32 0, %length 52; CHECK-NEXT: [[wide_cond:[^ ]+]] = and i1 [[first_iteration_check]], [[limit_check]] 53; CHECK-NEXT: br label %loop 54 br label %loop 55 56loop: 57; CHECK: loop: 58; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ] 59 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 60 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 61 %within.bounds = icmp ult i32 %i, %length 62 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 63 64 %i.i64 = zext i32 %i to i64 65 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 66 %array.i = load i32, i32* %array.i.ptr, align 4 67 %loop.acc.next = add i32 %loop.acc, %array.i 68 69 %i.next = add nuw i32 %i, 1 70 %continue = icmp ule i32 %i.next, %n 71 br i1 %continue, label %loop, label %exit 72 73exit: 74 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 75 ret i32 %result 76} 77 78define i32 @unsigned_loop_0_to_n_ugt_check(i32* %array, i32 %length, i32 %n) { 79; CHECK-LABEL: @unsigned_loop_0_to_n_ugt_check 80entry: 81 %tmp5 = icmp eq i32 %n, 0 82 br i1 %tmp5, label %exit, label %loop.preheader 83 84loop.preheader: 85; CHECK: loop.preheader: 86; CHECK: [[limit_check:[^ ]+]] = icmp ule i32 %n, %length 87; CHECK-NEXT: [[first_iteration_check:[^ ]+]] = icmp ult i32 0, %length 88; CHECK-NEXT: [[wide_cond:[^ ]+]] = and i1 [[first_iteration_check]], [[limit_check]] 89; CHECK-NEXT: br label %loop 90 br label %loop 91 92loop: 93; CHECK: loop: 94; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ] 95 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 96 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 97 %within.bounds = icmp ugt i32 %length, %i 98 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 99 100 %i.i64 = zext i32 %i to i64 101 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 102 %array.i = load i32, i32* %array.i.ptr, align 4 103 %loop.acc.next = add i32 %loop.acc, %array.i 104 105 %i.next = add nuw i32 %i, 1 106 %continue = icmp ult i32 %i.next, %n 107 br i1 %continue, label %loop, label %exit 108 109exit: 110 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 111 ret i32 %result 112} 113 114define i32 @signed_loop_0_to_n_ult_check(i32* %array, i32 %length, i32 %n) { 115; CHECK-LABEL: @signed_loop_0_to_n_ult_check 116entry: 117 %tmp5 = icmp sle i32 %n, 0 118 br i1 %tmp5, label %exit, label %loop.preheader 119 120loop.preheader: 121; CHECK: loop.preheader: 122; CHECK: [[limit_check:[^ ]+]] = icmp sle i32 %n, %length 123; CHECK-NEXT: [[first_iteration_check:[^ ]+]] = icmp ult i32 0, %length 124; CHECK-NEXT: [[wide_cond:[^ ]+]] = and i1 [[first_iteration_check]], [[limit_check]] 125; CHECK-NEXT: br label %loop 126 br label %loop 127 128loop: 129; CHECK: loop: 130; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ] 131 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 132 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 133 %within.bounds = icmp ult i32 %i, %length 134 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 135 136 %i.i64 = zext i32 %i to i64 137 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 138 %array.i = load i32, i32* %array.i.ptr, align 4 139 %loop.acc.next = add i32 %loop.acc, %array.i 140 141 %i.next = add nuw i32 %i, 1 142 %continue = icmp slt i32 %i.next, %n 143 br i1 %continue, label %loop, label %exit 144 145exit: 146 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 147 ret i32 %result 148} 149 150define i32 @signed_loop_0_to_n_ult_check_length_range_known(i32* %array, i32* %length.ptr, i32 %n) { 151; CHECK-LABEL: @signed_loop_0_to_n_ult_check_length_range_known 152entry: 153 %tmp5 = icmp sle i32 %n, 0 154 %length = load i32, i32* %length.ptr, !range !{i32 1, i32 2147483648} 155 br i1 %tmp5, label %exit, label %loop.preheader 156 157loop.preheader: 158; CHECK: loop.preheader: 159; CHECK: [[limit_check:[^ ]+]] = icmp sle i32 %n, %length 160; CHECK-NEXT: [[wide_cond:[^ ]+]] = and i1 true, [[limit_check]] 161; CHECK-NEXT: br label %loop 162 br label %loop 163 164loop: 165; CHECK: loop: 166; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ] 167 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 168 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 169 %within.bounds = icmp ult i32 %i, %length 170 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 171 172 %i.i64 = zext i32 %i to i64 173 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 174 %array.i = load i32, i32* %array.i.ptr, align 4 175 %loop.acc.next = add i32 %loop.acc, %array.i 176 177 %i.next = add nuw i32 %i, 1 178 %continue = icmp slt i32 %i.next, %n 179 br i1 %continue, label %loop, label %exit 180 181exit: 182 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 183 ret i32 %result 184} 185 186define i32 @signed_loop_0_to_n_inverse_latch_predicate(i32* %array, i32 %length, i32 %n) { 187; CHECK-LABEL: @signed_loop_0_to_n_inverse_latch_predicate 188entry: 189 %tmp5 = icmp sle i32 %n, 0 190 br i1 %tmp5, label %exit, label %loop.preheader 191 192loop.preheader: 193; CHECK: loop.preheader: 194; CHECK: [[limit_check:[^ ]+]] = icmp slt i32 %n, %length 195; CHECK-NEXT: [[first_iteration_check:[^ ]+]] = icmp ult i32 0, %length 196; CHECK-NEXT: [[wide_cond:[^ ]+]] = and i1 [[first_iteration_check]], [[limit_check]] 197; CHECK-NEXT: br label %loop 198 br label %loop 199 200loop: 201; CHECK: loop: 202; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ] 203 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 204 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 205 %within.bounds = icmp ult i32 %i, %length 206 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 207 208 %i.i64 = zext i32 %i to i64 209 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 210 %array.i = load i32, i32* %array.i.ptr, align 4 211 %loop.acc.next = add i32 %loop.acc, %array.i 212 213 %i.next = add nuw i32 %i, 1 214 %continue = icmp sgt i32 %i.next, %n 215 br i1 %continue, label %exit, label %loop 216 217exit: 218 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 219 ret i32 %result 220} 221 222define i32 @signed_loop_0_to_n_sle_latch_ult_check(i32* %array, i32 %length, i32 %n) { 223; CHECK-LABEL: @signed_loop_0_to_n_sle_latch_ult_check 224entry: 225 %tmp5 = icmp sle i32 %n, 0 226 br i1 %tmp5, label %exit, label %loop.preheader 227 228loop.preheader: 229; CHECK: loop.preheader: 230; CHECK: [[limit_check:[^ ]+]] = icmp slt i32 %n, %length 231; CHECK-NEXT: [[first_iteration_check:[^ ]+]] = icmp ult i32 0, %length 232; CHECK-NEXT: [[wide_cond:[^ ]+]] = and i1 [[first_iteration_check]], [[limit_check]] 233; CHECK-NEXT: br label %loop 234 br label %loop 235 236loop: 237; CHECK: loop: 238; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ] 239 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 240 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 241 %within.bounds = icmp ult i32 %i, %length 242 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 243 244 %i.i64 = zext i32 %i to i64 245 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 246 %array.i = load i32, i32* %array.i.ptr, align 4 247 %loop.acc.next = add i32 %loop.acc, %array.i 248 249 %i.next = add nuw i32 %i, 1 250 %continue = icmp sle i32 %i.next, %n 251 br i1 %continue, label %loop, label %exit 252 253exit: 254 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 255 ret i32 %result 256} 257 258define i32 @unsupported_latch_pred_loop_0_to_n(i32* %array, i32 %length, i32 %n) { 259; CHECK-LABEL: @unsupported_latch_pred_loop_0_to_n 260entry: 261 %tmp5 = icmp sle i32 %n, 0 262 br i1 %tmp5, label %exit, label %loop.preheader 263 264loop.preheader: 265; CHECK: loop.preheader: 266; CHECK-NEXT: br label %loop 267 br label %loop 268 269loop: 270; CHECK: loop: 271; CHECK: %within.bounds = icmp ult i32 %i, %length 272; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 273 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 274 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 275 %within.bounds = icmp ult i32 %i, %length 276 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 277 278 %i.i64 = zext i32 %i to i64 279 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 280 %array.i = load i32, i32* %array.i.ptr, align 4 281 %loop.acc.next = add i32 %loop.acc, %array.i 282 283 %i.next = add nsw i32 %i, 1 284 %continue = icmp ne i32 %i.next, %n 285 br i1 %continue, label %loop, label %exit 286 287exit: 288 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 289 ret i32 %result 290} 291 292define i32 @signed_loop_0_to_n_unsupported_iv_step(i32* %array, i32 %length, i32 %n) { 293; CHECK-LABEL: @signed_loop_0_to_n_unsupported_iv_step 294entry: 295 %tmp5 = icmp sle i32 %n, 0 296 br i1 %tmp5, label %exit, label %loop.preheader 297 298loop.preheader: 299; CHECK: loop.preheader: 300; CHECK-NEXT: br label %loop 301 br label %loop 302 303loop: 304; CHECK: loop: 305; CHECK: %within.bounds = icmp ult i32 %i, %length 306; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 307 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 308 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 309 %within.bounds = icmp ult i32 %i, %length 310 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 311 312 %i.i64 = zext i32 %i to i64 313 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 314 %array.i = load i32, i32* %array.i.ptr, align 4 315 %loop.acc.next = add i32 %loop.acc, %array.i 316 317 %i.next = add nsw i32 %i, 2 318 %continue = icmp slt i32 %i.next, %n 319 br i1 %continue, label %loop, label %exit 320 321exit: 322 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 323 ret i32 %result 324} 325 326define i32 @signed_loop_0_to_n_equal_iv_range_check(i32* %array, i32 %length, i32 %n) { 327; CHECK-LABEL: @signed_loop_0_to_n_equal_iv_range_check 328entry: 329 %tmp5 = icmp sle i32 %n, 0 330 br i1 %tmp5, label %exit, label %loop.preheader 331 332loop.preheader: 333; CHECK: loop.preheader: 334; CHECK: [[limit_check:[^ ]+]] = icmp sle i32 %n, %length 335; CHECK-NEXT: [[first_iteration_check:[^ ]+]] = icmp ult i32 0, %length 336; CHECK-NEXT: [[wide_cond:[^ ]+]] = and i1 [[first_iteration_check]], [[limit_check]] 337; CHECK-NEXT: br label %loop 338 br label %loop 339 340loop: 341; CHECK: loop: 342; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ] 343 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 344 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 345 %j = phi i32 [ %j.next, %loop ], [ 0, %loop.preheader ] 346 347 %within.bounds = icmp ult i32 %j, %length 348 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 349 350 %i.i64 = zext i32 %i to i64 351 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 352 %array.i = load i32, i32* %array.i.ptr, align 4 353 %loop.acc.next = add i32 %loop.acc, %array.i 354 355 %j.next = add nsw i32 %j, 1 356 %i.next = add nsw i32 %i, 1 357 %continue = icmp slt i32 %i.next, %n 358 br i1 %continue, label %loop, label %exit 359 360exit: 361 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 362 ret i32 %result 363} 364 365define i32 @signed_loop_0_to_n_unrelated_iv_range_check(i32* %array, i32 %start, i32 %length, i32 %n) { 366; CHECK-LABEL: @signed_loop_0_to_n_unrelated_iv_range_check 367entry: 368 %tmp5 = icmp sle i32 %n, 0 369 br i1 %tmp5, label %exit, label %loop.preheader 370 371loop.preheader: 372; CHECK: loop.preheader: 373; CHECK-NEXT: br label %loop 374 br label %loop 375 376loop: 377; CHECK: loop: 378; CHECK: %within.bounds = icmp ult i32 %j, %length 379; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 380 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 381 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 382 %j = phi i32 [ %j.next, %loop ], [ %start, %loop.preheader ] 383 384 %within.bounds = icmp ult i32 %j, %length 385 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 386 387 %i.i64 = zext i32 %i to i64 388 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 389 %array.i = load i32, i32* %array.i.ptr, align 4 390 %loop.acc.next = add i32 %loop.acc, %array.i 391 392 %j.next = add nsw i32 %j, 1 393 %i.next = add nsw i32 %i, 1 394 %continue = icmp slt i32 %i.next, %n 395 br i1 %continue, label %loop, label %exit 396 397exit: 398 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 399 ret i32 %result 400} 401 402define i32 @two_range_checks(i32* %array.1, i32 %length.1, 403 i32* %array.2, i32 %length.2, i32 %n) { 404; CHECK-LABEL: @two_range_checks 405entry: 406 %tmp5 = icmp eq i32 %n, 0 407 br i1 %tmp5, label %exit, label %loop.preheader 408 409loop.preheader: 410; CHECK: loop.preheader: 411; CHECK: [[limit_check_1:[^ ]+]] = icmp ule i32 %n, %length.{{1|2}} 412; CHECK-NEXT: [[first_iteration_check_1:[^ ]+]] = icmp ult i32 0, %length.{{1|2}} 413; CHECK-NEXT: [[wide_cond_1:[^ ]+]] = and i1 [[first_iteration_check_1]], [[limit_check_1]] 414; CHECK-NEXT: [[limit_check_2:[^ ]+]] = icmp ule i32 %n, %length.{{1|2}} 415; CHECK-NEXT: [[first_iteration_check_2:[^ ]+]] = icmp ult i32 0, %length.{{1|2}} 416; CHECK-NEXT: [[wide_cond_2:[^ ]+]] = and i1 [[first_iteration_check_2]], [[limit_check_2]] 417; CHECK-NEXT: br label %loop 418 br label %loop 419 420loop: 421; CHECK: loop: 422; CHECK: [[wide_cond:[^ ]+]] = and i1 [[wide_cond_1]], [[wide_cond_2]] 423; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ] 424 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 425 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 426 %within.bounds.1 = icmp ult i32 %i, %length.1 427 %within.bounds.2 = icmp ult i32 %i, %length.2 428 %within.bounds = and i1 %within.bounds.1, %within.bounds.2 429 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 430 431 %i.i64 = zext i32 %i to i64 432 %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64 433 %array.1.i = load i32, i32* %array.1.i.ptr, align 4 434 %loop.acc.1 = add i32 %loop.acc, %array.1.i 435 436 %array.2.i.ptr = getelementptr inbounds i32, i32* %array.2, i64 %i.i64 437 %array.2.i = load i32, i32* %array.2.i.ptr, align 4 438 %loop.acc.next = add i32 %loop.acc.1, %array.2.i 439 440 %i.next = add nuw i32 %i, 1 441 %continue = icmp ult i32 %i.next, %n 442 br i1 %continue, label %loop, label %exit 443 444exit: 445 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 446 ret i32 %result 447} 448 449define i32 @three_range_checks(i32* %array.1, i32 %length.1, 450 i32* %array.2, i32 %length.2, 451 i32* %array.3, i32 %length.3, i32 %n) { 452; CHECK-LABEL: @three_range_checks 453entry: 454 %tmp5 = icmp eq i32 %n, 0 455 br i1 %tmp5, label %exit, label %loop.preheader 456 457loop.preheader: 458; CHECK: loop.preheader: 459; CHECK: [[limit_check_1:[^ ]+]] = icmp ule i32 %n, %length.{{1|2|3}} 460; CHECK-NEXT: [[first_iteration_check_1:[^ ]+]] = icmp ult i32 0, %length.{{1|2|3}} 461; CHECK-NEXT: [[wide_cond_1:[^ ]+]] = and i1 [[first_iteration_check_1]], [[limit_check_1]] 462; CHECK-NEXT: [[limit_check_2:[^ ]+]] = icmp ule i32 %n, %length.{{1|2|3}} 463; CHECK-NEXT: [[first_iteration_check_2:[^ ]+]] = icmp ult i32 0, %length.{{1|2|3}} 464; CHECK-NEXT: [[wide_cond_2:[^ ]+]] = and i1 [[first_iteration_check_2]], [[limit_check_2]] 465; CHECK-NEXT: [[limit_check_3:[^ ]+]] = icmp ule i32 %n, %length.{{1|2|3}} 466; CHECK-NEXT: [[first_iteration_check_3:[^ ]+]] = icmp ult i32 0, %length.{{1|2|3}} 467; CHECK-NEXT: [[wide_cond_3:[^ ]+]] = and i1 [[first_iteration_check_3]], [[limit_check_3]] 468; CHECK-NEXT: br label %loop 469 br label %loop 470 471loop: 472; CHECK: loop: 473; CHECK: [[wide_cond_and:[^ ]+]] = and i1 [[wide_cond_1]], [[wide_cond_2]] 474; CHECK-NEXT: [[wide_cond:[^ ]+]] = and i1 [[wide_cond_and]], [[wide_cond_3]] 475; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ] 476 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 477 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 478 %within.bounds.1 = icmp ult i32 %i, %length.1 479 %within.bounds.2 = icmp ult i32 %i, %length.2 480 %within.bounds.3 = icmp ult i32 %i, %length.3 481 %within.bounds.1.and.2 = and i1 %within.bounds.1, %within.bounds.2 482 %within.bounds = and i1 %within.bounds.1.and.2, %within.bounds.3 483 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 484 485 %i.i64 = zext i32 %i to i64 486 %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64 487 %array.1.i = load i32, i32* %array.1.i.ptr, align 4 488 %loop.acc.1 = add i32 %loop.acc, %array.1.i 489 490 %array.2.i.ptr = getelementptr inbounds i32, i32* %array.2, i64 %i.i64 491 %array.2.i = load i32, i32* %array.2.i.ptr, align 4 492 %loop.acc.2 = add i32 %loop.acc.1, %array.2.i 493 494 %array.3.i.ptr = getelementptr inbounds i32, i32* %array.3, i64 %i.i64 495 %array.3.i = load i32, i32* %array.3.i.ptr, align 4 496 %loop.acc.next = add i32 %loop.acc.2, %array.3.i 497 498 %i.next = add nuw i32 %i, 1 499 %continue = icmp ult i32 %i.next, %n 500 br i1 %continue, label %loop, label %exit 501 502exit: 503 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 504 ret i32 %result 505} 506 507define i32 @three_guards(i32* %array.1, i32 %length.1, 508 i32* %array.2, i32 %length.2, 509 i32* %array.3, i32 %length.3, i32 %n) { 510; CHECK-LABEL: @three_guards 511entry: 512 %tmp5 = icmp eq i32 %n, 0 513 br i1 %tmp5, label %exit, label %loop.preheader 514 515loop.preheader: 516; CHECK: loop.preheader: 517; CHECK: [[limit_check_1:[^ ]+]] = icmp ule i32 %n, %length.{{1|2|3}} 518; CHECK-NEXT: [[first_iteration_check_1:[^ ]+]] = icmp ult i32 0, %length.{{1|2|3}} 519; CHECK-NEXT: [[wide_cond_1:[^ ]+]] = and i1 [[first_iteration_check_1]], [[limit_check_1]] 520; CHECK-NEXT: [[limit_check_2:[^ ]+]] = icmp ule i32 %n, %length.{{1|2|3}} 521; CHECK-NEXT: [[first_iteration_check_2:[^ ]+]] = icmp ult i32 0, %length.{{1|2|3}} 522; CHECK-NEXT: [[wide_cond_2:[^ ]+]] = and i1 [[first_iteration_check_2]], [[limit_check_2]] 523; CHECK-NEXT: [[limit_check_3:[^ ]+]] = icmp ule i32 %n, %length.{{1|2|3}} 524; CHECK-NEXT: [[first_iteration_check_3:[^ ]+]] = icmp ult i32 0, %length.{{1|2|3}} 525; CHECK-NEXT: [[wide_cond_3:[^ ]+]] = and i1 [[first_iteration_check_3]], [[limit_check_3]] 526; CHECK-NEXT: br label %loop 527 br label %loop 528 529loop: 530; CHECK: loop: 531; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond_1]], i32 9) [ "deopt"() ] 532; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond_2]], i32 9) [ "deopt"() ] 533; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond_3]], i32 9) [ "deopt"() ] 534 535 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 536 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 537 538 %within.bounds.1 = icmp ult i32 %i, %length.1 539 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds.1, i32 9) [ "deopt"() ] 540 541 %i.i64 = zext i32 %i to i64 542 %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64 543 %array.1.i = load i32, i32* %array.1.i.ptr, align 4 544 %loop.acc.1 = add i32 %loop.acc, %array.1.i 545 546 %within.bounds.2 = icmp ult i32 %i, %length.2 547 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds.2, i32 9) [ "deopt"() ] 548 549 %array.2.i.ptr = getelementptr inbounds i32, i32* %array.2, i64 %i.i64 550 %array.2.i = load i32, i32* %array.2.i.ptr, align 4 551 %loop.acc.2 = add i32 %loop.acc.1, %array.2.i 552 553 %within.bounds.3 = icmp ult i32 %i, %length.3 554 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds.3, i32 9) [ "deopt"() ] 555 556 %array.3.i.ptr = getelementptr inbounds i32, i32* %array.3, i64 %i.i64 557 %array.3.i = load i32, i32* %array.3.i.ptr, align 4 558 %loop.acc.next = add i32 %loop.acc.2, %array.3.i 559 560 %i.next = add nuw i32 %i, 1 561 %continue = icmp ult i32 %i.next, %n 562 br i1 %continue, label %loop, label %exit 563 564exit: 565 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 566 ret i32 %result 567} 568 569define i32 @unsigned_loop_0_to_n_unrelated_condition(i32* %array, i32 %length, i32 %n, i32 %x) { 570; CHECK-LABEL: @unsigned_loop_0_to_n_unrelated_condition 571entry: 572 %tmp5 = icmp eq i32 %n, 0 573 br i1 %tmp5, label %exit, label %loop.preheader 574 575loop.preheader: 576; CHECK: loop.preheader: 577; CHECK: [[limit_check:[^ ]+]] = icmp ule i32 %n, %length 578; CHECK-NEXT: [[first_iteration_check:[^ ]+]] = icmp ult i32 0, %length 579; CHECK-NEXT: [[wide_cond:[^ ]+]] = and i1 [[first_iteration_check]], [[limit_check]] 580; CHECK-NEXT: br label %loop 581 br label %loop 582 583loop: 584; CHECK: loop: 585; CHECK: %unrelated.cond = icmp ult i32 %x, %length 586; CHECK: [[guard_cond:[^ ]+]] = and i1 %unrelated.cond, [[wide_cond]] 587; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[guard_cond]], i32 9) [ "deopt"() ] 588 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 589 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 590 %within.bounds = icmp ult i32 %i, %length 591 %unrelated.cond = icmp ult i32 %x, %length 592 %guard.cond = and i1 %within.bounds, %unrelated.cond 593 call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ] 594 595 %i.i64 = zext i32 %i to i64 596 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 597 %array.i = load i32, i32* %array.i.ptr, align 4 598 %loop.acc.next = add i32 %loop.acc, %array.i 599 600 %i.next = add nuw i32 %i, 1 601 %continue = icmp ult i32 %i.next, %n 602 br i1 %continue, label %loop, label %exit 603 604exit: 605 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 606 ret i32 %result 607} 608 609; Don't change the guard condition if there were no widened subconditions 610define i32 @test_no_widened_conditions(i32* %array, i32 %length, i32 %n, i32 %x1, i32 %x2, i32 %x3) { 611; CHECK-LABEL: @test_no_widened_conditions 612entry: 613 %tmp5 = icmp eq i32 %n, 0 614 br i1 %tmp5, label %exit, label %loop.preheader 615 616loop.preheader: 617; CHECK: loop.preheader: 618; CHECK-NEXT: br label %loop 619 br label %loop 620 621loop: 622; CHECK: loop: 623; CHECK: %unrelated.cond.1 = icmp eq i32 %x1, %i 624; CHECK-NEXT: %unrelated.cond.2 = icmp eq i32 %x2, %i 625; CHECK-NEXT: %unrelated.cond.3 = icmp eq i32 %x3, %i 626; CHECK-NEXT: %unrelated.cond.and.1 = and i1 %unrelated.cond.1, %unrelated.cond.2 627; CHECK-NEXT: %guard.cond = and i1 %unrelated.cond.and.1, %unrelated.cond.3 628; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ] 629 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 630 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 631 %unrelated.cond.1 = icmp eq i32 %x1, %i 632 %unrelated.cond.2 = icmp eq i32 %x2, %i 633 %unrelated.cond.3 = icmp eq i32 %x3, %i 634 %unrelated.cond.and.1 = and i1 %unrelated.cond.1, %unrelated.cond.2 635 %guard.cond = and i1 %unrelated.cond.and.1, %unrelated.cond.3 636 637 call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ] 638 639 %i.i64 = zext i32 %i to i64 640 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 641 %array.i = load i32, i32* %array.i.ptr, align 4 642 %loop.acc.next = add i32 %loop.acc, %array.i 643 644 %i.next = add nuw i32 %i, 1 645 %continue = icmp ult i32 %i.next, %n 646 br i1 %continue, label %loop, label %exit 647 648exit: 649 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 650 ret i32 %result 651} 652 653define i32 @signed_loop_start_to_n_loop_variant_bound(i32* %array, i32 %x, i32 %start, i32 %n) { 654; CHECK-LABEL: @signed_loop_start_to_n_loop_variant_bound 655entry: 656 %tmp5 = icmp sle i32 %n, 0 657 br i1 %tmp5, label %exit, label %loop.preheader 658 659loop.preheader: 660; CHECK: loop.preheader: 661; CHECK-NEXT: br label %loop 662 br label %loop 663 664loop: 665; CHECK: loop: 666; CHECK: %bound = add i32 %i, %x 667; CHECK-NEXT: %within.bounds = icmp ult i32 %i, %bound 668; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 669 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 670 %i = phi i32 [ %i.next, %loop ], [ %start, %loop.preheader ] 671 %bound = add i32 %i, %x 672 %within.bounds = icmp ult i32 %i, %bound 673 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 674 675 %i.i64 = zext i32 %i to i64 676 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 677 %array.i = load i32, i32* %array.i.ptr, align 4 678 %loop.acc.next = add i32 %loop.acc, %array.i 679 680 %i.next = add nsw i32 %i, 1 681 %continue = icmp slt i32 %i.next, %n 682 br i1 %continue, label %loop, label %exit 683 684exit: 685 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 686 ret i32 %result 687} 688 689define i32 @signed_loop_start_to_n_non_monotonic_predicate(i32* %array, i32 %x, i32 %start, i32 %n) { 690; CHECK-LABEL: @signed_loop_start_to_n_non_monotonic_predicate 691entry: 692 %tmp5 = icmp sle i32 %n, 0 693 br i1 %tmp5, label %exit, label %loop.preheader 694 695loop.preheader: 696; CHECK: loop.preheader: 697; CHECK-NEXT: br label %loop 698 br label %loop 699 700loop: 701; CHECK: loop: 702; CHECK: %guard.cond = icmp eq i32 %i, %x 703; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ] 704 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 705 %i = phi i32 [ %i.next, %loop ], [ %start, %loop.preheader ] 706 %guard.cond = icmp eq i32 %i, %x 707 call void (i1, ...) @llvm.experimental.guard(i1 %guard.cond, i32 9) [ "deopt"() ] 708 709 %i.i64 = zext i32 %i to i64 710 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 711 %array.i = load i32, i32* %array.i.ptr, align 4 712 %loop.acc.next = add i32 %loop.acc, %array.i 713 714 %i.next = add nsw i32 %i, 1 715 %continue = icmp slt i32 %i.next, %n 716 br i1 %continue, label %loop, label %exit 717 718exit: 719 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 720 ret i32 %result 721} 722 723define i32 @unsigned_loop_0_to_n_hoist_length(i32* %array, i16 %length.i16, i32 %n) { 724; CHECK-LABEL: @unsigned_loop_0_to_n_hoist_length 725entry: 726 %tmp5 = icmp eq i32 %n, 0 727 br i1 %tmp5, label %exit, label %loop.preheader 728 729loop.preheader: 730; CHECK: loop.preheader: 731; CHECK: [[length:[^ ]+]] = zext i16 %length.i16 to i32 732; CHECK-NEXT: [[limit_check:[^ ]+]] = icmp ule i32 %n, [[length]] 733; CHECK-NEXT: [[first_iteration_check:[^ ]+]] = icmp ult i32 0, [[length]] 734; CHECK-NEXT: [[wide_cond:[^ ]+]] = and i1 [[first_iteration_check]], [[limit_check]] 735; CHECK-NEXT: br label %loop 736 br label %loop 737 738loop: 739; CHECK: loop: 740; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ] 741 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 742 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 743 %length = zext i16 %length.i16 to i32 744 %within.bounds = icmp ult i32 %i, %length 745 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 746 747 %i.i64 = zext i32 %i to i64 748 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 749 %array.i = load i32, i32* %array.i.ptr, align 4 750 %loop.acc.next = add i32 %loop.acc, %array.i 751 752 %i.next = add nuw i32 %i, 1 753 %continue = icmp ult i32 %i.next, %n 754 br i1 %continue, label %loop, label %exit 755 756exit: 757 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 758 ret i32 %result 759} 760 761define i32 @unsigned_loop_0_to_n_cant_hoist_length(i32* %array, i32 %length, i32 %divider, i32 %n) { 762; CHECK-LABEL: @unsigned_loop_0_to_n_cant_hoist_length 763entry: 764 %tmp5 = icmp eq i32 %n, 0 765 br i1 %tmp5, label %exit, label %loop.preheader 766 767loop.preheader: 768; CHECK: loop.preheader: 769; CHECK-NEXT: br label %loop 770 br label %loop 771 772loop: 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: %length.udiv = udiv i32 %length, %divider 777; CHECK-NEXT: %within.bounds = icmp ult i32 %i, %length.udiv 778; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 779 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 780 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 781 %length.udiv = udiv i32 %length, %divider 782 %within.bounds = icmp ult i32 %i, %length.udiv 783 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 784 785 %i.i64 = zext i32 %i to i64 786 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 787 %array.i = load i32, i32* %array.i.ptr, align 4 788 %loop.acc.next = add i32 %loop.acc, %array.i 789 790 %i.next = add nuw i32 %i, 1 791 %continue = icmp ult i32 %i.next, %n 792 br i1 %continue, label %loop, label %exit 793 794exit: 795 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 796 ret i32 %result 797} 798