1; RUN: opt -S -loop-predication < %s 2>&1 | FileCheck %s 2; RUN: opt -S -passes='require<scalar-evolution>,loop(loop-predication)' < %s 2>&1 | FileCheck %s 3 4declare void @llvm.experimental.guard(i1, ...) 5 6define i32 @signed_loop_0_to_n_nested_0_to_l_inner_index_check(i32* %array, i32 %length, i32 %n, i32 %l) { 7; CHECK-LABEL: @signed_loop_0_to_n_nested_0_to_l_inner_index_check 8entry: 9 %tmp5 = icmp sle i32 %n, 0 10 br i1 %tmp5, label %exit, label %outer.loop.preheader 11 12outer.loop.preheader: 13; CHECK: outer.loop.preheader: 14; CHECK: [[iteration_count:[^ ]+]] = add i32 %l, -1 15 br label %outer.loop 16 17outer.loop: 18 %outer.loop.acc = phi i32 [ %outer.loop.acc.next, %outer.loop.inc ], [ 0, %outer.loop.preheader ] 19 %i = phi i32 [ %i.next, %outer.loop.inc ], [ 0, %outer.loop.preheader ] 20 %tmp6 = icmp sle i32 %l, 0 21 br i1 %tmp6, label %outer.loop.inc, label %inner.loop.preheader 22 23inner.loop.preheader: 24; CHECK: inner.loop.preheader: 25; CHECK: [[wide_cond:[^ ]+]] = icmp slt i32 [[iteration_count]], %length 26 br label %inner.loop 27 28inner.loop: 29; CHECK: inner.loop: 30; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ] 31 %inner.loop.acc = phi i32 [ %inner.loop.acc.next, %inner.loop ], [ %outer.loop.acc, %inner.loop.preheader ] 32 %j = phi i32 [ %j.next, %inner.loop ], [ 0, %inner.loop.preheader ] 33 34 %within.bounds = icmp slt i32 %j, %length 35 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 36 37 %j.i64 = zext i32 %j to i64 38 %array.j.ptr = getelementptr inbounds i32, i32* %array, i64 %j.i64 39 %array.j = load i32, i32* %array.j.ptr, align 4 40 %inner.loop.acc.next = add i32 %inner.loop.acc, %array.j 41 42 %j.next = add nsw i32 %j, 1 43 %inner.continue = icmp slt i32 %j.next, %l 44 br i1 %inner.continue, label %inner.loop, label %outer.loop.inc 45 46outer.loop.inc: 47 %outer.loop.acc.next = phi i32 [ %inner.loop.acc.next, %inner.loop ], [ %outer.loop.acc, %outer.loop ] 48 %i.next = add nsw i32 %i, 1 49 %outer.continue = icmp slt i32 %i.next, %n 50 br i1 %outer.continue, label %outer.loop, label %exit 51 52exit: 53 %result = phi i32 [ 0, %entry ], [ %outer.loop.acc.next, %outer.loop.inc ] 54 ret i32 %result 55} 56 57define i32 @signed_loop_0_to_n_nested_0_to_l_outer_index_check(i32* %array, i32 %length, i32 %n, i32 %l) { 58; CHECK-LABEL: @signed_loop_0_to_n_nested_0_to_l_outer_index_check 59entry: 60 %tmp5 = icmp sle i32 %n, 0 61 br i1 %tmp5, label %exit, label %outer.loop.preheader 62 63outer.loop.preheader: 64; CHECK: outer.loop.preheader: 65; CHECK: [[iteration_count:[^ ]+]] = add i32 %n, -1 66; CHECK: [[wide_cond:[^ ]+]] = icmp slt i32 [[iteration_count]], %length 67 br label %outer.loop 68 69outer.loop: 70 %outer.loop.acc = phi i32 [ %outer.loop.acc.next, %outer.loop.inc ], [ 0, %outer.loop.preheader ] 71 %i = phi i32 [ %i.next, %outer.loop.inc ], [ 0, %outer.loop.preheader ] 72 %tmp6 = icmp sle i32 %l, 0 73 br i1 %tmp6, label %outer.loop.inc, label %inner.loop.preheader 74 75inner.loop.preheader: 76 br label %inner.loop 77 78inner.loop: 79; CHECK: inner.loop: 80; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ] 81 82 %inner.loop.acc = phi i32 [ %inner.loop.acc.next, %inner.loop ], [ %outer.loop.acc, %inner.loop.preheader ] 83 %j = phi i32 [ %j.next, %inner.loop ], [ 0, %inner.loop.preheader ] 84 85 %within.bounds = icmp slt i32 %i, %length 86 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 87 88 %i.i64 = zext i32 %i to i64 89 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 90 %array.i = load i32, i32* %array.i.ptr, align 4 91 %inner.loop.acc.next = add i32 %inner.loop.acc, %array.i 92 93 %j.next = add nsw i32 %j, 1 94 %inner.continue = icmp slt i32 %j.next, %l 95 br i1 %inner.continue, label %inner.loop, label %outer.loop.inc 96 97outer.loop.inc: 98 %outer.loop.acc.next = phi i32 [ %inner.loop.acc.next, %inner.loop ], [ %outer.loop.acc, %outer.loop ] 99 %i.next = add nsw i32 %i, 1 100 %outer.continue = icmp slt i32 %i.next, %n 101 br i1 %outer.continue, label %outer.loop, label %exit 102 103exit: 104 %result = phi i32 [ 0, %entry ], [ %outer.loop.acc.next, %outer.loop.inc ] 105 ret i32 %result 106} 107 108define i32 @signed_loop_0_to_n_nested_i_to_l_inner_index_check(i32* %array, i32 %length, i32 %n, i32 %l) { 109; CHECK-LABEL: @signed_loop_0_to_n_nested_i_to_l_inner_index_check 110entry: 111 %tmp5 = icmp sle i32 %n, 0 112 br i1 %tmp5, label %exit, label %outer.loop.preheader 113 114outer.loop.preheader: 115 br label %outer.loop 116 117outer.loop: 118; CHECK: outer.loop: 119; CHECK: [[i_1:[^ ]+]] = add i32 %i, 1 120; CHECK-NEXT: [[l_sgt_i_1:[^ ]+]] = icmp sgt i32 %l, [[i_1]] 121; CHECK-NEXT: [[smax:[^ ]+]] = select i1 [[l_sgt_i_1]], i32 %l, i32 [[i_1]] 122; CHECK-NEXT: [[max_j:[^ ]+]] = add i32 [[smax]], -1 123 %outer.loop.acc = phi i32 [ %outer.loop.acc.next, %outer.loop.inc ], [ 0, %outer.loop.preheader ] 124 %i = phi i32 [ %i.next, %outer.loop.inc ], [ 0, %outer.loop.preheader ] 125 %tmp6 = icmp sle i32 %l, 0 126 br i1 %tmp6, label %outer.loop.inc, label %inner.loop.preheader 127 128inner.loop.preheader: 129; CHECK: inner.loop.preheader: 130; CHECK: [[wide_cond:[^ ]+]] = icmp slt i32 [[max_j]], %length 131 br label %inner.loop 132 133inner.loop: 134; CHECK: inner.loop: 135; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 [[wide_cond]], i32 9) [ "deopt"() ] 136 %inner.loop.acc = phi i32 [ %inner.loop.acc.next, %inner.loop ], [ %outer.loop.acc, %inner.loop.preheader ] 137 %j = phi i32 [ %j.next, %inner.loop ], [ %i, %inner.loop.preheader ] 138 139 %within.bounds = icmp slt i32 %j, %length 140 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 141 142 %j.i64 = zext i32 %j to i64 143 %array.j.ptr = getelementptr inbounds i32, i32* %array, i64 %j.i64 144 %array.j = load i32, i32* %array.j.ptr, align 4 145 %inner.loop.acc.next = add i32 %inner.loop.acc, %array.j 146 147 %j.next = add nsw i32 %j, 1 148 %inner.continue = icmp slt i32 %j.next, %l 149 br i1 %inner.continue, label %inner.loop, label %outer.loop.inc 150 151outer.loop.inc: 152 %outer.loop.acc.next = phi i32 [ %inner.loop.acc.next, %inner.loop ], [ %outer.loop.acc, %outer.loop ] 153 %i.next = add nsw i32 %i, 1 154 %outer.continue = icmp slt i32 %i.next, %n 155 br i1 %outer.continue, label %outer.loop, label %exit 156 157exit: 158 %result = phi i32 [ 0, %entry ], [ %outer.loop.acc.next, %outer.loop.inc ] 159 ret i32 %result 160}