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_01u: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting> 6; CHECK-NOT: irce: in function test_02: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting> 7; CHECK: irce: in function test_03: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting> 8; CHECK: irce: in function test_04: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting> 9; CHECK: irce: in function test_05: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting> 10; CHECK-NOT: irce: in function test_06: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting> 11; CHECK: irce: in function test_07: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting> 12; CHECK-NOT: irce: in function test_08: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting> 13 14; Show that IRCE can turn 'ne' condition to 'slt' in increasing IV when the IV 15; can be negative at some point. 16define void @test_01(i32* %arr, i32* %a_len_ptr) #0 { 17 18; CHECK: test_01 19; CHECK: main.exit.selector: 20; CHECK-NEXT: [[PSEUDO_PHI:%[^ ]+]] = phi i32 [ %idx.next, %in.bounds ] 21; CHECK-NEXT: [[COND:%[^ ]+]] = icmp slt i32 [[PSEUDO_PHI]], 100 22; CHECK-NEXT: br i1 [[COND]] 23 24entry: 25 %len = load i32, i32* %a_len_ptr, !range !0 26 br label %loop 27 28loop: 29 %idx = phi i32 [ -3, %entry ], [ %idx.next, %in.bounds ] 30 %idx.next = add i32 %idx, 1 31 %abc = icmp slt i32 %idx, %len 32 br i1 %abc, label %in.bounds, label %out.of.bounds 33 34in.bounds: 35 %addr = getelementptr i32, i32* %arr, i32 %idx 36 store i32 0, i32* %addr 37 %next = icmp ne i32 %idx.next, 100 38 br i1 %next, label %loop, label %exit 39 40out.of.bounds: 41 ret void 42 43exit: 44 ret void 45} 46 47; Show that IRCE can turn 'ne' condition to 'ult' in increasing IV when IV is 48; non-negative. 49define void @test_01u(i32* %arr, i32* %a_len_ptr) #0 { 50 51; CHECK: test_01u 52; CHECK: main.exit.selector: 53; CHECK-NEXT: [[PSEUDO_PHI:%[^ ]+]] = phi i32 [ %idx.next, %in.bounds ] 54; CHECK-NEXT: [[COND:%[^ ]+]] = icmp ult i32 [[PSEUDO_PHI]], 100 55; CHECK-NEXT: br i1 [[COND]] 56 57entry: 58 %len = load i32, i32* %a_len_ptr, !range !0 59 br label %loop 60 61loop: 62 %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ] 63 %idx.next = add i32 %idx, 1 64 %abc = icmp slt i32 %idx, %len 65 br i1 %abc, label %in.bounds, label %out.of.bounds 66 67in.bounds: 68 %addr = getelementptr i32, i32* %arr, i32 %idx 69 store i32 0, i32* %addr 70 %next = icmp ne i32 %idx.next, 100 71 br i1 %next, label %loop, label %exit 72 73out.of.bounds: 74 ret void 75 76exit: 77 ret void 78} 79 80; Show that if n is not known to be greater than the starting value, IRCE 81; doesn't apply. 82define void @test_02(i32* %arr, i32* %a_len_ptr) #0 { 83 84; CHECK: test_02( 85 86entry: 87 %len = load i32, i32* %a_len_ptr, !range !0 88 br label %loop 89 90loop: 91 %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ] 92 %idx.next = add i32 %idx, 1 93 %abc = icmp slt i32 %idx, %len 94 br i1 %abc, label %in.bounds, label %out.of.bounds 95 96in.bounds: 97 %addr = getelementptr i32, i32* %arr, i32 %idx 98 store i32 0, i32* %addr 99 %next = icmp ne i32 %idx.next, -100 100 br i1 %next, label %loop, label %exit 101 102out.of.bounds: 103 ret void 104 105exit: 106 ret void 107} 108 109; Show that IRCE can turn 'eq' condition to 'sge' in increasing IV. 110define void @test_03(i32* %arr, i32* %a_len_ptr) #0 { 111 112; CHECK: test_03( 113; CHECK: main.exit.selector: 114; CHECK-NEXT: [[PSEUDO_PHI:%[^ ]+]] = phi i32 [ %idx.next, %in.bounds ] 115; CHECK-NEXT: [[COND:%[^ ]+]] = icmp ult i32 [[PSEUDO_PHI]], 100 116; CHECK-NEXT: br i1 [[COND]] 117 118entry: 119 %len = load i32, i32* %a_len_ptr, !range !0 120 br label %loop 121 122loop: 123 %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ] 124 %idx.next = add i32 %idx, 1 125 %abc = icmp slt i32 %idx, %len 126 br i1 %abc, label %in.bounds, label %out.of.bounds 127 128in.bounds: 129 %addr = getelementptr i32, i32* %arr, i32 %idx 130 store i32 0, i32* %addr 131 %next = icmp eq i32 %idx.next, 100 132 br i1 %next, label %exit, label %loop 133 134out.of.bounds: 135 ret void 136 137exit: 138 ret void 139} 140 141define void @test_04(i32* %arr, i32* %a_len_ptr) #0 { 142 143entry: 144 %len = load i32, i32* %a_len_ptr, !range !0 145 br label %loop 146 147loop: 148 %idx = phi i32 [ 0, %entry ], [ %idx.next, %in.bounds ] 149 %idx.next = add i32 %idx, 1 150 %abc = icmp slt i32 %idx, %len 151 br i1 %abc, label %in.bounds, label %out.of.bounds 152 153in.bounds: 154 %addr = getelementptr i32, i32* %arr, i32 %idx 155 store i32 0, i32* %addr 156 %next = icmp eq i32 %idx.next, -100 157 br i1 %next, label %exit, label %loop 158 159out.of.bounds: 160 ret void 161 162exit: 163 ret void 164} 165 166; Show that IRCE can turn 'ne' condition to 'sgt' in decreasing IV. 167define void @test_05(i32* %arr, i32* %a_len_ptr) #0 { 168 169; CHECK: test_05( 170; CHECK: preloop.exit.selector: 171; CHECK-NEXT: [[PSEUDO_PHI:%[^ ]+]] = phi i32 [ %idx.next.preloop, %in.bounds.preloop ] 172; CHECK-NEXT: [[COND:%[^ ]+]] = icmp sgt i32 [[PSEUDO_PHI]], 0 173; CHECK-NEXT: br i1 [[COND]] 174 175entry: 176 %len = load i32, i32* %a_len_ptr, !range !0 177 br label %loop 178 179loop: 180 %idx = phi i32 [ 100, %entry ], [ %idx.next, %in.bounds ] 181 %idx.next = add i32 %idx, -1 182 %abc = icmp slt i32 %idx, %len 183 br i1 %abc, label %in.bounds, label %out.of.bounds 184 185in.bounds: 186 %addr = getelementptr i32, i32* %arr, i32 %idx 187 store i32 0, i32* %addr 188 %next = icmp ne i32 %idx.next, 0 189 br i1 %next, label %loop, label %exit 190 191out.of.bounds: 192 ret void 193 194exit: 195 ret void 196} 197 198; Show that IRCE cannot turn 'ne' condition to 'sgt' in decreasing IV if the end 199; value is not proved to be less than the start value. 200define void @test_06(i32* %arr, i32* %a_len_ptr) #0 { 201 202; CHECK: test_06( 203 204entry: 205 %len = load i32, i32* %a_len_ptr, !range !0 206 br label %loop 207 208loop: 209 %idx = phi i32 [ 100, %entry ], [ %idx.next, %in.bounds ] 210 %idx.next = add i32 %idx, -1 211 %abc = icmp slt i32 %idx, %len 212 br i1 %abc, label %in.bounds, label %out.of.bounds 213 214in.bounds: 215 %addr = getelementptr i32, i32* %arr, i32 %idx 216 store i32 0, i32* %addr 217 %next = icmp ne i32 %idx.next, 120 218 br i1 %next, label %loop, label %exit 219 220out.of.bounds: 221 ret void 222 223exit: 224 ret void 225} 226 227; Show that IRCE can turn 'eq' condition to 'slt' in decreasing IV. 228define void @test_07(i32* %arr, i32* %a_len_ptr) #0 { 229 230; CHECK: test_07( 231; CHECK: preloop.exit.selector: 232; CHECK-NEXT: [[PSEUDO_PHI:%[^ ]+]] = phi i32 [ %idx.next.preloop, %in.bounds.preloop ] 233; CHECK-NEXT: [[COND:%[^ ]+]] = icmp sgt i32 [[PSEUDO_PHI]], 0 234; CHECK-NEXT: br i1 [[COND]] 235 236entry: 237 %len = load i32, i32* %a_len_ptr, !range !0 238 br label %loop 239 240loop: 241 %idx = phi i32 [ 100, %entry ], [ %idx.next, %in.bounds ] 242 %idx.next = add i32 %idx, -1 243 %abc = icmp slt i32 %idx, %len 244 br i1 %abc, label %in.bounds, label %out.of.bounds 245 246in.bounds: 247 %addr = getelementptr i32, i32* %arr, i32 %idx 248 store i32 0, i32* %addr 249 %next = icmp eq i32 %idx.next, 0 250 br i1 %next, label %exit, label %loop 251 252out.of.bounds: 253 ret void 254 255exit: 256 ret void 257} 258 259; Show that IRCE cannot turn 'eq' condition to 'slt' in decreasing IV if the end 260; value is not proved to be less than the start value. 261define void @test_08(i32* %arr, i32* %a_len_ptr) #0 { 262 263; CHECK: test_08( 264 265entry: 266 %len = load i32, i32* %a_len_ptr, !range !0 267 br label %loop 268 269loop: 270 %idx = phi i32 [ 100, %entry ], [ %idx.next, %in.bounds ] 271 %idx.next = add i32 %idx, -1 272 %abc = icmp slt i32 %idx, %len 273 br i1 %abc, label %in.bounds, label %out.of.bounds 274 275in.bounds: 276 %addr = getelementptr i32, i32* %arr, i32 %idx 277 store i32 0, i32* %addr 278 %next = icmp eq i32 %idx.next, 120 279 br i1 %next, label %exit, label %loop 280 281out.of.bounds: 282 ret void 283 284exit: 285 ret void 286} 287 288!0 = !{i32 0, i32 50} 289