1 ; RUN: opt -verify-loop-info -irce -S < %s | FileCheck %s 2 ; RUN: opt -verify-loop-info -passes='require<branch-prob>,loop(irce)' -S < %s | FileCheck %s 3 4 define void @decrementing_loop(i32 *%arr, i32 *%a_len_ptr, i32 %n) { 5 entry: 6 %len = load i32, i32* %a_len_ptr, !range !0 7 %first.itr.check = icmp sgt i32 %n, 0 8 %start = sub i32 %n, 1 9 br i1 %first.itr.check, label %loop, label %exit 10 11 loop: 12 %idx = phi i32 [ %start, %entry ] , [ %idx.dec, %in.bounds ] 13 %idx.dec = sub i32 %idx, 1 14 %abc.high = icmp slt i32 %idx, %len 15 %abc.low = icmp sge i32 %idx, 0 16 %abc = and i1 %abc.low, %abc.high 17 br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1 18 19 in.bounds: 20 %addr = getelementptr i32, i32* %arr, i32 %idx 21 store i32 0, i32* %addr 22 %next = icmp sgt i32 %idx.dec, -1 23 br i1 %next, label %loop, label %exit 24 25 out.of.bounds: 26 ret void 27 28 exit: 29 ret void 30 31 ; CHECK: loop.preheader: 32 ; CHECK: [[not_len:[^ ]+]] = sub i32 -1, %len 33 ; CHECK: [[not_n:[^ ]+]] = sub i32 -1, %n 34 ; CHECK: [[not_len_hiclamp_cmp:[^ ]+]] = icmp sgt i32 [[not_len]], [[not_n]] 35 ; CHECK: [[not_len_hiclamp:[^ ]+]] = select i1 [[not_len_hiclamp_cmp]], i32 [[not_len]], i32 [[not_n]] 36 ; CHECK: [[len_hiclamp:[^ ]+]] = sub i32 -1, [[not_len_hiclamp]] 37 ; CHECK: [[not_exit_preloop_at_cmp:[^ ]+]] = icmp sgt i32 [[len_hiclamp]], 0 38 ; CHECK: [[not_exit_preloop_at:[^ ]+]] = select i1 [[not_exit_preloop_at_cmp]], i32 [[len_hiclamp]], i32 0 39 ; CHECK: %exit.preloop.at = add i32 [[not_exit_preloop_at]], -1 40 } 41 42 ; Make sure that we can eliminate the range check when the loop looks like: 43 ; for (i = len.a - 1; i >= 0; --i) 44 ; b[i] = a[i]; 45 define void @test_01(i32* %a, i32* %b, i32* %a_len_ptr, i32* %b_len_ptr) { 46 47 ; CHECK-LABEL: test_01 48 ; CHECK: mainloop: 49 ; CHECK-NEXT: br label %loop 50 ; CHECK: loop: 51 ; CHECK: %rc = and i1 true, true 52 ; CHECK: loop.preloop: 53 54 entry: 55 %len.a = load i32, i32* %a_len_ptr, !range !0 56 %len.b = load i32, i32* %b_len_ptr, !range !0 57 %first.itr.check = icmp ne i32 %len.a, 0 58 br i1 %first.itr.check, label %loop, label %exit 59 60 loop: 61 %idx = phi i32 [ %len.a, %entry ] , [ %idx.next, %in.bounds ] 62 %idx.next = sub i32 %idx, 1 63 %rca = icmp ult i32 %idx.next, %len.a 64 %rcb = icmp ult i32 %idx.next, %len.b 65 %rc = and i1 %rca, %rcb 66 br i1 %rc, label %in.bounds, label %out.of.bounds, !prof !1 67 68 in.bounds: 69 %el.a = getelementptr i32, i32* %a, i32 %idx.next 70 %el.b = getelementptr i32, i32* %b, i32 %idx.next 71 %v = load i32, i32* %el.a 72 store i32 %v, i32* %el.b 73 %loop.cond = icmp slt i32 %idx, 2 74 br i1 %loop.cond, label %exit, label %loop 75 76 out.of.bounds: 77 ret void 78 79 exit: 80 ret void 81 } 82 83 ; Same as test_01, but the latch condition is unsigned 84 define void @test_02(i32* %a, i32* %b, i32* %a_len_ptr, i32* %b_len_ptr) { 85 86 ; CHECK-LABEL: test_02 87 ; CHECK: mainloop: 88 ; CHECK-NEXT: br label %loop 89 ; CHECK: loop: 90 ; CHECK: %rc = and i1 true, true 91 ; CHECK: loop.preloop: 92 93 entry: 94 %len.a = load i32, i32* %a_len_ptr, !range !0 95 %len.b = load i32, i32* %b_len_ptr, !range !0 96 %first.itr.check = icmp ne i32 %len.a, 0 97 br i1 %first.itr.check, label %loop, label %exit 98 99 loop: 100 %idx = phi i32 [ %len.a, %entry ] , [ %idx.next, %in.bounds ] 101 %idx.next = sub i32 %idx, 1 102 %rca = icmp ult i32 %idx.next, %len.a 103 %rcb = icmp ult i32 %idx.next, %len.b 104 %rc = and i1 %rca, %rcb 105 br i1 %rc, label %in.bounds, label %out.of.bounds, !prof !1 106 107 in.bounds: 108 %el.a = getelementptr i32, i32* %a, i32 %idx.next 109 %el.b = getelementptr i32, i32* %b, i32 %idx.next 110 %v = load i32, i32* %el.a 111 store i32 %v, i32* %el.b 112 %loop.cond = icmp ult i32 %idx, 2 113 br i1 %loop.cond, label %exit, label %loop 114 115 out.of.bounds: 116 ret void 117 118 exit: 119 ret void 120 } 121 122 ; Check that we can figure out that IV is non-negative via implication through 123 ; Phi node. 124 define void @test_03(i32* %a, i32* %a_len_ptr, i1 %cond) { 125 126 ; CHECK-LABEL: test_03 127 ; CHECK: mainloop: 128 ; CHECK-NEXT: br label %loop 129 ; CHECK: loop: 130 ; CHECK: br i1 true, label %in.bounds, label %out.of.bounds 131 ; CHECK: loop.preloop: 132 133 entry: 134 %len.a = load i32, i32* %a_len_ptr, !range !0 135 %len.minus.one = sub nsw i32 %len.a, 1 136 %len.minus.two = sub nsw i32 %len.a, 2 137 br i1 %cond, label %if.true, label %if.false 138 139 if.true: 140 br label %merge 141 142 if.false: 143 br label %merge 144 145 merge: 146 %starting.value = phi i32 [ %len.minus.two, %if.true ], [ %len.minus.one, %if.false ] 147 %first.itr.check = icmp sgt i32 %len.a, 3 148 br i1 %first.itr.check, label %loop, label %exit 149 150 loop: 151 %idx = phi i32 [ %starting.value, %merge ] , [ %idx.next, %in.bounds ] 152 %idx.next = sub i32 %idx, 1 153 %rc = icmp ult i32 %idx.next, %len.a 154 br i1 %rc, label %in.bounds, label %out.of.bounds, !prof !1 155 156 in.bounds: 157 %el.a = getelementptr i32, i32* %a, i32 %idx.next 158 %v = load i32, i32* %el.a 159 %loop.cond = icmp slt i32 %idx, 2 160 br i1 %loop.cond, label %exit, label %loop 161 162 out.of.bounds: 163 ret void 164 165 exit: 166 ret void 167 } 168 169 ; Check that we can figure out that IV is non-negative via implication through 170 ; two Phi nodes. 171 define void @test_04(i32* %a, i32* %a_len_ptr, i1 %cond) { 172 173 ; CHECK-LABEL: test_04 174 ; CHECK: mainloop: 175 ; CHECK-NEXT: br label %loop 176 ; CHECK: loop: 177 ; CHECK: br i1 true, label %in.bounds, label %out.of.bounds 178 ; CHECK: loop.preloop: 179 180 entry: 181 %len.a = load i32, i32* %a_len_ptr, !range !0 182 %len.minus.one = sub nsw i32 %len.a, 1 183 %len.plus.one = add nsw i32 %len.a, 1 184 %len.minus.two = sub nsw i32 %len.a, 2 185 br i1 %cond, label %if.true, label %if.false 186 187 if.true: 188 br label %merge 189 190 if.false: 191 br label %merge 192 193 merge: 194 %starting.value = phi i32 [ %len.minus.two, %if.true ], [ %len.minus.one, %if.false ] 195 %len.phi = phi i32 [ %len.a, %if.true ], [ %len.plus.one, %if.false ] 196 %first.itr.check = icmp sgt i32 %len.a, 3 197 br i1 %first.itr.check, label %loop, label %exit 198 199 loop: 200 %idx = phi i32 [ %starting.value, %merge ] , [ %idx.next, %in.bounds ] 201 %idx.next = sub i32 %idx, 1 202 %rc = icmp ult i32 %idx.next, %len.phi 203 br i1 %rc, label %in.bounds, label %out.of.bounds, !prof !1 204 205 in.bounds: 206 %el.a = getelementptr i32, i32* %a, i32 %idx.next 207 %v = load i32, i32* %el.a 208 %loop.cond = icmp slt i32 %idx, 2 209 br i1 %loop.cond, label %exit, label %loop 210 211 out.of.bounds: 212 ret void 213 214 exit: 215 ret void 216 } 217 218 ; Check that we can figure out that IV is non-negative via implication through 219 ; two Phi nodes, one being AddRec. 220 define void @test_05(i32* %a, i32* %a_len_ptr, i1 %cond) { 221 222 ; CHECK-LABEL: test_05 223 ; CHECK: mainloop: 224 ; CHECK-NEXT: br label %loop 225 ; CHECK: loop: 226 ; CHECK: br i1 true, label %in.bounds, label %out.of.bounds 227 ; CHECK: loop.preloop: 228 229 entry: 230 %len.a = load i32, i32* %a_len_ptr, !range !0 231 %len.minus.one = sub nsw i32 %len.a, 1 232 %len.plus.one = add nsw i32 %len.a, 1 233 %len.minus.two = sub nsw i32 %len.a, 2 234 br label %merge 235 236 merge: 237 %starting.value = phi i32 [ %len.minus.two, %entry ], [ %len.minus.one, %merge ] 238 %len.phi = phi i32 [ %len.a, %entry ], [ %len.phi.next, %merge ] 239 %len.phi.next = add nsw i32 %len.phi, 1 240 br i1 true, label %first.iter.check, label %merge 241 242 first.iter.check: 243 %first.itr.check = icmp sgt i32 %len.a, 3 244 br i1 %first.itr.check, label %loop, label %exit 245 246 loop: 247 %idx = phi i32 [ %starting.value, %first.iter.check ] , [ %idx.next, %in.bounds ] 248 %idx.next = sub i32 %idx, 1 249 %rc = icmp ult i32 %idx.next, %len.phi 250 br i1 %rc, label %in.bounds, label %out.of.bounds, !prof !1 251 252 in.bounds: 253 %el.a = getelementptr i32, i32* %a, i32 %idx.next 254 %v = load i32, i32* %el.a 255 %loop.cond = icmp slt i32 %idx, 2 256 br i1 %loop.cond, label %exit, label %loop 257 258 out.of.bounds: 259 ret void 260 261 exit: 262 ret void 263 } 264 265 !0 = !{i32 0, i32 2147483647} 266 !1 = !{!"branch_weights", i32 64, i32 4} 267