[llvm] e9b33d0 - [ConstraintElim] Add extra tests with nested loops and iv decrements.

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 2 04:52:19 PDT 2023


Author: Florian Hahn
Date: 2023-10-02T12:51:51+01:00
New Revision: e9b33d085da05da6ce943dc563134f5ba91ca35b

URL: https://github.com/llvm/llvm-project/commit/e9b33d085da05da6ce943dc563134f5ba91ca35b
DIFF: https://github.com/llvm/llvm-project/commit/e9b33d085da05da6ce943dc563134f5ba91ca35b.diff

LOG: [ConstraintElim] Add extra tests with nested loops and iv decrements.

Add extra test coverage for induction logic to cover nested loops and
loops with induction decrements. This adds coverage for upcoming
patches.

Added: 
    llvm/test/Transforms/ConstraintElimination/monotonic-int-phis-decrement.ll
    llvm/test/Transforms/ConstraintElimination/monotonic-int-phis-nested-loops.ll

Modified: 
    

Removed: 
    


################################################################################
diff  --git a/llvm/test/Transforms/ConstraintElimination/monotonic-int-phis-decrement.ll b/llvm/test/Transforms/ConstraintElimination/monotonic-int-phis-decrement.ll
new file mode 100644
index 000000000000000..4ebbae54965a43b
--- /dev/null
+++ b/llvm/test/Transforms/ConstraintElimination/monotonic-int-phis-decrement.ll
@@ -0,0 +1,260 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3
+; RUN: opt -p constraint-elimination -S %s | FileCheck %s
+
+declare void @use(i1)
+declare void @llvm.assume(i1)
+
+define void @add_rec_decreasing_cond_true_constant(i8 noundef %len) {
+; CHECK-LABEL: define void @add_rec_decreasing_cond_true_constant(
+; CHECK-SAME: i8 noundef [[LEN:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
+; CHECK:       loop.header:
+; CHECK-NEXT:    [[K_0:%.*]] = phi i8 [ 4, [[ENTRY:%.*]] ], [ [[K_DEC:%.*]], [[LOOP_LATCH:%.*]] ]
+; CHECK-NEXT:    [[CMP2_NOT:%.*]] = icmp eq i8 [[K_0]], 0
+; CHECK-NEXT:    br i1 [[CMP2_NOT]], label [[EXIT:%.*]], label [[LOOP_LATCH]]
+; CHECK:       loop.latch:
+; CHECK-NEXT:    [[CMP_NOT_I:%.*]] = icmp ult i8 [[K_0]], 5
+; CHECK-NEXT:    call void @use(i1 [[CMP_NOT_I]])
+; CHECK-NEXT:    [[K_DEC]] = add i8 [[K_0]], -1
+; CHECK-NEXT:    br label [[LOOP_HEADER]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  br label %loop.header
+
+loop.header:
+  %k.0 = phi i8 [ 4, %entry], [ %k.dec, %loop.latch ]
+  %cmp2.not = icmp eq i8 %k.0, 0
+  br i1 %cmp2.not, label %exit, label %loop.latch
+
+loop.latch:
+  %cmp.not.i = icmp ult i8 %k.0, 5
+  call void @use(i1 %cmp.not.i)
+  %k.dec = add i8 %k.0, -1
+  br label %loop.header
+
+exit:
+  ret void
+}
+
+define void @add_rec_decreasing_cond_not_true_constant(i8 noundef %len) {
+; CHECK-LABEL: define void @add_rec_decreasing_cond_not_true_constant(
+; CHECK-SAME: i8 noundef [[LEN:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
+; CHECK:       loop.header:
+; CHECK-NEXT:    [[K_0:%.*]] = phi i8 [ 4, [[ENTRY:%.*]] ], [ [[K_DEC:%.*]], [[LOOP_LATCH:%.*]] ]
+; CHECK-NEXT:    [[CMP2_NOT:%.*]] = icmp eq i8 [[K_0]], 0
+; CHECK-NEXT:    br i1 [[CMP2_NOT]], label [[EXIT:%.*]], label [[LOOP_LATCH]]
+; CHECK:       loop.latch:
+; CHECK-NEXT:    [[CMP_NOT_I:%.*]] = icmp ult i8 [[K_0]], 4
+; CHECK-NEXT:    call void @use(i1 [[CMP_NOT_I]])
+; CHECK-NEXT:    [[K_DEC]] = add i8 [[K_0]], -1
+; CHECK-NEXT:    br label [[LOOP_HEADER]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  br label %loop.header
+
+loop.header:
+  %k.0 = phi i8 [ 4, %entry], [ %k.dec, %loop.latch ]
+  %cmp2.not = icmp eq i8 %k.0, 0
+  br i1 %cmp2.not, label %exit, label %loop.latch
+
+loop.latch:
+  %cmp.not.i = icmp ult i8 %k.0, 4
+  call void @use(i1 %cmp.not.i)
+  %k.dec = add i8 %k.0, -1
+  br label %loop.header
+
+exit:
+  ret void
+}
+
+define void @add_rec_decreasing_cond_true_start_signed_positive(i8 noundef %start) {
+; CHECK-LABEL: define void @add_rec_decreasing_cond_true_start_signed_positive(
+; CHECK-SAME: i8 noundef [[START:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[PRECOND:%.*]] = icmp sge i8 [[START]], 1
+; CHECK-NEXT:    call void @llvm.assume(i1 [[PRECOND]])
+; CHECK-NEXT:    [[START_1:%.*]] = add i8 [[START]], -1
+; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
+; CHECK:       loop.header:
+; CHECK-NEXT:    [[K_0:%.*]] = phi i8 [ [[START_1]], [[ENTRY:%.*]] ], [ [[K_DEC:%.*]], [[LOOP_LATCH:%.*]] ]
+; CHECK-NEXT:    [[CMP2_NOT:%.*]] = icmp eq i8 [[K_0]], 0
+; CHECK-NEXT:    br i1 [[CMP2_NOT]], label [[EXIT:%.*]], label [[LOOP_LATCH]]
+; CHECK:       loop.latch:
+; CHECK-NEXT:    [[CMP_NOT_I:%.*]] = icmp ult i8 [[K_0]], [[START]]
+; CHECK-NEXT:    call void @use(i1 [[CMP_NOT_I]])
+; CHECK-NEXT:    [[K_DEC]] = add i8 [[K_0]], -1
+; CHECK-NEXT:    br label [[LOOP_HEADER]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %precond = icmp sge i8 %start, 1
+  call void @llvm.assume(i1 %precond)
+  %start.1 = add i8 %start, -1
+  br label %loop.header
+
+loop.header:
+  %k.0 = phi i8 [ %start.1, %entry], [ %k.dec, %loop.latch ]
+  %cmp2.not = icmp eq i8 %k.0, 0
+  br i1 %cmp2.not, label %exit, label %loop.latch
+
+loop.latch:
+  %cmp.not.i = icmp ult i8 %k.0, %start
+  call void @use(i1 %cmp.not.i)
+  %k.dec = add i8 %k.0, -1
+  br label %loop.header
+
+exit:
+  ret void
+}
+
+define void @add_rec_decreasing_cond_not_true_start_signed_positive(i8 noundef %start) {
+; CHECK-LABEL: define void @add_rec_decreasing_cond_not_true_start_signed_positive(
+; CHECK-SAME: i8 noundef [[START:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[PRECOND:%.*]] = icmp sge i8 [[START]], 1
+; CHECK-NEXT:    call void @llvm.assume(i1 [[PRECOND]])
+; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
+; CHECK:       loop.header:
+; CHECK-NEXT:    [[K_0:%.*]] = phi i8 [ [[START]], [[ENTRY:%.*]] ], [ [[K_DEC:%.*]], [[LOOP_LATCH:%.*]] ]
+; CHECK-NEXT:    [[CMP2_NOT:%.*]] = icmp eq i8 [[K_0]], 0
+; CHECK-NEXT:    br i1 [[CMP2_NOT]], label [[EXIT:%.*]], label [[LOOP_LATCH]]
+; CHECK:       loop.latch:
+; CHECK-NEXT:    [[CMP_NOT_I:%.*]] = icmp ult i8 [[K_0]], [[START]]
+; CHECK-NEXT:    call void @use(i1 [[CMP_NOT_I]])
+; CHECK-NEXT:    [[K_DEC]] = add i8 [[K_0]], -1
+; CHECK-NEXT:    br label [[LOOP_HEADER]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %precond = icmp sge i8 %start, 1
+  call void @llvm.assume(i1 %precond)
+  br label %loop.header
+
+loop.header:
+  %k.0 = phi i8 [ %start, %entry], [ %k.dec, %loop.latch ]
+  %cmp2.not = icmp eq i8 %k.0, 0
+  br i1 %cmp2.not, label %exit, label %loop.latch
+
+loop.latch:
+  %cmp.not.i = icmp ult i8 %k.0, %start
+  call void @use(i1 %cmp.not.i)
+  %k.dec = add i8 %k.0, -1
+  br label %loop.header
+
+exit:
+  ret void
+}
+
+define void @add_rec_decreasing_add_rec_positive_to_negative(i8 noundef %len) {
+; CHECK-LABEL: define void @add_rec_decreasing_add_rec_positive_to_negative(
+; CHECK-SAME: i8 noundef [[LEN:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
+; CHECK:       loop.header:
+; CHECK-NEXT:    [[K_0:%.*]] = phi i8 [ 4, [[ENTRY:%.*]] ], [ [[K_DEC:%.*]], [[LOOP_LATCH:%.*]] ]
+; CHECK-NEXT:    [[CMP2_NOT:%.*]] = icmp eq i8 [[K_0]], -2
+; CHECK-NEXT:    br i1 [[CMP2_NOT]], label [[EXIT:%.*]], label [[LOOP_LATCH]]
+; CHECK:       loop.latch:
+; CHECK-NEXT:    [[CMP_NOT_I:%.*]] = icmp ult i8 [[K_0]], 5
+; CHECK-NEXT:    call void @use(i1 [[CMP_NOT_I]])
+; CHECK-NEXT:    [[K_DEC]] = add i8 [[K_0]], -1
+; CHECK-NEXT:    br label [[LOOP_HEADER]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  br label %loop.header
+
+loop.header:
+  %k.0 = phi i8 [ 4, %entry], [ %k.dec, %loop.latch ]
+  %cmp2.not = icmp eq i8 %k.0, -2
+  br i1 %cmp2.not, label %exit, label %loop.latch
+
+loop.latch:
+  %cmp.not.i = icmp ult i8 %k.0, 5
+  call void @use(i1 %cmp.not.i)
+  %k.dec = add i8 %k.0, -1
+  br label %loop.header
+
+exit:
+  ret void
+}
+
+define void @add_rec_decreasing_2_cond_true_constant(i8 noundef %len) {
+; CHECK-LABEL: define void @add_rec_decreasing_2_cond_true_constant(
+; CHECK-SAME: i8 noundef [[LEN:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
+; CHECK:       loop.header:
+; CHECK-NEXT:    [[K_0:%.*]] = phi i8 [ 4, [[ENTRY:%.*]] ], [ [[K_DEC:%.*]], [[LOOP_LATCH:%.*]] ]
+; CHECK-NEXT:    [[CMP2_NOT:%.*]] = icmp eq i8 [[K_0]], 0
+; CHECK-NEXT:    br i1 [[CMP2_NOT]], label [[EXIT:%.*]], label [[LOOP_LATCH]]
+; CHECK:       loop.latch:
+; CHECK-NEXT:    [[CMP_NOT_I:%.*]] = icmp ult i8 [[K_0]], 5
+; CHECK-NEXT:    call void @use(i1 [[CMP_NOT_I]])
+; CHECK-NEXT:    [[K_DEC]] = add i8 [[K_0]], -2
+; CHECK-NEXT:    br label [[LOOP_HEADER]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  br label %loop.header
+
+loop.header:
+  %k.0 = phi i8 [ 4, %entry], [ %k.dec, %loop.latch ]
+  %cmp2.not = icmp eq i8 %k.0, 0
+  br i1 %cmp2.not, label %exit, label %loop.latch
+
+loop.latch:
+  %cmp.not.i = icmp ult i8 %k.0, 5
+  call void @use(i1 %cmp.not.i)
+  %k.dec = add i8 %k.0, -2
+  br label %loop.header
+
+exit:
+  ret void
+}
+
+define void @add_rec_decreasing_2_cond_not_true_constant(i8 noundef %len) {
+; CHECK-LABEL: define void @add_rec_decreasing_2_cond_not_true_constant(
+; CHECK-SAME: i8 noundef [[LEN:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
+; CHECK:       loop.header:
+; CHECK-NEXT:    [[K_0:%.*]] = phi i8 [ 5, [[ENTRY:%.*]] ], [ [[K_DEC:%.*]], [[LOOP_LATCH:%.*]] ]
+; CHECK-NEXT:    [[CMP2_NOT:%.*]] = icmp eq i8 [[K_0]], 0
+; CHECK-NEXT:    br i1 [[CMP2_NOT]], label [[EXIT:%.*]], label [[LOOP_LATCH]]
+; CHECK:       loop.latch:
+; CHECK-NEXT:    [[CMP_NOT_I:%.*]] = icmp ult i8 [[K_0]], 5
+; CHECK-NEXT:    call void @use(i1 [[CMP_NOT_I]])
+; CHECK-NEXT:    [[K_DEC]] = add i8 [[K_0]], -2
+; CHECK-NEXT:    br label [[LOOP_HEADER]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  br label %loop.header
+
+loop.header:
+  %k.0 = phi i8 [ 5, %entry], [ %k.dec, %loop.latch ]
+  %cmp2.not = icmp eq i8 %k.0, 0
+  br i1 %cmp2.not, label %exit, label %loop.latch
+
+loop.latch:
+  %cmp.not.i = icmp ult i8 %k.0, 5
+  call void @use(i1 %cmp.not.i)
+  %k.dec = add i8 %k.0, -2
+  br label %loop.header
+
+exit:
+  ret void
+}

diff  --git a/llvm/test/Transforms/ConstraintElimination/monotonic-int-phis-nested-loops.ll b/llvm/test/Transforms/ConstraintElimination/monotonic-int-phis-nested-loops.ll
new file mode 100644
index 000000000000000..4835d48c57b6327
--- /dev/null
+++ b/llvm/test/Transforms/ConstraintElimination/monotonic-int-phis-nested-loops.ll
@@ -0,0 +1,156 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3
+; RUN: opt -p constraint-elimination -S %s | FileCheck %s
+
+declare void @use(i1)
+
+define void @start_value_of_inner_add_rec_is_add_rec_condition_can_be_simplified(i32 noundef %len) {
+; CHECK-LABEL: define void @start_value_of_inner_add_rec_is_add_rec_condition_can_be_simplified(
+; CHECK-SAME: i32 noundef [[LEN:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[OUTER_HEADER:%.*]]
+; CHECK:       outer.header:
+; CHECK-NEXT:    [[I_0:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[OUTER_LATCH:%.*]] ]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[I_0]], [[LEN]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[INNER_HEADER:%.*]], label [[EXIT:%.*]]
+; CHECK:       inner.header:
+; CHECK-NEXT:    [[K_0:%.*]] = phi i32 [ [[I_0]], [[OUTER_HEADER]] ], [ [[K_INC:%.*]], [[INNER_LATCH:%.*]] ]
+; CHECK-NEXT:    [[CMP2_NOT:%.*]] = icmp eq i32 [[K_0]], [[LEN]]
+; CHECK-NEXT:    br i1 [[CMP2_NOT]], label [[OUTER_LATCH]], label [[INNER_LATCH]]
+; CHECK:       inner.latch:
+; CHECK-NEXT:    [[CMP_NOT_I:%.*]] = icmp ult i32 [[K_0]], [[LEN]]
+; CHECK-NEXT:    call void @use(i1 [[CMP_NOT_I]])
+; CHECK-NEXT:    [[K_INC]] = add i32 [[K_0]], 1
+; CHECK-NEXT:    br label [[INNER_HEADER]]
+; CHECK:       outer.latch:
+; CHECK-NEXT:    [[I_INC]] = add i32 [[I_0]], 1
+; CHECK-NEXT:    br label [[OUTER_HEADER]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  br label %outer.header
+
+outer.header:
+  %i.0 = phi i32 [ 1, %entry ], [ %i.inc, %outer.latch ]
+  %cmp = icmp ult i32 %i.0, %len
+  br i1 %cmp, label %inner.header, label %exit
+
+inner.header:
+  %k.0 = phi i32 [ %i.0, %outer.header ], [ %k.inc, %inner.latch ]
+  %cmp2.not = icmp eq i32 %k.0, %len
+  br i1 %cmp2.not, label %outer.latch, label %inner.latch
+
+inner.latch:
+  %cmp.not.i = icmp ult i32 %k.0, %len
+  call void @use(i1 %cmp.not.i)
+  %k.inc = add i32 %k.0, 1
+  br label %inner.header
+
+outer.latch:
+  %i.inc = add i32 %i.0, 1
+  br label %outer.header
+
+exit:
+  ret void
+}
+
+define void @start_value_of_inner_add_rec_is_add_rec_condition_cannot_be_simplified(i32 noundef %len) {
+; CHECK-LABEL: define void @start_value_of_inner_add_rec_is_add_rec_condition_cannot_be_simplified(
+; CHECK-SAME: i32 noundef [[LEN:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[OUTER_HEADER:%.*]]
+; CHECK:       outer.header:
+; CHECK-NEXT:    [[I_0:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[OUTER_LATCH:%.*]] ]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[I_0]], [[LEN]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[INNER_HEADER:%.*]], label [[EXIT:%.*]]
+; CHECK:       inner.header:
+; CHECK-NEXT:    [[K_0:%.*]] = phi i32 [ [[I_0]], [[OUTER_HEADER]] ], [ [[K_INC:%.*]], [[INNER_LATCH:%.*]] ]
+; CHECK-NEXT:    [[CMP2_NOT:%.*]] = icmp eq i32 [[K_0]], [[LEN]]
+; CHECK-NEXT:    br i1 [[CMP2_NOT]], label [[OUTER_LATCH]], label [[INNER_LATCH]]
+; CHECK:       inner.latch:
+; CHECK-NEXT:    [[CMP_NOT_I:%.*]] = icmp ult i32 [[K_0]], 3
+; CHECK-NEXT:    call void @use(i1 [[CMP_NOT_I]])
+; CHECK-NEXT:    [[K_INC]] = add i32 [[K_0]], 1
+; CHECK-NEXT:    br label [[INNER_HEADER]]
+; CHECK:       outer.latch:
+; CHECK-NEXT:    [[I_INC]] = add i32 [[I_0]], 1
+; CHECK-NEXT:    br label [[OUTER_HEADER]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  br label %outer.header
+
+outer.header:
+  %i.0 = phi i32 [ 1, %entry ], [ %i.inc, %outer.latch ]
+  %cmp = icmp ult i32 %i.0, %len
+  br i1 %cmp, label %inner.header, label %exit
+
+inner.header:
+  %k.0 = phi i32 [ %i.0, %outer.header ], [ %k.inc, %inner.latch ]
+  %cmp2.not = icmp eq i32 %k.0, %len
+  br i1 %cmp2.not, label %outer.latch, label %inner.latch
+
+inner.latch:
+  %cmp.not.i = icmp ult i32 %k.0, 3
+  call void @use(i1 %cmp.not.i)
+  %k.inc = add i32 %k.0, 1
+  br label %inner.header
+
+outer.latch:
+  %i.inc = add i32 %i.0, 1
+  br label %outer.header
+
+exit:
+  ret void
+}
+define void @inner_add_rec_decreasing(i32 noundef %len) {
+; CHECK-LABEL: define void @inner_add_rec_decreasing(
+; CHECK-SAME: i32 noundef [[LEN:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[OUTER_HEADER:%.*]]
+; CHECK:       outer.header:
+; CHECK-NEXT:    [[I_0:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[OUTER_LATCH:%.*]] ]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i32 [[I_0]], [[LEN]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[INNER_HEADER:%.*]], label [[EXIT:%.*]]
+; CHECK:       inner.header:
+; CHECK-NEXT:    [[K_0:%.*]] = phi i32 [ [[I_0]], [[OUTER_HEADER]] ], [ [[K_DEC:%.*]], [[INNER_LATCH:%.*]] ]
+; CHECK-NEXT:    [[CMP2_NOT:%.*]] = icmp eq i32 [[K_0]], 0
+; CHECK-NEXT:    br i1 [[CMP2_NOT]], label [[OUTER_LATCH]], label [[INNER_LATCH]]
+; CHECK:       inner.latch:
+; CHECK-NEXT:    [[CMP_NOT_I:%.*]] = icmp ult i32 [[K_0]], [[LEN]]
+; CHECK-NEXT:    call void @use(i1 [[CMP_NOT_I]])
+; CHECK-NEXT:    [[K_DEC]] = add i32 [[K_0]], -1
+; CHECK-NEXT:    br label [[INNER_HEADER]]
+; CHECK:       outer.latch:
+; CHECK-NEXT:    [[I_INC]] = add i32 [[I_0]], 1
+; CHECK-NEXT:    br label [[OUTER_HEADER]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  br label %outer.header
+
+outer.header:
+  %i.0 = phi i32 [ 1, %entry ], [ %i.inc, %outer.latch ]
+  %cmp = icmp ult i32 %i.0, %len
+  br i1 %cmp, label %inner.header, label %exit
+
+inner.header:
+  %k.0 = phi i32 [ %i.0, %outer.header ], [ %k.dec, %inner.latch ]
+  %cmp2.not = icmp eq i32 %k.0, 0
+  br i1 %cmp2.not, label %outer.latch, label %inner.latch
+
+inner.latch:
+  %cmp.not.i = icmp ult i32 %k.0, %len
+  call void @use(i1 %cmp.not.i)
+  %k.dec = add i32 %k.0, -1
+  br label %inner.header
+
+outer.latch:
+  %i.inc = add i32 %i.0, 1
+  br label %outer.header
+
+exit:
+  ret void
+}


        


More information about the llvm-commits mailing list