1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=indvars -indvars-post-increment-ranges -S | FileCheck %s 3 4target datalayout = "p:64:64:64-n32:64" 5 6; When the IV in this loop is widened we want to widen this use as well: 7; icmp slt i32 %i.inc, %limit 8; In order to do this indvars need to prove that the narrow IV def (%i.inc) 9; is not-negative from the range check inside of the loop. 10define void @test(ptr %base, i32 %limit, i32 %start) { 11; CHECK-LABEL: @test( 12; CHECK-NEXT: for.body.lr.ph: 13; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[START:%.*]], i32 64) 14; CHECK-NEXT: [[TMP0:%.*]] = sub i32 [[UMAX]], [[START]] 15; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[START]], 1 16; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[LIMIT:%.*]], i32 [[TMP1]]) 17; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[SMAX]], -1 18; CHECK-NEXT: [[TMP3:%.*]] = sub i32 [[TMP2]], [[START]] 19; CHECK-NEXT: [[TMP4:%.*]] = freeze i32 [[TMP3]] 20; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP4]], i32 [[TMP0]]) 21; CHECK-NEXT: [[TMP5:%.*]] = icmp ne i32 [[TMP0]], [[UMIN]] 22; CHECK-NEXT: [[TMP6:%.*]] = icmp ne i32 [[TMP3]], [[UMIN]] 23; CHECK-NEXT: br label [[FOR_BODY:%.*]] 24; CHECK: for.body: 25; CHECK-NEXT: br i1 [[TMP5]], label [[CONTINUE:%.*]], label [[FOR_END:%.*]] 26; CHECK: continue: 27; CHECK-NEXT: br label [[FOR_INC:%.*]] 28; CHECK: for.inc: 29; CHECK-NEXT: br i1 [[TMP6]], label [[FOR_BODY]], label [[FOR_END]] 30; CHECK: for.end: 31; CHECK-NEXT: br label [[EXIT:%.*]] 32; CHECK: exit: 33; CHECK-NEXT: ret void 34; 35 36for.body.lr.ph: 37 br label %for.body 38 39for.body: 40 %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ] 41 %within_limits = icmp ult i32 %i, 64 42 br i1 %within_limits, label %continue, label %for.end 43 44continue: 45 %i.i64 = zext i32 %i to i64 46 %arrayidx = getelementptr inbounds i32, ptr %base, i64 %i.i64 47 %val = load i32, ptr %arrayidx, align 4 48 br label %for.inc 49 50for.inc: 51 %i.inc = add nsw nuw i32 %i, 1 52 %cmp = icmp slt i32 %i.inc, %limit 53 br i1 %cmp, label %for.body, label %for.end 54 55for.end: 56 br label %exit 57 58exit: 59 ret void 60} 61 62define void @test_false_edge(ptr %base, i32 %limit, i32 %start) { 63; CHECK-LABEL: @test_false_edge( 64; CHECK-NEXT: for.body.lr.ph: 65; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[START:%.*]], i32 65) 66; CHECK-NEXT: [[TMP0:%.*]] = sub i32 [[UMAX]], [[START]] 67; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[START]], 1 68; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[LIMIT:%.*]], i32 [[TMP1]]) 69; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[SMAX]], -1 70; CHECK-NEXT: [[TMP3:%.*]] = sub i32 [[TMP2]], [[START]] 71; CHECK-NEXT: [[TMP4:%.*]] = freeze i32 [[TMP3]] 72; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP4]], i32 [[TMP0]]) 73; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[TMP0]], [[UMIN]] 74; CHECK-NEXT: [[TMP6:%.*]] = icmp ne i32 [[TMP3]], [[UMIN]] 75; CHECK-NEXT: br label [[FOR_BODY:%.*]] 76; CHECK: for.body: 77; CHECK-NEXT: br i1 [[TMP5]], label [[FOR_END:%.*]], label [[CONTINUE:%.*]] 78; CHECK: continue: 79; CHECK-NEXT: br label [[FOR_INC:%.*]] 80; CHECK: for.inc: 81; CHECK-NEXT: br i1 [[TMP6]], label [[FOR_BODY]], label [[FOR_END]] 82; CHECK: for.end: 83; CHECK-NEXT: br label [[EXIT:%.*]] 84; CHECK: exit: 85; CHECK-NEXT: ret void 86; 87 88for.body.lr.ph: 89 br label %for.body 90 91for.body: 92 %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ] 93 %out_of_bounds = icmp ugt i32 %i, 64 94 br i1 %out_of_bounds, label %for.end, label %continue 95 96continue: 97 %i.i64 = zext i32 %i to i64 98 %arrayidx = getelementptr inbounds i32, ptr %base, i64 %i.i64 99 %val = load i32, ptr %arrayidx, align 4 100 br label %for.inc 101 102for.inc: 103 %i.inc = add nsw nuw i32 %i, 1 104 %cmp = icmp slt i32 %i.inc, %limit 105 br i1 %cmp, label %for.body, label %for.end 106 107for.end: 108 br label %exit 109 110exit: 111 ret void 112} 113 114define void @test_range_metadata(ptr %array_length_ptr, ptr %base, 115; CHECK-LABEL: @test_range_metadata( 116; CHECK-NEXT: for.body.lr.ph: 117; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64 118; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[LIMIT:%.*]] to i64 119; CHECK-NEXT: br label [[FOR_BODY:%.*]] 120; CHECK: for.body: 121; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ [[TMP0]], [[FOR_BODY_LR_PH:%.*]] ] 122; CHECK-NEXT: [[ARRAY_LENGTH:%.*]] = load i32, ptr [[ARRAY_LENGTH_PTR:%.*]], align 4, !range [[RNG0:![0-9]+]] 123; CHECK-NEXT: [[TMP2:%.*]] = zext i32 [[ARRAY_LENGTH]] to i64 124; CHECK-NEXT: [[WITHIN_LIMITS:%.*]] = icmp ult i64 [[INDVARS_IV]], [[TMP2]] 125; CHECK-NEXT: br i1 [[WITHIN_LIMITS]], label [[CONTINUE:%.*]], label [[FOR_END:%.*]] 126; CHECK: continue: 127; CHECK-NEXT: br label [[FOR_INC]] 128; CHECK: for.inc: 129; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 130; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[INDVARS_IV_NEXT]], [[TMP1]] 131; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END]] 132; CHECK: for.end: 133; CHECK-NEXT: br label [[EXIT:%.*]] 134; CHECK: exit: 135; CHECK-NEXT: ret void 136; 137 i32 %limit, i32 %start) { 138 139for.body.lr.ph: 140 br label %for.body 141 142for.body: 143 %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ] 144 %array_length = load i32, ptr %array_length_ptr, !range !{i32 0, i32 64 } 145 %within_limits = icmp ult i32 %i, %array_length 146 br i1 %within_limits, label %continue, label %for.end 147 148continue: 149 %i.i64 = zext i32 %i to i64 150 %arrayidx = getelementptr inbounds i32, ptr %base, i64 %i.i64 151 %val = load i32, ptr %arrayidx, align 4 152 br label %for.inc 153 154for.inc: 155 %i.inc = add nsw nuw i32 %i, 1 156 %cmp = icmp slt i32 %i.inc, %limit 157 br i1 %cmp, label %for.body, label %for.end 158 159for.end: 160 br label %exit 161 162exit: 163 ret void 164} 165 166; Negative version of the test above, we don't know anything about 167; array_length_ptr range. 168define void @test_neg(ptr %array_length_ptr, ptr %base, 169; CHECK-LABEL: @test_neg( 170; CHECK-NEXT: for.body.lr.ph: 171; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64 172; CHECK-NEXT: br label [[FOR_BODY:%.*]] 173; CHECK: for.body: 174; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ [[TMP0]], [[FOR_BODY_LR_PH:%.*]] ] 175; CHECK-NEXT: [[ARRAY_LENGTH:%.*]] = load i32, ptr [[ARRAY_LENGTH_PTR:%.*]], align 4 176; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[ARRAY_LENGTH]] to i64 177; CHECK-NEXT: [[WITHIN_LIMITS:%.*]] = icmp ult i64 [[INDVARS_IV]], [[TMP1]] 178; CHECK-NEXT: br i1 [[WITHIN_LIMITS]], label [[CONTINUE:%.*]], label [[FOR_END:%.*]] 179; CHECK: continue: 180; CHECK-NEXT: br label [[FOR_INC]] 181; CHECK: for.inc: 182; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 183; CHECK-NEXT: [[TMP2:%.*]] = trunc nuw i64 [[INDVARS_IV_NEXT]] to i32 184; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP2]], [[LIMIT:%.*]] 185; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END]] 186; CHECK: for.end: 187; CHECK-NEXT: br label [[EXIT:%.*]] 188; CHECK: exit: 189; CHECK-NEXT: ret void 190; 191 i32 %limit, i32 %start) { 192 193for.body.lr.ph: 194 br label %for.body 195 196for.body: 197 %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ] 198 %array_length = load i32, ptr %array_length_ptr 199 %within_limits = icmp ult i32 %i, %array_length 200 br i1 %within_limits, label %continue, label %for.end 201 202continue: 203 %i.i64 = zext i32 %i to i64 204 %arrayidx = getelementptr inbounds i32, ptr %base, i64 %i.i64 205 %val = load i32, ptr %arrayidx, align 4 206 br label %for.inc 207 208for.inc: 209 %i.inc = add nsw nuw i32 %i, 1 210 %cmp = icmp slt i32 %i.inc, %limit 211 br i1 %cmp, label %for.body, label %for.end 212 213for.end: 214 br label %exit 215 216exit: 217 ret void 218} 219 220define void @test_transitive_use(ptr %base, i32 %limit, i32 %start) { 221; CHECK-LABEL: @test_transitive_use( 222; CHECK-NEXT: for.body.lr.ph: 223; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64 224; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[LIMIT:%.*]] to i64 225; CHECK-NEXT: [[TMP2:%.*]] = sext i32 [[LIMIT]] to i64 226; CHECK-NEXT: [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[START]], i32 64) 227; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[UMAX]] to i64 228; CHECK-NEXT: br label [[FOR_BODY:%.*]] 229; CHECK: for.body: 230; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ [[TMP0]], [[FOR_BODY_LR_PH:%.*]] ] 231; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV]], [[WIDE_TRIP_COUNT]] 232; CHECK-NEXT: br i1 [[EXITCOND]], label [[CONTINUE:%.*]], label [[FOR_END:%.*]] 233; CHECK: continue: 234; CHECK-NEXT: [[TMP3:%.*]] = mul nuw nsw i64 [[INDVARS_IV]], 3 235; CHECK-NEXT: [[MUL_WITHIN:%.*]] = icmp ult i64 [[TMP3]], 64 236; CHECK-NEXT: br i1 [[MUL_WITHIN]], label [[GUARDED:%.*]], label [[CONTINUE_2:%.*]] 237; CHECK: guarded: 238; CHECK-NEXT: [[TMP4:%.*]] = add nuw nsw i64 [[TMP3]], 1 239; CHECK-NEXT: [[RESULT:%.*]] = icmp slt i64 [[TMP4]], [[TMP1]] 240; CHECK-NEXT: br i1 [[RESULT]], label [[CONTINUE_2]], label [[FOR_END]] 241; CHECK: continue.2: 242; CHECK-NEXT: br label [[FOR_INC]] 243; CHECK: for.inc: 244; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 245; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[INDVARS_IV_NEXT]], [[TMP2]] 246; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END]] 247; CHECK: for.end: 248; CHECK-NEXT: br label [[EXIT:%.*]] 249; CHECK: exit: 250; CHECK-NEXT: ret void 251; 252 253for.body.lr.ph: 254 br label %for.body 255 256for.body: 257 %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ] 258 %within_limits = icmp ult i32 %i, 64 259 br i1 %within_limits, label %continue, label %for.end 260 261continue: 262 %i.mul.3 = mul nsw nuw i32 %i, 3 263 %mul_within = icmp ult i32 %i.mul.3, 64 264 br i1 %mul_within, label %guarded, label %continue.2 265 266guarded: 267 %i.mul.3.inc = add nsw nuw i32 %i.mul.3, 1 268 %result = icmp slt i32 %i.mul.3.inc, %limit 269 br i1 %result, label %continue.2, label %for.end 270 271continue.2: 272 %i.i64 = zext i32 %i to i64 273 %arrayidx = getelementptr inbounds i32, ptr %base, i64 %i.i64 274 %val = load i32, ptr %arrayidx, align 4 275 br label %for.inc 276 277for.inc: 278 %i.inc = add nsw nuw i32 %i, 1 279 %cmp = icmp slt i32 %i.inc, %limit 280 br i1 %cmp, label %for.body, label %for.end 281 282 283for.end: 284 br label %exit 285 286exit: 287 ret void 288} 289 290declare void @llvm.experimental.guard(i1, ...) 291 292define void @test_guard_one_bb(ptr %base, i32 %limit, i32 %start) { 293; CHECK-LABEL: @test_guard_one_bb( 294; CHECK-NEXT: for.body.lr.ph: 295; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64 296; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[LIMIT:%.*]] to i64 297; CHECK-NEXT: br label [[FOR_BODY:%.*]] 298; CHECK: for.body: 299; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[TMP0]], [[FOR_BODY_LR_PH:%.*]] ] 300; CHECK-NEXT: [[WITHIN_LIMITS:%.*]] = icmp ult i64 [[INDVARS_IV]], 64 301; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_LIMITS]]) [ "deopt"() ] 302; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 303; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[INDVARS_IV_NEXT]], [[TMP1]] 304; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 305; CHECK: for.end: 306; CHECK-NEXT: br label [[EXIT:%.*]] 307; CHECK: exit: 308; CHECK-NEXT: ret void 309; 310 311for.body.lr.ph: 312 br label %for.body 313 314for.body: 315 %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.body ] 316 %within_limits = icmp ult i32 %i, 64 317 %i.i64 = zext i32 %i to i64 318 %arrayidx = getelementptr inbounds i32, ptr %base, i64 %i.i64 319 %val = load i32, ptr %arrayidx, align 4 320 call void(i1, ...) @llvm.experimental.guard(i1 %within_limits) [ "deopt"() ] 321 %i.inc = add nsw nuw i32 %i, 1 322 %cmp = icmp slt i32 %i.inc, %limit 323 br i1 %cmp, label %for.body, label %for.end 324 325for.end: 326 br label %exit 327 328exit: 329 ret void 330} 331 332define void @test_guard_in_the_same_bb(ptr %base, i32 %limit, i32 %start) { 333; CHECK-LABEL: @test_guard_in_the_same_bb( 334; CHECK-NEXT: for.body.lr.ph: 335; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64 336; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[LIMIT:%.*]] to i64 337; CHECK-NEXT: br label [[FOR_BODY:%.*]] 338; CHECK: for.body: 339; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ [[TMP0]], [[FOR_BODY_LR_PH:%.*]] ] 340; CHECK-NEXT: [[WITHIN_LIMITS:%.*]] = icmp ult i64 [[INDVARS_IV]], 64 341; CHECK-NEXT: br label [[FOR_INC]] 342; CHECK: for.inc: 343; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_LIMITS]]) [ "deopt"() ] 344; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 345; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[INDVARS_IV_NEXT]], [[TMP1]] 346; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 347; CHECK: for.end: 348; CHECK-NEXT: br label [[EXIT:%.*]] 349; CHECK: exit: 350; CHECK-NEXT: ret void 351; 352 353for.body.lr.ph: 354 br label %for.body 355 356for.body: 357 %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ] 358 %within_limits = icmp ult i32 %i, 64 359 %i.i64 = zext i32 %i to i64 360 %arrayidx = getelementptr inbounds i32, ptr %base, i64 %i.i64 361 %val = load i32, ptr %arrayidx, align 4 362 br label %for.inc 363 364for.inc: 365 call void(i1, ...) @llvm.experimental.guard(i1 %within_limits) [ "deopt"() ] 366 %i.inc = add nsw nuw i32 %i, 1 367 %cmp = icmp slt i32 %i.inc, %limit 368 br i1 %cmp, label %for.body, label %for.end 369 370for.end: 371 br label %exit 372 373exit: 374 ret void 375} 376 377define void @test_guard_in_idom(ptr %base, i32 %limit, i32 %start) { 378; CHECK-LABEL: @test_guard_in_idom( 379; CHECK-NEXT: for.body.lr.ph: 380; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64 381; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[LIMIT:%.*]] to i64 382; CHECK-NEXT: br label [[FOR_BODY:%.*]] 383; CHECK: for.body: 384; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ [[TMP0]], [[FOR_BODY_LR_PH:%.*]] ] 385; CHECK-NEXT: [[WITHIN_LIMITS:%.*]] = icmp ult i64 [[INDVARS_IV]], 64 386; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_LIMITS]]) [ "deopt"() ] 387; CHECK-NEXT: br label [[FOR_INC]] 388; CHECK: for.inc: 389; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 390; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[INDVARS_IV_NEXT]], [[TMP1]] 391; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 392; CHECK: for.end: 393; CHECK-NEXT: br label [[EXIT:%.*]] 394; CHECK: exit: 395; CHECK-NEXT: ret void 396; 397 398for.body.lr.ph: 399 br label %for.body 400 401for.body: 402 %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ] 403 %within_limits = icmp ult i32 %i, 64 404 call void(i1, ...) @llvm.experimental.guard(i1 %within_limits) [ "deopt"() ] 405 %i.i64 = zext i32 %i to i64 406 %arrayidx = getelementptr inbounds i32, ptr %base, i64 %i.i64 407 %val = load i32, ptr %arrayidx, align 4 408 br label %for.inc 409 410for.inc: 411 %i.inc = add nsw nuw i32 %i, 1 412 %cmp = icmp slt i32 %i.inc, %limit 413 br i1 %cmp, label %for.body, label %for.end 414 415for.end: 416 br label %exit 417 418exit: 419 ret void 420} 421 422define void @test_guard_merge_ranges(ptr %base, i32 %limit, i32 %start) { 423; CHECK-LABEL: @test_guard_merge_ranges( 424; CHECK-NEXT: for.body.lr.ph: 425; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64 426; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[LIMIT:%.*]] to i64 427; CHECK-NEXT: br label [[FOR_BODY:%.*]] 428; CHECK: for.body: 429; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[TMP0]], [[FOR_BODY_LR_PH:%.*]] ] 430; CHECK-NEXT: [[WITHIN_LIMITS_1:%.*]] = icmp ult i64 [[INDVARS_IV]], 64 431; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_LIMITS_1]]) [ "deopt"() ] 432; CHECK-NEXT: [[WITHIN_LIMITS_2:%.*]] = icmp ult i64 [[INDVARS_IV]], 2147483647 433; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_LIMITS_2]]) [ "deopt"() ] 434; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 435; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[INDVARS_IV_NEXT]], [[TMP1]] 436; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 437; CHECK: for.end: 438; CHECK-NEXT: br label [[EXIT:%.*]] 439; CHECK: exit: 440; CHECK-NEXT: ret void 441; 442 443for.body.lr.ph: 444 br label %for.body 445 446for.body: 447 %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.body ] 448 %within_limits.1 = icmp ult i32 %i, 64 449 call void(i1, ...) @llvm.experimental.guard(i1 %within_limits.1) [ "deopt"() ] 450 %within_limits.2 = icmp ult i32 %i, 2147483647 451 call void(i1, ...) @llvm.experimental.guard(i1 %within_limits.2) [ "deopt"() ] 452 %i.i64 = zext i32 %i to i64 453 %arrayidx = getelementptr inbounds i32, ptr %base, i64 %i.i64 454 %val = load i32, ptr %arrayidx, align 4 455 %i.inc = add nsw nuw i32 %i, 1 456 %cmp = icmp slt i32 %i.inc, %limit 457 br i1 %cmp, label %for.body, label %for.end 458 459for.end: 460 br label %exit 461 462exit: 463 ret void 464} 465