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>,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 7; Iterate from 0 to SINT_MAX, check that the post-loop is generated. 8define void @test_01(i32* %arr, i32* %a_len_ptr) { 9 10; CHECK: test_01( 11; CHECK: entry: 12; CHECK-NEXT: %exit.mainloop.at = load i32, i32* %a_len_ptr 13; CHECK: loop: 14; CHECK-NEXT: %idx = phi i32 [ %idx.next, %in.bounds ], [ 0, %loop.preheader ] 15; CHECK-NEXT: %idx.next = add i32 %idx, 1 16; CHECK-NEXT: %abc = icmp slt i32 %idx, %exit.mainloop.at 17; CHECK-NEXT: br i1 true, label %in.bounds, 18; CHECK: in.bounds: 19; CHECK-NEXT: %addr = getelementptr i32, i32* %arr, i32 %idx 20; CHECK-NEXT: store i32 0, i32* %addr 21; CHECK-NEXT: %next = icmp slt i32 %idx.next, 2147483647 22; CHECK-NEXT: [[COND:%[^ ]+]] = icmp slt i32 %idx.next, %exit.mainloop.at 23; CHECK-NEXT: br i1 [[COND]], label %loop, label %main.exit.selector 24; CHECK: main.pseudo.exit: 25; CHECK-NEXT: %idx.copy = phi i32 [ 0, %entry ], [ %idx.next.lcssa, %main.exit.selector ] 26; CHECK-NEXT: %indvar.end = phi i32 [ 0, %entry ], [ %idx.next.lcssa, %main.exit.selector ] 27; CHECK-NEXT: br label %postloop 28; CHECK: postloop: 29; CHECK-NEXT: br label %loop.postloop 30; CHECK: loop.postloop: 31; CHECK-NEXT: %idx.postloop = phi i32 [ %idx.copy, %postloop ], [ %idx.next.postloop, %in.bounds.postloop ] 32; CHECK-NEXT: %idx.next.postloop = add i32 %idx.postloop, 1 33; CHECK-NEXT: %abc.postloop = icmp slt i32 %idx.postloop, %exit.mainloop.at 34; CHECK-NEXT: br i1 %abc.postloop, label %in.bounds.postloop, label %out.of.bounds.loopexit 35; CHECK: in.bounds.postloop: 36; CHECK-NEXT: %addr.postloop = getelementptr i32, i32* %arr, i32 %idx.postloop 37; CHECK-NEXT: store i32 0, i32* %addr.postloop 38; CHECK-NEXT: %next.postloop = icmp slt i32 %idx.next.postloop, 2147483647 39; CHECK-NEXT: br i1 %next.postloop, label %loop.postloop, label %exit.loopexit 40 41entry: 42 %len = load i32, i32* %a_len_ptr, !range !0 43 br label %loop 44 45loop: 46 %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ] 47 %idx.next = add i32 %idx, 1 48 %abc = icmp slt i32 %idx, %len 49 br i1 %abc, label %in.bounds, label %out.of.bounds 50 51in.bounds: 52 %addr = getelementptr i32, i32* %arr, i32 %idx 53 store i32 0, i32* %addr 54 %next = icmp slt i32 %idx.next, 2147483647 55 br i1 %next, label %loop, label %exit 56 57out.of.bounds: 58 ret void 59 60exit: 61 ret void 62} 63 64; Iterate from SINT_MAX to 0, check that the pre-loop is generated. 65define void @test_02(i32* %arr, i32* %a_len_ptr) { 66 67; CHECK: test_02( 68; CHECK: entry: 69; CHECK-NEXT: %len = load i32, i32* %a_len_ptr, align 4, !range !0 70; CHECK-NEXT: br i1 true, label %loop.preloop.preheader 71; CHECK: mainloop: 72; CHECK-NEXT: br label %loop 73; CHECK: loop: 74; CHECK-NEXT: %idx = phi i32 [ %idx.preloop.copy, %mainloop ], [ %idx.next, %in.bounds ] 75; CHECK-NEXT: %idx.next = add i32 %idx, -1 76; CHECK-NEXT: %abc = icmp slt i32 %idx, %len 77; CHECK-NEXT: br i1 true, label %in.bounds 78; CHECK: in.bounds: 79; CHECK-NEXT: %addr = getelementptr i32, i32* %arr, i32 %idx 80; CHECK-NEXT: store i32 0, i32* %addr 81; CHECK-NEXT: %next = icmp sgt i32 %idx.next, -1 82; CHECK-NEXT: br i1 %next, label %loop, label %exit.loopexit 83; CHECK: loop.preloop: 84; CHECK-NEXT: %idx.preloop = phi i32 [ %idx.next.preloop, %in.bounds.preloop ], [ 2147483647, %loop.preloop.preheader ] 85; CHECK-NEXT: %idx.next.preloop = add i32 %idx.preloop, -1 86; CHECK-NEXT: %abc.preloop = icmp slt i32 %idx.preloop, %len 87; CHECK-NEXT: br i1 %abc.preloop, label %in.bounds.preloop, label %out.of.bounds.loopexit 88; CHECK: in.bounds.preloop: 89; CHECK-NEXT: %addr.preloop = getelementptr i32, i32* %arr, i32 %idx.preloop 90; CHECK-NEXT: store i32 0, i32* %addr.preloop 91; CHECK-NEXT: %next.preloop = icmp sgt i32 %idx.next.preloop, -1 92; CHECK-NEXT: [[COND:%[^ ]+]] = icmp sgt i32 %idx.next.preloop, -1 93; CHECK-NEXT: br i1 [[COND]], label %loop.preloop, label %preloop.exit.selector 94 95entry: 96 %len = load i32, i32* %a_len_ptr, !range !0 97 br label %loop 98 99loop: 100 %idx = phi i32 [ 2147483647, %entry ], [ %idx.next, %in.bounds ] 101 %idx.next = add i32 %idx, -1 102 %abc = icmp slt i32 %idx, %len 103 br i1 %abc, label %in.bounds, label %out.of.bounds 104 105in.bounds: 106 %addr = getelementptr i32, i32* %arr, i32 %idx 107 store i32 0, i32* %addr 108 %next = icmp sgt i32 %idx.next, -1 109 br i1 %next, label %loop, label %exit 110 111out.of.bounds: 112 ret void 113 114exit: 115 ret void 116} 117 118!0 = !{i32 0, i32 50} 119