1011f25a4SAleksandr Popov; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3 2011f25a4SAleksandr Popov; RUN: opt -passes=irce < %s -S | FileCheck %s 3011f25a4SAleksandr Popov 4011f25a4SAleksandr Popov; if (K > 0 && M > 0) 5011f25a4SAleksandr Popov; for (i = 0; i < min(K, M); i++) {...} 6011f25a4SAleksandr Popov; 7011f25a4SAleksandr Popov; TODO: Loop bounds are safe according to loop guards. IRCE is allowed. 8011f25a4SAleksandr Popovdefine void @incrementing_loop(ptr %arr, ptr %len_ptr, i32 %K, i32 %M) { 9011f25a4SAleksandr Popov; CHECK-LABEL: define void @incrementing_loop( 10011f25a4SAleksandr Popov; CHECK-SAME: ptr [[ARR:%.*]], ptr [[LEN_PTR:%.*]], i32 [[K:%.*]], i32 [[M:%.*]]) { 11011f25a4SAleksandr Popov; CHECK-NEXT: entry: 12011f25a4SAleksandr Popov; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[LEN_PTR]], align 4, !range [[RNG0:![0-9]+]] 13011f25a4SAleksandr Popov; CHECK-NEXT: [[CHECK0:%.*]] = icmp sgt i32 [[K]], 0 14011f25a4SAleksandr Popov; CHECK-NEXT: [[CHECK1:%.*]] = icmp sgt i32 [[M]], 0 15011f25a4SAleksandr Popov; CHECK-NEXT: [[AND:%.*]] = and i1 [[CHECK0]], [[CHECK1]] 16011f25a4SAleksandr Popov; CHECK-NEXT: br i1 [[AND]], label [[PREHEADER:%.*]], label [[EXIT:%.*]] 17011f25a4SAleksandr Popov; CHECK: preheader: 18011f25a4SAleksandr Popov; CHECK-NEXT: [[SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[K]], i32 [[M]]) 19*cd206007SAleksandr Popov; CHECK-NEXT: [[SMIN1:%.*]] = call i32 @llvm.smin.i32(i32 [[LEN]], i32 [[M]]) 20*cd206007SAleksandr Popov; CHECK-NEXT: [[SMIN2:%.*]] = call i32 @llvm.smin.i32(i32 [[SMIN1]], i32 [[K]]) 21*cd206007SAleksandr Popov; CHECK-NEXT: [[EXIT_MAINLOOP_AT:%.*]] = call i32 @llvm.smax.i32(i32 [[SMIN2]], i32 0) 22*cd206007SAleksandr Popov; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 0, [[EXIT_MAINLOOP_AT]] 23*cd206007SAleksandr Popov; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_PREHEADER:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]] 24*cd206007SAleksandr Popov; CHECK: loop.preheader: 25011f25a4SAleksandr Popov; CHECK-NEXT: br label [[LOOP:%.*]] 26011f25a4SAleksandr Popov; CHECK: loop: 27*cd206007SAleksandr Popov; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_NEXT:%.*]], [[IN_BOUNDS:%.*]] ], [ 0, [[LOOP_PREHEADER]] ] 28*cd206007SAleksandr Popov; CHECK-NEXT: [[IDX_NEXT]] = add nsw i32 [[IDX]], 1 29011f25a4SAleksandr Popov; CHECK-NEXT: [[GUARD:%.*]] = icmp slt i32 [[IDX]], [[LEN]] 30*cd206007SAleksandr Popov; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT3:%.*]] 31011f25a4SAleksandr Popov; CHECK: in.bounds: 32011f25a4SAleksandr Popov; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]] 33011f25a4SAleksandr Popov; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4 34011f25a4SAleksandr Popov; CHECK-NEXT: [[NEXT:%.*]] = icmp slt i32 [[IDX_NEXT]], [[SMIN]] 35*cd206007SAleksandr Popov; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[IDX_NEXT]], [[EXIT_MAINLOOP_AT]] 36*cd206007SAleksandr Popov; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP]], label [[MAIN_EXIT_SELECTOR:%.*]] 37*cd206007SAleksandr Popov; CHECK: main.exit.selector: 38*cd206007SAleksandr Popov; CHECK-NEXT: [[IDX_NEXT_LCSSA:%.*]] = phi i32 [ [[IDX_NEXT]], [[IN_BOUNDS]] ] 39*cd206007SAleksandr Popov; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[IDX_NEXT_LCSSA]], [[SMIN]] 40*cd206007SAleksandr Popov; CHECK-NEXT: br i1 [[TMP2]], label [[MAIN_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT:%.*]] 41*cd206007SAleksandr Popov; CHECK: main.pseudo.exit: 42*cd206007SAleksandr Popov; CHECK-NEXT: [[IDX_COPY:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] 43*cd206007SAleksandr Popov; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[IDX_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ] 44*cd206007SAleksandr Popov; CHECK-NEXT: br label [[POSTLOOP:%.*]] 45*cd206007SAleksandr Popov; CHECK: out.of.bounds.loopexit: 46*cd206007SAleksandr Popov; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]] 47*cd206007SAleksandr Popov; CHECK: out.of.bounds.loopexit3: 48*cd206007SAleksandr Popov; CHECK-NEXT: br label [[OUT_OF_BOUNDS]] 49011f25a4SAleksandr Popov; CHECK: out.of.bounds: 50011f25a4SAleksandr Popov; CHECK-NEXT: ret void 51*cd206007SAleksandr Popov; CHECK: exit.loopexit.loopexit: 52*cd206007SAleksandr Popov; CHECK-NEXT: br label [[EXIT_LOOPEXIT]] 53011f25a4SAleksandr Popov; CHECK: exit.loopexit: 54011f25a4SAleksandr Popov; CHECK-NEXT: br label [[EXIT]] 55011f25a4SAleksandr Popov; CHECK: exit: 56011f25a4SAleksandr Popov; CHECK-NEXT: ret void 57*cd206007SAleksandr Popov; CHECK: postloop: 58*cd206007SAleksandr Popov; CHECK-NEXT: br label [[LOOP_POSTLOOP:%.*]] 59*cd206007SAleksandr Popov; CHECK: loop.postloop: 60*cd206007SAleksandr Popov; CHECK-NEXT: [[IDX_POSTLOOP:%.*]] = phi i32 [ [[IDX_COPY]], [[POSTLOOP]] ], [ [[IDX_NEXT_POSTLOOP:%.*]], [[IN_BOUNDS_POSTLOOP:%.*]] ] 61*cd206007SAleksandr Popov; CHECK-NEXT: [[IDX_NEXT_POSTLOOP]] = add i32 [[IDX_POSTLOOP]], 1 62*cd206007SAleksandr Popov; CHECK-NEXT: [[GUARD_POSTLOOP:%.*]] = icmp slt i32 [[IDX_POSTLOOP]], [[LEN]] 63*cd206007SAleksandr Popov; CHECK-NEXT: br i1 [[GUARD_POSTLOOP]], label [[IN_BOUNDS_POSTLOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] 64*cd206007SAleksandr Popov; CHECK: in.bounds.postloop: 65*cd206007SAleksandr Popov; CHECK-NEXT: [[ADDR_POSTLOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_POSTLOOP]] 66*cd206007SAleksandr Popov; CHECK-NEXT: store i32 0, ptr [[ADDR_POSTLOOP]], align 4 67*cd206007SAleksandr Popov; CHECK-NEXT: [[NEXT_POSTLOOP:%.*]] = icmp slt i32 [[IDX_NEXT_POSTLOOP]], [[SMIN]] 68*cd206007SAleksandr Popov; CHECK-NEXT: br i1 [[NEXT_POSTLOOP]], label [[LOOP_POSTLOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP1:![0-9]+]], !loop_constrainer.loop.clone !6 69011f25a4SAleksandr Popov; 70011f25a4SAleksandr Popoventry: 71011f25a4SAleksandr Popov %len = load i32, ptr %len_ptr, !range !0 72011f25a4SAleksandr Popov %check0 = icmp sgt i32 %K, 0 73011f25a4SAleksandr Popov %check1 = icmp sgt i32 %M, 0 74011f25a4SAleksandr Popov %and = and i1 %check0, %check1 75011f25a4SAleksandr Popov br i1 %and, label %preheader, label %exit 76011f25a4SAleksandr Popov 77011f25a4SAleksandr Popovpreheader: 78011f25a4SAleksandr Popov %smin = call i32 @llvm.smin.i32(i32 %K, i32 %M) 79011f25a4SAleksandr Popov br label %loop 80011f25a4SAleksandr Popov 81011f25a4SAleksandr Popovloop: 82011f25a4SAleksandr Popov %idx = phi i32 [ 0, %preheader ], [ %idx.next, %in.bounds ] 83011f25a4SAleksandr Popov %idx.next = add i32 %idx, 1 84011f25a4SAleksandr Popov %guard = icmp slt i32 %idx, %len 85011f25a4SAleksandr Popov br i1 %guard, label %in.bounds, label %out.of.bounds 86011f25a4SAleksandr Popov 87011f25a4SAleksandr Popovin.bounds: 88011f25a4SAleksandr Popov %addr = getelementptr i32, ptr %arr, i32 %idx 89011f25a4SAleksandr Popov store i32 0, ptr %addr 90011f25a4SAleksandr Popov %next = icmp slt i32 %idx.next, %smin 91011f25a4SAleksandr Popov br i1 %next, label %loop, label %exit 92011f25a4SAleksandr Popov 93011f25a4SAleksandr Popovout.of.bounds: 94011f25a4SAleksandr Popov ret void 95011f25a4SAleksandr Popov 96011f25a4SAleksandr Popovexit: 97011f25a4SAleksandr Popov ret void 98011f25a4SAleksandr Popov} 99011f25a4SAleksandr Popov 100011f25a4SAleksandr Popov; if (K > 0 && M > 0) 101011f25a4SAleksandr Popov; for (i = min(K, M); i >= 0; i--) {...} 102011f25a4SAleksandr Popov; 103011f25a4SAleksandr Popov; TODO: Loop bounds are safe according to loop guards. IRCE is allowed. 104011f25a4SAleksandr Popovdefine void @decrementing_loop(ptr %arr, ptr %len_ptr, i32 %K, i32 %M) { 105011f25a4SAleksandr Popov; CHECK-LABEL: define void @decrementing_loop( 106011f25a4SAleksandr Popov; CHECK-SAME: ptr [[ARR:%.*]], ptr [[LEN_PTR:%.*]], i32 [[K:%.*]], i32 [[M:%.*]]) { 107011f25a4SAleksandr Popov; CHECK-NEXT: entry: 108011f25a4SAleksandr Popov; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[LEN_PTR]], align 4, !range [[RNG0]] 109011f25a4SAleksandr Popov; CHECK-NEXT: [[CHECK0:%.*]] = icmp sgt i32 [[K]], 0 110011f25a4SAleksandr Popov; CHECK-NEXT: [[CHECK1:%.*]] = icmp sgt i32 [[M]], 0 111011f25a4SAleksandr Popov; CHECK-NEXT: [[AND:%.*]] = and i1 [[CHECK0]], [[CHECK1]] 112011f25a4SAleksandr Popov; CHECK-NEXT: br i1 [[AND]], label [[PREHEADER:%.*]], label [[EXIT:%.*]] 113011f25a4SAleksandr Popov; CHECK: preheader: 114*cd206007SAleksandr Popov; CHECK-NEXT: [[INDVAR_START:%.*]] = call i32 @llvm.smin.i32(i32 [[K]], i32 [[M]]) 115*cd206007SAleksandr Popov; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[INDVAR_START]], 1 116*cd206007SAleksandr Popov; CHECK-NEXT: [[SMIN:%.*]] = call i32 @llvm.smin.i32(i32 [[LEN]], i32 [[TMP0]]) 117*cd206007SAleksandr Popov; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[SMIN]], i32 0) 118*cd206007SAleksandr Popov; CHECK-NEXT: [[EXIT_PRELOOP_AT:%.*]] = add nsw i32 [[SMAX]], -1 119*cd206007SAleksandr Popov; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[INDVAR_START]], [[EXIT_PRELOOP_AT]] 120*cd206007SAleksandr Popov; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_PRELOOP_PREHEADER:%.*]], label [[PRELOOP_PSEUDO_EXIT:%.*]] 121*cd206007SAleksandr Popov; CHECK: loop.preloop.preheader: 122*cd206007SAleksandr Popov; CHECK-NEXT: br label [[LOOP_PRELOOP:%.*]] 123*cd206007SAleksandr Popov; CHECK: mainloop: 124011f25a4SAleksandr Popov; CHECK-NEXT: br label [[LOOP:%.*]] 125011f25a4SAleksandr Popov; CHECK: loop: 126*cd206007SAleksandr Popov; CHECK-NEXT: [[IDX:%.*]] = phi i32 [ [[IDX_PRELOOP_COPY:%.*]], [[MAINLOOP:%.*]] ], [ [[IDX_DEC:%.*]], [[IN_BOUNDS:%.*]] ] 127*cd206007SAleksandr Popov; CHECK-NEXT: [[IDX_DEC]] = sub nsw i32 [[IDX]], 1 128011f25a4SAleksandr Popov; CHECK-NEXT: [[GUARD:%.*]] = icmp slt i32 [[IDX]], [[LEN]] 129*cd206007SAleksandr Popov; CHECK-NEXT: br i1 true, label [[IN_BOUNDS]], label [[OUT_OF_BOUNDS_LOOPEXIT1:%.*]] 130011f25a4SAleksandr Popov; CHECK: in.bounds: 131011f25a4SAleksandr Popov; CHECK-NEXT: [[ADDR:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX]] 132011f25a4SAleksandr Popov; CHECK-NEXT: store i32 0, ptr [[ADDR]], align 4 133011f25a4SAleksandr Popov; CHECK-NEXT: [[NEXT:%.*]] = icmp sgt i32 [[IDX_DEC]], -1 134*cd206007SAleksandr Popov; CHECK-NEXT: br i1 [[NEXT]], label [[LOOP]], label [[EXIT_LOOPEXIT_LOOPEXIT:%.*]] 135*cd206007SAleksandr Popov; CHECK: out.of.bounds.loopexit: 136*cd206007SAleksandr Popov; CHECK-NEXT: br label [[OUT_OF_BOUNDS:%.*]] 137*cd206007SAleksandr Popov; CHECK: out.of.bounds.loopexit1: 138*cd206007SAleksandr Popov; CHECK-NEXT: br label [[OUT_OF_BOUNDS]] 139011f25a4SAleksandr Popov; CHECK: out.of.bounds: 140011f25a4SAleksandr Popov; CHECK-NEXT: ret void 141*cd206007SAleksandr Popov; CHECK: exit.loopexit.loopexit: 142*cd206007SAleksandr Popov; CHECK-NEXT: br label [[EXIT_LOOPEXIT:%.*]] 143011f25a4SAleksandr Popov; CHECK: exit.loopexit: 144011f25a4SAleksandr Popov; CHECK-NEXT: br label [[EXIT]] 145011f25a4SAleksandr Popov; CHECK: exit: 146011f25a4SAleksandr Popov; CHECK-NEXT: ret void 147*cd206007SAleksandr Popov; CHECK: loop.preloop: 148*cd206007SAleksandr Popov; CHECK-NEXT: [[IDX_PRELOOP:%.*]] = phi i32 [ [[IDX_DEC_PRELOOP:%.*]], [[IN_BOUNDS_PRELOOP:%.*]] ], [ [[INDVAR_START]], [[LOOP_PRELOOP_PREHEADER]] ] 149*cd206007SAleksandr Popov; CHECK-NEXT: [[IDX_DEC_PRELOOP]] = sub i32 [[IDX_PRELOOP]], 1 150*cd206007SAleksandr Popov; CHECK-NEXT: [[GUARD_PRELOOP:%.*]] = icmp slt i32 [[IDX_PRELOOP]], [[LEN]] 151*cd206007SAleksandr Popov; CHECK-NEXT: br i1 [[GUARD_PRELOOP]], label [[IN_BOUNDS_PRELOOP]], label [[OUT_OF_BOUNDS_LOOPEXIT:%.*]] 152*cd206007SAleksandr Popov; CHECK: in.bounds.preloop: 153*cd206007SAleksandr Popov; CHECK-NEXT: [[ADDR_PRELOOP:%.*]] = getelementptr i32, ptr [[ARR]], i32 [[IDX_PRELOOP]] 154*cd206007SAleksandr Popov; CHECK-NEXT: store i32 0, ptr [[ADDR_PRELOOP]], align 4 155*cd206007SAleksandr Popov; CHECK-NEXT: [[NEXT_PRELOOP:%.*]] = icmp sgt i32 [[IDX_DEC_PRELOOP]], -1 156*cd206007SAleksandr Popov; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[IDX_DEC_PRELOOP]], [[EXIT_PRELOOP_AT]] 157*cd206007SAleksandr Popov; CHECK-NEXT: br i1 [[TMP2]], label [[LOOP_PRELOOP]], label [[PRELOOP_EXIT_SELECTOR:%.*]], !llvm.loop [[LOOP7:![0-9]+]], !loop_constrainer.loop.clone !6 158*cd206007SAleksandr Popov; CHECK: preloop.exit.selector: 159*cd206007SAleksandr Popov; CHECK-NEXT: [[IDX_DEC_PRELOOP_LCSSA:%.*]] = phi i32 [ [[IDX_DEC_PRELOOP]], [[IN_BOUNDS_PRELOOP]] ] 160*cd206007SAleksandr Popov; CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[IDX_DEC_PRELOOP_LCSSA]], -1 161*cd206007SAleksandr Popov; CHECK-NEXT: br i1 [[TMP3]], label [[PRELOOP_PSEUDO_EXIT]], label [[EXIT_LOOPEXIT]] 162*cd206007SAleksandr Popov; CHECK: preloop.pseudo.exit: 163*cd206007SAleksandr Popov; CHECK-NEXT: [[IDX_PRELOOP_COPY]] = phi i32 [ [[INDVAR_START]], [[PREHEADER]] ], [ [[IDX_DEC_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ] 164*cd206007SAleksandr Popov; CHECK-NEXT: [[INDVAR_END:%.*]] = phi i32 [ [[INDVAR_START]], [[PREHEADER]] ], [ [[IDX_DEC_PRELOOP_LCSSA]], [[PRELOOP_EXIT_SELECTOR]] ] 165*cd206007SAleksandr Popov; CHECK-NEXT: br label [[MAINLOOP]] 166011f25a4SAleksandr Popov; 167011f25a4SAleksandr Popov entry: 168011f25a4SAleksandr Popov %len = load i32, ptr %len_ptr, !range !0 169011f25a4SAleksandr Popov %check0 = icmp sgt i32 %K, 0 170011f25a4SAleksandr Popov %check1 = icmp sgt i32 %M, 0 171011f25a4SAleksandr Popov %and = and i1 %check0, %check1 172011f25a4SAleksandr Popov br i1 %and, label %preheader, label %exit 173011f25a4SAleksandr Popov 174011f25a4SAleksandr Popov preheader: 175011f25a4SAleksandr Popov %smin = call i32 @llvm.smin.i32(i32 %K, i32 %M) 176011f25a4SAleksandr Popov br label %loop 177011f25a4SAleksandr Popov 178011f25a4SAleksandr Popov loop: 179011f25a4SAleksandr Popov %idx = phi i32 [ %smin, %preheader ] , [ %idx.dec, %in.bounds ] 180011f25a4SAleksandr Popov %idx.dec = sub i32 %idx, 1 181011f25a4SAleksandr Popov %guard = icmp slt i32 %idx, %len 182011f25a4SAleksandr Popov br i1 %guard, label %in.bounds, label %out.of.bounds 183011f25a4SAleksandr Popov 184011f25a4SAleksandr Popov in.bounds: 185011f25a4SAleksandr Popov %addr = getelementptr i32, ptr %arr, i32 %idx 186011f25a4SAleksandr Popov store i32 0, ptr %addr 187011f25a4SAleksandr Popov %next = icmp sgt i32 %idx.dec, -1 188011f25a4SAleksandr Popov br i1 %next, label %loop, label %exit 189011f25a4SAleksandr Popov 190011f25a4SAleksandr Popov out.of.bounds: 191011f25a4SAleksandr Popov ret void 192011f25a4SAleksandr Popov 193011f25a4SAleksandr Popov exit: 194011f25a4SAleksandr Popov ret void 195011f25a4SAleksandr Popov} 196011f25a4SAleksandr Popov 197011f25a4SAleksandr Popovdeclare i32 @llvm.smin.i32(i32, i32) 198011f25a4SAleksandr Popov 199011f25a4SAleksandr Popov!0 = !{i32 0, i32 2147483647} 200