1; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s 2; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,loop(irce)' -S < %s 2>&1 | FileCheck %s 3 4; CHECK: irce: in function test_01: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting> 5; CHECK: irce: in function test_02: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting> 6; CHECK: irce: in function test_03: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting> 7; CHECK: irce: in function test_04: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting> 8; CHECK: irce: in function test_05: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting> 9; CHECK: irce: in function test_06: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting> 10; CHECK-NOT: irce: in function test_07: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting> 11; CHECK: irce: in function test_08: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting> 12 13; IV = 0; IV <s 100; IV += 7; 0 <= Len <= 50. IRCE is allowed. 14define void @test_01(i32* %arr, i32* %a_len_ptr) { 15 16; CHECK: @test_01( 17; CHECK: entry: 18; CHECK-NEXT: %exit.mainloop.at = load i32, i32* %a_len_ptr 19; CHECK-NEXT: [[COND1:%[^ ]+]] = icmp slt i32 0, %exit.mainloop.at 20; CHECK-NEXT: br i1 [[COND1]], label %loop.preheader, label %main.pseudo.exit 21; CHECK: loop.preheader: 22; CHECK-NEXT: br label %loop 23; CHECK: loop: 24; CHECK-NEXT: %idx = phi i32 [ %idx.next, %in.bounds ], [ 0, %loop.preheader ] 25; CHECK-NEXT: %idx.next = add i32 %idx, 7 26; CHECK-NEXT: %abc = icmp slt i32 %idx, %exit.mainloop.at 27; CHECK-NEXT: br i1 true, label %in.bounds, label %out.of.bounds.loopexit1 28; CHECK: in.bounds: 29; CHECK-NEXT: %addr = getelementptr i32, i32* %arr, i32 %idx 30; CHECK-NEXT: store i32 0, i32* %addr 31; CHECK-NEXT: %next = icmp slt i32 %idx.next, 100 32; CHECK-NEXT: [[COND2:%[^ ]+]] = icmp slt i32 %idx.next, %exit.mainloop.at 33; CHECK-NEXT: br i1 [[COND2]], label %loop, label %main.exit.selector 34; CHECK: main.exit.selector: 35; CHECK-NEXT: %idx.next.lcssa = phi i32 [ %idx.next, %in.bounds ] 36; CHECK-NEXT: [[COND3:%[^ ]+]] = icmp slt i32 %idx.next.lcssa, 100 37; CHECK-NEXT: br i1 [[COND3]], label %main.pseudo.exit, label %exit 38; CHECK: main.pseudo.exit: 39; CHECK-NEXT: %idx.copy = phi i32 [ 0, %entry ], [ %idx.next.lcssa, %main.exit.selector ] 40; CHECK-NEXT: %indvar.end = phi i32 [ 0, %entry ], [ %idx.next.lcssa, %main.exit.selector ] 41; CHECK-NEXT: br label %postloop 42; CHECK: postloop: 43; CHECK-NEXT: br label %loop.postloop 44; CHECK: loop.postloop: 45; CHECK-NEXT: %idx.postloop = phi i32 [ %idx.copy, %postloop ], [ %idx.next.postloop, %in.bounds.postloop ] 46; CHECK-NEXT: %idx.next.postloop = add i32 %idx.postloop, 7 47; CHECK-NEXT: %abc.postloop = icmp slt i32 %idx.postloop, %exit.mainloop.at 48; CHECK-NEXT: br i1 %abc.postloop, label %in.bounds.postloop, label %out.of.bounds.loopexit 49; CHECK: in.bounds.postloop: 50; CHECK-NEXT: %addr.postloop = getelementptr i32, i32* %arr, i32 %idx.postloop 51; CHECK-NEXT: store i32 0, i32* %addr.postloop 52; CHECK-NEXT: %next.postloop = icmp slt i32 %idx.next.postloop, 100 53; CHECK-NEXT: br i1 %next.postloop, label %loop.postloop, label %exit.loopexit 54 55entry: 56 %len = load i32, i32* %a_len_ptr, !range !0 57 br label %loop 58 59loop: 60 %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ] 61 %idx.next = add i32 %idx, 7 62 %abc = icmp slt i32 %idx, %len 63 br i1 %abc, label %in.bounds, label %out.of.bounds 64 65in.bounds: 66 %addr = getelementptr i32, i32* %arr, i32 %idx 67 store i32 0, i32* %addr 68 %next = icmp slt i32 %idx.next, 100 69 br i1 %next, label %loop, label %exit 70 71out.of.bounds: 72 ret void 73 74exit: 75 ret void 76} 77 78; IV = 0; IV <s MAX_INT - 7; IV += 7; 0 <= Len <= 50. IRCE is allowed. 79define void @test_02(i32* %arr, i32* %a_len_ptr) { 80 81; CHECK: @test_02( 82; CHECK: entry: 83; CHECK-NEXT: %exit.mainloop.at = load i32, i32* %a_len_ptr 84; CHECK-NEXT: [[COND1:%[^ ]+]] = icmp slt i32 0, %exit.mainloop.at 85; CHECK-NEXT: br i1 [[COND1]], label %loop.preheader, label %main.pseudo.exit 86; CHECK: loop.preheader: 87; CHECK-NEXT: br label %loop 88; CHECK: loop: 89; CHECK-NEXT: %idx = phi i32 [ %idx.next, %in.bounds ], [ 0, %loop.preheader ] 90; CHECK-NEXT: %idx.next = add i32 %idx, 7 91; CHECK-NEXT: %abc = icmp slt i32 %idx, %exit.mainloop.at 92; CHECK-NEXT: br i1 true, label %in.bounds, label %out.of.bounds.loopexit1 93; CHECK: in.bounds: 94; CHECK-NEXT: %addr = getelementptr i32, i32* %arr, i32 %idx 95; CHECK-NEXT: store i32 0, i32* %addr 96; CHECK-NEXT: %next = icmp slt i32 %idx.next, 2147483640 97; CHECK-NEXT: [[COND2:%[^ ]+]] = icmp slt i32 %idx.next, %exit.mainloop.at 98; CHECK-NEXT: br i1 [[COND2]], label %loop, label %main.exit.selector 99; CHECK: main.exit.selector: 100; CHECK-NEXT: %idx.next.lcssa = phi i32 [ %idx.next, %in.bounds ] 101; CHECK-NEXT: [[COND3:%[^ ]+]] = icmp slt i32 %idx.next.lcssa, 2147483640 102; CHECK-NEXT: br i1 [[COND3]], label %main.pseudo.exit, label %exit 103; CHECK: main.pseudo.exit: 104; CHECK-NEXT: %idx.copy = phi i32 [ 0, %entry ], [ %idx.next.lcssa, %main.exit.selector ] 105; CHECK-NEXT: %indvar.end = phi i32 [ 0, %entry ], [ %idx.next.lcssa, %main.exit.selector ] 106; CHECK-NEXT: br label %postloop 107; CHECK: postloop: 108; CHECK-NEXT: br label %loop.postloop 109; CHECK: loop.postloop: 110; CHECK-NEXT: %idx.postloop = phi i32 [ %idx.copy, %postloop ], [ %idx.next.postloop, %in.bounds.postloop ] 111; CHECK-NEXT: %idx.next.postloop = add i32 %idx.postloop, 7 112; CHECK-NEXT: %abc.postloop = icmp slt i32 %idx.postloop, %exit.mainloop.at 113; CHECK-NEXT: br i1 %abc.postloop, label %in.bounds.postloop, label %out.of.bounds.loopexit 114; CHECK: in.bounds.postloop: 115; CHECK-NEXT: %addr.postloop = getelementptr i32, i32* %arr, i32 %idx.postloop 116; CHECK-NEXT: store i32 0, i32* %addr.postloop 117; CHECK-NEXT: %next.postloop = icmp slt i32 %idx.next.postloop, 2147483640 118; CHECK-NEXT: br i1 %next.postloop, label %loop.postloop, label %exit.loopexit 119 120entry: 121 %len = load i32, i32* %a_len_ptr, !range !0 122 br label %loop 123 124loop: 125 %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ] 126 %idx.next = add i32 %idx, 7 127 %abc = icmp slt i32 %idx, %len 128 br i1 %abc, label %in.bounds, label %out.of.bounds 129 130in.bounds: 131 %addr = getelementptr i32, i32* %arr, i32 %idx 132 store i32 0, i32* %addr 133 %next = icmp slt i32 %idx.next, 2147483640 134 br i1 %next, label %loop, label %exit 135 136out.of.bounds: 137 ret void 138 139exit: 140 ret void 141} 142 143; IV = 0; IV <s MAX_INT; IV += 7; 0 <= Len <= MAX_INT - 7. This is the greatest 144; value of Len for which IRCE is allowed. 145define void @test_03(i32* %arr, i32* %a_len_ptr) { 146 147; CHECK: @test_03( 148; CHECK: entry: 149; CHECK-NEXT: %exit.mainloop.at = load i32, i32* %a_len_ptr 150; CHECK-NEXT: [[COND1:%[^ ]+]] = icmp slt i32 0, %exit.mainloop.at 151; CHECK-NEXT: br i1 [[COND1]], label %loop.preheader, label %main.pseudo.exit 152; CHECK: loop.preheader: 153; CHECK-NEXT: br label %loop 154; CHECK: loop: 155; CHECK-NEXT: %idx = phi i32 [ %idx.next, %in.bounds ], [ 0, %loop.preheader ] 156; CHECK-NEXT: %idx.next = add i32 %idx, 7 157; CHECK-NEXT: %abc = icmp slt i32 %idx, %exit.mainloop.at 158; CHECK-NEXT: br i1 true, label %in.bounds, label %out.of.bounds.loopexit1 159; CHECK: in.bounds: 160; CHECK-NEXT: %addr = getelementptr i32, i32* %arr, i32 %idx 161; CHECK-NEXT: store i32 0, i32* %addr 162; CHECK-NEXT: %next = icmp slt i32 %idx.next, 2147483647 163; CHECK-NEXT: [[COND2:%[^ ]+]] = icmp slt i32 %idx.next, %exit.mainloop.at 164; CHECK-NEXT: br i1 [[COND2]], label %loop, label %main.exit.selector 165; CHECK: main.exit.selector: 166; CHECK-NEXT: %idx.next.lcssa = phi i32 [ %idx.next, %in.bounds ] 167; CHECK-NEXT: [[COND3:%[^ ]+]] = icmp slt i32 %idx.next.lcssa, 2147483647 168; CHECK-NEXT: br i1 [[COND3]], label %main.pseudo.exit, label %exit 169; CHECK: main.pseudo.exit: 170; CHECK-NEXT: %idx.copy = phi i32 [ 0, %entry ], [ %idx.next.lcssa, %main.exit.selector ] 171; CHECK-NEXT: %indvar.end = phi i32 [ 0, %entry ], [ %idx.next.lcssa, %main.exit.selector ] 172; CHECK-NEXT: br label %postloop 173; CHECK: postloop: 174; CHECK-NEXT: br label %loop.postloop 175; CHECK: loop.postloop: 176; CHECK-NEXT: %idx.postloop = phi i32 [ %idx.copy, %postloop ], [ %idx.next.postloop, %in.bounds.postloop ] 177; CHECK-NEXT: %idx.next.postloop = add i32 %idx.postloop, 7 178; CHECK-NEXT: %abc.postloop = icmp slt i32 %idx.postloop, %exit.mainloop.at 179; CHECK-NEXT: br i1 %abc.postloop, label %in.bounds.postloop, label %out.of.bounds.loopexit 180; CHECK: in.bounds.postloop: 181; CHECK-NEXT: %addr.postloop = getelementptr i32, i32* %arr, i32 %idx.postloop 182; CHECK-NEXT: store i32 0, i32* %addr.postloop 183; CHECK-NEXT: %next.postloop = icmp slt i32 %idx.next.postloop, 2147483647 184; CHECK-NEXT: br i1 %next.postloop, label %loop.postloop, label %exit.loopexit 185 186entry: 187 %len = load i32, i32* %a_len_ptr, !range !1 188 br label %loop 189 190loop: 191 %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ] 192 %idx.next = add i32 %idx, 7 193 %abc = icmp slt i32 %idx, %len 194 br i1 %abc, label %in.bounds, label %out.of.bounds 195 196in.bounds: 197 %addr = getelementptr i32, i32* %arr, i32 %idx 198 store i32 0, i32* %addr 199 %next = icmp slt i32 %idx.next, 2147483647 200 br i1 %next, label %loop, label %exit 201 202out.of.bounds: 203 ret void 204 205exit: 206 ret void 207} 208 209; IV = 0; IV <s MAX_INT; IV += 7; 0 <= Len <= MAX_INT - 6. IRCE is allowed 210; because the branch would fail once idx.next == MAX_INT - 1 keeping the 211; access in bounds. 212define void @test_04(i32* %arr, i32* %a_len_ptr) { 213 ; CHECK: @test_04( 214 ; CHECK: loop: 215 ; CHECK: [[IV:%[^ ]+]] = phi i32 216 ; CHECK: [[IDX_NEXT:%[^ ]+]] = add i32 [[IV]], 7 217 218 ; CHECK: main.exit.selector: 219 ; CHECK: [[PSEUDO_PHI:%[^ ]+]] = phi i32 [ [[IDX_NEXT]], %in.bounds ] 220 ; CHECK: [[COND:%[^ ]+]] = icmp slt i32 [[PSEUDO_PHI]], 2147483647 221 ; CHECK: br i1 [[COND]], label %main.pseudo.exit, label %exit 222 223 ; CHECK: loop.postloop: 224 ; CHECK: [[IDX_POST:%[^ ]+]] = phi i32 225 ; CHECK: [[COND_POST:%[^ ]+]] = icmp slt i32 [[IDX_POST]], %exit.mainloop.at 226 ; CHECK: br i1 [[COND_POST]], label %in.bounds.postloop, label %out.of.bounds.loopexit 227 228entry: 229 %len = load i32, i32* %a_len_ptr, !range !2 230 br label %loop 231 232loop: 233 %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ] 234 %idx.next = add i32 %idx, 7 235 %abc = icmp slt i32 %idx, %len 236 br i1 %abc, label %in.bounds, label %out.of.bounds 237 238in.bounds: 239 %addr = getelementptr i32, i32* %arr, i32 %idx 240 store i32 0, i32* %addr 241 %next = icmp slt i32 %idx.next, 2147483647 242 br i1 %next, label %loop, label %exit 243 244out.of.bounds: 245 ret void 246 247exit: 248 ret void 249} 250 251; IV = 100; IV >s -1; IV -= 7; 0 <= Len <= 50. IRCE is allowed. 252define void @test_05(i32* %arr, i32* %a_len_ptr) { 253 254; CHECK: @test_05( 255; CHECK: entry: 256; CHECK-NEXT: %len = load i32, i32* %a_len_ptr 257; CHECK-NEXT: %exit.preloop.at = add i32 %len, -1 258; CHECK-NEXT: [[COND1:%[^ ]+]] = icmp sgt i32 100, %exit.preloop.at 259; CHECK-NEXT: br i1 [[COND1]], label %loop.preloop.preheader, label %preloop.pseudo.exit 260; CHECK: loop.preloop.preheader: 261; CHECK-NEXT: br label %loop.preloop 262; CHECK: mainloop: 263; CHECK-NEXT: br label %loop 264; CHECK: loop: 265; CHECK-NEXT: %idx = phi i32 [ %idx.preloop.copy, %mainloop ], [ %idx.next, %in.bounds ] 266; CHECK-NEXT: %idx.next = add i32 %idx, -7 267; CHECK-NEXT: %abc = icmp slt i32 %idx, %len 268; CHECK-NEXT: br i1 true, label %in.bounds, label %out.of.bounds.loopexit1 269; CHECK: in.bounds: 270; CHECK-NEXT: %addr = getelementptr i32, i32* %arr, i32 %idx 271; CHECK-NEXT: store i32 0, i32* %addr 272; CHECK-NEXT: %next = icmp sgt i32 %idx.next, -1 273; CHECK-NEXT: br i1 %next, label %loop, label %exit.loopexit 274; CHECK: loop.preloop: 275; CHECK-NEXT: %idx.preloop = phi i32 [ %idx.next.preloop, %in.bounds.preloop ], [ 100, %loop.preloop.preheader ] 276; CHECK-NEXT: %idx.next.preloop = add i32 %idx.preloop, -7 277; CHECK-NEXT: %abc.preloop = icmp slt i32 %idx.preloop, %len 278; CHECK-NEXT: br i1 %abc.preloop, label %in.bounds.preloop, label %out.of.bounds.loopexit 279; CHECK: in.bounds.preloop: 280; CHECK-NEXT: %addr.preloop = getelementptr i32, i32* %arr, i32 %idx.preloop 281; CHECK-NEXT: store i32 0, i32* %addr.preloop 282; CHECK-NEXT: %next.preloop = icmp sgt i32 %idx.next.preloop, -1 283; CHECK-NEXT: [[COND2:%[^ ]+]] = icmp sgt i32 %idx.next.preloop, %exit.preloop.at 284; CHECK-NEXT: br i1 [[COND2]], label %loop.preloop, label %preloop.exit.selector 285; CHECK: preloop.exit.selector: 286; CHECK-NEXT: %idx.next.preloop.lcssa = phi i32 [ %idx.next.preloop, %in.bounds.preloop ] 287; CHECK-NEXT: [[COND3:%[^ ]+]] = icmp sgt i32 %idx.next.preloop.lcssa, -1 288; CHECK-NEXT: br i1 [[COND3]], label %preloop.pseudo.exit, label %exit 289; CHECK: preloop.pseudo.exit: 290; CHECK-NEXT: %idx.preloop.copy = phi i32 [ 100, %entry ], [ %idx.next.preloop.lcssa, %preloop.exit.selector ] 291; CHECK-NEXT: %indvar.end = phi i32 [ 100, %entry ], [ %idx.next.preloop.lcssa, %preloop.exit.selector ] 292; CHECK-NEXT: br label %mainloop 293 294entry: 295 %len = load i32, i32* %a_len_ptr, !range !0 296 br label %loop 297 298loop: 299 %idx = phi i32 [ 100, %entry ], [ %idx.next, %in.bounds ] 300 %idx.next = add i32 %idx, -7 301 %abc = icmp slt i32 %idx, %len 302 br i1 %abc, label %in.bounds, label %out.of.bounds 303 304in.bounds: 305 %addr = getelementptr i32, i32* %arr, i32 %idx 306 store i32 0, i32* %addr 307 %next = icmp sgt i32 %idx.next, -1 308 br i1 %next, label %loop, label %exit 309 310out.of.bounds: 311 ret void 312 313exit: 314 ret void 315} 316 317; IV = MAX_INT - 7; IV >u 6; IV -= 7; 10 <= Len <= 50. IRCE is allowed. 318define void @test_06(i32* %arr, i32* %a_len_ptr) { 319 320; CHECK: @test_06( 321; CHECK: entry: 322; CHECK-NEXT: %len = load i32, i32* %a_len_ptr 323; CHECK-NEXT: %exit.preloop.at = add i32 %len, -1 324; CHECK-NEXT: [[COND1:%[^ ]+]] = icmp ugt i32 2147483640, %exit.preloop.at 325; CHECK-NEXT: br i1 [[COND1]], label %loop.preloop.preheader, label %preloop.pseudo.exit 326; CHECK: loop.preloop.preheader: 327; CHECK-NEXT: br label %loop.preloop 328; CHECK: mainloop: 329; CHECK-NEXT: br label %loop 330; CHECK: loop: 331; CHECK-NEXT: %idx = phi i32 [ %idx.preloop.copy, %mainloop ], [ %idx.next, %in.bounds ] 332; CHECK-NEXT: %idx.next = add i32 %idx, -7 333; CHECK-NEXT: %abc = icmp slt i32 %idx, %len 334; CHECK-NEXT: br i1 true, label %in.bounds, label %out.of.bounds.loopexit1 335; CHECK: in.bounds: 336; CHECK-NEXT: %addr = getelementptr i32, i32* %arr, i32 %idx 337; CHECK-NEXT: store i32 0, i32* %addr 338; CHECK-NEXT: %next = icmp ugt i32 %idx.next, 6 339; CHECK-NEXT: br i1 %next, label %loop, label %exit.loopexit 340; CHECK: loop.preloop: 341; CHECK-NEXT: %idx.preloop = phi i32 [ %idx.next.preloop, %in.bounds.preloop ], [ 2147483640, %loop.preloop.preheader ] 342; CHECK-NEXT: %idx.next.preloop = add i32 %idx.preloop, -7 343; CHECK-NEXT: %abc.preloop = icmp slt i32 %idx.preloop, %len 344; CHECK-NEXT: br i1 %abc.preloop, label %in.bounds.preloop, label %out.of.bounds.loopexit 345; CHECK: in.bounds.preloop: 346; CHECK-NEXT: %addr.preloop = getelementptr i32, i32* %arr, i32 %idx.preloop 347; CHECK-NEXT: store i32 0, i32* %addr.preloop 348; CHECK-NEXT: %next.preloop = icmp ugt i32 %idx.next.preloop, 6 349; CHECK-NEXT: [[COND2:%[^ ]+]] = icmp ugt i32 %idx.next.preloop, %exit.preloop.at 350; CHECK-NEXT: br i1 [[COND2]], label %loop.preloop, label %preloop.exit.selector 351; CHECK: preloop.exit.selector: 352; CHECK-NEXT: %idx.next.preloop.lcssa = phi i32 [ %idx.next.preloop, %in.bounds.preloop ] 353; CHECK-NEXT: [[COND3:%[^ ]+]] = icmp ugt i32 %idx.next.preloop.lcssa, 6 354; CHECK-NEXT: br i1 [[COND3]], label %preloop.pseudo.exit, label %exit 355; CHECK: preloop.pseudo.exit: 356; CHECK-NEXT: %idx.preloop.copy = phi i32 [ 2147483640, %entry ], [ %idx.next.preloop.lcssa, %preloop.exit.selector ] 357; CHECK-NEXT: %indvar.end = phi i32 [ 2147483640, %entry ], [ %idx.next.preloop.lcssa, %preloop.exit.selector ] 358; CHECK-NEXT: br label %mainloop 359 360entry: 361 %len = load i32, i32* %a_len_ptr, !range !3 362 br label %loop 363 364loop: 365 %idx = phi i32 [ 2147483640, %entry ], [ %idx.next, %in.bounds ] 366 %idx.next = add i32 %idx, -7 367 %abc = icmp slt i32 %idx, %len 368 br i1 %abc, label %in.bounds, label %out.of.bounds 369 370in.bounds: 371 %addr = getelementptr i32, i32* %arr, i32 %idx 372 store i32 0, i32* %addr 373 %next = icmp ugt i32 %idx.next, 6 374 br i1 %next, label %loop, label %exit 375 376out.of.bounds: 377 ret void 378 379exit: 380 ret void 381} 382 383; IV = MAX_INT - 7; IV >u 5; IV -= 7; 10 <= Len <= 50. IRCE is not allowed, 384; because we can cross the 0 border. 385define void @test_07(i32* %arr, i32* %a_len_ptr) { 386 387; CHECK: @test_07( 388 389entry: 390 %len = load i32, i32* %a_len_ptr, !range !3 391 br label %loop 392 393loop: 394 %idx = phi i32 [ 2147483640, %entry ], [ %idx.next, %in.bounds ] 395 %idx.next = add i32 %idx, -7 396 %abc = icmp slt i32 %idx, %len 397 br i1 %abc, label %in.bounds, label %out.of.bounds 398 399in.bounds: 400 %addr = getelementptr i32, i32* %arr, i32 %idx 401 store i32 0, i32* %addr 402 %next = icmp ugt i32 %idx.next, 5 403 br i1 %next, label %loop, label %exit 404 405out.of.bounds: 406 ret void 407 408exit: 409 ret void 410} 411 412; IV = MAX_INT; IV >u 6; IV -= 7; 10 <= Len <= 50. IRCE is allowed. 413define void @test_08(i32* %arr, i32* %a_len_ptr) { 414 415; CHECK: @test_08( 416; CHECK: entry: 417; CHECK-NEXT: %len = load i32, i32* %a_len_ptr 418; CHECK-NEXT: %exit.preloop.at = add i32 %len, -1 419; CHECK-NEXT: [[COND1:%[^ ]+]] = icmp ugt i32 2147483647, %exit.preloop.at 420; CHECK-NEXT: br i1 [[COND1]], label %loop.preloop.preheader, label %preloop.pseudo.exit 421; CHECK: loop.preloop.preheader: 422; CHECK-NEXT: br label %loop.preloop 423; CHECK: mainloop: 424; CHECK-NEXT: br label %loop 425; CHECK: loop: 426; CHECK-NEXT: %idx = phi i32 [ %idx.preloop.copy, %mainloop ], [ %idx.next, %in.bounds ] 427; CHECK-NEXT: %idx.next = add i32 %idx, -7 428; CHECK-NEXT: %abc = icmp slt i32 %idx, %len 429; CHECK-NEXT: br i1 true, label %in.bounds, label %out.of.bounds.loopexit1 430; CHECK: in.bounds: 431; CHECK-NEXT: %addr = getelementptr i32, i32* %arr, i32 %idx 432; CHECK-NEXT: store i32 0, i32* %addr 433; CHECK-NEXT: %next = icmp ugt i32 %idx.next, 6 434; CHECK-NEXT: br i1 %next, label %loop, label %exit.loopexit 435; CHECK: loop.preloop: 436; CHECK-NEXT: %idx.preloop = phi i32 [ %idx.next.preloop, %in.bounds.preloop ], [ 2147483647, %loop.preloop.preheader ] 437; CHECK-NEXT: %idx.next.preloop = add i32 %idx.preloop, -7 438; CHECK-NEXT: %abc.preloop = icmp slt i32 %idx.preloop, %len 439; CHECK-NEXT: br i1 %abc.preloop, label %in.bounds.preloop, label %out.of.bounds.loopexit 440; CHECK: in.bounds.preloop: 441; CHECK-NEXT: %addr.preloop = getelementptr i32, i32* %arr, i32 %idx.preloop 442; CHECK-NEXT: store i32 0, i32* %addr.preloop 443; CHECK-NEXT: %next.preloop = icmp ugt i32 %idx.next.preloop, 6 444; CHECK-NEXT: [[COND2:%[^ ]+]] = icmp ugt i32 %idx.next.preloop, %exit.preloop.at 445; CHECK-NEXT: br i1 [[COND2]], label %loop.preloop, label %preloop.exit.selector 446; CHECK: preloop.exit.selector: 447; CHECK-NEXT: %idx.next.preloop.lcssa = phi i32 [ %idx.next.preloop, %in.bounds.preloop ] 448; CHECK-NEXT: [[COND3:%[^ ]+]] = icmp ugt i32 %idx.next.preloop.lcssa, 6 449; CHECK-NEXT: br i1 [[COND3]], label %preloop.pseudo.exit, label %exit 450; CHECK: preloop.pseudo.exit: 451; CHECK-NEXT: %idx.preloop.copy = phi i32 [ 2147483647, %entry ], [ %idx.next.preloop.lcssa, %preloop.exit.selector ] 452; CHECK-NEXT: %indvar.end = phi i32 [ 2147483647, %entry ], [ %idx.next.preloop.lcssa, %preloop.exit.selector ] 453; CHECK-NEXT: br label %mainloop 454 455entry: 456 %len = load i32, i32* %a_len_ptr, !range !3 457 br label %loop 458 459loop: 460 %idx = phi i32 [ 2147483647, %entry ], [ %idx.next, %in.bounds ] 461 %idx.next = add i32 %idx, -7 462 %abc = icmp slt i32 %idx, %len 463 br i1 %abc, label %in.bounds, label %out.of.bounds 464 465in.bounds: 466 %addr = getelementptr i32, i32* %arr, i32 %idx 467 store i32 0, i32* %addr 468 %next = icmp ugt i32 %idx.next, 6 469 br i1 %next, label %loop, label %exit 470 471out.of.bounds: 472 ret void 473 474exit: 475 ret void 476} 477 478!0 = !{i32 0, i32 50} 479!1 = !{i32 0, i32 2147483640} 480!2 = !{i32 0, i32 2147483641} 481!3 = !{i32 10, i32 50} 482