1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -indvars -indvars-predicate-loops=0 %s | FileCheck %s 3target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 4target triple = "x86_64-unknown-linux-gnu" 5 6define void @test1(i64 %start) { 7; CHECK-LABEL: @test1( 8; CHECK-NEXT: entry: 9; CHECK-NEXT: br label [[LOOP:%.*]] 10; CHECK: loop: 11; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i64 [[START:%.*]], -1 12; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_END:%.*]], label [[LOOP]] 13; CHECK: for.end: 14; CHECK-NEXT: ret void 15; 16entry: 17 br label %loop 18 19loop: 20 %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ] 21 %indvars.iv.next = add nsw i64 %indvars.iv, 1 22 %cmp1 = icmp slt i64 %indvars.iv, -1 23 br i1 %cmp1, label %for.end, label %loop 24 25for.end: ; preds = %if.end, %entry 26 ret void 27} 28 29define void @test2(i64 %start) { 30; CHECK-LABEL: @test2( 31; CHECK-NEXT: entry: 32; CHECK-NEXT: br label [[LOOP:%.*]] 33; CHECK: loop: 34; CHECK-NEXT: [[CMP1:%.*]] = icmp sle i64 [[START:%.*]], -1 35; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_END:%.*]], label [[LOOP]] 36; CHECK: for.end: 37; CHECK-NEXT: ret void 38; 39entry: 40 br label %loop 41 42loop: 43 %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ] 44 %indvars.iv.next = add nsw i64 %indvars.iv, 1 45 %cmp1 = icmp sle i64 %indvars.iv, -1 46 br i1 %cmp1, label %for.end, label %loop 47 48for.end: ; preds = %if.end, %entry 49 ret void 50} 51 52; As long as the test dominates the backedge, we're good 53define void @test3(i64 %start) { 54; CHECK-LABEL: @test3( 55; CHECK-NEXT: entry: 56; CHECK-NEXT: br label [[LOOP:%.*]] 57; CHECK: loop: 58; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 59; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1 60; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], 25 61; CHECK-NEXT: br i1 [[CMP]], label [[BACKEDGE]], label [[FOR_END:%.*]] 62; CHECK: backedge: 63; CHECK-NEXT: call void @foo() 64; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i64 [[START]], -1 65; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_END]], label [[LOOP]] 66; CHECK: for.end: 67; CHECK-NEXT: ret void 68; 69entry: 70 br label %loop 71 72loop: 73 %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ] 74 %indvars.iv.next = add nsw i64 %indvars.iv, 1 75 %cmp = icmp eq i64 %indvars.iv.next, 25 76 br i1 %cmp, label %backedge, label %for.end 77 78backedge: 79 ; prevent flattening, needed to make sure we're testing what we intend 80 call void @foo() 81 %cmp1 = icmp slt i64 %indvars.iv, -1 82 br i1 %cmp1, label %for.end, label %loop 83 84for.end: ; preds = %if.end, %entry 85 ret void 86} 87 88define void @test4(i64 %start) { 89; CHECK-LABEL: @test4( 90; CHECK-NEXT: entry: 91; CHECK-NEXT: br label [[LOOP:%.*]] 92; CHECK: loop: 93; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 94; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1 95; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], 25 96; CHECK-NEXT: br i1 [[CMP]], label [[BACKEDGE]], label [[FOR_END:%.*]] 97; CHECK: backedge: 98; CHECK-NEXT: call void @foo() 99; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i64 [[START]], -1 100; CHECK-NEXT: br i1 [[CMP1]], label [[LOOP]], label [[FOR_END]] 101; CHECK: for.end: 102; CHECK-NEXT: ret void 103; 104entry: 105 br label %loop 106 107loop: 108 %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ] 109 %indvars.iv.next = add nsw i64 %indvars.iv, 1 110 %cmp = icmp eq i64 %indvars.iv.next, 25 111 br i1 %cmp, label %backedge, label %for.end 112 113backedge: 114 ; prevent flattening, needed to make sure we're testing what we intend 115 call void @foo() 116 %cmp1 = icmp sgt i64 %indvars.iv, -1 117 br i1 %cmp1, label %loop, label %for.end 118 119for.end: ; preds = %if.end, %entry 120 ret void 121} 122 123define void @test5(i64 %start) { 124; CHECK-LABEL: @test5( 125; CHECK-NEXT: entry: 126; CHECK-NEXT: br label [[LOOP:%.*]] 127; CHECK: loop: 128; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 129; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw i64 [[INDVARS_IV]], 1 130; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], 25 131; CHECK-NEXT: br i1 [[CMP]], label [[BACKEDGE]], label [[FOR_END:%.*]] 132; CHECK: backedge: 133; CHECK-NEXT: call void @foo() 134; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i64 [[START]], 100 135; CHECK-NEXT: br i1 [[CMP1]], label [[LOOP]], label [[FOR_END]] 136; CHECK: for.end: 137; CHECK-NEXT: ret void 138; 139entry: 140 br label %loop 141 142loop: 143 %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ] 144 %indvars.iv.next = add nuw i64 %indvars.iv, 1 145 %cmp = icmp eq i64 %indvars.iv.next, 25 146 br i1 %cmp, label %backedge, label %for.end 147 148backedge: 149 ; prevent flattening, needed to make sure we're testing what we intend 150 call void @foo() 151 %cmp1 = icmp ugt i64 %indvars.iv, 100 152 br i1 %cmp1, label %loop, label %for.end 153 154for.end: ; preds = %if.end, %entry 155 ret void 156} 157 158define void @test6(i64 %start) { 159; CHECK-LABEL: @test6( 160; CHECK-NEXT: entry: 161; CHECK-NEXT: br label [[LOOP:%.*]] 162; CHECK: loop: 163; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 164; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw i64 [[INDVARS_IV]], 1 165; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], 25 166; CHECK-NEXT: br i1 [[CMP]], label [[BACKEDGE]], label [[FOR_END:%.*]] 167; CHECK: backedge: 168; CHECK-NEXT: call void @foo() 169; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i64 [[START]], 100 170; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_END]], label [[LOOP]] 171; CHECK: for.end: 172; CHECK-NEXT: ret void 173; 174entry: 175 br label %loop 176 177loop: 178 %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ] 179 %indvars.iv.next = add nuw i64 %indvars.iv, 1 180 %cmp = icmp eq i64 %indvars.iv.next, 25 181 br i1 %cmp, label %backedge, label %for.end 182 183backedge: 184 ; prevent flattening, needed to make sure we're testing what we intend 185 call void @foo() 186 %cmp1 = icmp ult i64 %indvars.iv, 100 187 br i1 %cmp1, label %for.end, label %loop 188 189for.end: ; preds = %if.end, %entry 190 ret void 191} 192 193define void @test7(i64 %start, i64* %inc_ptr) { 194; CHECK-LABEL: @test7( 195; CHECK-NEXT: entry: 196; CHECK-NEXT: [[INC:%.*]] = load i64, i64* [[INC_PTR:%.*]], !range !0 197; CHECK-NEXT: [[OK:%.*]] = icmp sge i64 [[INC]], 0 198; CHECK-NEXT: br i1 [[OK]], label [[LOOP_PREHEADER:%.*]], label [[FOR_END:%.*]] 199; CHECK: loop.preheader: 200; CHECK-NEXT: br label [[LOOP:%.*]] 201; CHECK: loop: 202; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i64 [[START:%.*]], -1 203; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_END_LOOPEXIT:%.*]], label [[LOOP]] 204; CHECK: for.end.loopexit: 205; CHECK-NEXT: br label [[FOR_END]] 206; CHECK: for.end: 207; CHECK-NEXT: ret void 208; 209entry: 210 %inc = load i64, i64* %inc_ptr, !range !0 211 %ok = icmp sge i64 %inc, 0 212 br i1 %ok, label %loop, label %for.end 213 214loop: 215 %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ] 216 %indvars.iv.next = add nsw i64 %indvars.iv, %inc 217 %cmp1 = icmp slt i64 %indvars.iv, -1 218 br i1 %cmp1, label %for.end, label %loop 219 220for.end: ; preds = %if.end, %entry 221 ret void 222} 223 224; Negative test - we can't show that the internal branch executes, so we can't 225; fold the test to a loop invariant one. 226define void @test1_neg(i64 %start) { 227; CHECK-LABEL: @test1_neg( 228; CHECK-NEXT: entry: 229; CHECK-NEXT: br label [[LOOP:%.*]] 230; CHECK: loop: 231; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 232; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1 233; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], 25 234; CHECK-NEXT: br i1 [[CMP]], label [[BACKEDGE]], label [[SKIP:%.*]] 235; CHECK: skip: 236; CHECK-NEXT: call void @foo() 237; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i64 [[INDVARS_IV]], -1 238; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_END:%.*]], label [[BACKEDGE]] 239; CHECK: backedge: 240; CHECK-NEXT: call void @foo() 241; CHECK-NEXT: br label [[LOOP]] 242; CHECK: for.end: 243; CHECK-NEXT: ret void 244; 245entry: 246 br label %loop 247 248loop: 249 %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ] 250 %indvars.iv.next = add nsw i64 %indvars.iv, 1 251 %cmp = icmp eq i64 %indvars.iv.next, 25 252 br i1 %cmp, label %backedge, label %skip 253skip: 254 ; prevent flattening, needed to make sure we're testing what we intend 255 call void @foo() 256 %cmp1 = icmp slt i64 %indvars.iv, -1 257 br i1 %cmp1, label %for.end, label %backedge 258backedge: 259 ; prevent flattening, needed to make sure we're testing what we intend 260 call void @foo() 261 br label %loop 262 263for.end: ; preds = %if.end, %entry 264 ret void 265} 266 267; Slightly subtle version of @test4 where the icmp dominates the backedge, 268; but the exit branch doesn't. 269define void @test2_neg(i64 %start) { 270; CHECK-LABEL: @test2_neg( 271; CHECK-NEXT: entry: 272; CHECK-NEXT: br label [[LOOP:%.*]] 273; CHECK: loop: 274; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 275; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], 1 276; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], 25 277; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i64 [[INDVARS_IV]], -1 278; CHECK-NEXT: br i1 [[CMP]], label [[BACKEDGE]], label [[SKIP:%.*]] 279; CHECK: skip: 280; CHECK-NEXT: call void @foo() 281; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_END:%.*]], label [[BACKEDGE]] 282; CHECK: backedge: 283; CHECK-NEXT: call void @foo() 284; CHECK-NEXT: br label [[LOOP]] 285; CHECK: for.end: 286; CHECK-NEXT: ret void 287; 288entry: 289 br label %loop 290 291loop: 292 %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ] 293 %indvars.iv.next = add nsw i64 %indvars.iv, 1 294 %cmp = icmp eq i64 %indvars.iv.next, 25 295 %cmp1 = icmp slt i64 %indvars.iv, -1 296 br i1 %cmp, label %backedge, label %skip 297skip: 298 ; prevent flattening, needed to make sure we're testing what we intend 299 call void @foo() 300 br i1 %cmp1, label %for.end, label %backedge 301backedge: 302 ; prevent flattening, needed to make sure we're testing what we intend 303 call void @foo() 304 br label %loop 305 306for.end: ; preds = %if.end, %entry 307 ret void 308} 309 310; The branch has to exit the loop if the condition is true 311define void @test3_neg(i64 %start) { 312; CHECK-LABEL: @test3_neg( 313; CHECK-NEXT: entry: 314; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i64 [[START:%.*]], -1 315; CHECK-NEXT: [[SMAX:%.*]] = select i1 [[TMP0]], i64 [[START]], i64 -1 316; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[SMAX]], 1 317; CHECK-NEXT: br label [[LOOP:%.*]] 318; CHECK: loop: 319; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[START]], [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ] 320; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 1 321; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[TMP1]] 322; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[FOR_END:%.*]] 323; CHECK: for.end: 324; CHECK-NEXT: ret void 325; 326entry: 327 br label %loop 328 329loop: 330 %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ] 331 %indvars.iv.next = add nsw i64 %indvars.iv, 1 332 %cmp1 = icmp slt i64 %indvars.iv, -1 333 br i1 %cmp1, label %loop, label %for.end 334 335for.end: ; preds = %if.end, %entry 336 ret void 337} 338 339define void @test4_neg(i64 %start) { 340; CHECK-LABEL: @test4_neg( 341; CHECK-NEXT: entry: 342; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i64 [[START:%.*]], 0 343; CHECK-NEXT: [[SMAX:%.*]] = select i1 [[TMP0]], i64 [[START]], i64 0 344; CHECK-NEXT: [[TMP1:%.*]] = add nuw i64 [[SMAX]], 1 345; CHECK-NEXT: br label [[LOOP:%.*]] 346; CHECK: loop: 347; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[START]], [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 348; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 1 349; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], 25 350; CHECK-NEXT: br i1 [[CMP]], label [[BACKEDGE]], label [[FOR_END:%.*]] 351; CHECK: backedge: 352; CHECK-NEXT: call void @foo() 353; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], [[TMP1]] 354; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END]], label [[LOOP]] 355; CHECK: for.end: 356; CHECK-NEXT: ret void 357; 358entry: 359 br label %loop 360 361loop: 362 %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %backedge ] 363 %indvars.iv.next = add nsw i64 %indvars.iv, 1 364 %cmp = icmp eq i64 %indvars.iv.next, 25 365 br i1 %cmp, label %backedge, label %for.end 366 367backedge: 368 ; prevent flattening, needed to make sure we're testing what we intend 369 call void @foo() 370 %cmp1 = icmp sgt i64 %indvars.iv, -1 371 372; %cmp1 can be made loop invariant only if the branch below goes to 373; %the header when %cmp1 is true. 374 br i1 %cmp1, label %for.end, label %loop 375 376for.end: ; preds = %if.end, %entry 377 ret void 378} 379 380define void @test5_neg(i64 %start, i64 %inc) { 381; CHECK-LABEL: @test5_neg( 382; CHECK-NEXT: entry: 383; CHECK-NEXT: br label [[LOOP:%.*]] 384; CHECK: loop: 385; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ] 386; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], [[INC:%.*]] 387; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i64 [[INDVARS_IV]], -1 388; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_END:%.*]], label [[LOOP]] 389; CHECK: for.end: 390; CHECK-NEXT: ret void 391; 392entry: 393 br label %loop 394 395loop: 396 %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ] 397 %indvars.iv.next = add nsw i64 %indvars.iv, %inc 398 %cmp1 = icmp slt i64 %indvars.iv, -1 399 br i1 %cmp1, label %for.end, label %loop 400 401for.end: ; preds = %if.end, %entry 402 ret void 403} 404 405define void @test8(i64 %start, i64* %inc_ptr) { 406; CHECK-LABEL: @test8( 407; CHECK-NEXT: entry: 408; CHECK-NEXT: [[INC:%.*]] = load i64, i64* [[INC_PTR:%.*]], !range !1 409; CHECK-NEXT: [[OK:%.*]] = icmp sge i64 [[INC]], 0 410; CHECK-NEXT: br i1 [[OK]], label [[LOOP_PREHEADER:%.*]], label [[FOR_END:%.*]] 411; CHECK: loop.preheader: 412; CHECK-NEXT: br label [[LOOP:%.*]] 413; CHECK: loop: 414; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ], [ [[START:%.*]], [[LOOP_PREHEADER]] ] 415; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], [[INC]] 416; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i64 [[INDVARS_IV]], -1 417; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_END_LOOPEXIT:%.*]], label [[LOOP]] 418; CHECK: for.end.loopexit: 419; CHECK-NEXT: br label [[FOR_END]] 420; CHECK: for.end: 421; CHECK-NEXT: ret void 422; 423entry: 424 %inc = load i64, i64* %inc_ptr, !range !1 425 %ok = icmp sge i64 %inc, 0 426 br i1 %ok, label %loop, label %for.end 427 428loop: 429 %indvars.iv = phi i64 [ %start, %entry ], [ %indvars.iv.next, %loop ] 430 %indvars.iv.next = add nsw i64 %indvars.iv, %inc 431 %cmp1 = icmp slt i64 %indvars.iv, -1 432 br i1 %cmp1, label %for.end, label %loop 433 434for.end: ; preds = %if.end, %entry 435 ret void 436} 437 438; check to handle loops without preheaders, but invariant operands 439; (we handle this today by inserting a preheader) 440define void @test9(i1 %cnd, i64 %start) { 441; CHECK-LABEL: @test9( 442; CHECK-NEXT: entry: 443; CHECK-NEXT: br i1 [[CND:%.*]], label [[ENTRY1:%.*]], label [[ENTRY2:%.*]] 444; CHECK: entry1: 445; CHECK-NEXT: br label [[LOOP_PREHEADER:%.*]] 446; CHECK: entry2: 447; CHECK-NEXT: br label [[LOOP_PREHEADER]] 448; CHECK: loop.preheader: 449; CHECK-NEXT: br label [[LOOP:%.*]] 450; CHECK: loop: 451; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i64 [[START:%.*]], -1 452; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_END:%.*]], label [[LOOP]] 453; CHECK: for.end: 454; CHECK-NEXT: ret void 455; 456entry: 457 br i1 %cnd, label %entry1, label %entry2 458entry1: 459 br label %loop 460entry2: 461 br label %loop 462loop: 463 %indvars.iv = phi i64 [ %start, %entry1 ],[ %start, %entry2 ], [ %indvars.iv.next, %loop ] 464 %indvars.iv.next = add nsw i64 %indvars.iv, 1 465 %cmp1 = icmp slt i64 %indvars.iv, -1 466 br i1 %cmp1, label %for.end, label %loop 467 468for.end: ; preds = %if.end, %entry 469 ret void 470} 471 472declare void @use(i1 %x) 473 474; check that we handle conditions with loop invariant operands which 475; *aren't* in the header - this is a very rare and fragile case where 476; we have a "loop" which is known to run exactly one iteration but 477; haven't yet simplified the uses of the IV 478define void @test10() { 479; CHECK-LABEL: @test10( 480; CHECK-NEXT: entry: 481; CHECK-NEXT: br label [[LOOP:%.*]] 482; CHECK: loop: 483; CHECK-NEXT: [[PHI1:%.*]] = phi i32 [ [[PHI2:%.*]], [[LATCH:%.*]] ], [ 0, [[ENTRY:%.*]] ] 484; CHECK-NEXT: [[DEC:%.*]] = add nuw nsw i32 [[PHI1]], -1 485; CHECK-NEXT: br i1 false, label [[LEFT:%.*]], label [[RIGHT:%.*]] 486; CHECK: left: 487; CHECK-NEXT: br label [[LATCH]] 488; CHECK: right: 489; CHECK-NEXT: br label [[LATCH]] 490; CHECK: latch: 491; CHECK-NEXT: [[PHI2]] = phi i32 [ [[PHI1]], [[LEFT]] ], [ [[DEC]], [[RIGHT]] ] 492; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 -1, undef 493; CHECK-NEXT: br i1 true, label [[EXIT:%.*]], label [[LOOP]] 494; CHECK: exit: 495; CHECK-NEXT: [[CMP_LCSSA:%.*]] = phi i1 [ [[CMP]], [[LATCH]] ] 496; CHECK-NEXT: call void @use(i1 [[CMP_LCSSA]]) 497; CHECK-NEXT: ret void 498; 499entry: 500 br label %loop 501 502loop: 503 %phi1 = phi i32 [ %phi2, %latch ], [ 0, %entry ] 504 %dec = add i32 %phi1, -1 505 br i1 false, label %left, label %right 506 507left: 508 br label %latch 509 510right: 511 br label %latch 512 513latch: 514 %phi2 = phi i32 [ %phi1, %left ], [ %dec, %right ] 515 %cmp = icmp slt i32 %phi2, undef 516 br i1 true, label %exit, label %loop 517 518exit: 519 call void @use(i1 %cmp) 520 ret void 521} 522 523; check that we can figure out that iv.next > 1 from the facts that iv >= 0 and 524; iv.start != 0. 525define void @test11(i64* %inc_ptr) { 526; CHECK-LABEL: @test11( 527; CHECK-NEXT: entry: 528; CHECK-NEXT: [[INC:%.*]] = load i64, i64* [[INC_PTR:%.*]], !range !0 529; CHECK-NEXT: [[NE_COND:%.*]] = icmp ne i64 [[INC]], 0 530; CHECK-NEXT: br i1 [[NE_COND]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 531; CHECK: loop.preheader: 532; CHECK-NEXT: br label [[LOOP:%.*]] 533; CHECK: loop: 534; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[INC]], [[LOOP_PREHEADER]] ] 535; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 536; CHECK-NEXT: br i1 true, label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] 537; CHECK: if.true: 538; CHECK-NEXT: br label [[BACKEDGE]] 539; CHECK: if.false: 540; CHECK-NEXT: br label [[BACKEDGE]] 541; CHECK: backedge: 542; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], 201 543; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 544; CHECK: exit.loopexit: 545; CHECK-NEXT: br label [[EXIT]] 546; CHECK: exit: 547; CHECK-NEXT: ret void 548; 549entry: 550 %inc = load i64, i64* %inc_ptr, !range !0 551 %ne.cond = icmp ne i64 %inc, 0 552 br i1 %ne.cond, label %loop, label %exit 553 554loop: 555 %iv = phi i64 [ %inc, %entry ], [ %iv.next, %backedge ] 556 %iv.next = add i64 %iv, 1 557 %brcond = icmp sgt i64 %iv.next, 1 558 br i1 %brcond, label %if.true, label %if.false 559 560if.true: 561 br label %backedge 562 563if.false: 564 br label %backedge 565 566backedge: 567 %loopcond = icmp slt i64 %iv, 200 568 br i1 %loopcond, label %loop, label %exit 569 570exit: 571 ret void 572} 573 574; check that we can prove that a recurrency is greater than another recurrency 575; in the same loop, with the same step, and with smaller starting value. 576define void @test12(i64* %inc_ptr) { 577; CHECK-LABEL: @test12( 578; CHECK-NEXT: entry: 579; CHECK-NEXT: [[INC:%.*]] = load i64, i64* [[INC_PTR:%.*]], !range !0 580; CHECK-NEXT: br label [[LOOP:%.*]] 581; CHECK: loop: 582; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 583; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 584; CHECK-NEXT: br i1 true, label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] 585; CHECK: if.true: 586; CHECK-NEXT: br label [[BACKEDGE]] 587; CHECK: if.false: 588; CHECK-NEXT: br label [[BACKEDGE]] 589; CHECK: backedge: 590; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[IV_NEXT]], 201 591; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]] 592; CHECK: exit: 593; CHECK-NEXT: ret void 594; 595entry: 596 %inc = load i64, i64* %inc_ptr, !range !0 597 %inc.minus.1 = sub i64 %inc, 1 598 br label %loop 599 600loop: 601 %iv = phi i64 [ %inc, %entry ], [ %iv.next, %backedge ] 602 %iv.minus.1 = phi i64 [ %inc.minus.1, %entry ], [ %iv.minus.1.next, %backedge ] 603 %iv.next = add i64 %iv, 1 604 %iv.minus.1.next = add i64 %iv.minus.1, 1 605 %brcond = icmp sgt i64 %iv.next, %iv.minus.1.next 606 br i1 %brcond, label %if.true, label %if.false 607 608if.true: 609 br label %backedge 610 611if.false: 612 br label %backedge 613 614backedge: 615 %loopcond = icmp slt i64 %iv, 200 616 br i1 %loopcond, label %loop, label %exit 617 618exit: 619 ret void 620} 621 622!0 = !{i64 0, i64 100} 623!1 = !{i64 -1, i64 100} 624 625declare void @foo() 626