1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=indvars -S | FileCheck %s 3 4declare void @fail(i32) 5declare i1 @cond() 6declare i32 @switch.cond() 7declare i32 @llvm.smax.i32(i32 %a, i32 %b) 8 9; Unsigned comparison here is redundant and can be safely deleted. 10define i32 @trivial.case(i32* %len.ptr) { 11; CHECK-LABEL: @trivial.case( 12; CHECK-NEXT: entry: 13; CHECK-NEXT: [[LEN:%.*]] = load i32, i32* [[LEN_PTR:%.*]], align 4, !range [[RNG0:![0-9]+]] 14; CHECK-NEXT: br label [[PREHEADER:%.*]] 15; CHECK: preheader: 16; CHECK-NEXT: br label [[LOOP:%.*]] 17; CHECK: loop: 18; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 19; CHECK-NEXT: [[SIGNED_CMP:%.*]] = icmp ult i32 [[IV]], [[LEN]] 20; CHECK-NEXT: br i1 [[SIGNED_CMP]], label [[SIGNED_PASSED:%.*]], label [[FAILED_SIGNED:%.*]] 21; CHECK: signed.passed: 22; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[FAILED_SIGNED]] 23; CHECK: backedge: 24; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 25; CHECK-NEXT: [[COND:%.*]] = call i1 @cond() 26; CHECK-NEXT: br i1 [[COND]], label [[LOOP]], label [[DONE:%.*]] 27; CHECK: failed.signed: 28; CHECK-NEXT: call void @fail(i32 1) 29; CHECK-NEXT: unreachable 30; CHECK: failed.unsigned: 31; CHECK-NEXT: call void @fail(i32 2) 32; CHECK-NEXT: unreachable 33; CHECK: done: 34; CHECK-NEXT: [[IV_LCSSA1:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ] 35; CHECK-NEXT: ret i32 [[IV_LCSSA1]] 36; 37entry: 38 %len = load i32, i32* %len.ptr, !range !0 39 br label %preheader 40 41preheader: 42 br label %loop 43 44loop: 45 %iv = phi i32 [0, %preheader], [%iv.next, %backedge] 46 %signed.cmp = icmp slt i32 %iv, %len 47 br i1 %signed.cmp, label %signed.passed, label %failed.signed 48 49signed.passed: 50 %unsigned.cmp = icmp ult i32 %iv, %len 51 br i1 %unsigned.cmp, label %backedge, label %failed.signed 52 53backedge: 54 %iv.next = add i32 %iv, 1 55 %cond = call i1 @cond() 56 br i1 %cond, label %loop, label %done 57 58failed.signed: 59 call void @fail(i32 1) 60 unreachable 61 62failed.unsigned: 63 call void @fail(i32 2) 64 unreachable 65 66done: 67 ret i32 %iv 68} 69 70; TODO: We should be able to prove that: 71; - %sibling.iv.next is non-negative; 72; - therefore, %iv is non-negative; 73; - therefore, unsigned check can be removed. 74define i32 @start.from.sibling.iv(i32* %len.ptr, i32* %sibling.len.ptr) { 75; CHECK-LABEL: @start.from.sibling.iv( 76; CHECK-NEXT: entry: 77; CHECK-NEXT: [[LEN:%.*]] = load i32, i32* [[LEN_PTR:%.*]], align 4, !range [[RNG0]] 78; CHECK-NEXT: [[SIBLING_LEN:%.*]] = load i32, i32* [[SIBLING_LEN_PTR:%.*]], align 4, !range [[RNG0]] 79; CHECK-NEXT: br label [[SIBLING_LOOP:%.*]] 80; CHECK: sibling.loop: 81; CHECK-NEXT: [[SIBLING_IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[SIBLING_IV_NEXT:%.*]], [[SIBLING_BACKEDGE:%.*]] ] 82; CHECK-NEXT: [[SIBLING_RC:%.*]] = icmp ult i32 [[SIBLING_IV]], [[SIBLING_LEN]] 83; CHECK-NEXT: br i1 [[SIBLING_RC]], label [[SIBLING_BACKEDGE]], label [[FAILED_SIBLING:%.*]] 84; CHECK: sibling.backedge: 85; CHECK-NEXT: [[SIBLING_IV_NEXT]] = add nuw nsw i32 [[SIBLING_IV]], 1 86; CHECK-NEXT: [[SIBLING_COND:%.*]] = call i1 @cond() 87; CHECK-NEXT: br i1 [[SIBLING_COND]], label [[SIBLING_LOOP]], label [[PREHEADER:%.*]] 88; CHECK: preheader: 89; CHECK-NEXT: [[SIBLING_IV_NEXT_LCSSA:%.*]] = phi i32 [ [[SIBLING_IV_NEXT]], [[SIBLING_BACKEDGE]] ] 90; CHECK-NEXT: br label [[LOOP:%.*]] 91; CHECK: loop: 92; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[SIBLING_IV_NEXT_LCSSA]], [[PREHEADER]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 93; CHECK-NEXT: [[SIGNED_CMP:%.*]] = icmp slt i32 [[IV]], [[LEN]] 94; CHECK-NEXT: br i1 [[SIGNED_CMP]], label [[SIGNED_PASSED:%.*]], label [[FAILED_SIGNED:%.*]] 95; CHECK: signed.passed: 96; CHECK-NEXT: [[UNSIGNED_CMP:%.*]] = icmp ult i32 [[IV]], [[LEN]] 97; CHECK-NEXT: br i1 [[UNSIGNED_CMP]], label [[BACKEDGE]], label [[FAILED_SIGNED]] 98; CHECK: backedge: 99; CHECK-NEXT: [[IV_NEXT]] = add nuw i32 [[IV]], 1 100; CHECK-NEXT: [[COND:%.*]] = call i1 @cond() 101; CHECK-NEXT: br i1 [[COND]], label [[LOOP]], label [[DONE:%.*]] 102; CHECK: failed.signed: 103; CHECK-NEXT: call void @fail(i32 1) 104; CHECK-NEXT: unreachable 105; CHECK: failed.unsigned: 106; CHECK-NEXT: call void @fail(i32 2) 107; CHECK-NEXT: unreachable 108; CHECK: failed.sibling: 109; CHECK-NEXT: call void @fail(i32 3) 110; CHECK-NEXT: unreachable 111; CHECK: done: 112; CHECK-NEXT: [[IV_LCSSA1:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ] 113; CHECK-NEXT: ret i32 [[IV_LCSSA1]] 114; 115entry: 116 %len = load i32, i32* %len.ptr, !range !0 117 %sibling.len = load i32, i32* %sibling.len.ptr, !range !0 118 br label %sibling.loop 119 120sibling.loop: 121 %sibling.iv = phi i32 [0, %entry], [%sibling.iv.next, %sibling.backedge] 122 %sibling.rc = icmp ult i32 %sibling.iv, %sibling.len 123 br i1 %sibling.rc, label %sibling.backedge, label %failed.sibling 124 125sibling.backedge: 126 %sibling.iv.next = add nuw nsw i32 %sibling.iv, 1 127 %sibling.cond = call i1 @cond() 128 br i1 %sibling.cond, label %sibling.loop, label %preheader 129 130preheader: 131 br label %loop 132 133loop: 134 %iv = phi i32 [%sibling.iv.next, %preheader], [%iv.next, %backedge] 135 %signed.cmp = icmp slt i32 %iv, %len 136 br i1 %signed.cmp, label %signed.passed, label %failed.signed 137 138signed.passed: 139 %unsigned.cmp = icmp ult i32 %iv, %len 140 br i1 %unsigned.cmp, label %backedge, label %failed.signed 141 142backedge: 143 %iv.next = add i32 %iv, 1 144 %cond = call i1 @cond() 145 br i1 %cond, label %loop, label %done 146 147failed.signed: 148 call void @fail(i32 1) 149 unreachable 150 151failed.unsigned: 152 call void @fail(i32 2) 153 unreachable 154 155failed.sibling: 156 call void @fail(i32 3) 157 unreachable 158 159done: 160 ret i32 %iv 161} 162 163; Same as above, but the sibling loop is now wide. We can eliminate the unsigned comparison here. 164define i32 @start.from.sibling.iv.wide(i32* %len.ptr, i32* %sibling.len.ptr) { 165; CHECK-LABEL: @start.from.sibling.iv.wide( 166; CHECK-NEXT: entry: 167; CHECK-NEXT: [[LEN:%.*]] = load i32, i32* [[LEN_PTR:%.*]], align 4, !range [[RNG0]] 168; CHECK-NEXT: [[SIBLING_LEN:%.*]] = load i32, i32* [[SIBLING_LEN_PTR:%.*]], align 4, !range [[RNG0]] 169; CHECK-NEXT: [[SIBLING_LEN_WIDE:%.*]] = zext i32 [[SIBLING_LEN]] to i64 170; CHECK-NEXT: br label [[SIBLING_LOOP:%.*]] 171; CHECK: sibling.loop: 172; CHECK-NEXT: [[SIBLING_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[SIBLING_IV_NEXT:%.*]], [[SIBLING_BACKEDGE:%.*]] ] 173; CHECK-NEXT: [[SIBLING_RC:%.*]] = icmp ult i64 [[SIBLING_IV]], [[SIBLING_LEN_WIDE]] 174; CHECK-NEXT: br i1 [[SIBLING_RC]], label [[SIBLING_BACKEDGE]], label [[FAILED_SIBLING:%.*]] 175; CHECK: sibling.backedge: 176; CHECK-NEXT: [[SIBLING_IV_NEXT]] = add nuw nsw i64 [[SIBLING_IV]], 1 177; CHECK-NEXT: [[SIBLING_COND:%.*]] = call i1 @cond() 178; CHECK-NEXT: br i1 [[SIBLING_COND]], label [[SIBLING_LOOP]], label [[PREHEADER:%.*]] 179; CHECK: preheader: 180; CHECK-NEXT: [[SIBLING_IV_NEXT_LCSSA:%.*]] = phi i64 [ [[SIBLING_IV_NEXT]], [[SIBLING_BACKEDGE]] ] 181; CHECK-NEXT: [[SIBLING_IV_NEXT_TRUNC:%.*]] = trunc i64 [[SIBLING_IV_NEXT_LCSSA]] to i32 182; CHECK-NEXT: br label [[LOOP:%.*]] 183; CHECK: loop: 184; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[SIBLING_IV_NEXT_TRUNC]], [[PREHEADER]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 185; CHECK-NEXT: [[SIGNED_CMP:%.*]] = icmp ult i32 [[IV]], [[LEN]] 186; CHECK-NEXT: br i1 [[SIGNED_CMP]], label [[SIGNED_PASSED:%.*]], label [[FAILED_SIGNED:%.*]] 187; CHECK: signed.passed: 188; CHECK-NEXT: br i1 true, label [[BACKEDGE]], label [[FAILED_SIGNED]] 189; CHECK: backedge: 190; CHECK-NEXT: [[IV_NEXT]] = add nuw i32 [[IV]], 1 191; CHECK-NEXT: [[COND:%.*]] = call i1 @cond() 192; CHECK-NEXT: br i1 [[COND]], label [[LOOP]], label [[DONE:%.*]] 193; CHECK: failed.signed: 194; CHECK-NEXT: call void @fail(i32 1) 195; CHECK-NEXT: unreachable 196; CHECK: failed.unsigned: 197; CHECK-NEXT: call void @fail(i32 2) 198; CHECK-NEXT: unreachable 199; CHECK: failed.sibling: 200; CHECK-NEXT: call void @fail(i32 3) 201; CHECK-NEXT: unreachable 202; CHECK: done: 203; CHECK-NEXT: [[IV_LCSSA1:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ] 204; CHECK-NEXT: ret i32 [[IV_LCSSA1]] 205; 206entry: 207 %len = load i32, i32* %len.ptr, !range !0 208 %sibling.len = load i32, i32* %sibling.len.ptr, !range !0 209 %sibling.len.wide = zext i32 %sibling.len to i64 210 br label %sibling.loop 211 212sibling.loop: 213 %sibling.iv = phi i64 [0, %entry], [%sibling.iv.next, %sibling.backedge] 214 %sibling.rc = icmp ult i64 %sibling.iv, %sibling.len.wide 215 br i1 %sibling.rc, label %sibling.backedge, label %failed.sibling 216 217sibling.backedge: 218 %sibling.iv.next = add nuw nsw i64 %sibling.iv, 1 219 %sibling.cond = call i1 @cond() 220 br i1 %sibling.cond, label %sibling.loop, label %preheader 221 222preheader: 223 %sibling.iv.next.trunc = trunc i64 %sibling.iv.next to i32 224 br label %loop 225 226loop: 227 %iv = phi i32 [%sibling.iv.next.trunc, %preheader], [%iv.next, %backedge] 228 %signed.cmp = icmp slt i32 %iv, %len 229 br i1 %signed.cmp, label %signed.passed, label %failed.signed 230 231signed.passed: 232 %unsigned.cmp = icmp ult i32 %iv, %len 233 br i1 %unsigned.cmp, label %backedge, label %failed.signed 234 235backedge: 236 %iv.next = add i32 %iv, 1 237 %cond = call i1 @cond() 238 br i1 %cond, label %loop, label %done 239 240failed.signed: 241 call void @fail(i32 1) 242 unreachable 243 244failed.unsigned: 245 call void @fail(i32 2) 246 unreachable 247 248failed.sibling: 249 call void @fail(i32 3) 250 unreachable 251 252done: 253 ret i32 %iv 254} 255 256; Slightly more complex version of previous one (cycled phis). 257; TODO: remove unsigned comparison by proving non-negativity of iv.start. 258define i32 @start.from.sibling.iv.wide.cycled.phis(i32* %len.ptr, i32* %sibling.len.ptr) { 259; CHECK-LABEL: @start.from.sibling.iv.wide.cycled.phis( 260; CHECK-NEXT: entry: 261; CHECK-NEXT: [[LEN:%.*]] = load i32, i32* [[LEN_PTR:%.*]], align 4, !range [[RNG0]] 262; CHECK-NEXT: [[SIBLING_LEN:%.*]] = load i32, i32* [[SIBLING_LEN_PTR:%.*]], align 4, !range [[RNG0]] 263; CHECK-NEXT: [[SIBLING_LEN_WIDE:%.*]] = zext i32 [[SIBLING_LEN]] to i64 264; CHECK-NEXT: br label [[SIBLING_LOOP:%.*]] 265; CHECK: sibling.loop: 266; CHECK-NEXT: [[SIBLING_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[SIBLING_IV_NEXT:%.*]], [[SIBLING_BACKEDGE:%.*]] ] 267; CHECK-NEXT: [[SIBLING_RC:%.*]] = icmp ult i64 [[SIBLING_IV]], [[SIBLING_LEN_WIDE]] 268; CHECK-NEXT: br i1 [[SIBLING_RC]], label [[SIBLING_BACKEDGE]], label [[FAILED_SIBLING:%.*]] 269; CHECK: sibling.backedge: 270; CHECK-NEXT: [[SIBLING_IV_NEXT]] = add nuw nsw i64 [[SIBLING_IV]], 1 271; CHECK-NEXT: [[SIBLING_COND:%.*]] = call i1 @cond() 272; CHECK-NEXT: br i1 [[SIBLING_COND]], label [[SIBLING_LOOP]], label [[OUTER_LOOP_PREHEADER:%.*]] 273; CHECK: outer.loop.preheader: 274; CHECK-NEXT: [[SIBLING_IV_NEXT_LCSSA:%.*]] = phi i64 [ [[SIBLING_IV_NEXT]], [[SIBLING_BACKEDGE]] ] 275; CHECK-NEXT: [[SIBLING_IV_NEXT_TRUNC:%.*]] = trunc i64 [[SIBLING_IV_NEXT_LCSSA]] to i32 276; CHECK-NEXT: br label [[OUTER_LOOP:%.*]] 277; CHECK: outer.loop: 278; CHECK-NEXT: [[IV_START:%.*]] = phi i32 [ [[SIBLING_IV_NEXT_TRUNC]], [[OUTER_LOOP_PREHEADER]] ], [ [[IV_NEXT_LCSSA:%.*]], [[OUTER_LOOP_BACKEDGE:%.*]] ] 279; CHECK-NEXT: br label [[PREHEADER:%.*]] 280; CHECK: preheader: 281; CHECK-NEXT: br label [[LOOP:%.*]] 282; CHECK: loop: 283; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_START]], [[PREHEADER]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 284; CHECK-NEXT: [[SIGNED_CMP:%.*]] = icmp slt i32 [[IV]], [[LEN]] 285; CHECK-NEXT: br i1 [[SIGNED_CMP]], label [[SIGNED_PASSED:%.*]], label [[FAILED_SIGNED:%.*]] 286; CHECK: signed.passed: 287; CHECK-NEXT: [[UNSIGNED_CMP:%.*]] = icmp ult i32 [[IV]], [[LEN]] 288; CHECK-NEXT: br i1 [[UNSIGNED_CMP]], label [[BACKEDGE]], label [[FAILED_SIGNED]] 289; CHECK: backedge: 290; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 291; CHECK-NEXT: [[COND:%.*]] = call i1 @cond() 292; CHECK-NEXT: br i1 [[COND]], label [[LOOP]], label [[OUTER_LOOP_BACKEDGE]] 293; CHECK: outer.loop.backedge: 294; CHECK-NEXT: [[IV_NEXT_LCSSA]] = phi i32 [ [[IV_NEXT]], [[BACKEDGE]] ] 295; CHECK-NEXT: [[IV_LCSSA1:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ] 296; CHECK-NEXT: [[OUTER_COND:%.*]] = call i1 @cond() 297; CHECK-NEXT: br i1 [[OUTER_COND]], label [[OUTER_LOOP]], label [[DONE:%.*]] 298; CHECK: failed.signed: 299; CHECK-NEXT: call void @fail(i32 1) 300; CHECK-NEXT: unreachable 301; CHECK: failed.unsigned: 302; CHECK-NEXT: call void @fail(i32 2) 303; CHECK-NEXT: unreachable 304; CHECK: failed.sibling: 305; CHECK-NEXT: call void @fail(i32 3) 306; CHECK-NEXT: unreachable 307; CHECK: done: 308; CHECK-NEXT: [[IV_LCSSA1_LCSSA:%.*]] = phi i32 [ [[IV_LCSSA1]], [[OUTER_LOOP_BACKEDGE]] ] 309; CHECK-NEXT: ret i32 [[IV_LCSSA1_LCSSA]] 310; 311entry: 312 %len = load i32, i32* %len.ptr, !range !0 313 %sibling.len = load i32, i32* %sibling.len.ptr, !range !0 314 %sibling.len.wide = zext i32 %sibling.len to i64 315 br label %sibling.loop 316 317sibling.loop: 318 %sibling.iv = phi i64 [0, %entry], [%sibling.iv.next, %sibling.backedge] 319 %sibling.rc = icmp ult i64 %sibling.iv, %sibling.len.wide 320 br i1 %sibling.rc, label %sibling.backedge, label %failed.sibling 321 322sibling.backedge: 323 %sibling.iv.next = add nuw nsw i64 %sibling.iv, 1 324 %sibling.cond = call i1 @cond() 325 br i1 %sibling.cond, label %sibling.loop, label %outer.loop.preheader 326 327outer.loop.preheader: 328 %sibling.iv.next.trunc = trunc i64 %sibling.iv.next to i32 329 br label %outer.loop 330 331outer.loop: 332 %iv.start = phi i32 [%sibling.iv.next.trunc, %outer.loop.preheader], [%iv.next, %outer.loop.backedge] 333 br label %preheader 334 335preheader: 336 br label %loop 337 338loop: 339 %iv = phi i32 [%iv.start, %preheader], [%iv.next, %backedge] 340 %signed.cmp = icmp slt i32 %iv, %len 341 br i1 %signed.cmp, label %signed.passed, label %failed.signed 342 343signed.passed: 344 %unsigned.cmp = icmp ult i32 %iv, %len 345 br i1 %unsigned.cmp, label %backedge, label %failed.signed 346 347backedge: 348 %iv.next = add i32 %iv, 1 349 %cond = call i1 @cond() 350 br i1 %cond, label %loop, label %outer.loop.backedge 351 352 353outer.loop.backedge: 354 %outer.cond = call i1 @cond() 355 br i1 %outer.cond, label %outer.loop, label %done 356 357failed.signed: 358 call void @fail(i32 1) 359 unreachable 360 361failed.unsigned: 362 call void @fail(i32 2) 363 unreachable 364 365failed.sibling: 366 call void @fail(i32 3) 367 unreachable 368 369done: 370 ret i32 %iv 371} 372 373 374; Even more complex version of previous one (more sophisticated cycled phis). 375; TODO: remove unsigned comparison by proving non-negativity of iv.start. 376define i32 @start.from.sibling.iv.wide.cycled.phis.complex.phis(i32* %len.ptr, i32* %sibling.len.ptr, i32 %some.random.value) { 377; CHECK-LABEL: @start.from.sibling.iv.wide.cycled.phis.complex.phis( 378; CHECK-NEXT: entry: 379; CHECK-NEXT: [[LEN:%.*]] = load i32, i32* [[LEN_PTR:%.*]], align 4, !range [[RNG0]] 380; CHECK-NEXT: [[SIBLING_LEN:%.*]] = load i32, i32* [[SIBLING_LEN_PTR:%.*]], align 4, !range [[RNG0]] 381; CHECK-NEXT: [[SIBLING_LEN_WIDE:%.*]] = zext i32 [[SIBLING_LEN]] to i64 382; CHECK-NEXT: br label [[SIBLING_LOOP:%.*]] 383; CHECK: sibling.loop: 384; CHECK-NEXT: [[SIBLING_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[SIBLING_IV_NEXT:%.*]], [[SIBLING_BACKEDGE:%.*]] ] 385; CHECK-NEXT: [[SIBLING_RC:%.*]] = icmp ult i64 [[SIBLING_IV]], [[SIBLING_LEN_WIDE]] 386; CHECK-NEXT: br i1 [[SIBLING_RC]], label [[SIBLING_BACKEDGE]], label [[FAILED_SIBLING:%.*]] 387; CHECK: sibling.backedge: 388; CHECK-NEXT: [[SIBLING_IV_NEXT]] = add nuw nsw i64 [[SIBLING_IV]], 1 389; CHECK-NEXT: [[SIBLING_COND:%.*]] = call i1 @cond() 390; CHECK-NEXT: br i1 [[SIBLING_COND]], label [[SIBLING_LOOP]], label [[OUTER_LOOP_PREHEADER:%.*]] 391; CHECK: outer.loop.preheader: 392; CHECK-NEXT: [[SIBLING_IV_NEXT_LCSSA:%.*]] = phi i64 [ [[SIBLING_IV_NEXT]], [[SIBLING_BACKEDGE]] ] 393; CHECK-NEXT: [[SIBLING_IV_NEXT_TRUNC:%.*]] = trunc i64 [[SIBLING_IV_NEXT_LCSSA]] to i32 394; CHECK-NEXT: br label [[OUTER_LOOP:%.*]] 395; CHECK: outer.loop: 396; CHECK-NEXT: [[IV_START:%.*]] = phi i32 [ [[SIBLING_IV_NEXT_TRUNC]], [[OUTER_LOOP_PREHEADER]] ], [ [[IV_START_UPDATED:%.*]], [[OUTER_LOOP_BACKEDGE:%.*]] ] 397; CHECK-NEXT: br label [[PREHEADER:%.*]] 398; CHECK: preheader: 399; CHECK-NEXT: br label [[LOOP:%.*]] 400; CHECK: loop: 401; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_START]], [[PREHEADER]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] 402; CHECK-NEXT: [[SIGNED_CMP:%.*]] = icmp slt i32 [[IV]], [[LEN]] 403; CHECK-NEXT: br i1 [[SIGNED_CMP]], label [[SIGNED_PASSED:%.*]], label [[FAILED_SIGNED:%.*]] 404; CHECK: signed.passed: 405; CHECK-NEXT: [[UNSIGNED_CMP:%.*]] = icmp ult i32 [[IV]], [[LEN]] 406; CHECK-NEXT: br i1 [[UNSIGNED_CMP]], label [[BACKEDGE]], label [[FAILED_SIGNED]] 407; CHECK: backedge: 408; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1 409; CHECK-NEXT: [[COND:%.*]] = call i1 @cond() 410; CHECK-NEXT: br i1 [[COND]], label [[LOOP]], label [[OUTER_LOOP_SELECTION:%.*]] 411; CHECK: outer.loop.selection: 412; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[BACKEDGE]] ] 413; CHECK-NEXT: [[IV_LCSSA1:%.*]] = phi i32 [ [[IV]], [[BACKEDGE]] ] 414; CHECK-NEXT: [[SWITCH_COND:%.*]] = call i32 @switch.cond() 415; CHECK-NEXT: switch i32 [[SWITCH_COND]], label [[TAKE_SAME:%.*]] [ 416; CHECK-NEXT: i32 1, label [[TAKE_INCREMENT:%.*]] 417; CHECK-NEXT: i32 2, label [[TAKE_SMAX:%.*]] 418; CHECK-NEXT: ] 419; CHECK: take.same: 420; CHECK-NEXT: br label [[OUTER_LOOP_BACKEDGE]] 421; CHECK: take.increment: 422; CHECK-NEXT: br label [[OUTER_LOOP_BACKEDGE]] 423; CHECK: take.smax: 424; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[IV_START]], i32 [[SOME_RANDOM_VALUE:%.*]]) 425; CHECK-NEXT: br label [[OUTER_LOOP_BACKEDGE]] 426; CHECK: outer.loop.backedge: 427; CHECK-NEXT: [[IV_START_UPDATED]] = phi i32 [ [[IV_START]], [[TAKE_SAME]] ], [ [[IV_NEXT_LCSSA]], [[TAKE_INCREMENT]] ], [ [[SMAX]], [[TAKE_SMAX]] ] 428; CHECK-NEXT: [[OUTER_COND:%.*]] = call i1 @cond() 429; CHECK-NEXT: br i1 [[OUTER_COND]], label [[OUTER_LOOP]], label [[DONE:%.*]] 430; CHECK: failed.signed: 431; CHECK-NEXT: call void @fail(i32 1) 432; CHECK-NEXT: unreachable 433; CHECK: failed.unsigned: 434; CHECK-NEXT: call void @fail(i32 2) 435; CHECK-NEXT: unreachable 436; CHECK: failed.sibling: 437; CHECK-NEXT: call void @fail(i32 3) 438; CHECK-NEXT: unreachable 439; CHECK: done: 440; CHECK-NEXT: [[IV_LCSSA1_LCSSA:%.*]] = phi i32 [ [[IV_LCSSA1]], [[OUTER_LOOP_BACKEDGE]] ] 441; CHECK-NEXT: ret i32 [[IV_LCSSA1_LCSSA]] 442; 443entry: 444 %len = load i32, i32* %len.ptr, !range !0 445 %sibling.len = load i32, i32* %sibling.len.ptr, !range !0 446 %sibling.len.wide = zext i32 %sibling.len to i64 447 br label %sibling.loop 448 449sibling.loop: 450 %sibling.iv = phi i64 [0, %entry], [%sibling.iv.next, %sibling.backedge] 451 %sibling.rc = icmp ult i64 %sibling.iv, %sibling.len.wide 452 br i1 %sibling.rc, label %sibling.backedge, label %failed.sibling 453 454sibling.backedge: 455 %sibling.iv.next = add nuw nsw i64 %sibling.iv, 1 456 %sibling.cond = call i1 @cond() 457 br i1 %sibling.cond, label %sibling.loop, label %outer.loop.preheader 458 459outer.loop.preheader: 460 %sibling.iv.next.trunc = trunc i64 %sibling.iv.next to i32 461 br label %outer.loop 462 463outer.loop: 464 %iv.start = phi i32 [%sibling.iv.next.trunc, %outer.loop.preheader], [%iv.start.updated, %outer.loop.backedge] 465 br label %preheader 466 467preheader: 468 br label %loop 469 470loop: 471 %iv = phi i32 [%iv.start, %preheader], [%iv.next, %backedge] 472 %signed.cmp = icmp slt i32 %iv, %len 473 br i1 %signed.cmp, label %signed.passed, label %failed.signed 474 475signed.passed: 476 %unsigned.cmp = icmp ult i32 %iv, %len 477 br i1 %unsigned.cmp, label %backedge, label %failed.signed 478 479backedge: 480 %iv.next = add i32 %iv, 1 481 %cond = call i1 @cond() 482 br i1 %cond, label %loop, label %outer.loop.selection 483 484outer.loop.selection: 485 %switch.cond = call i32 @switch.cond() 486 switch i32 %switch.cond, label %take.same 487 [ 488 i32 1, label %take.increment 489 i32 2, label %take.smax 490 ] 491 492take.same: 493 br label %outer.loop.backedge 494 495take.increment: 496 br label %outer.loop.backedge 497 498take.smax: 499 %smax = call i32 @llvm.smax.i32(i32 %iv.start, i32 %some.random.value) 500 br label %outer.loop.backedge 501 502outer.loop.backedge: 503 %iv.start.updated = phi i32 [%iv.start, %take.same], 504 [%iv.next, %take.increment], 505 [%smax, %take.smax] 506 %outer.cond = call i1 @cond() 507 br i1 %outer.cond, label %outer.loop, label %done 508 509failed.signed: 510 call void @fail(i32 1) 511 unreachable 512 513failed.unsigned: 514 call void @fail(i32 2) 515 unreachable 516 517failed.sibling: 518 call void @fail(i32 3) 519 unreachable 520 521done: 522 ret i32 %iv 523} 524 525!0 = !{ i32 0, i32 2147483646 } 526