1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -indvars -S | FileCheck %s 3; RUN: opt < %s -passes=indvars -S | FileCheck %s 4 5declare i1 @cond() 6declare i32 @llvm.smax.i32(i32, i32) 7 8; FIXME: In all tests in this file, signed_cond is equivalent to unsigned_cond, and therefore 9; one of the checks in the inner loop can be removed. The key to proving it is to prove that 10; %iv starts from something that is non-negative and only goes up. The positivity of its start 11; follows from the fact that %outer.iv also starts from somethign non-negative and only goes 12; up or remains same between iterations. 13define i32 @test_01(i32 %a, i32 %b) { 14; CHECK-LABEL: @test_01( 15; CHECK-NEXT: entry: 16; CHECK-NEXT: [[B_IS_NON_NEGATIVE:%.*]] = icmp sge i32 [[B:%.*]], 0 17; CHECK-NEXT: br i1 [[B_IS_NON_NEGATIVE]], label [[OUTER_PREHEADER:%.*]], label [[FAILURE:%.*]] 18; CHECK: outer.preheader: 19; CHECK-NEXT: br label [[OUTER:%.*]] 20; CHECK: outer: 21; CHECK-NEXT: [[OUTER_IV:%.*]] = phi i32 [ [[IV_NEXT_LCSSA:%.*]], [[OUTER_BACKEDGE:%.*]] ], [ 0, [[OUTER_PREHEADER]] ] 22; CHECK-NEXT: br label [[INNER:%.*]] 23; CHECK: inner: 24; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[OUTER_IV]], [[OUTER]] ], [ [[IV_NEXT:%.*]], [[INNER_BACKEDGE:%.*]] ] 25; CHECK-NEXT: [[SIGNED_COND:%.*]] = icmp slt i32 [[IV]], [[B]] 26; CHECK-NEXT: br i1 [[SIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]] 27; CHECK: inner.1: 28; CHECK-NEXT: [[UNSIGNED_COND:%.*]] = icmp ult i32 [[IV]], [[B]] 29; CHECK-NEXT: br i1 [[UNSIGNED_COND]], label [[INNER_BACKEDGE]], label [[SIDE_EXIT]] 30; CHECK: inner.backedge: 31; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 32; CHECK-NEXT: [[INNER_LOOP_COND:%.*]] = call i1 @cond() 33; CHECK-NEXT: br i1 [[INNER_LOOP_COND]], label [[INNER]], label [[OUTER_BACKEDGE]] 34; CHECK: outer.backedge: 35; CHECK-NEXT: [[IV_NEXT_LCSSA]] = phi i32 [ [[IV_NEXT]], [[INNER_BACKEDGE]] ] 36; CHECK-NEXT: [[OUTER_LOOP_COND:%.*]] = call i1 @cond() 37; CHECK-NEXT: br i1 [[OUTER_LOOP_COND]], label [[OUTER]], label [[EXIT:%.*]] 38; CHECK: failure: 39; CHECK-NEXT: unreachable 40; CHECK: side.exit: 41; CHECK-NEXT: ret i32 0 42; CHECK: exit: 43; CHECK-NEXT: ret i32 1 44; 45entry: 46 %b_is_non_negative = icmp sge i32 %b, 0 47 br i1 %b_is_non_negative, label %outer, label %failure 48 49outer: 50 %outer.iv = phi i32 [0, %entry], [%iv.next, %outer.backedge] 51 br label %inner 52 53 54inner: 55 %iv = phi i32 [%outer.iv, %outer], [%iv.next, %inner.backedge] 56 %signed_cond = icmp slt i32 %iv, %b 57 br i1 %signed_cond, label %inner.1, label %side.exit 58 59inner.1: 60 %unsigned_cond = icmp ult i32 %iv, %b 61 br i1 %unsigned_cond, label %inner.backedge, label %side.exit 62 63inner.backedge: 64 %iv.next = add nuw nsw i32 %iv, 1 65 %inner.loop.cond = call i1 @cond() 66 br i1 %inner.loop.cond, label %inner, label %outer.backedge 67 68outer.backedge: 69 %outer.loop.cond = call i1 @cond() 70 br i1 %outer.loop.cond, label %outer, label %exit 71 72failure: 73 unreachable 74 75side.exit: 76 ret i32 0 77 78exit: 79 ret i32 1 80} 81 82; FIXME: iv <u b, b >=s 0 --> iv <s b. We should be able to remove the 2nd check. 83define i32 @test_01a(i32 %a, i32 %b) { 84; CHECK-LABEL: @test_01a( 85; CHECK-NEXT: entry: 86; CHECK-NEXT: [[B_IS_NON_NEGATIVE:%.*]] = icmp sge i32 [[B:%.*]], 0 87; CHECK-NEXT: br i1 [[B_IS_NON_NEGATIVE]], label [[OUTER_PREHEADER:%.*]], label [[FAILURE:%.*]] 88; CHECK: outer.preheader: 89; CHECK-NEXT: br label [[OUTER:%.*]] 90; CHECK: outer: 91; CHECK-NEXT: [[OUTER_IV:%.*]] = phi i32 [ [[IV_NEXT_LCSSA:%.*]], [[OUTER_BACKEDGE:%.*]] ], [ 0, [[OUTER_PREHEADER]] ] 92; CHECK-NEXT: br label [[INNER:%.*]] 93; CHECK: inner: 94; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[OUTER_IV]], [[OUTER]] ], [ [[IV_NEXT:%.*]], [[INNER_BACKEDGE:%.*]] ] 95; CHECK-NEXT: [[SIGNED_COND:%.*]] = icmp ult i32 [[IV]], [[B]] 96; CHECK-NEXT: br i1 [[SIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]] 97; CHECK: inner.1: 98; CHECK-NEXT: [[UNSIGNED_COND:%.*]] = icmp slt i32 [[IV]], [[B]] 99; CHECK-NEXT: br i1 [[UNSIGNED_COND]], label [[INNER_BACKEDGE]], label [[SIDE_EXIT]] 100; CHECK: inner.backedge: 101; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 102; CHECK-NEXT: [[INNER_LOOP_COND:%.*]] = call i1 @cond() 103; CHECK-NEXT: br i1 [[INNER_LOOP_COND]], label [[INNER]], label [[OUTER_BACKEDGE]] 104; CHECK: outer.backedge: 105; CHECK-NEXT: [[IV_NEXT_LCSSA]] = phi i32 [ [[IV_NEXT]], [[INNER_BACKEDGE]] ] 106; CHECK-NEXT: [[OUTER_LOOP_COND:%.*]] = call i1 @cond() 107; CHECK-NEXT: br i1 [[OUTER_LOOP_COND]], label [[OUTER]], label [[EXIT:%.*]] 108; CHECK: failure: 109; CHECK-NEXT: unreachable 110; CHECK: side.exit: 111; CHECK-NEXT: ret i32 0 112; CHECK: exit: 113; CHECK-NEXT: ret i32 1 114; 115entry: 116 %b_is_non_negative = icmp sge i32 %b, 0 117 br i1 %b_is_non_negative, label %outer, label %failure 118 119outer: 120 %outer.iv = phi i32 [0, %entry], [%iv.next, %outer.backedge] 121 br label %inner 122 123 124inner: 125 %iv = phi i32 [%outer.iv, %outer], [%iv.next, %inner.backedge] 126 %signed_cond = icmp ult i32 %iv, %b 127 br i1 %signed_cond, label %inner.1, label %side.exit 128 129inner.1: 130 %unsigned_cond = icmp slt i32 %iv, %b 131 br i1 %unsigned_cond, label %inner.backedge, label %side.exit 132 133inner.backedge: 134 %iv.next = add nuw nsw i32 %iv, 1 135 %inner.loop.cond = call i1 @cond() 136 br i1 %inner.loop.cond, label %inner, label %outer.backedge 137 138outer.backedge: 139 %outer.loop.cond = call i1 @cond() 140 br i1 %outer.loop.cond, label %outer, label %exit 141 142failure: 143 unreachable 144 145side.exit: 146 ret i32 0 147 148exit: 149 ret i32 1 150} 151 152define i32 @test_02(i32 %a, i32 %b) { 153; CHECK-LABEL: @test_02( 154; CHECK-NEXT: entry: 155; CHECK-NEXT: [[B_IS_NON_NEGATIVE:%.*]] = icmp sge i32 [[B:%.*]], 0 156; CHECK-NEXT: br i1 [[B_IS_NON_NEGATIVE]], label [[OUTER_PREHEADER:%.*]], label [[FAILURE:%.*]] 157; CHECK: outer.preheader: 158; CHECK-NEXT: br label [[OUTER:%.*]] 159; CHECK: outer: 160; CHECK-NEXT: [[OUTER_IV:%.*]] = phi i32 [ [[OUTER_MERGE:%.*]], [[OUTER_BACKEDGE:%.*]] ], [ 0, [[OUTER_PREHEADER]] ] 161; CHECK-NEXT: br label [[INNER:%.*]] 162; CHECK: inner: 163; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[OUTER_IV]], [[OUTER]] ], [ [[IV_NEXT:%.*]], [[INNER_BACKEDGE:%.*]] ] 164; CHECK-NEXT: [[SIGNED_COND:%.*]] = icmp slt i32 [[IV]], [[B]] 165; CHECK-NEXT: br i1 [[SIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]] 166; CHECK: inner.1: 167; CHECK-NEXT: [[UNSIGNED_COND:%.*]] = icmp ult i32 [[IV]], [[B]] 168; CHECK-NEXT: br i1 [[UNSIGNED_COND]], label [[INNER_BACKEDGE]], label [[SIDE_EXIT]] 169; CHECK: inner.backedge: 170; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 171; CHECK-NEXT: [[INNER_LOOP_COND:%.*]] = call i1 @cond() 172; CHECK-NEXT: br i1 [[INNER_LOOP_COND]], label [[INNER]], label [[OUTER_BACKEDGE]] 173; CHECK: outer.backedge: 174; CHECK-NEXT: [[OUTER_MERGE]] = phi i32 [ [[IV_NEXT]], [[INNER_BACKEDGE]] ] 175; CHECK-NEXT: [[OUTER_LOOP_COND:%.*]] = call i1 @cond() 176; CHECK-NEXT: br i1 [[OUTER_LOOP_COND]], label [[OUTER]], label [[EXIT:%.*]] 177; CHECK: failure: 178; CHECK-NEXT: unreachable 179; CHECK: side.exit: 180; CHECK-NEXT: ret i32 0 181; CHECK: exit: 182; CHECK-NEXT: ret i32 1 183; 184entry: 185 %b_is_non_negative = icmp sge i32 %b, 0 186 br i1 %b_is_non_negative, label %outer, label %failure 187 188outer: 189 %outer.iv = phi i32 [0, %entry], [%outer.merge, %outer.backedge] 190 br label %inner 191 192 193inner: 194 %iv = phi i32 [%outer.iv, %outer], [%iv.next, %inner.backedge] 195 %signed_cond = icmp slt i32 %iv, %b 196 br i1 %signed_cond, label %inner.1, label %side.exit 197 198inner.1: 199 %unsigned_cond = icmp ult i32 %iv, %b 200 br i1 %unsigned_cond, label %inner.backedge, label %side.exit 201 202inner.backedge: 203 %iv.next = add nuw nsw i32 %iv, 1 204 %inner.loop.cond = call i1 @cond() 205 br i1 %inner.loop.cond, label %inner, label %outer.backedge 206 207outer.backedge: 208 %outer.merge = phi i32 [%iv.next, %inner.backedge] 209 %outer.loop.cond = call i1 @cond() 210 br i1 %outer.loop.cond, label %outer, label %exit 211 212failure: 213 unreachable 214 215side.exit: 216 ret i32 0 217 218exit: 219 ret i32 1 220} 221 222define i32 @test_03(i32 %a, i32 %b) { 223; CHECK-LABEL: @test_03( 224; CHECK-NEXT: entry: 225; CHECK-NEXT: [[B_IS_NON_NEGATIVE:%.*]] = icmp sge i32 [[B:%.*]], 0 226; CHECK-NEXT: br i1 [[B_IS_NON_NEGATIVE]], label [[OUTER_PREHEADER:%.*]], label [[FAILURE:%.*]] 227; CHECK: outer.preheader: 228; CHECK-NEXT: br label [[OUTER:%.*]] 229; CHECK: outer: 230; CHECK-NEXT: [[OUTER_IV:%.*]] = phi i32 [ [[OUTER_MERGE:%.*]], [[OUTER_BACKEDGE:%.*]] ], [ 0, [[OUTER_PREHEADER]] ] 231; CHECK-NEXT: [[OUTER_COND_1:%.*]] = call i1 @cond() 232; CHECK-NEXT: br i1 [[OUTER_COND_1]], label [[INNER_PREHEADER:%.*]], label [[NO_INNER:%.*]] 233; CHECK: inner.preheader: 234; CHECK-NEXT: br label [[INNER:%.*]] 235; CHECK: no_inner: 236; CHECK-NEXT: [[OUTER_COND_2:%.*]] = call i1 @cond() 237; CHECK-NEXT: br label [[OUTER_BACKEDGE]] 238; CHECK: inner: 239; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[INNER_BACKEDGE:%.*]] ], [ [[OUTER_IV]], [[INNER_PREHEADER]] ] 240; CHECK-NEXT: [[SIGNED_COND:%.*]] = icmp slt i32 [[IV]], [[B]] 241; CHECK-NEXT: br i1 [[SIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]] 242; CHECK: inner.1: 243; CHECK-NEXT: [[UNSIGNED_COND:%.*]] = icmp ult i32 [[IV]], [[B]] 244; CHECK-NEXT: br i1 [[UNSIGNED_COND]], label [[INNER_BACKEDGE]], label [[SIDE_EXIT]] 245; CHECK: inner.backedge: 246; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 247; CHECK-NEXT: [[INNER_LOOP_COND:%.*]] = call i1 @cond() 248; CHECK-NEXT: br i1 [[INNER_LOOP_COND]], label [[INNER]], label [[OUTER_BACKEDGE_LOOPEXIT:%.*]] 249; CHECK: outer.backedge.loopexit: 250; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[INNER_BACKEDGE]] ] 251; CHECK-NEXT: br label [[OUTER_BACKEDGE]] 252; CHECK: outer.backedge: 253; CHECK-NEXT: [[OUTER_MERGE]] = phi i32 [ [[OUTER_IV]], [[NO_INNER]] ], [ [[IV_NEXT_LCSSA]], [[OUTER_BACKEDGE_LOOPEXIT]] ] 254; CHECK-NEXT: [[OUTER_LOOP_COND:%.*]] = call i1 @cond() 255; CHECK-NEXT: br i1 [[OUTER_LOOP_COND]], label [[OUTER]], label [[EXIT:%.*]] 256; CHECK: failure: 257; CHECK-NEXT: unreachable 258; CHECK: side.exit: 259; CHECK-NEXT: ret i32 0 260; CHECK: exit: 261; CHECK-NEXT: ret i32 1 262; 263entry: 264 %b_is_non_negative = icmp sge i32 %b, 0 265 br i1 %b_is_non_negative, label %outer, label %failure 266 267outer: 268 %outer.iv = phi i32 [0, %entry], [%outer.merge, %outer.backedge] 269 %outer_cond_1 = call i1 @cond() 270 br i1 %outer_cond_1, label %inner, label %no_inner 271 272no_inner: 273 %outer_cond_2 = call i1 @cond() 274 br label %outer.backedge 275 276inner: 277 %iv = phi i32 [%outer.iv, %outer], [%iv.next, %inner.backedge] 278 %signed_cond = icmp slt i32 %iv, %b 279 br i1 %signed_cond, label %inner.1, label %side.exit 280 281inner.1: 282 %unsigned_cond = icmp ult i32 %iv, %b 283 br i1 %unsigned_cond, label %inner.backedge, label %side.exit 284 285inner.backedge: 286 %iv.next = add nuw nsw i32 %iv, 1 287 %inner.loop.cond = call i1 @cond() 288 br i1 %inner.loop.cond, label %inner, label %outer.backedge 289 290outer.backedge: 291 %outer.merge = phi i32 [%outer.iv, %no_inner], [%iv.next, %inner.backedge] 292 %outer.loop.cond = call i1 @cond() 293 br i1 %outer.loop.cond, label %outer, label %exit 294 295failure: 296 unreachable 297 298side.exit: 299 ret i32 0 300 301exit: 302 ret i32 1 303} 304 305define i32 @test_04(i32 %a, i32 %b) { 306; CHECK-LABEL: @test_04( 307; CHECK-NEXT: entry: 308; CHECK-NEXT: [[B_IS_NON_NEGATIVE:%.*]] = icmp sge i32 [[B:%.*]], 0 309; CHECK-NEXT: br i1 [[B_IS_NON_NEGATIVE]], label [[OUTER_PREHEADER:%.*]], label [[FAILURE:%.*]] 310; CHECK: outer.preheader: 311; CHECK-NEXT: br label [[OUTER:%.*]] 312; CHECK: outer: 313; CHECK-NEXT: [[OUTER_IV:%.*]] = phi i32 [ [[OUTER_MERGE:%.*]], [[OUTER_BACKEDGE:%.*]] ], [ 0, [[OUTER_PREHEADER]] ] 314; CHECK-NEXT: [[OUTER_COND_1:%.*]] = call i1 @cond() 315; CHECK-NEXT: br i1 [[OUTER_COND_1]], label [[INNER_PREHEADER:%.*]], label [[NO_INNER:%.*]] 316; CHECK: inner.preheader: 317; CHECK-NEXT: br label [[INNER:%.*]] 318; CHECK: no_inner: 319; CHECK-NEXT: [[OUTER_COND_2:%.*]] = call i1 @cond() 320; CHECK-NEXT: br i1 [[OUTER_COND_2]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] 321; CHECK: if.true: 322; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[A:%.*]], i32 [[OUTER_IV]]) 323; CHECK-NEXT: br label [[OUTER_BACKEDGE]] 324; CHECK: if.false: 325; CHECK-NEXT: br label [[OUTER_BACKEDGE]] 326; CHECK: inner: 327; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[INNER_BACKEDGE:%.*]] ], [ [[OUTER_IV]], [[INNER_PREHEADER]] ] 328; CHECK-NEXT: [[SIGNED_COND:%.*]] = icmp slt i32 [[IV]], [[B]] 329; CHECK-NEXT: br i1 [[SIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]] 330; CHECK: inner.1: 331; CHECK-NEXT: [[UNSIGNED_COND:%.*]] = icmp ult i32 [[IV]], [[B]] 332; CHECK-NEXT: br i1 [[UNSIGNED_COND]], label [[INNER_BACKEDGE]], label [[SIDE_EXIT]] 333; CHECK: inner.backedge: 334; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 335; CHECK-NEXT: [[INNER_LOOP_COND:%.*]] = call i1 @cond() 336; CHECK-NEXT: br i1 [[INNER_LOOP_COND]], label [[INNER]], label [[OUTER_BACKEDGE_LOOPEXIT:%.*]] 337; CHECK: outer.backedge.loopexit: 338; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[INNER_BACKEDGE]] ] 339; CHECK-NEXT: br label [[OUTER_BACKEDGE]] 340; CHECK: outer.backedge: 341; CHECK-NEXT: [[OUTER_MERGE]] = phi i32 [ [[SMAX]], [[IF_TRUE]] ], [ [[OUTER_IV]], [[IF_FALSE]] ], [ [[IV_NEXT_LCSSA]], [[OUTER_BACKEDGE_LOOPEXIT]] ] 342; CHECK-NEXT: [[OUTER_LOOP_COND:%.*]] = call i1 @cond() 343; CHECK-NEXT: br i1 [[OUTER_LOOP_COND]], label [[OUTER]], label [[EXIT:%.*]] 344; CHECK: failure: 345; CHECK-NEXT: unreachable 346; CHECK: side.exit: 347; CHECK-NEXT: ret i32 0 348; CHECK: exit: 349; CHECK-NEXT: ret i32 1 350; 351entry: 352 %b_is_non_negative = icmp sge i32 %b, 0 353 br i1 %b_is_non_negative, label %outer, label %failure 354 355outer: 356 %outer.iv = phi i32 [0, %entry], [%outer.merge, %outer.backedge] 357 %outer_cond_1 = call i1 @cond() 358 br i1 %outer_cond_1, label %inner, label %no_inner 359 360no_inner: 361 %outer_cond_2 = call i1 @cond() 362 br i1 %outer_cond_2, label %if.true, label %if.false 363 364if.true: 365 %smax = call i32 @llvm.smax.i32(i32 %a, i32 %outer.iv) 366 br label %outer.backedge 367 368if.false: 369 br label %outer.backedge 370 371inner: 372 %iv = phi i32 [%outer.iv, %outer], [%iv.next, %inner.backedge] 373 %signed_cond = icmp slt i32 %iv, %b 374 br i1 %signed_cond, label %inner.1, label %side.exit 375 376inner.1: 377 %unsigned_cond = icmp ult i32 %iv, %b 378 br i1 %unsigned_cond, label %inner.backedge, label %side.exit 379 380inner.backedge: 381 %iv.next = add nuw nsw i32 %iv, 1 382 %inner.loop.cond = call i1 @cond() 383 br i1 %inner.loop.cond, label %inner, label %outer.backedge 384 385outer.backedge: 386 %outer.merge = phi i32 [%smax, %if.true], [%outer.iv, %if.false], [%iv.next, %inner.backedge] 387 %outer.loop.cond = call i1 @cond() 388 br i1 %outer.loop.cond, label %outer, label %exit 389 390failure: 391 unreachable 392 393side.exit: 394 ret i32 0 395 396exit: 397 ret i32 1 398} 399 400; Same as test_01, but non-negativity of %b is known without context. 401; FIXME: We can remove 2nd check in loop. 402define i32 @test_05(i32 %a, i32* %bp) { 403; CHECK-LABEL: @test_05( 404; CHECK-NEXT: entry: 405; CHECK-NEXT: [[B:%.*]] = load i32, i32* [[BP:%.*]], align 4, !range [[RNG0:![0-9]+]] 406; CHECK-NEXT: br label [[OUTER:%.*]] 407; CHECK: outer: 408; CHECK-NEXT: [[OUTER_IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA:%.*]], [[OUTER_BACKEDGE:%.*]] ] 409; CHECK-NEXT: br label [[INNER:%.*]] 410; CHECK: inner: 411; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[OUTER_IV]], [[OUTER]] ], [ [[IV_NEXT:%.*]], [[INNER_BACKEDGE:%.*]] ] 412; CHECK-NEXT: [[SIGNED_COND:%.*]] = icmp slt i32 [[IV]], [[B]] 413; CHECK-NEXT: br i1 [[SIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]] 414; CHECK: inner.1: 415; CHECK-NEXT: [[UNSIGNED_COND:%.*]] = icmp ult i32 [[IV]], [[B]] 416; CHECK-NEXT: br i1 [[UNSIGNED_COND]], label [[INNER_BACKEDGE]], label [[SIDE_EXIT]] 417; CHECK: inner.backedge: 418; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 419; CHECK-NEXT: [[INNER_LOOP_COND:%.*]] = call i1 @cond() 420; CHECK-NEXT: br i1 [[INNER_LOOP_COND]], label [[INNER]], label [[OUTER_BACKEDGE]] 421; CHECK: outer.backedge: 422; CHECK-NEXT: [[IV_NEXT_LCSSA]] = phi i32 [ [[IV_NEXT]], [[INNER_BACKEDGE]] ] 423; CHECK-NEXT: [[OUTER_LOOP_COND:%.*]] = call i1 @cond() 424; CHECK-NEXT: br i1 [[OUTER_LOOP_COND]], label [[OUTER]], label [[EXIT:%.*]] 425; CHECK: side.exit: 426; CHECK-NEXT: ret i32 0 427; CHECK: exit: 428; CHECK-NEXT: ret i32 1 429; 430entry: 431 %b = load i32, i32* %bp, !range !0 432 br label %outer 433 434outer: 435 %outer.iv = phi i32 [0, %entry], [%iv.next, %outer.backedge] 436 br label %inner 437 438 439inner: 440 %iv = phi i32 [%outer.iv, %outer], [%iv.next, %inner.backedge] 441 %signed_cond = icmp slt i32 %iv, %b 442 br i1 %signed_cond, label %inner.1, label %side.exit 443 444inner.1: 445 %unsigned_cond = icmp ult i32 %iv, %b 446 br i1 %unsigned_cond, label %inner.backedge, label %side.exit 447 448inner.backedge: 449 %iv.next = add nuw nsw i32 %iv, 1 450 %inner.loop.cond = call i1 @cond() 451 br i1 %inner.loop.cond, label %inner, label %outer.backedge 452 453outer.backedge: 454 %outer.loop.cond = call i1 @cond() 455 br i1 %outer.loop.cond, label %outer, label %exit 456 457side.exit: 458 ret i32 0 459 460exit: 461 ret i32 1 462} 463 464 465; Same as test_01a, but non-negativity of %b is known without context. 466; FIXME: We can remove 2nd check in loop. 467define i32 @test_05a(i32 %a, i32* %bp) { 468; CHECK-LABEL: @test_05a( 469; CHECK-NEXT: entry: 470; CHECK-NEXT: [[B:%.*]] = load i32, i32* [[BP:%.*]], align 4, !range [[RNG0]] 471; CHECK-NEXT: br label [[OUTER:%.*]] 472; CHECK: outer: 473; CHECK-NEXT: [[OUTER_IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA:%.*]], [[OUTER_BACKEDGE:%.*]] ] 474; CHECK-NEXT: br label [[INNER:%.*]] 475; CHECK: inner: 476; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[OUTER_IV]], [[OUTER]] ], [ [[IV_NEXT:%.*]], [[INNER_BACKEDGE:%.*]] ] 477; CHECK-NEXT: [[UNSIGNED_COND:%.*]] = icmp ult i32 [[IV]], [[B]] 478; CHECK-NEXT: br i1 [[UNSIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]] 479; CHECK: inner.1: 480; CHECK-NEXT: [[SIGNED_COND:%.*]] = icmp slt i32 [[IV]], [[B]] 481; CHECK-NEXT: br i1 [[SIGNED_COND]], label [[INNER_BACKEDGE]], label [[SIDE_EXIT]] 482; CHECK: inner.backedge: 483; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 484; CHECK-NEXT: [[INNER_LOOP_COND:%.*]] = call i1 @cond() 485; CHECK-NEXT: br i1 [[INNER_LOOP_COND]], label [[INNER]], label [[OUTER_BACKEDGE]] 486; CHECK: outer.backedge: 487; CHECK-NEXT: [[IV_NEXT_LCSSA]] = phi i32 [ [[IV_NEXT]], [[INNER_BACKEDGE]] ] 488; CHECK-NEXT: [[OUTER_LOOP_COND:%.*]] = call i1 @cond() 489; CHECK-NEXT: br i1 [[OUTER_LOOP_COND]], label [[OUTER]], label [[EXIT:%.*]] 490; CHECK: side.exit: 491; CHECK-NEXT: ret i32 0 492; CHECK: exit: 493; CHECK-NEXT: ret i32 1 494; 495entry: 496 %b = load i32, i32* %bp, !range !0 497 br label %outer 498 499outer: 500 %outer.iv = phi i32 [0, %entry], [%iv.next, %outer.backedge] 501 br label %inner 502 503 504inner: 505 %iv = phi i32 [%outer.iv, %outer], [%iv.next, %inner.backedge] 506 %unsigned_cond = icmp ult i32 %iv, %b 507 br i1 %unsigned_cond, label %inner.1, label %side.exit 508 509inner.1: 510 %signed_cond = icmp slt i32 %iv, %b 511 br i1 %signed_cond, label %inner.backedge, label %side.exit 512 513inner.backedge: 514 %iv.next = add nuw nsw i32 %iv, 1 515 %inner.loop.cond = call i1 @cond() 516 br i1 %inner.loop.cond, label %inner, label %outer.backedge 517 518outer.backedge: 519 %outer.loop.cond = call i1 @cond() 520 br i1 %outer.loop.cond, label %outer, label %exit 521 522side.exit: 523 ret i32 0 524 525exit: 526 ret i32 1 527} 528 529; Similar to test_05a, but inverted 2nd condition. 530; FIXME: We can remove 2nd check in loop. 531define i32 @test_05b(i32 %a, i32* %bp) { 532; CHECK-LABEL: @test_05b( 533; CHECK-NEXT: entry: 534; CHECK-NEXT: [[B:%.*]] = load i32, i32* [[BP:%.*]], align 4, !range [[RNG0]] 535; CHECK-NEXT: br label [[OUTER:%.*]] 536; CHECK: outer: 537; CHECK-NEXT: [[OUTER_IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA:%.*]], [[OUTER_BACKEDGE:%.*]] ] 538; CHECK-NEXT: br label [[INNER:%.*]] 539; CHECK: inner: 540; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[OUTER_IV]], [[OUTER]] ], [ [[IV_NEXT:%.*]], [[INNER_BACKEDGE:%.*]] ] 541; CHECK-NEXT: [[UNSIGNED_COND:%.*]] = icmp ult i32 [[IV]], [[B]] 542; CHECK-NEXT: br i1 [[UNSIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]] 543; CHECK: inner.1: 544; CHECK-NEXT: [[SIGNED_COND:%.*]] = icmp sgt i32 [[B]], [[IV]] 545; CHECK-NEXT: br i1 [[SIGNED_COND]], label [[INNER_BACKEDGE]], label [[SIDE_EXIT]] 546; CHECK: inner.backedge: 547; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 548; CHECK-NEXT: [[INNER_LOOP_COND:%.*]] = call i1 @cond() 549; CHECK-NEXT: br i1 [[INNER_LOOP_COND]], label [[INNER]], label [[OUTER_BACKEDGE]] 550; CHECK: outer.backedge: 551; CHECK-NEXT: [[IV_NEXT_LCSSA]] = phi i32 [ [[IV_NEXT]], [[INNER_BACKEDGE]] ] 552; CHECK-NEXT: [[OUTER_LOOP_COND:%.*]] = call i1 @cond() 553; CHECK-NEXT: br i1 [[OUTER_LOOP_COND]], label [[OUTER]], label [[EXIT:%.*]] 554; CHECK: side.exit: 555; CHECK-NEXT: ret i32 0 556; CHECK: exit: 557; CHECK-NEXT: ret i32 1 558; 559entry: 560 %b = load i32, i32* %bp, !range !0 561 br label %outer 562 563outer: 564 %outer.iv = phi i32 [0, %entry], [%iv.next, %outer.backedge] 565 br label %inner 566 567 568inner: 569 %iv = phi i32 [%outer.iv, %outer], [%iv.next, %inner.backedge] 570 %unsigned_cond = icmp ult i32 %iv, %b 571 br i1 %unsigned_cond, label %inner.1, label %side.exit 572 573inner.1: 574 %signed_cond = icmp sgt i32 %b, %iv 575 br i1 %signed_cond, label %inner.backedge, label %side.exit 576 577inner.backedge: 578 %iv.next = add nuw nsw i32 %iv, 1 579 %inner.loop.cond = call i1 @cond() 580 br i1 %inner.loop.cond, label %inner, label %outer.backedge 581 582outer.backedge: 583 %outer.loop.cond = call i1 @cond() 584 br i1 %outer.loop.cond, label %outer, label %exit 585 586side.exit: 587 ret i32 0 588 589exit: 590 ret i32 1 591} 592 593; We should prove implication: iv <s b, b <s 0 => iv <u b. 594; FIXME: Can remove 2nd check 595define i32 @test_05c(i32 %a, i32* %bp) { 596; CHECK-LABEL: @test_05c( 597; CHECK-NEXT: entry: 598; CHECK-NEXT: [[B:%.*]] = load i32, i32* [[BP:%.*]], align 4, !range [[RNG1:![0-9]+]] 599; CHECK-NEXT: br label [[OUTER:%.*]] 600; CHECK: outer: 601; CHECK-NEXT: [[OUTER_IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA:%.*]], [[OUTER_BACKEDGE:%.*]] ] 602; CHECK-NEXT: br label [[INNER:%.*]] 603; CHECK: inner: 604; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[OUTER_IV]], [[OUTER]] ], [ [[IV_NEXT:%.*]], [[INNER_BACKEDGE:%.*]] ] 605; CHECK-NEXT: [[SIGNED_COND:%.*]] = icmp slt i32 [[IV]], [[B]] 606; CHECK-NEXT: br i1 [[SIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]] 607; CHECK: inner.1: 608; CHECK-NEXT: [[UNSIGNED_COND:%.*]] = icmp ult i32 [[IV]], [[B]] 609; CHECK-NEXT: br i1 [[UNSIGNED_COND]], label [[INNER_BACKEDGE]], label [[SIDE_EXIT]] 610; CHECK: inner.backedge: 611; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 612; CHECK-NEXT: [[INNER_LOOP_COND:%.*]] = call i1 @cond() 613; CHECK-NEXT: br i1 [[INNER_LOOP_COND]], label [[INNER]], label [[OUTER_BACKEDGE]] 614; CHECK: outer.backedge: 615; CHECK-NEXT: [[IV_NEXT_LCSSA]] = phi i32 [ [[IV_NEXT]], [[INNER_BACKEDGE]] ] 616; CHECK-NEXT: [[OUTER_LOOP_COND:%.*]] = call i1 @cond() 617; CHECK-NEXT: br i1 [[OUTER_LOOP_COND]], label [[OUTER]], label [[EXIT:%.*]] 618; CHECK: side.exit: 619; CHECK-NEXT: ret i32 0 620; CHECK: exit: 621; CHECK-NEXT: ret i32 1 622; 623entry: 624 %b = load i32, i32* %bp, !range !1 625 br label %outer 626 627outer: 628 %outer.iv = phi i32 [0, %entry], [%iv.next, %outer.backedge] 629 br label %inner 630 631 632inner: 633 %iv = phi i32 [%outer.iv, %outer], [%iv.next, %inner.backedge] 634 %signed_cond = icmp slt i32 %iv, %b 635 br i1 %signed_cond, label %inner.1, label %side.exit 636 637inner.1: 638 %unsigned_cond = icmp ult i32 %iv, %b 639 br i1 %unsigned_cond, label %inner.backedge, label %side.exit 640 641inner.backedge: 642 %iv.next = add nuw nsw i32 %iv, 1 643 %inner.loop.cond = call i1 @cond() 644 br i1 %inner.loop.cond, label %inner, label %outer.backedge 645 646outer.backedge: 647 %outer.loop.cond = call i1 @cond() 648 br i1 %outer.loop.cond, label %outer, label %exit 649 650side.exit: 651 ret i32 0 652 653exit: 654 ret i32 1 655} 656 657; Same as test_05c, but 2nd condition reversed. 658; FIXME: Can remove 2nd check 659define i32 @test_05d(i32 %a, i32* %bp) { 660; CHECK-LABEL: @test_05d( 661; CHECK-NEXT: entry: 662; CHECK-NEXT: [[B:%.*]] = load i32, i32* [[BP:%.*]], align 4, !range [[RNG1]] 663; CHECK-NEXT: br label [[OUTER:%.*]] 664; CHECK: outer: 665; CHECK-NEXT: [[OUTER_IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA:%.*]], [[OUTER_BACKEDGE:%.*]] ] 666; CHECK-NEXT: br label [[INNER:%.*]] 667; CHECK: inner: 668; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[OUTER_IV]], [[OUTER]] ], [ [[IV_NEXT:%.*]], [[INNER_BACKEDGE:%.*]] ] 669; CHECK-NEXT: [[SIGNED_COND:%.*]] = icmp slt i32 [[IV]], [[B]] 670; CHECK-NEXT: br i1 [[SIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]] 671; CHECK: inner.1: 672; CHECK-NEXT: [[UNSIGNED_COND:%.*]] = icmp ugt i32 [[B]], [[IV]] 673; CHECK-NEXT: br i1 [[UNSIGNED_COND]], label [[INNER_BACKEDGE]], label [[SIDE_EXIT]] 674; CHECK: inner.backedge: 675; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 676; CHECK-NEXT: [[INNER_LOOP_COND:%.*]] = call i1 @cond() 677; CHECK-NEXT: br i1 [[INNER_LOOP_COND]], label [[INNER]], label [[OUTER_BACKEDGE]] 678; CHECK: outer.backedge: 679; CHECK-NEXT: [[IV_NEXT_LCSSA]] = phi i32 [ [[IV_NEXT]], [[INNER_BACKEDGE]] ] 680; CHECK-NEXT: [[OUTER_LOOP_COND:%.*]] = call i1 @cond() 681; CHECK-NEXT: br i1 [[OUTER_LOOP_COND]], label [[OUTER]], label [[EXIT:%.*]] 682; CHECK: side.exit: 683; CHECK-NEXT: ret i32 0 684; CHECK: exit: 685; CHECK-NEXT: ret i32 1 686; 687entry: 688 %b = load i32, i32* %bp, !range !1 689 br label %outer 690 691outer: 692 %outer.iv = phi i32 [0, %entry], [%iv.next, %outer.backedge] 693 br label %inner 694 695 696inner: 697 %iv = phi i32 [%outer.iv, %outer], [%iv.next, %inner.backedge] 698 %signed_cond = icmp slt i32 %iv, %b 699 br i1 %signed_cond, label %inner.1, label %side.exit 700 701inner.1: 702 %unsigned_cond = icmp ugt i32 %b, %iv 703 br i1 %unsigned_cond, label %inner.backedge, label %side.exit 704 705inner.backedge: 706 %iv.next = add nuw nsw i32 %iv, 1 707 %inner.loop.cond = call i1 @cond() 708 br i1 %inner.loop.cond, label %inner, label %outer.backedge 709 710outer.backedge: 711 %outer.loop.cond = call i1 @cond() 712 br i1 %outer.loop.cond, label %outer, label %exit 713 714side.exit: 715 ret i32 0 716 717exit: 718 ret i32 1 719} 720 721 722; Same as test_05a, but 1st condition inverted. 723; FIXME: We can remove 2nd check in loop. 724define i32 @test_05e(i32 %a, i32* %bp) { 725; CHECK-LABEL: @test_05e( 726; CHECK-NEXT: entry: 727; CHECK-NEXT: [[B:%.*]] = load i32, i32* [[BP:%.*]], align 4, !range [[RNG0]] 728; CHECK-NEXT: br label [[OUTER:%.*]] 729; CHECK: outer: 730; CHECK-NEXT: [[OUTER_IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA:%.*]], [[OUTER_BACKEDGE:%.*]] ] 731; CHECK-NEXT: br label [[INNER:%.*]] 732; CHECK: inner: 733; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[OUTER_IV]], [[OUTER]] ], [ [[IV_NEXT:%.*]], [[INNER_BACKEDGE:%.*]] ] 734; CHECK-NEXT: [[UNSIGNED_COND:%.*]] = icmp ugt i32 [[B]], [[IV]] 735; CHECK-NEXT: br i1 [[UNSIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]] 736; CHECK: inner.1: 737; CHECK-NEXT: [[SIGNED_COND:%.*]] = icmp slt i32 [[IV]], [[B]] 738; CHECK-NEXT: br i1 [[SIGNED_COND]], label [[INNER_BACKEDGE]], label [[SIDE_EXIT]] 739; CHECK: inner.backedge: 740; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 741; CHECK-NEXT: [[INNER_LOOP_COND:%.*]] = call i1 @cond() 742; CHECK-NEXT: br i1 [[INNER_LOOP_COND]], label [[INNER]], label [[OUTER_BACKEDGE]] 743; CHECK: outer.backedge: 744; CHECK-NEXT: [[IV_NEXT_LCSSA]] = phi i32 [ [[IV_NEXT]], [[INNER_BACKEDGE]] ] 745; CHECK-NEXT: [[OUTER_LOOP_COND:%.*]] = call i1 @cond() 746; CHECK-NEXT: br i1 [[OUTER_LOOP_COND]], label [[OUTER]], label [[EXIT:%.*]] 747; CHECK: side.exit: 748; CHECK-NEXT: ret i32 0 749; CHECK: exit: 750; CHECK-NEXT: ret i32 1 751; 752entry: 753 %b = load i32, i32* %bp, !range !0 754 br label %outer 755 756outer: 757 %outer.iv = phi i32 [0, %entry], [%iv.next, %outer.backedge] 758 br label %inner 759 760 761inner: 762 %iv = phi i32 [%outer.iv, %outer], [%iv.next, %inner.backedge] 763 %unsigned_cond = icmp ugt i32 %b, %iv 764 br i1 %unsigned_cond, label %inner.1, label %side.exit 765 766inner.1: 767 %signed_cond = icmp slt i32 %iv, %b 768 br i1 %signed_cond, label %inner.backedge, label %side.exit 769 770inner.backedge: 771 %iv.next = add nuw nsw i32 %iv, 1 772 %inner.loop.cond = call i1 @cond() 773 br i1 %inner.loop.cond, label %inner, label %outer.backedge 774 775outer.backedge: 776 %outer.loop.cond = call i1 @cond() 777 br i1 %outer.loop.cond, label %outer, label %exit 778 779side.exit: 780 ret i32 0 781 782exit: 783 ret i32 1 784} 785 786; Same as test_05b, but 1st condition inverted. 787; FIXME: We can remove 2nd check in loop. 788define i32 @test_05f(i32 %a, i32* %bp) { 789; CHECK-LABEL: @test_05f( 790; CHECK-NEXT: entry: 791; CHECK-NEXT: [[B:%.*]] = load i32, i32* [[BP:%.*]], align 4, !range [[RNG0]] 792; CHECK-NEXT: br label [[OUTER:%.*]] 793; CHECK: outer: 794; CHECK-NEXT: [[OUTER_IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA:%.*]], [[OUTER_BACKEDGE:%.*]] ] 795; CHECK-NEXT: br label [[INNER:%.*]] 796; CHECK: inner: 797; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[OUTER_IV]], [[OUTER]] ], [ [[IV_NEXT:%.*]], [[INNER_BACKEDGE:%.*]] ] 798; CHECK-NEXT: [[UNSIGNED_COND:%.*]] = icmp ugt i32 [[B]], [[IV]] 799; CHECK-NEXT: br i1 [[UNSIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]] 800; CHECK: inner.1: 801; CHECK-NEXT: [[SIGNED_COND:%.*]] = icmp sgt i32 [[B]], [[IV]] 802; CHECK-NEXT: br i1 [[SIGNED_COND]], label [[INNER_BACKEDGE]], label [[SIDE_EXIT]] 803; CHECK: inner.backedge: 804; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 805; CHECK-NEXT: [[INNER_LOOP_COND:%.*]] = call i1 @cond() 806; CHECK-NEXT: br i1 [[INNER_LOOP_COND]], label [[INNER]], label [[OUTER_BACKEDGE]] 807; CHECK: outer.backedge: 808; CHECK-NEXT: [[IV_NEXT_LCSSA]] = phi i32 [ [[IV_NEXT]], [[INNER_BACKEDGE]] ] 809; CHECK-NEXT: [[OUTER_LOOP_COND:%.*]] = call i1 @cond() 810; CHECK-NEXT: br i1 [[OUTER_LOOP_COND]], label [[OUTER]], label [[EXIT:%.*]] 811; CHECK: side.exit: 812; CHECK-NEXT: ret i32 0 813; CHECK: exit: 814; CHECK-NEXT: ret i32 1 815; 816entry: 817 %b = load i32, i32* %bp, !range !0 818 br label %outer 819 820outer: 821 %outer.iv = phi i32 [0, %entry], [%iv.next, %outer.backedge] 822 br label %inner 823 824 825inner: 826 %iv = phi i32 [%outer.iv, %outer], [%iv.next, %inner.backedge] 827 %unsigned_cond = icmp ugt i32 %b, %iv 828 br i1 %unsigned_cond, label %inner.1, label %side.exit 829 830inner.1: 831 %signed_cond = icmp sgt i32 %b, %iv 832 br i1 %signed_cond, label %inner.backedge, label %side.exit 833 834inner.backedge: 835 %iv.next = add nuw nsw i32 %iv, 1 836 %inner.loop.cond = call i1 @cond() 837 br i1 %inner.loop.cond, label %inner, label %outer.backedge 838 839outer.backedge: 840 %outer.loop.cond = call i1 @cond() 841 br i1 %outer.loop.cond, label %outer, label %exit 842 843side.exit: 844 ret i32 0 845 846exit: 847 ret i32 1 848} 849 850; Same as test_05c, but 1st condition inverted. 851; FIXME: We can remove 2nd check in loop. 852define i32 @test_05g(i32 %a, i32* %bp) { 853; CHECK-LABEL: @test_05g( 854; CHECK-NEXT: entry: 855; CHECK-NEXT: [[B:%.*]] = load i32, i32* [[BP:%.*]], align 4, !range [[RNG1]] 856; CHECK-NEXT: br label [[OUTER:%.*]] 857; CHECK: outer: 858; CHECK-NEXT: [[OUTER_IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA:%.*]], [[OUTER_BACKEDGE:%.*]] ] 859; CHECK-NEXT: br label [[INNER:%.*]] 860; CHECK: inner: 861; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[OUTER_IV]], [[OUTER]] ], [ [[IV_NEXT:%.*]], [[INNER_BACKEDGE:%.*]] ] 862; CHECK-NEXT: [[SIGNED_COND:%.*]] = icmp sgt i32 [[B]], [[IV]] 863; CHECK-NEXT: br i1 [[SIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]] 864; CHECK: inner.1: 865; CHECK-NEXT: [[UNSIGNED_COND:%.*]] = icmp ult i32 [[IV]], [[B]] 866; CHECK-NEXT: br i1 [[UNSIGNED_COND]], label [[INNER_BACKEDGE]], label [[SIDE_EXIT]] 867; CHECK: inner.backedge: 868; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 869; CHECK-NEXT: [[INNER_LOOP_COND:%.*]] = call i1 @cond() 870; CHECK-NEXT: br i1 [[INNER_LOOP_COND]], label [[INNER]], label [[OUTER_BACKEDGE]] 871; CHECK: outer.backedge: 872; CHECK-NEXT: [[IV_NEXT_LCSSA]] = phi i32 [ [[IV_NEXT]], [[INNER_BACKEDGE]] ] 873; CHECK-NEXT: [[OUTER_LOOP_COND:%.*]] = call i1 @cond() 874; CHECK-NEXT: br i1 [[OUTER_LOOP_COND]], label [[OUTER]], label [[EXIT:%.*]] 875; CHECK: side.exit: 876; CHECK-NEXT: ret i32 0 877; CHECK: exit: 878; CHECK-NEXT: ret i32 1 879; 880entry: 881 %b = load i32, i32* %bp, !range !1 882 br label %outer 883 884outer: 885 %outer.iv = phi i32 [0, %entry], [%iv.next, %outer.backedge] 886 br label %inner 887 888 889inner: 890 %iv = phi i32 [%outer.iv, %outer], [%iv.next, %inner.backedge] 891 %signed_cond = icmp sgt i32 %b, %iv 892 br i1 %signed_cond, label %inner.1, label %side.exit 893 894inner.1: 895 %unsigned_cond = icmp ult i32 %iv, %b 896 br i1 %unsigned_cond, label %inner.backedge, label %side.exit 897 898inner.backedge: 899 %iv.next = add nuw nsw i32 %iv, 1 900 %inner.loop.cond = call i1 @cond() 901 br i1 %inner.loop.cond, label %inner, label %outer.backedge 902 903outer.backedge: 904 %outer.loop.cond = call i1 @cond() 905 br i1 %outer.loop.cond, label %outer, label %exit 906 907side.exit: 908 ret i32 0 909 910exit: 911 ret i32 1 912} 913 914; Same as test_05d, but 1st condition inverted. 915; FIXME: We can remove 2nd check in loop. 916define i32 @test_05h(i32 %a, i32* %bp) { 917; CHECK-LABEL: @test_05h( 918; CHECK-NEXT: entry: 919; CHECK-NEXT: [[B:%.*]] = load i32, i32* [[BP:%.*]], align 4, !range [[RNG1]] 920; CHECK-NEXT: br label [[OUTER:%.*]] 921; CHECK: outer: 922; CHECK-NEXT: [[OUTER_IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT_LCSSA:%.*]], [[OUTER_BACKEDGE:%.*]] ] 923; CHECK-NEXT: br label [[INNER:%.*]] 924; CHECK: inner: 925; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[OUTER_IV]], [[OUTER]] ], [ [[IV_NEXT:%.*]], [[INNER_BACKEDGE:%.*]] ] 926; CHECK-NEXT: [[SIGNED_COND:%.*]] = icmp sgt i32 [[B]], [[IV]] 927; CHECK-NEXT: br i1 [[SIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]] 928; CHECK: inner.1: 929; CHECK-NEXT: [[UNSIGNED_COND:%.*]] = icmp ugt i32 [[B]], [[IV]] 930; CHECK-NEXT: br i1 [[UNSIGNED_COND]], label [[INNER_BACKEDGE]], label [[SIDE_EXIT]] 931; CHECK: inner.backedge: 932; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 933; CHECK-NEXT: [[INNER_LOOP_COND:%.*]] = call i1 @cond() 934; CHECK-NEXT: br i1 [[INNER_LOOP_COND]], label [[INNER]], label [[OUTER_BACKEDGE]] 935; CHECK: outer.backedge: 936; CHECK-NEXT: [[IV_NEXT_LCSSA]] = phi i32 [ [[IV_NEXT]], [[INNER_BACKEDGE]] ] 937; CHECK-NEXT: [[OUTER_LOOP_COND:%.*]] = call i1 @cond() 938; CHECK-NEXT: br i1 [[OUTER_LOOP_COND]], label [[OUTER]], label [[EXIT:%.*]] 939; CHECK: side.exit: 940; CHECK-NEXT: ret i32 0 941; CHECK: exit: 942; CHECK-NEXT: ret i32 1 943; 944entry: 945 %b = load i32, i32* %bp, !range !1 946 br label %outer 947 948outer: 949 %outer.iv = phi i32 [0, %entry], [%iv.next, %outer.backedge] 950 br label %inner 951 952 953inner: 954 %iv = phi i32 [%outer.iv, %outer], [%iv.next, %inner.backedge] 955 %signed_cond = icmp sgt i32 %b, %iv 956 br i1 %signed_cond, label %inner.1, label %side.exit 957 958inner.1: 959 %unsigned_cond = icmp ugt i32 %b, %iv 960 br i1 %unsigned_cond, label %inner.backedge, label %side.exit 961 962inner.backedge: 963 %iv.next = add nuw nsw i32 %iv, 1 964 %inner.loop.cond = call i1 @cond() 965 br i1 %inner.loop.cond, label %inner, label %outer.backedge 966 967outer.backedge: 968 %outer.loop.cond = call i1 @cond() 969 br i1 %outer.loop.cond, label %outer, label %exit 970 971side.exit: 972 ret i32 0 973 974exit: 975 ret i32 1 976} 977 978; Same as test_02, but non-negativity of %b is known without context. 979; FIXME: We can remove 2nd check in loop. 980define i32 @test_06(i32 %a, i32* %bp) { 981; CHECK-LABEL: @test_06( 982; CHECK-NEXT: entry: 983; CHECK-NEXT: [[B:%.*]] = load i32, i32* [[BP:%.*]], align 4, !range [[RNG0]] 984; CHECK-NEXT: br label [[OUTER:%.*]] 985; CHECK: outer: 986; CHECK-NEXT: [[OUTER_IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[OUTER_MERGE:%.*]], [[OUTER_BACKEDGE:%.*]] ] 987; CHECK-NEXT: br label [[INNER:%.*]] 988; CHECK: inner: 989; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[OUTER_IV]], [[OUTER]] ], [ [[IV_NEXT:%.*]], [[INNER_BACKEDGE:%.*]] ] 990; CHECK-NEXT: [[SIGNED_COND:%.*]] = icmp slt i32 [[IV]], [[B]] 991; CHECK-NEXT: br i1 [[SIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]] 992; CHECK: inner.1: 993; CHECK-NEXT: [[UNSIGNED_COND:%.*]] = icmp ult i32 [[IV]], [[B]] 994; CHECK-NEXT: br i1 [[UNSIGNED_COND]], label [[INNER_BACKEDGE]], label [[SIDE_EXIT]] 995; CHECK: inner.backedge: 996; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 997; CHECK-NEXT: [[INNER_LOOP_COND:%.*]] = call i1 @cond() 998; CHECK-NEXT: br i1 [[INNER_LOOP_COND]], label [[INNER]], label [[OUTER_BACKEDGE]] 999; CHECK: outer.backedge: 1000; CHECK-NEXT: [[OUTER_MERGE]] = phi i32 [ [[IV_NEXT]], [[INNER_BACKEDGE]] ] 1001; CHECK-NEXT: [[OUTER_LOOP_COND:%.*]] = call i1 @cond() 1002; CHECK-NEXT: br i1 [[OUTER_LOOP_COND]], label [[OUTER]], label [[EXIT:%.*]] 1003; CHECK: side.exit: 1004; CHECK-NEXT: ret i32 0 1005; CHECK: exit: 1006; CHECK-NEXT: ret i32 1 1007; 1008entry: 1009 %b = load i32, i32* %bp, !range !0 1010 br label %outer 1011 1012outer: 1013 %outer.iv = phi i32 [0, %entry], [%outer.merge, %outer.backedge] 1014 br label %inner 1015 1016 1017inner: 1018 %iv = phi i32 [%outer.iv, %outer], [%iv.next, %inner.backedge] 1019 %signed_cond = icmp slt i32 %iv, %b 1020 br i1 %signed_cond, label %inner.1, label %side.exit 1021 1022inner.1: 1023 %unsigned_cond = icmp ult i32 %iv, %b 1024 br i1 %unsigned_cond, label %inner.backedge, label %side.exit 1025 1026inner.backedge: 1027 %iv.next = add nuw nsw i32 %iv, 1 1028 %inner.loop.cond = call i1 @cond() 1029 br i1 %inner.loop.cond, label %inner, label %outer.backedge 1030 1031outer.backedge: 1032 %outer.merge = phi i32 [%iv.next, %inner.backedge] 1033 %outer.loop.cond = call i1 @cond() 1034 br i1 %outer.loop.cond, label %outer, label %exit 1035 1036side.exit: 1037 ret i32 0 1038 1039exit: 1040 ret i32 1 1041} 1042 1043; Same as test_03, but non-negativity of %b is known without context. 1044; FIXME: We can remove 2nd check in loop. 1045define i32 @test_07(i32 %a, i32* %bp) { 1046; CHECK-LABEL: @test_07( 1047; CHECK-NEXT: entry: 1048; CHECK-NEXT: [[B:%.*]] = load i32, i32* [[BP:%.*]], align 4, !range [[RNG0]] 1049; CHECK-NEXT: br label [[OUTER:%.*]] 1050; CHECK: outer: 1051; CHECK-NEXT: [[OUTER_IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[OUTER_MERGE:%.*]], [[OUTER_BACKEDGE:%.*]] ] 1052; CHECK-NEXT: [[OUTER_COND_1:%.*]] = call i1 @cond() 1053; CHECK-NEXT: br i1 [[OUTER_COND_1]], label [[INNER_PREHEADER:%.*]], label [[NO_INNER:%.*]] 1054; CHECK: inner.preheader: 1055; CHECK-NEXT: br label [[INNER:%.*]] 1056; CHECK: no_inner: 1057; CHECK-NEXT: [[OUTER_COND_2:%.*]] = call i1 @cond() 1058; CHECK-NEXT: br label [[OUTER_BACKEDGE]] 1059; CHECK: inner: 1060; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[INNER_BACKEDGE:%.*]] ], [ [[OUTER_IV]], [[INNER_PREHEADER]] ] 1061; CHECK-NEXT: [[SIGNED_COND:%.*]] = icmp slt i32 [[IV]], [[B]] 1062; CHECK-NEXT: br i1 [[SIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]] 1063; CHECK: inner.1: 1064; CHECK-NEXT: [[UNSIGNED_COND:%.*]] = icmp ult i32 [[IV]], [[B]] 1065; CHECK-NEXT: br i1 [[UNSIGNED_COND]], label [[INNER_BACKEDGE]], label [[SIDE_EXIT]] 1066; CHECK: inner.backedge: 1067; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 1068; CHECK-NEXT: [[INNER_LOOP_COND:%.*]] = call i1 @cond() 1069; CHECK-NEXT: br i1 [[INNER_LOOP_COND]], label [[INNER]], label [[OUTER_BACKEDGE_LOOPEXIT:%.*]] 1070; CHECK: outer.backedge.loopexit: 1071; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[INNER_BACKEDGE]] ] 1072; CHECK-NEXT: br label [[OUTER_BACKEDGE]] 1073; CHECK: outer.backedge: 1074; CHECK-NEXT: [[OUTER_MERGE]] = phi i32 [ [[OUTER_IV]], [[NO_INNER]] ], [ [[IV_NEXT_LCSSA]], [[OUTER_BACKEDGE_LOOPEXIT]] ] 1075; CHECK-NEXT: [[OUTER_LOOP_COND:%.*]] = call i1 @cond() 1076; CHECK-NEXT: br i1 [[OUTER_LOOP_COND]], label [[OUTER]], label [[EXIT:%.*]] 1077; CHECK: side.exit: 1078; CHECK-NEXT: ret i32 0 1079; CHECK: exit: 1080; CHECK-NEXT: ret i32 1 1081; 1082entry: 1083 %b = load i32, i32* %bp, !range !0 1084 br label %outer 1085 1086outer: 1087 %outer.iv = phi i32 [0, %entry], [%outer.merge, %outer.backedge] 1088 %outer_cond_1 = call i1 @cond() 1089 br i1 %outer_cond_1, label %inner, label %no_inner 1090 1091no_inner: 1092 %outer_cond_2 = call i1 @cond() 1093 br label %outer.backedge 1094 1095inner: 1096 %iv = phi i32 [%outer.iv, %outer], [%iv.next, %inner.backedge] 1097 %signed_cond = icmp slt i32 %iv, %b 1098 br i1 %signed_cond, label %inner.1, label %side.exit 1099 1100inner.1: 1101 %unsigned_cond = icmp ult i32 %iv, %b 1102 br i1 %unsigned_cond, label %inner.backedge, label %side.exit 1103 1104inner.backedge: 1105 %iv.next = add nuw nsw i32 %iv, 1 1106 %inner.loop.cond = call i1 @cond() 1107 br i1 %inner.loop.cond, label %inner, label %outer.backedge 1108 1109outer.backedge: 1110 %outer.merge = phi i32 [%outer.iv, %no_inner], [%iv.next, %inner.backedge] 1111 %outer.loop.cond = call i1 @cond() 1112 br i1 %outer.loop.cond, label %outer, label %exit 1113 1114side.exit: 1115 ret i32 0 1116 1117exit: 1118 ret i32 1 1119} 1120 1121; Same as test_04, but non-negativity of %b is known without context. 1122; FIXME: We can remove 2nd check in loop. 1123define i32 @test_08(i32 %a, i32* %bp) { 1124; CHECK-LABEL: @test_08( 1125; CHECK-NEXT: entry: 1126; CHECK-NEXT: [[B:%.*]] = load i32, i32* [[BP:%.*]], align 4, !range [[RNG0]] 1127; CHECK-NEXT: br label [[OUTER:%.*]] 1128; CHECK: outer: 1129; CHECK-NEXT: [[OUTER_IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[OUTER_MERGE:%.*]], [[OUTER_BACKEDGE:%.*]] ] 1130; CHECK-NEXT: [[OUTER_COND_1:%.*]] = call i1 @cond() 1131; CHECK-NEXT: br i1 [[OUTER_COND_1]], label [[INNER_PREHEADER:%.*]], label [[NO_INNER:%.*]] 1132; CHECK: inner.preheader: 1133; CHECK-NEXT: br label [[INNER:%.*]] 1134; CHECK: no_inner: 1135; CHECK-NEXT: [[OUTER_COND_2:%.*]] = call i1 @cond() 1136; CHECK-NEXT: br i1 [[OUTER_COND_2]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] 1137; CHECK: if.true: 1138; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[A:%.*]], i32 [[OUTER_IV]]) 1139; CHECK-NEXT: br label [[OUTER_BACKEDGE]] 1140; CHECK: if.false: 1141; CHECK-NEXT: br label [[OUTER_BACKEDGE]] 1142; CHECK: inner: 1143; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[INNER_BACKEDGE:%.*]] ], [ [[OUTER_IV]], [[INNER_PREHEADER]] ] 1144; CHECK-NEXT: [[SIGNED_COND:%.*]] = icmp slt i32 [[IV]], [[B]] 1145; CHECK-NEXT: br i1 [[SIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]] 1146; CHECK: inner.1: 1147; CHECK-NEXT: [[UNSIGNED_COND:%.*]] = icmp ult i32 [[IV]], [[B]] 1148; CHECK-NEXT: br i1 [[UNSIGNED_COND]], label [[INNER_BACKEDGE]], label [[SIDE_EXIT]] 1149; CHECK: inner.backedge: 1150; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 1151; CHECK-NEXT: [[INNER_LOOP_COND:%.*]] = call i1 @cond() 1152; CHECK-NEXT: br i1 [[INNER_LOOP_COND]], label [[INNER]], label [[OUTER_BACKEDGE_LOOPEXIT:%.*]] 1153; CHECK: outer.backedge.loopexit: 1154; CHECK-NEXT: [[IV_NEXT_LCSSA:%.*]] = phi i32 [ [[IV_NEXT]], [[INNER_BACKEDGE]] ] 1155; CHECK-NEXT: br label [[OUTER_BACKEDGE]] 1156; CHECK: outer.backedge: 1157; CHECK-NEXT: [[OUTER_MERGE]] = phi i32 [ [[SMAX]], [[IF_TRUE]] ], [ [[OUTER_IV]], [[IF_FALSE]] ], [ [[IV_NEXT_LCSSA]], [[OUTER_BACKEDGE_LOOPEXIT]] ] 1158; CHECK-NEXT: [[OUTER_LOOP_COND:%.*]] = call i1 @cond() 1159; CHECK-NEXT: br i1 [[OUTER_LOOP_COND]], label [[OUTER]], label [[EXIT:%.*]] 1160; CHECK: side.exit: 1161; CHECK-NEXT: ret i32 0 1162; CHECK: exit: 1163; CHECK-NEXT: ret i32 1 1164; 1165entry: 1166 %b = load i32, i32* %bp, !range !0 1167 br label %outer 1168 1169outer: 1170 %outer.iv = phi i32 [0, %entry], [%outer.merge, %outer.backedge] 1171 %outer_cond_1 = call i1 @cond() 1172 br i1 %outer_cond_1, label %inner, label %no_inner 1173 1174no_inner: 1175 %outer_cond_2 = call i1 @cond() 1176 br i1 %outer_cond_2, label %if.true, label %if.false 1177 1178if.true: 1179 %smax = call i32 @llvm.smax.i32(i32 %a, i32 %outer.iv) 1180 br label %outer.backedge 1181 1182if.false: 1183 br label %outer.backedge 1184 1185inner: 1186 %iv = phi i32 [%outer.iv, %outer], [%iv.next, %inner.backedge] 1187 %signed_cond = icmp slt i32 %iv, %b 1188 br i1 %signed_cond, label %inner.1, label %side.exit 1189 1190inner.1: 1191 %unsigned_cond = icmp ult i32 %iv, %b 1192 br i1 %unsigned_cond, label %inner.backedge, label %side.exit 1193 1194inner.backedge: 1195 %iv.next = add nuw nsw i32 %iv, 1 1196 %inner.loop.cond = call i1 @cond() 1197 br i1 %inner.loop.cond, label %inner, label %outer.backedge 1198 1199outer.backedge: 1200 %outer.merge = phi i32 [%smax, %if.true], [%outer.iv, %if.false], [%iv.next, %inner.backedge] 1201 %outer.loop.cond = call i1 @cond() 1202 br i1 %outer.loop.cond, label %outer, label %exit 1203 1204side.exit: 1205 ret i32 0 1206 1207exit: 1208 ret i32 1 1209} 1210 1211!0 = !{i32 0, i32 2147483647} 1212!1 = !{i32 -2147483648, i32 0} 1213