1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2 ; RUN: opt -verify-loop-info -irce-print-changed-loops -irce -S < %s 2>&1 | FileCheck %s 3 ; RUN: opt -verify-loop-info -irce-print-changed-loops -passes='require<branch-prob>,loop(irce)' -S < %s 2>&1 | FileCheck %s 4 5 ; CHECK-NOT: irce: in function test_01: constrained Loop 6 ; CHECK-NOT: irce: in function test_02: constrained Loop 7 ; CHECK: irce: in function test_03: constrained Loop 8 9 ; RC against known negative value. We should not do IRCE here. 10 define void @test_01(i32 *%arr, i32 %n) { 11 ; CHECK-LABEL: @test_01( 12 ; CHECK-NEXT: entry: 13 ; CHECK-NEXT: [[FIRST_ITR_CHECK:%.*]] = icmp sgt i32 [[N:%.*]], 0 14 ; CHECK-NEXT: br i1 [[FIRST_ITR_CHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 15 ; CHECK: loop.preheader: 16 ; CHECK-NEXT: br label [[LOOP:%.*]] 17 ; CHECK: loop: 18 ; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] 19 ; CHECK-NEXT: [[IDX_NEXT]] = add i32 [[IDX]], 1 20 ; CHECK-NEXT: [[ABC:%.*]] = icmp slt i32 [[IDX]], -9 21 ; CHECK-NEXT: br i1 [[ABC]], label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS:%.*]], !prof !0 22 ; CHECK: in.bounds: 23 ; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, i32* [[ARR:%.*]], i32 [[IDX]] 24 ; CHECK-NEXT: store i32 0, i32* [[ADDR]] 25 ; CHECK-NEXT: [[NEXT:%.*]] = icmp slt i32 [[IDX_NEXT]], [[N]] 26 ; CHECK-NEXT: br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 27 ; CHECK: out.of.bounds: 28 ; CHECK-NEXT: ret void 29 ; CHECK: exit.loopexit: 30 ; CHECK-NEXT: br label [[EXIT]] 31 ; CHECK: exit: 32 ; CHECK-NEXT: ret void 33 ; 34 35 entry: 36 %first.itr.check = icmp sgt i32 %n, 0 37 br i1 %first.itr.check, label %loop, label %exit 38 39 loop: 40 %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ] 41 %idx.next = add i32 %idx, 1 42 %abc = icmp slt i32 %idx, -9 43 br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !0 44 45 in.bounds: 46 %addr = getelementptr i32, i32* %arr, i32 %idx 47 store i32 0, i32* %addr 48 %next = icmp slt i32 %idx.next, %n 49 br i1 %next, label %loop, label %exit 50 51 out.of.bounds: 52 ret void 53 54 exit: 55 ret void 56 } 57 58 ; Same as test_01, but the latch condition is unsigned. 59 define void @test_02(i32 *%arr, i32 %n) { 60 ; CHECK-LABEL: @test_02( 61 ; CHECK-NEXT: entry: 62 ; CHECK-NEXT: [[FIRST_ITR_CHECK:%.*]] = icmp sgt i32 [[N:%.*]], 0 63 ; CHECK-NEXT: br i1 [[FIRST_ITR_CHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 64 ; CHECK: loop.preheader: 65 ; CHECK-NEXT: br label [[LOOP:%.*]] 66 ; CHECK: loop: 67 ; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] 68 ; CHECK-NEXT: [[IDX_NEXT]] = add i32 [[IDX]], 1 69 ; CHECK-NEXT: [[ABC:%.*]] = icmp slt i32 [[IDX]], -9 70 ; CHECK-NEXT: br i1 [[ABC]], label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS:%.*]], !prof !0 71 ; CHECK: in.bounds: 72 ; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, i32* [[ARR:%.*]], i32 [[IDX]] 73 ; CHECK-NEXT: store i32 0, i32* [[ADDR]] 74 ; CHECK-NEXT: [[NEXT:%.*]] = icmp ult i32 [[IDX_NEXT]], [[N]] 75 ; CHECK-NEXT: br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 76 ; CHECK: out.of.bounds: 77 ; CHECK-NEXT: ret void 78 ; CHECK: exit.loopexit: 79 ; CHECK-NEXT: br label [[EXIT]] 80 ; CHECK: exit: 81 ; CHECK-NEXT: ret void 82 ; 83 84 entry: 85 %first.itr.check = icmp sgt i32 %n, 0 86 br i1 %first.itr.check, label %loop, label %exit 87 88 loop: 89 %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ] 90 %idx.next = add i32 %idx, 1 91 %abc = icmp slt i32 %idx, -9 92 br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !0 93 94 in.bounds: 95 %addr = getelementptr i32, i32* %arr, i32 %idx 96 store i32 0, i32* %addr 97 %next = icmp ult i32 %idx.next, %n 98 br i1 %next, label %loop, label %exit 99 100 out.of.bounds: 101 ret void 102 103 exit: 104 ret void 105 } 106 107 ; RC against a value which is not known to be non-negative. Here we should 108 ; expand runtime checks against bound being positive or negative. 109 define void @test_03(i32 *%arr, i32 %n, i32 %bound) { 110 ; CHECK-LABEL: @test_03( 111 ; CHECK-NEXT: entry: 112 ; CHECK-NEXT: [[FIRST_ITR_CHECK:%.*]] = icmp sgt i32 [[N:%.*]], 0 113 ; CHECK-NEXT: br i1 [[FIRST_ITR_CHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 114 ; CHECK: loop.preheader: 115 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[BOUND:%.*]], -2147483647 116 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[TMP0]], 0 117 ; CHECK-NEXT: [[SMAX:%.*]] = select i1 [[TMP1]], i32 [[TMP0]], i32 0 118 ; CHECK-NEXT: [[TMP2:%.*]] = sub i32 [[BOUND]], [[SMAX]] 119 ; CHECK-NEXT: [[TMP3:%.*]] = sub i32 -1, [[BOUND]] 120 ; CHECK-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[TMP3]], -1 121 ; CHECK-NEXT: [[SMAX1:%.*]] = select i1 [[TMP4]], i32 [[TMP3]], i32 -1 122 ; CHECK-NEXT: [[TMP5:%.*]] = sub i32 -1, [[SMAX1]] 123 ; CHECK-NEXT: [[TMP6:%.*]] = icmp sgt i32 [[TMP5]], -1 124 ; CHECK-NEXT: [[SMAX2:%.*]] = select i1 [[TMP6]], i32 [[TMP5]], i32 -1 125 ; CHECK-NEXT: [[TMP7:%.*]] = add i32 [[SMAX2]], 1 126 ; CHECK-NEXT: [[TMP8:%.*]] = mul i32 [[TMP2]], [[TMP7]] 127 ; CHECK-NEXT: [[TMP9:%.*]] = sub i32 -1, [[TMP8]] 128 ; CHECK-NEXT: [[TMP10:%.*]] = sub i32 -1, [[N]] 129 ; CHECK-NEXT: [[TMP11:%.*]] = icmp sgt i32 [[TMP9]], [[TMP10]] 130 ; CHECK-NEXT: [[SMAX3:%.*]] = select i1 [[TMP11]], i32 [[TMP9]], i32 [[TMP10]] 131 ; CHECK-NEXT: [[TMP12:%.*]] = sub i32 -1, [[SMAX3]] 132 ; CHECK-NEXT: [[TMP13:%.*]] = icmp sgt i32 [[TMP12]], 0 133 ; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = select i1 [[TMP13]], i32 [[TMP12]], i32 0 134 ; CHECK-NEXT: [[TMP14:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]] 135 ; CHECK-NEXT: br i1 [[TMP14]], label [[LOOP_PREHEADER5:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]] 136 ; CHECK: loop.preheader5: 137 ; CHECK-NEXT: br label [[LOOP:%.*]] 138 ; CHECK: loop: 139 ; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER5]] ] 140 ; CHECK-NEXT: [[IDX_NEXT]] = add i32 [[IDX]], 1 141 ; CHECK-NEXT: [[ABC:%.*]] = icmp slt i32 [[IDX]], [[BOUND]] 142 ; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT6:%.*]], !prof !0 143 ; CHECK: in.bounds: 144 ; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, i32* [[ARR:%.*]], i32 [[IDX]] 145 ; CHECK-NEXT: store i32 0, i32* [[ADDR]] 146 ; CHECK-NEXT: [[NEXT:%.*]] = icmp slt i32 [[IDX_NEXT]], [[N]] 147 ; CHECK-NEXT: [[TMP15:%.*]] = icmp slt i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]] 148 ; CHECK-NEXT: br i1 [[TMP15]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]] 149 ; CHECK: main.exit.selector: 150 ; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ] 151 ; CHECK-NEXT: [[TMP16:%.*]] = icmp slt i32 [[IDX_NEXT_LCSSA]], [[N]] 152 ; CHECK-NEXT: br i1 [[TMP16]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]] 153 ; CHECK: main.pseudo.exit: 154 ; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i32 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] 155 ; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] 156 ; CHECK-NEXT: br label [[POSTLOOP:%.*]] 157 ; CHECK: out.of.bounds.loopexit: 158 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]] 159 ; CHECK: out.of.bounds.loopexit6: 160 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS]] 161 ; CHECK: out.of.bounds: 162 ; CHECK-NEXT: ret void 163 ; CHECK: exit.loopexit.loopexit: 164 ; CHECK-NEXT: br label [[EXIT_LOOPEXIT]] 165 ; CHECK: exit.loopexit: 166 ; CHECK-NEXT: br label [[EXIT]] 167 ; CHECK: exit: 168 ; CHECK-NEXT: ret void 169 ; CHECK: postloop: 170 ; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]] 171 ; CHECK: loop.postloop: 172 ; CHECK-NEXT: [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ], [ [[IDX_COPY]], [[POSTLOOP]] ] 173 ; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add i32 [[IDX_POSTLOOP]], 1 174 ; CHECK-NEXT: [[ABC_POSTLOOP:%.*]] = icmp slt i32 [[IDX_POSTLOOP]], [[BOUND]] 175 ; CHECK-NEXT: br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]], !prof !0 176 ; CHECK: in.bounds.postloop: 177 ; CHECK-NEXT: [[ADDR_POSTLOOP:%.*]] = getelementptr i32, i32* [[ARR]], i32 [[IDX_POSTLOOP]] 178 ; CHECK-NEXT: store i32 0, i32* [[ADDR_POSTLOOP]] 179 ; CHECK-NEXT: [[NEXT_POSTLOOP:%.*]] = icmp slt i32 [[IDX_NEXT_POSTLOOP]], [[N]] 180 ; CHECK-NEXT: br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT:%.*]], !llvm.loop !1, !irce.loop.clone !6 181 ; 182 183 entry: 184 %first.itr.check = icmp sgt i32 %n, 0 185 br i1 %first.itr.check, label %loop, label %exit 186 187 loop: 188 %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ] 189 %idx.next = add i32 %idx, 1 190 %abc = icmp slt i32 %idx, %bound 191 br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !0 192 193 in.bounds: 194 %addr = getelementptr i32, i32* %arr, i32 %idx 195 store i32 0, i32* %addr 196 %next = icmp slt i32 %idx.next, %n 197 br i1 %next, label %loop, label %exit 198 199 out.of.bounds: 200 ret void 201 202 exit: 203 ret void 204 } 205 206 ; RC against a value which is not known to be non-negative. Here we should 207 ; expand runtime checks against bound being positive or negative. 208 define void @test_04(i32 *%arr, i32 %n, i32 %bound) { 209 ; CHECK-LABEL: @test_04( 210 ; CHECK-NEXT: entry: 211 ; CHECK-NEXT: [[FIRST_ITR_CHECK:%.*]] = icmp sgt i32 [[N:%.*]], 0 212 ; CHECK-NEXT: br i1 [[FIRST_ITR_CHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 213 ; CHECK: loop.preheader: 214 ; CHECK-NEXT: [[TMP0:%.*]] = sub i32 -1, [[BOUND:%.*]] 215 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[TMP0]], -1 216 ; CHECK-NEXT: [[SMAX:%.*]] = select i1 [[TMP1]], i32 [[TMP0]], i32 -1 217 ; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[BOUND]], [[SMAX]] 218 ; CHECK-NEXT: [[TMP3:%.*]] = add i32 [[TMP2]], 1 219 ; CHECK-NEXT: [[TMP4:%.*]] = sub i32 -1, [[SMAX]] 220 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sgt i32 [[TMP4]], -1 221 ; CHECK-NEXT: [[SMAX1:%.*]] = select i1 [[TMP5]], i32 [[TMP4]], i32 -1 222 ; CHECK-NEXT: [[TMP6:%.*]] = add i32 [[SMAX1]], 1 223 ; CHECK-NEXT: [[TMP7:%.*]] = mul i32 [[TMP3]], [[TMP6]] 224 ; CHECK-NEXT: [[TMP8:%.*]] = sub i32 -1, [[TMP7]] 225 ; CHECK-NEXT: [[TMP9:%.*]] = sub i32 -1, [[N]] 226 ; CHECK-NEXT: [[TMP10:%.*]] = icmp ugt i32 [[TMP8]], [[TMP9]] 227 ; CHECK-NEXT: [[UMAX:%.*]] = select i1 [[TMP10]], i32 [[TMP8]], i32 [[TMP9]] 228 ; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = sub i32 -1, [[UMAX]] 229 ; CHECK-NEXT: [[TMP11:%.*]] = icmp ult i32 0, [[EXIT_MAINLOOP_AT]] 230 ; CHECK-NEXT: br i1 [[TMP11]], label [[LOOP_PREHEADER2:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]] 231 ; CHECK: loop.preheader2: 232 ; CHECK-NEXT: br label [[LOOP:%.*]] 233 ; CHECK: loop: 234 ; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER2]] ] 235 ; CHECK-NEXT: [[IDX_NEXT]] = add i32 [[IDX]], 1 236 ; CHECK-NEXT: [[ABC:%.*]] = icmp slt i32 [[IDX]], [[BOUND]] 237 ; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT3:%.*]], !prof !0 238 ; CHECK: in.bounds: 239 ; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, i32* [[ARR:%.*]], i32 [[IDX]] 240 ; CHECK-NEXT: store i32 0, i32* [[ADDR]] 241 ; CHECK-NEXT: [[NEXT:%.*]] = icmp ult i32 [[IDX_NEXT]], [[N]] 242 ; CHECK-NEXT: [[TMP12:%.*]] = icmp ult i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]] 243 ; CHECK-NEXT: br i1 [[TMP12]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]] 244 ; CHECK: main.exit.selector: 245 ; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ] 246 ; CHECK-NEXT: [[TMP13:%.*]] = icmp ult i32 [[IDX_NEXT_LCSSA]], [[N]] 247 ; CHECK-NEXT: br i1 [[TMP13]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]] 248 ; CHECK: main.pseudo.exit: 249 ; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i32 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] 250 ; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] 251 ; CHECK-NEXT: br label [[POSTLOOP:%.*]] 252 ; CHECK: out.of.bounds.loopexit: 253 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]] 254 ; CHECK: out.of.bounds.loopexit3: 255 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS]] 256 ; CHECK: out.of.bounds: 257 ; CHECK-NEXT: ret void 258 ; CHECK: exit.loopexit.loopexit: 259 ; CHECK-NEXT: br label [[EXIT_LOOPEXIT]] 260 ; CHECK: exit.loopexit: 261 ; CHECK-NEXT: br label [[EXIT]] 262 ; CHECK: exit: 263 ; CHECK-NEXT: ret void 264 ; CHECK: postloop: 265 ; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]] 266 ; CHECK: loop.postloop: 267 ; CHECK-NEXT: [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ], [ [[IDX_COPY]], [[POSTLOOP]] ] 268 ; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add i32 [[IDX_POSTLOOP]], 1 269 ; CHECK-NEXT: [[ABC_POSTLOOP:%.*]] = icmp slt i32 [[IDX_POSTLOOP]], [[BOUND]] 270 ; CHECK-NEXT: br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]], !prof !0 271 ; CHECK: in.bounds.postloop: 272 ; CHECK-NEXT: [[ADDR_POSTLOOP:%.*]] = getelementptr i32, i32* [[ARR]], i32 [[IDX_POSTLOOP]] 273 ; CHECK-NEXT: store i32 0, i32* [[ADDR_POSTLOOP]] 274 ; CHECK-NEXT: [[NEXT_POSTLOOP:%.*]] = icmp ult i32 [[IDX_NEXT_POSTLOOP]], [[N]] 275 ; CHECK-NEXT: br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT:%.*]], !llvm.loop !7, !irce.loop.clone !6 276 ; 277 278 entry: 279 %first.itr.check = icmp sgt i32 %n, 0 280 br i1 %first.itr.check, label %loop, label %exit 281 282 loop: 283 %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ] 284 %idx.next = add i32 %idx, 1 285 %abc = icmp slt i32 %idx, %bound 286 br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !0 287 288 in.bounds: 289 %addr = getelementptr i32, i32* %arr, i32 %idx 290 store i32 0, i32* %addr 291 %next = icmp ult i32 %idx.next, %n 292 br i1 %next, label %loop, label %exit 293 294 out.of.bounds: 295 ret void 296 297 exit: 298 ret void 299 } 300 301 ; Same as test_01, unsigned range check. 302 ; FIXME: We could remove the range check here, but it does not happen due to the 303 ; limintation we posed to fix the miscompile (see comments in the method 304 ; computeSafeIterationSpace). 305 define void @test_05(i32 *%arr, i32 %n) { 306 ; CHECK-LABEL: @test_05( 307 ; CHECK-NEXT: entry: 308 ; CHECK-NEXT: [[FIRST_ITR_CHECK:%.*]] = icmp sgt i32 [[N:%.*]], 0 309 ; CHECK-NEXT: br i1 [[FIRST_ITR_CHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 310 ; CHECK: loop.preheader: 311 ; CHECK-NEXT: br label [[LOOP:%.*]] 312 ; CHECK: loop: 313 ; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] 314 ; CHECK-NEXT: [[IDX_NEXT]] = add i32 [[IDX]], 1 315 ; CHECK-NEXT: [[ABC:%.*]] = icmp ult i32 [[IDX]], -9 316 ; CHECK-NEXT: br i1 [[ABC]], label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS:%.*]], !prof !0 317 ; CHECK: in.bounds: 318 ; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, i32* [[ARR:%.*]], i32 [[IDX]] 319 ; CHECK-NEXT: store i32 0, i32* [[ADDR]] 320 ; CHECK-NEXT: [[NEXT:%.*]] = icmp slt i32 [[IDX_NEXT]], [[N]] 321 ; CHECK-NEXT: br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 322 ; CHECK: out.of.bounds: 323 ; CHECK-NEXT: ret void 324 ; CHECK: exit.loopexit: 325 ; CHECK-NEXT: br label [[EXIT]] 326 ; CHECK: exit: 327 ; CHECK-NEXT: ret void 328 ; 329 entry: 330 %first.itr.check = icmp sgt i32 %n, 0 331 br i1 %first.itr.check, label %loop, label %exit 332 333 loop: 334 %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ] 335 %idx.next = add i32 %idx, 1 336 %abc = icmp ult i32 %idx, -9 337 br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !0 338 339 in.bounds: 340 %addr = getelementptr i32, i32* %arr, i32 %idx 341 store i32 0, i32* %addr 342 %next = icmp slt i32 %idx.next, %n 343 br i1 %next, label %loop, label %exit 344 345 out.of.bounds: 346 ret void 347 348 exit: 349 ret void 350 } 351 352 ; Same as test_02, unsigned range check. 353 ; FIXME: We could remove the range check here, but it does not happen due to the 354 ; limintation we posed to fix the miscompile (see comments in the method 355 ; computeSafeIterationSpace). 356 define void @test_06(i32 *%arr, i32 %n) { 357 ; CHECK-LABEL: @test_06( 358 ; CHECK-NEXT: entry: 359 ; CHECK-NEXT: [[FIRST_ITR_CHECK:%.*]] = icmp sgt i32 [[N:%.*]], 0 360 ; CHECK-NEXT: br i1 [[FIRST_ITR_CHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 361 ; CHECK: loop.preheader: 362 ; CHECK-NEXT: br label [[LOOP:%.*]] 363 ; CHECK: loop: 364 ; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] 365 ; CHECK-NEXT: [[IDX_NEXT]] = add i32 [[IDX]], 1 366 ; CHECK-NEXT: [[ABC:%.*]] = icmp ult i32 [[IDX]], -9 367 ; CHECK-NEXT: br i1 [[ABC]], label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS:%.*]], !prof !0 368 ; CHECK: in.bounds: 369 ; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, i32* [[ARR:%.*]], i32 [[IDX]] 370 ; CHECK-NEXT: store i32 0, i32* [[ADDR]] 371 ; CHECK-NEXT: [[NEXT:%.*]] = icmp ult i32 [[IDX_NEXT]], [[N]] 372 ; CHECK-NEXT: br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 373 ; CHECK: out.of.bounds: 374 ; CHECK-NEXT: ret void 375 ; CHECK: exit.loopexit: 376 ; CHECK-NEXT: br label [[EXIT]] 377 ; CHECK: exit: 378 ; CHECK-NEXT: ret void 379 ; 380 entry: 381 %first.itr.check = icmp sgt i32 %n, 0 382 br i1 %first.itr.check, label %loop, label %exit 383 384 loop: 385 %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ] 386 %idx.next = add i32 %idx, 1 387 %abc = icmp ult i32 %idx, -9 388 br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !0 389 390 in.bounds: 391 %addr = getelementptr i32, i32* %arr, i32 %idx 392 store i32 0, i32* %addr 393 %next = icmp ult i32 %idx.next, %n 394 br i1 %next, label %loop, label %exit 395 396 out.of.bounds: 397 ret void 398 399 exit: 400 ret void 401 } 402 403 ; Same as test_03, unsigned range check. 404 ; FIXME: Currently we remove the check, but we will not execute the main loop if 405 ; %bound is negative (i.e. in [SINT_MAX + 1, UINT_MAX)). We should be able to 406 ; safely remove this check (see comments in the method 407 ; computeSafeIterationSpace). 408 define void @test_07(i32 *%arr, i32 %n, i32 %bound) { 409 ; CHECK-LABEL: @test_07( 410 ; CHECK-NEXT: entry: 411 ; CHECK-NEXT: [[FIRST_ITR_CHECK:%.*]] = icmp sgt i32 [[N:%.*]], 0 412 ; CHECK-NEXT: br i1 [[FIRST_ITR_CHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 413 ; CHECK: loop.preheader: 414 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[BOUND:%.*]], -2147483647 415 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[TMP0]], 0 416 ; CHECK-NEXT: [[SMAX:%.*]] = select i1 [[TMP1]], i32 [[TMP0]], i32 0 417 ; CHECK-NEXT: [[TMP2:%.*]] = sub i32 [[BOUND]], [[SMAX]] 418 ; CHECK-NEXT: [[TMP3:%.*]] = sub i32 -1, [[BOUND]] 419 ; CHECK-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[TMP3]], -1 420 ; CHECK-NEXT: [[SMAX1:%.*]] = select i1 [[TMP4]], i32 [[TMP3]], i32 -1 421 ; CHECK-NEXT: [[TMP5:%.*]] = sub i32 -1, [[SMAX1]] 422 ; CHECK-NEXT: [[TMP6:%.*]] = icmp sgt i32 [[TMP5]], -1 423 ; CHECK-NEXT: [[SMAX2:%.*]] = select i1 [[TMP6]], i32 [[TMP5]], i32 -1 424 ; CHECK-NEXT: [[TMP7:%.*]] = add i32 [[SMAX2]], 1 425 ; CHECK-NEXT: [[TMP8:%.*]] = mul i32 [[TMP2]], [[TMP7]] 426 ; CHECK-NEXT: [[TMP9:%.*]] = sub i32 -1, [[TMP8]] 427 ; CHECK-NEXT: [[TMP10:%.*]] = sub i32 -1, [[N]] 428 ; CHECK-NEXT: [[TMP11:%.*]] = icmp sgt i32 [[TMP9]], [[TMP10]] 429 ; CHECK-NEXT: [[SMAX3:%.*]] = select i1 [[TMP11]], i32 [[TMP9]], i32 [[TMP10]] 430 ; CHECK-NEXT: [[TMP12:%.*]] = sub i32 -1, [[SMAX3]] 431 ; CHECK-NEXT: [[TMP13:%.*]] = icmp sgt i32 [[TMP12]], 0 432 ; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = select i1 [[TMP13]], i32 [[TMP12]], i32 0 433 ; CHECK-NEXT: [[TMP14:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]] 434 ; CHECK-NEXT: br i1 [[TMP14]], label [[LOOP_PREHEADER5:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]] 435 ; CHECK: loop.preheader5: 436 ; CHECK-NEXT: br label [[LOOP:%.*]] 437 ; CHECK: loop: 438 ; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER5]] ] 439 ; CHECK-NEXT: [[IDX_NEXT]] = add i32 [[IDX]], 1 440 ; CHECK-NEXT: [[ABC:%.*]] = icmp ult i32 [[IDX]], [[BOUND]] 441 ; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT6:%.*]], !prof !0 442 ; CHECK: in.bounds: 443 ; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, i32* [[ARR:%.*]], i32 [[IDX]] 444 ; CHECK-NEXT: store i32 0, i32* [[ADDR]] 445 ; CHECK-NEXT: [[NEXT:%.*]] = icmp slt i32 [[IDX_NEXT]], [[N]] 446 ; CHECK-NEXT: [[TMP15:%.*]] = icmp slt i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]] 447 ; CHECK-NEXT: br i1 [[TMP15]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]] 448 ; CHECK: main.exit.selector: 449 ; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ] 450 ; CHECK-NEXT: [[TMP16:%.*]] = icmp slt i32 [[IDX_NEXT_LCSSA]], [[N]] 451 ; CHECK-NEXT: br i1 [[TMP16]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]] 452 ; CHECK: main.pseudo.exit: 453 ; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i32 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] 454 ; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] 455 ; CHECK-NEXT: br label [[POSTLOOP:%.*]] 456 ; CHECK: out.of.bounds.loopexit: 457 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]] 458 ; CHECK: out.of.bounds.loopexit6: 459 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS]] 460 ; CHECK: out.of.bounds: 461 ; CHECK-NEXT: ret void 462 ; CHECK: exit.loopexit.loopexit: 463 ; CHECK-NEXT: br label [[EXIT_LOOPEXIT]] 464 ; CHECK: exit.loopexit: 465 ; CHECK-NEXT: br label [[EXIT]] 466 ; CHECK: exit: 467 ; CHECK-NEXT: ret void 468 ; CHECK: postloop: 469 ; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]] 470 ; CHECK: loop.postloop: 471 ; CHECK-NEXT: [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ], [ [[IDX_COPY]], [[POSTLOOP]] ] 472 ; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add i32 [[IDX_POSTLOOP]], 1 473 ; CHECK-NEXT: [[ABC_POSTLOOP:%.*]] = icmp ult i32 [[IDX_POSTLOOP]], [[BOUND]] 474 ; CHECK-NEXT: br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]], !prof !0 475 ; CHECK: in.bounds.postloop: 476 ; CHECK-NEXT: [[ADDR_POSTLOOP:%.*]] = getelementptr i32, i32* [[ARR]], i32 [[IDX_POSTLOOP]] 477 ; CHECK-NEXT: store i32 0, i32* [[ADDR_POSTLOOP]] 478 ; CHECK-NEXT: [[NEXT_POSTLOOP:%.*]] = icmp slt i32 [[IDX_NEXT_POSTLOOP]], [[N]] 479 ; CHECK-NEXT: br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT:%.*]], !llvm.loop !8, !irce.loop.clone !6 480 ; 481 entry: 482 %first.itr.check = icmp sgt i32 %n, 0 483 br i1 %first.itr.check, label %loop, label %exit 484 485 loop: 486 %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ] 487 %idx.next = add i32 %idx, 1 488 %abc = icmp ult i32 %idx, %bound 489 br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !0 490 491 in.bounds: 492 %addr = getelementptr i32, i32* %arr, i32 %idx 493 store i32 0, i32* %addr 494 %next = icmp slt i32 %idx.next, %n 495 br i1 %next, label %loop, label %exit 496 497 out.of.bounds: 498 ret void 499 500 exit: 501 ret void 502 } 503 504 ; Same as test_04, unsigned range check. 505 ; FIXME: Currently we remove the check, but we will not execute the main loop if 506 ; %bound is negative (i.e. in [SINT_MAX + 1, UINT_MAX)). We should be able to 507 ; safely remove this check (see comments in the method 508 ; computeSafeIterationSpace). 509 define void @test_08(i32 *%arr, i32 %n, i32 %bound) { 510 ; CHECK-LABEL: @test_08( 511 ; CHECK-NEXT: entry: 512 ; CHECK-NEXT: [[FIRST_ITR_CHECK:%.*]] = icmp sgt i32 [[N:%.*]], 0 513 ; CHECK-NEXT: br i1 [[FIRST_ITR_CHECK]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]] 514 ; CHECK: loop.preheader: 515 ; CHECK-NEXT: [[TMP0:%.*]] = sub i32 -1, [[BOUND:%.*]] 516 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[TMP0]], -1 517 ; CHECK-NEXT: [[SMAX:%.*]] = select i1 [[TMP1]], i32 [[TMP0]], i32 -1 518 ; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[BOUND]], [[SMAX]] 519 ; CHECK-NEXT: [[TMP3:%.*]] = add i32 [[TMP2]], 1 520 ; CHECK-NEXT: [[TMP4:%.*]] = sub i32 -1, [[SMAX]] 521 ; CHECK-NEXT: [[TMP5:%.*]] = icmp sgt i32 [[TMP4]], -1 522 ; CHECK-NEXT: [[SMAX1:%.*]] = select i1 [[TMP5]], i32 [[TMP4]], i32 -1 523 ; CHECK-NEXT: [[TMP6:%.*]] = add i32 [[SMAX1]], 1 524 ; CHECK-NEXT: [[TMP7:%.*]] = mul i32 [[TMP3]], [[TMP6]] 525 ; CHECK-NEXT: [[TMP8:%.*]] = sub i32 -1, [[TMP7]] 526 ; CHECK-NEXT: [[TMP9:%.*]] = sub i32 -1, [[N]] 527 ; CHECK-NEXT: [[TMP10:%.*]] = icmp ugt i32 [[TMP8]], [[TMP9]] 528 ; CHECK-NEXT: [[UMAX:%.*]] = select i1 [[TMP10]], i32 [[TMP8]], i32 [[TMP9]] 529 ; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = sub i32 -1, [[UMAX]] 530 ; CHECK-NEXT: [[TMP11:%.*]] = icmp ult i32 0, [[EXIT_MAINLOOP_AT]] 531 ; CHECK-NEXT: br i1 [[TMP11]], label [[LOOP_PREHEADER2:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]] 532 ; CHECK: loop.preheader2: 533 ; CHECK-NEXT: br label [[LOOP:%.*]] 534 ; CHECK: loop: 535 ; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER2]] ] 536 ; CHECK-NEXT: [[IDX_NEXT]] = add i32 [[IDX]], 1 537 ; CHECK-NEXT: [[ABC:%.*]] = icmp ult i32 [[IDX]], [[BOUND]] 538 ; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT3:%.*]], !prof !0 539 ; CHECK: in.bounds: 540 ; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, i32* [[ARR:%.*]], i32 [[IDX]] 541 ; CHECK-NEXT: store i32 0, i32* [[ADDR]] 542 ; CHECK-NEXT: [[NEXT:%.*]] = icmp ult i32 [[IDX_NEXT]], [[N]] 543 ; CHECK-NEXT: [[TMP12:%.*]] = icmp ult i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]] 544 ; CHECK-NEXT: br i1 [[TMP12]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]] 545 ; CHECK: main.exit.selector: 546 ; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ] 547 ; CHECK-NEXT: [[TMP13:%.*]] = icmp ult i32 [[IDX_NEXT_LCSSA]], [[N]] 548 ; CHECK-NEXT: br i1 [[TMP13]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]] 549 ; CHECK: main.pseudo.exit: 550 ; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i32 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] 551 ; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 0, [[LOOP_PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] 552 ; CHECK-NEXT: br label [[POSTLOOP:%.*]] 553 ; CHECK: out.of.bounds.loopexit: 554 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]] 555 ; CHECK: out.of.bounds.loopexit3: 556 ; CHECK-NEXT: br label [[OUT_OF_BOUNDS]] 557 ; CHECK: out.of.bounds: 558 ; CHECK-NEXT: ret void 559 ; CHECK: exit.loopexit.loopexit: 560 ; CHECK-NEXT: br label [[EXIT_LOOPEXIT]] 561 ; CHECK: exit.loopexit: 562 ; CHECK-NEXT: br label [[EXIT]] 563 ; CHECK: exit: 564 ; CHECK-NEXT: ret void 565 ; CHECK: postloop: 566 ; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]] 567 ; CHECK: loop.postloop: 568 ; CHECK-NEXT: [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ], [ [[IDX_COPY]], [[POSTLOOP]] ] 569 ; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add i32 [[IDX_POSTLOOP]], 1 570 ; CHECK-NEXT: [[ABC_POSTLOOP:%.*]] = icmp ult i32 [[IDX_POSTLOOP]], [[BOUND]] 571 ; CHECK-NEXT: br i1 [[ABC_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]], !prof !0 572 ; CHECK: in.bounds.postloop: 573 ; CHECK-NEXT: [[ADDR_POSTLOOP:%.*]] = getelementptr i32, i32* [[ARR]], i32 [[IDX_POSTLOOP]] 574 ; CHECK-NEXT: store i32 0, i32* [[ADDR_POSTLOOP]] 575 ; CHECK-NEXT: [[NEXT_POSTLOOP:%.*]] = icmp ult i32 [[IDX_NEXT_POSTLOOP]], [[N]] 576 ; CHECK-NEXT: br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT:%.*]], !llvm.loop !9, !irce.loop.clone !6 577 ; 578 entry: 579 %first.itr.check = icmp sgt i32 %n, 0 580 br i1 %first.itr.check, label %loop, label %exit 581 582 loop: 583 %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ] 584 %idx.next = add i32 %idx, 1 585 %abc = icmp ult i32 %idx, %bound 586 br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !0 587 588 in.bounds: 589 %addr = getelementptr i32, i32* %arr, i32 %idx 590 store i32 0, i32* %addr 591 %next = icmp ult i32 %idx.next, %n 592 br i1 %next, label %loop, label %exit 593 594 out.of.bounds: 595 ret void 596 597 exit: 598 ret void 599 } 600 !0 = !{!"branch_weights", i32 64, i32 4} 601