1cee313d2SEric Christopher; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2e23e1594SRoman Lebedev; RUN: opt -S -passes=loop-predication -loop-predication-enable-count-down-loop=true < %s 2>&1 | FileCheck %s 355bdb140SAnna Thomas; RUN: opt -S -passes='require<scalar-evolution>,loop-mssa(loop-predication)' -loop-predication-enable-count-down-loop=true < %s 2>&1 | FileCheck %s 4cee313d2SEric Christopher 5cee313d2SEric Christopherdeclare void @llvm.experimental.guard(i1, ...) 6cee313d2SEric Christopher 7ba89c667SNikita Popovdefine i32 @signed_reverse_loop_n_to_lower_limit(ptr %array, i32 %length, i32 %n, i32 %lowerlimit) { 8cee313d2SEric Christopher; CHECK-LABEL: @signed_reverse_loop_n_to_lower_limit( 9cee313d2SEric Christopher; CHECK-NEXT: entry: 10cee313d2SEric Christopher; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0 11cee313d2SEric Christopher; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 12cee313d2SEric Christopher; CHECK: loop.preheader: 13cee313d2SEric Christopher; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N]], -1 14cee313d2SEric Christopher; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[TMP0]], [[LENGTH:%.*]] 15cee313d2SEric Christopher; CHECK-NEXT: [[TMP2:%.*]] = icmp sge i32 [[LOWERLIMIT:%.*]], 1 16cee313d2SEric Christopher; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP1]], [[TMP2]] 17*99da3173SSerguei Katkov; CHECK-NEXT: [[TMP4:%.*]] = freeze i1 [[TMP3]] 18cee313d2SEric Christopher; CHECK-NEXT: br label [[LOOP:%.*]] 19cee313d2SEric Christopher; CHECK: loop: 20cee313d2SEric Christopher; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 21cee313d2SEric Christopher; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ] 22cee313d2SEric Christopher; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], -1 238307f6c8SDmitry Makogon; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_NEXT]], [[LENGTH]] 24*99da3173SSerguei Katkov; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP4]], i32 9) [ "deopt"() ] 258307f6c8SDmitry Makogon; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) 26cee313d2SEric Christopher; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64 27ba89c667SNikita Popov; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]] 28ba89c667SNikita Popov; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4 29cee313d2SEric Christopher; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 30cee313d2SEric Christopher; CHECK-NEXT: [[CONTINUE:%.*]] = icmp sgt i32 [[I]], [[LOWERLIMIT]] 31cee313d2SEric Christopher; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 32cee313d2SEric Christopher; CHECK: exit.loopexit: 33cee313d2SEric Christopher; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 34cee313d2SEric Christopher; CHECK-NEXT: br label [[EXIT]] 35cee313d2SEric Christopher; CHECK: exit: 36cee313d2SEric Christopher; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 37cee313d2SEric Christopher; CHECK-NEXT: ret i32 [[RESULT]] 38cee313d2SEric Christopher; 39cee313d2SEric Christopherentry: 40cee313d2SEric Christopher %tmp5 = icmp eq i32 %n, 0 41cee313d2SEric Christopher br i1 %tmp5, label %exit, label %loop.preheader 42cee313d2SEric Christopher 43cee313d2SEric Christopherloop.preheader: 44cee313d2SEric Christopher br label %loop 45cee313d2SEric Christopher 46cee313d2SEric Christopherloop: 47cee313d2SEric Christopher %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 48cee313d2SEric Christopher %i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ] 49cee313d2SEric Christopher %i.next = add nsw i32 %i, -1 50cee313d2SEric Christopher %within.bounds = icmp ult i32 %i.next, %length 51cee313d2SEric Christopher call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 52cee313d2SEric Christopher %i.i64 = zext i32 %i.next to i64 53ba89c667SNikita Popov %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64 54ba89c667SNikita Popov %array.i = load i32, ptr %array.i.ptr, align 4 55cee313d2SEric Christopher %loop.acc.next = add i32 %loop.acc, %array.i 56cee313d2SEric Christopher %continue = icmp sgt i32 %i, %lowerlimit 57cee313d2SEric Christopher br i1 %continue, label %loop, label %exit 58cee313d2SEric Christopher 59cee313d2SEric Christopherexit: 60cee313d2SEric Christopher %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 61cee313d2SEric Christopher ret i32 %result 62cee313d2SEric Christopher} 63cee313d2SEric Christopher 64ba89c667SNikita Popovdefine i32 @unsigned_reverse_loop_n_to_lower_limit(ptr %array, i32 %length, i32 %n, i32 %lowerlimit) { 65cee313d2SEric Christopher; CHECK-LABEL: @unsigned_reverse_loop_n_to_lower_limit( 66cee313d2SEric Christopher; CHECK-NEXT: entry: 67cee313d2SEric Christopher; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0 68cee313d2SEric Christopher; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 69cee313d2SEric Christopher; CHECK: loop.preheader: 70cee313d2SEric Christopher; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N]], -1 71cee313d2SEric Christopher; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[TMP0]], [[LENGTH:%.*]] 72cee313d2SEric Christopher; CHECK-NEXT: [[TMP2:%.*]] = icmp uge i32 [[LOWERLIMIT:%.*]], 1 73cee313d2SEric Christopher; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP1]], [[TMP2]] 74*99da3173SSerguei Katkov; CHECK-NEXT: [[TMP4:%.*]] = freeze i1 [[TMP3]] 75cee313d2SEric Christopher; CHECK-NEXT: br label [[LOOP:%.*]] 76cee313d2SEric Christopher; CHECK: loop: 77cee313d2SEric Christopher; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 78cee313d2SEric Christopher; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ] 79cee313d2SEric Christopher; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], -1 808307f6c8SDmitry Makogon; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_NEXT]], [[LENGTH]] 81*99da3173SSerguei Katkov; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP4]], i32 9) [ "deopt"() ] 828307f6c8SDmitry Makogon; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) 83cee313d2SEric Christopher; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64 84ba89c667SNikita Popov; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]] 85ba89c667SNikita Popov; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4 86cee313d2SEric Christopher; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 87cee313d2SEric Christopher; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ugt i32 [[I]], [[LOWERLIMIT]] 88cee313d2SEric Christopher; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 89cee313d2SEric Christopher; CHECK: exit.loopexit: 90cee313d2SEric Christopher; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 91cee313d2SEric Christopher; CHECK-NEXT: br label [[EXIT]] 92cee313d2SEric Christopher; CHECK: exit: 93cee313d2SEric Christopher; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 94cee313d2SEric Christopher; CHECK-NEXT: ret i32 [[RESULT]] 95cee313d2SEric Christopher; 96cee313d2SEric Christopherentry: 97cee313d2SEric Christopher %tmp5 = icmp eq i32 %n, 0 98cee313d2SEric Christopher br i1 %tmp5, label %exit, label %loop.preheader 99cee313d2SEric Christopher 100cee313d2SEric Christopherloop.preheader: 101cee313d2SEric Christopher br label %loop 102cee313d2SEric Christopher 103cee313d2SEric Christopherloop: 104cee313d2SEric Christopher %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 105cee313d2SEric Christopher %i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ] 106cee313d2SEric Christopher %i.next = add nsw i32 %i, -1 107cee313d2SEric Christopher %within.bounds = icmp ult i32 %i.next, %length 108cee313d2SEric Christopher call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 109cee313d2SEric Christopher %i.i64 = zext i32 %i.next to i64 110ba89c667SNikita Popov %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64 111ba89c667SNikita Popov %array.i = load i32, ptr %array.i.ptr, align 4 112cee313d2SEric Christopher %loop.acc.next = add i32 %loop.acc, %array.i 113cee313d2SEric Christopher %continue = icmp ugt i32 %i, %lowerlimit 114cee313d2SEric Christopher br i1 %continue, label %loop, label %exit 115cee313d2SEric Christopher 116cee313d2SEric Christopherexit: 117cee313d2SEric Christopher %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 118cee313d2SEric Christopher ret i32 %result 119cee313d2SEric Christopher} 120cee313d2SEric Christopher 121cee313d2SEric Christopher 122cee313d2SEric Christopher; if we predicated the loop, the guard will definitely fail and we will 123cee313d2SEric Christopher; deoptimize early on. 124ba89c667SNikita Popovdefine i32 @unsigned_reverse_loop_n_to_0(ptr %array, i32 %length, i32 %n, i32 %lowerlimit) { 125cee313d2SEric Christopher; CHECK-LABEL: @unsigned_reverse_loop_n_to_0( 126cee313d2SEric Christopher; CHECK-NEXT: entry: 127cee313d2SEric Christopher; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0 128cee313d2SEric Christopher; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 129cee313d2SEric Christopher; CHECK: loop.preheader: 130cee313d2SEric Christopher; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N]], -1 131cee313d2SEric Christopher; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[TMP0]], [[LENGTH:%.*]] 132b2915971SRoman Lebedev; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], false 133*99da3173SSerguei Katkov; CHECK-NEXT: [[TMP3:%.*]] = freeze i1 [[TMP2]] 134cee313d2SEric Christopher; CHECK-NEXT: br label [[LOOP:%.*]] 135cee313d2SEric Christopher; CHECK: loop: 136cee313d2SEric Christopher; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 137cee313d2SEric Christopher; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ] 138cee313d2SEric Christopher; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], -1 1398307f6c8SDmitry Makogon; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_NEXT]], [[LENGTH]] 140*99da3173SSerguei Katkov; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ] 1418307f6c8SDmitry Makogon; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) 142cee313d2SEric Christopher; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64 143ba89c667SNikita Popov; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]] 144ba89c667SNikita Popov; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4 145cee313d2SEric Christopher; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 146cee313d2SEric Christopher; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ugt i32 [[I]], 0 147cee313d2SEric Christopher; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 148cee313d2SEric Christopher; CHECK: exit.loopexit: 149cee313d2SEric Christopher; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 150cee313d2SEric Christopher; CHECK-NEXT: br label [[EXIT]] 151cee313d2SEric Christopher; CHECK: exit: 152cee313d2SEric Christopher; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 153cee313d2SEric Christopher; CHECK-NEXT: ret i32 [[RESULT]] 154cee313d2SEric Christopher; 155cee313d2SEric Christopherentry: 156cee313d2SEric Christopher %tmp5 = icmp eq i32 %n, 0 157cee313d2SEric Christopher br i1 %tmp5, label %exit, label %loop.preheader 158cee313d2SEric Christopher 159cee313d2SEric Christopherloop.preheader: 160cee313d2SEric Christopher br label %loop 161cee313d2SEric Christopher 162cee313d2SEric Christopherloop: 163cee313d2SEric Christopher %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 164cee313d2SEric Christopher %i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ] 165cee313d2SEric Christopher %i.next = add nsw i32 %i, -1 166cee313d2SEric Christopher %within.bounds = icmp ult i32 %i.next, %length 167cee313d2SEric Christopher call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 168cee313d2SEric Christopher %i.i64 = zext i32 %i.next to i64 169ba89c667SNikita Popov %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64 170ba89c667SNikita Popov %array.i = load i32, ptr %array.i.ptr, align 4 171cee313d2SEric Christopher %loop.acc.next = add i32 %loop.acc, %array.i 172cee313d2SEric Christopher %continue = icmp ugt i32 %i, 0 173cee313d2SEric Christopher br i1 %continue, label %loop, label %exit 174cee313d2SEric Christopher 175cee313d2SEric Christopherexit: 176cee313d2SEric Christopher %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 177cee313d2SEric Christopher ret i32 %result 178cee313d2SEric Christopher} 179cee313d2SEric Christopher 180cee313d2SEric Christopher; do not loop predicate when the range has step -1 and latch has step 1. 181ba89c667SNikita Popovdefine i32 @reverse_loop_range_step_increment(i32 %n, ptr %array, i32 %length) { 182cee313d2SEric Christopher; CHECK-LABEL: @reverse_loop_range_step_increment( 183cee313d2SEric Christopher; CHECK-NEXT: entry: 184cee313d2SEric Christopher; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0 185cee313d2SEric Christopher; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 186cee313d2SEric Christopher; CHECK: loop.preheader: 187cee313d2SEric Christopher; CHECK-NEXT: br label [[LOOP:%.*]] 188cee313d2SEric Christopher; CHECK: loop: 189cee313d2SEric Christopher; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 190cee313d2SEric Christopher; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ] 191cee313d2SEric Christopher; CHECK-NEXT: [[IRC:%.*]] = phi i32 [ [[I_INC:%.*]], [[LOOP]] ], [ 1, [[LOOP_PREHEADER]] ] 192cee313d2SEric Christopher; CHECK-NEXT: [[I_INC]] = add nuw nsw i32 [[IRC]], 1 193cee313d2SEric Christopher; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[IRC]], [[LENGTH:%.*]] 194cee313d2SEric Christopher; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ] 195cee313d2SEric Christopher; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[IRC]] to i64 196ba89c667SNikita Popov; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]] 197ba89c667SNikita Popov; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4 198cee313d2SEric Christopher; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], -1 199cee313d2SEric Christopher; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 200cee313d2SEric Christopher; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ugt i32 [[I]], 65534 201cee313d2SEric Christopher; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 202cee313d2SEric Christopher; CHECK: exit.loopexit: 203cee313d2SEric Christopher; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 204cee313d2SEric Christopher; CHECK-NEXT: br label [[EXIT]] 205cee313d2SEric Christopher; CHECK: exit: 206cee313d2SEric Christopher; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 207cee313d2SEric Christopher; CHECK-NEXT: ret i32 [[RESULT]] 208cee313d2SEric Christopher; 209cee313d2SEric Christopherentry: 210cee313d2SEric Christopher %tmp5 = icmp eq i32 %n, 0 211cee313d2SEric Christopher br i1 %tmp5, label %exit, label %loop.preheader 212cee313d2SEric Christopher 213cee313d2SEric Christopherloop.preheader: 214cee313d2SEric Christopher br label %loop 215cee313d2SEric Christopher 216cee313d2SEric Christopherloop: 217cee313d2SEric Christopher %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 218cee313d2SEric Christopher %i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ] 219cee313d2SEric Christopher %irc = phi i32 [ %i.inc, %loop ], [ 1, %loop.preheader ] 220cee313d2SEric Christopher %i.inc = add nuw nsw i32 %irc, 1 221cee313d2SEric Christopher %within.bounds = icmp ult i32 %irc, %length 222cee313d2SEric Christopher call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 223cee313d2SEric Christopher %i.i64 = zext i32 %irc to i64 224ba89c667SNikita Popov %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64 225ba89c667SNikita Popov %array.i = load i32, ptr %array.i.ptr, align 4 226cee313d2SEric Christopher %i.next = add nsw i32 %i, -1 227cee313d2SEric Christopher %loop.acc.next = add i32 %loop.acc, %array.i 228cee313d2SEric Christopher %continue = icmp ugt i32 %i, 65534 229cee313d2SEric Christopher br i1 %continue, label %loop, label %exit 230cee313d2SEric Christopher 231cee313d2SEric Christopherexit: 232cee313d2SEric Christopher %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 233cee313d2SEric Christopher ret i32 %result 234cee313d2SEric Christopher} 235cee313d2SEric Christopher 236ba89c667SNikita Popovdefine i32 @signed_reverse_loop_n_to_lower_limit_equal(ptr %array, i32 %length, i32 %n, i32 %lowerlimit) { 237cee313d2SEric Christopher; CHECK-LABEL: @signed_reverse_loop_n_to_lower_limit_equal( 238cee313d2SEric Christopher; CHECK-NEXT: entry: 239cee313d2SEric Christopher; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0 240cee313d2SEric Christopher; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 241cee313d2SEric Christopher; CHECK: loop.preheader: 242cee313d2SEric Christopher; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N]], -1 243cee313d2SEric Christopher; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[TMP0]], [[LENGTH:%.*]] 244cee313d2SEric Christopher; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[LOWERLIMIT:%.*]], 1 245cee313d2SEric Christopher; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP1]], [[TMP2]] 246*99da3173SSerguei Katkov; CHECK-NEXT: [[TMP4:%.*]] = freeze i1 [[TMP3]] 247cee313d2SEric Christopher; CHECK-NEXT: br label [[LOOP:%.*]] 248cee313d2SEric Christopher; CHECK: loop: 249cee313d2SEric Christopher; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 250cee313d2SEric Christopher; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ] 251cee313d2SEric Christopher; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], -1 2528307f6c8SDmitry Makogon; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_NEXT]], [[LENGTH]] 253*99da3173SSerguei Katkov; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP4]], i32 9) [ "deopt"() ] 2548307f6c8SDmitry Makogon; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) 255cee313d2SEric Christopher; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64 256ba89c667SNikita Popov; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]] 257ba89c667SNikita Popov; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4 258cee313d2SEric Christopher; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 259cee313d2SEric Christopher; CHECK-NEXT: [[CONTINUE:%.*]] = icmp sge i32 [[I]], [[LOWERLIMIT]] 260cee313d2SEric Christopher; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 261cee313d2SEric Christopher; CHECK: exit.loopexit: 262cee313d2SEric Christopher; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 263cee313d2SEric Christopher; CHECK-NEXT: br label [[EXIT]] 264cee313d2SEric Christopher; CHECK: exit: 265cee313d2SEric Christopher; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 266cee313d2SEric Christopher; CHECK-NEXT: ret i32 [[RESULT]] 267cee313d2SEric Christopher; 268cee313d2SEric Christopherentry: 269cee313d2SEric Christopher %tmp5 = icmp eq i32 %n, 0 270cee313d2SEric Christopher br i1 %tmp5, label %exit, label %loop.preheader 271cee313d2SEric Christopher 272cee313d2SEric Christopherloop.preheader: 273cee313d2SEric Christopher br label %loop 274cee313d2SEric Christopher 275cee313d2SEric Christopherloop: 276cee313d2SEric Christopher %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 277cee313d2SEric Christopher %i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ] 278cee313d2SEric Christopher %i.next = add nsw i32 %i, -1 279cee313d2SEric Christopher %within.bounds = icmp ult i32 %i.next, %length 280cee313d2SEric Christopher call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 281cee313d2SEric Christopher %i.i64 = zext i32 %i.next to i64 282ba89c667SNikita Popov %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64 283ba89c667SNikita Popov %array.i = load i32, ptr %array.i.ptr, align 4 284cee313d2SEric Christopher %loop.acc.next = add i32 %loop.acc, %array.i 285cee313d2SEric Christopher %continue = icmp sge i32 %i, %lowerlimit 286cee313d2SEric Christopher br i1 %continue, label %loop, label %exit 287cee313d2SEric Christopher 288cee313d2SEric Christopherexit: 289cee313d2SEric Christopher %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 290cee313d2SEric Christopher ret i32 %result 291cee313d2SEric Christopher} 292cee313d2SEric Christopher 293ba89c667SNikita Popovdefine i32 @unsigned_reverse_loop_n_to_lower_limit_equal(ptr %array, i32 %length, i32 %n, i32 %lowerlimit) { 294cee313d2SEric Christopher; CHECK-LABEL: @unsigned_reverse_loop_n_to_lower_limit_equal( 295cee313d2SEric Christopher; CHECK-NEXT: entry: 296cee313d2SEric Christopher; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0 297cee313d2SEric Christopher; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 298cee313d2SEric Christopher; CHECK: loop.preheader: 299cee313d2SEric Christopher; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N]], -1 300cee313d2SEric Christopher; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[TMP0]], [[LENGTH:%.*]] 301cee313d2SEric Christopher; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt i32 [[LOWERLIMIT:%.*]], 1 302cee313d2SEric Christopher; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP1]], [[TMP2]] 303*99da3173SSerguei Katkov; CHECK-NEXT: [[TMP4:%.*]] = freeze i1 [[TMP3]] 304cee313d2SEric Christopher; CHECK-NEXT: br label [[LOOP:%.*]] 305cee313d2SEric Christopher; CHECK: loop: 306cee313d2SEric Christopher; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 307cee313d2SEric Christopher; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ] 308cee313d2SEric Christopher; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], -1 3098307f6c8SDmitry Makogon; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_NEXT]], [[LENGTH]] 310*99da3173SSerguei Katkov; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP4]], i32 9) [ "deopt"() ] 3118307f6c8SDmitry Makogon; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) 312cee313d2SEric Christopher; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64 313ba89c667SNikita Popov; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]] 314ba89c667SNikita Popov; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4 315cee313d2SEric Christopher; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 316cee313d2SEric Christopher; CHECK-NEXT: [[CONTINUE:%.*]] = icmp uge i32 [[I]], [[LOWERLIMIT]] 317cee313d2SEric Christopher; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 318cee313d2SEric Christopher; CHECK: exit.loopexit: 319cee313d2SEric Christopher; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 320cee313d2SEric Christopher; CHECK-NEXT: br label [[EXIT]] 321cee313d2SEric Christopher; CHECK: exit: 322cee313d2SEric Christopher; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 323cee313d2SEric Christopher; CHECK-NEXT: ret i32 [[RESULT]] 324cee313d2SEric Christopher; 325cee313d2SEric Christopherentry: 326cee313d2SEric Christopher %tmp5 = icmp eq i32 %n, 0 327cee313d2SEric Christopher br i1 %tmp5, label %exit, label %loop.preheader 328cee313d2SEric Christopher 329cee313d2SEric Christopherloop.preheader: 330cee313d2SEric Christopher br label %loop 331cee313d2SEric Christopher 332cee313d2SEric Christopherloop: 333cee313d2SEric Christopher %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 334cee313d2SEric Christopher %i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ] 335cee313d2SEric Christopher %i.next = add nsw i32 %i, -1 336cee313d2SEric Christopher %within.bounds = icmp ult i32 %i.next, %length 337cee313d2SEric Christopher call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 338cee313d2SEric Christopher %i.i64 = zext i32 %i.next to i64 339ba89c667SNikita Popov %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64 340ba89c667SNikita Popov %array.i = load i32, ptr %array.i.ptr, align 4 341cee313d2SEric Christopher %loop.acc.next = add i32 %loop.acc, %array.i 342cee313d2SEric Christopher %continue = icmp uge i32 %i, %lowerlimit 343cee313d2SEric Christopher br i1 %continue, label %loop, label %exit 344cee313d2SEric Christopher 345cee313d2SEric Christopherexit: 346cee313d2SEric Christopher %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 347cee313d2SEric Christopher ret i32 %result 348cee313d2SEric Christopher} 349cee313d2SEric Christopher 350cee313d2SEric Christopher 351cee313d2SEric Christopher; if we predicated the loop, the guard will definitely fail and we will 352cee313d2SEric Christopher; deoptimize early on. 353ba89c667SNikita Popovdefine i32 @unsigned_reverse_loop_n_to_1(ptr %array, i32 %length, i32 %n, i32 %lowerlimit) { 354cee313d2SEric Christopher; CHECK-LABEL: @unsigned_reverse_loop_n_to_1( 355cee313d2SEric Christopher; CHECK-NEXT: entry: 356cee313d2SEric Christopher; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0 357cee313d2SEric Christopher; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 358cee313d2SEric Christopher; CHECK: loop.preheader: 359cee313d2SEric Christopher; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N]], -1 360cee313d2SEric Christopher; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[TMP0]], [[LENGTH:%.*]] 361b2915971SRoman Lebedev; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], false 362*99da3173SSerguei Katkov; CHECK-NEXT: [[TMP3:%.*]] = freeze i1 [[TMP2]] 363cee313d2SEric Christopher; CHECK-NEXT: br label [[LOOP:%.*]] 364cee313d2SEric Christopher; CHECK: loop: 365cee313d2SEric Christopher; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 366cee313d2SEric Christopher; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ [[N]], [[LOOP_PREHEADER]] ] 367cee313d2SEric Christopher; CHECK-NEXT: [[I_NEXT]] = add nsw i32 [[I]], -1 3688307f6c8SDmitry Makogon; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_NEXT]], [[LENGTH]] 369*99da3173SSerguei Katkov; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP3]], i32 9) [ "deopt"() ] 3708307f6c8SDmitry Makogon; CHECK-NEXT: call void @llvm.assume(i1 [[WITHIN_BOUNDS]]) 371cee313d2SEric Christopher; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I_NEXT]] to i64 372ba89c667SNikita Popov; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]] 373ba89c667SNikita Popov; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4 374cee313d2SEric Christopher; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 375cee313d2SEric Christopher; CHECK-NEXT: [[CONTINUE:%.*]] = icmp uge i32 [[I]], 1 376cee313d2SEric Christopher; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 377cee313d2SEric Christopher; CHECK: exit.loopexit: 378cee313d2SEric Christopher; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 379cee313d2SEric Christopher; CHECK-NEXT: br label [[EXIT]] 380cee313d2SEric Christopher; CHECK: exit: 381cee313d2SEric Christopher; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 382cee313d2SEric Christopher; CHECK-NEXT: ret i32 [[RESULT]] 383cee313d2SEric Christopher; 384cee313d2SEric Christopherentry: 385cee313d2SEric Christopher %tmp5 = icmp eq i32 %n, 0 386cee313d2SEric Christopher br i1 %tmp5, label %exit, label %loop.preheader 387cee313d2SEric Christopher 388cee313d2SEric Christopherloop.preheader: 389cee313d2SEric Christopher br label %loop 390cee313d2SEric Christopher 391cee313d2SEric Christopherloop: 392cee313d2SEric Christopher %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 393cee313d2SEric Christopher %i = phi i32 [ %i.next, %loop ], [ %n, %loop.preheader ] 394cee313d2SEric Christopher %i.next = add nsw i32 %i, -1 395cee313d2SEric Christopher %within.bounds = icmp ult i32 %i.next, %length 396cee313d2SEric Christopher call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 397cee313d2SEric Christopher %i.i64 = zext i32 %i.next to i64 398ba89c667SNikita Popov %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64 399ba89c667SNikita Popov %array.i = load i32, ptr %array.i.ptr, align 4 400cee313d2SEric Christopher %loop.acc.next = add i32 %loop.acc, %array.i 401cee313d2SEric Christopher %continue = icmp uge i32 %i, 1 402cee313d2SEric Christopher br i1 %continue, label %loop, label %exit 403cee313d2SEric Christopher 404cee313d2SEric Christopherexit: 405cee313d2SEric Christopher %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 406cee313d2SEric Christopher ret i32 %result 407cee313d2SEric Christopher} 408cee313d2SEric Christopher 409