aboutsummaryrefslogtreecommitdiff
path: root/test/Transforms/LoopUnroll/runtime-loop-multiple-exits.ll
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-07-01 13:22:02 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-07-01 13:22:02 +0000
commit9df3605dea17e84f8183581f6103bd0c79e2a606 (patch)
tree70a2f36ce9eb9bb213603cd7f2f120af53fc176f /test/Transforms/LoopUnroll/runtime-loop-multiple-exits.ll
parent08bbd35a80bf7765fe0d3043f9eb5a2f2786b649 (diff)
downloadsrc-9df3605dea17e84f8183581f6103bd0c79e2a606.tar.gz
src-9df3605dea17e84f8183581f6103bd0c79e2a606.zip
Vendor import of llvm trunk r306956:vendor/llvm/llvm-trunk-r306956
Notes
Notes: svn path=/vendor/llvm/dist/; revision=320533 svn path=/vendor/llvm/llvm-trunk-r306956/; revision=320534; tag=vendor/llvm/llvm-trunk-r306956
Diffstat (limited to 'test/Transforms/LoopUnroll/runtime-loop-multiple-exits.ll')
-rw-r--r--test/Transforms/LoopUnroll/runtime-loop-multiple-exits.ll279
1 files changed, 279 insertions, 0 deletions
diff --git a/test/Transforms/LoopUnroll/runtime-loop-multiple-exits.ll b/test/Transforms/LoopUnroll/runtime-loop-multiple-exits.ll
new file mode 100644
index 000000000000..1f31a133e34d
--- /dev/null
+++ b/test/Transforms/LoopUnroll/runtime-loop-multiple-exits.ll
@@ -0,0 +1,279 @@
+; RUN: opt < %s -loop-unroll -unroll-runtime=true -unroll-runtime-epilog=true -unroll-runtime-multi-exit=true -verify-dom-info -verify-loop-info -instcombine -S| FileCheck %s
+; RUN: opt < %s -loop-unroll -unroll-runtime -unroll-count=2 -unroll-runtime-epilog=true -unroll-runtime-multi-exit=true -verify-dom-info -verify-loop-info -instcombine
+
+; the second RUN generates an epilog remainder block for all the test
+; cases below (it does not generate a loop).
+
+; test with three exiting and three exit blocks.
+; none of the exit blocks have successors
+define void @test1(i64 %trip, i1 %cond) {
+; CHECK-LABEL: test1
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[TRIP:%.*]], -1
+; CHECK-NEXT: [[XTRAITER:%.*]] = and i64 [[TRIP]], 7
+; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i64 [[TMP0]], 7
+; CHECK-NEXT: br i1 [[TMP1]], label %exit2.loopexit.unr-lcssa, label [[ENTRY_NEW:%.*]]
+; CHECK: entry.new:
+; CHECK-NEXT: [[UNROLL_ITER:%.*]] = sub i64 [[TRIP]], [[XTRAITER]]
+; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
+; CHECK-LABEL: loop_latch.epil:
+; CHECK-NEXT: %epil.iter.sub = add i64 %epil.iter, -1
+; CHECK-NEXT: %epil.iter.cmp = icmp eq i64 %epil.iter.sub, 0
+; CHECK-NEXT: br i1 %epil.iter.cmp, label %exit2.loopexit.epilog-lcssa, label %loop_header.epil
+; CHECK-LABEL: loop_latch.7:
+; CHECK-NEXT: %niter.nsub.7 = add i64 %niter, -8
+; CHECK-NEXT: %niter.ncmp.7 = icmp eq i64 %niter.nsub.7, 0
+; CHECK-NEXT: br i1 %niter.ncmp.7, label %exit2.loopexit.unr-lcssa.loopexit, label %loop_header
+entry:
+ br label %loop_header
+
+loop_header:
+ %iv = phi i64 [ 0, %entry ], [ %iv_next, %loop_latch ]
+ br i1 %cond, label %loop_latch, label %loop_exiting_bb1
+
+loop_exiting_bb1:
+ br i1 false, label %loop_exiting_bb2, label %exit1
+
+loop_exiting_bb2:
+ br i1 false, label %loop_latch, label %exit3
+
+exit3:
+ ret void
+
+loop_latch:
+ %iv_next = add i64 %iv, 1
+ %cmp = icmp ne i64 %iv_next, %trip
+ br i1 %cmp, label %loop_header, label %exit2.loopexit
+
+exit1:
+ ret void
+
+exit2.loopexit:
+ ret void
+}
+
+
+; test with three exiting and two exit blocks.
+; The non-latch exit block has 2 unique predecessors.
+; There are 2 values passed to the exit blocks that are calculated at every iteration.
+; %sum.02 and %add. Both of these are incoming values for phi from every exiting
+; unrolled block.
+define i32 @test2(i32* nocapture %a, i64 %n) {
+; CHECK-LABEL: test2
+; CHECK-LABEL: for.exit2.loopexit:
+; CHECK-NEXT: %retval.ph = phi i32 [ 42, %for.exiting_block ], [ %sum.02, %header ], [ %add, %for.body ], [ 42, %for.exiting_block.1 ], [ %add.1, %for.body.1 ], [ 42, %for.exiting_block.2 ], [ %add.2, %for.body.2 ], [ 42, %for.exiting_block.3 ],
+; CHECK-NEXT: br label %for.exit2
+; CHECK-LABEL: for.exit2.loopexit2:
+; CHECK-NEXT: %retval.ph3 = phi i32 [ 42, %for.exiting_block.epil ], [ %sum.02.epil, %header.epil ]
+; CHECK-NEXT: br label %for.exit2
+; CHECK-LABEL: for.exit2:
+; CHECK-NEXT: %retval = phi i32 [ %retval.ph, %for.exit2.loopexit ], [ %retval.ph3, %for.exit2.loopexit2 ]
+; CHECK-NEXT: ret i32 %retval
+; CHECK: %niter.nsub.7 = add i64 %niter, -8
+entry:
+ br label %header
+
+header:
+ %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ]
+ %sum.02 = phi i32 [ %add, %for.body ], [ 0, %entry ]
+ br i1 false, label %for.exit2, label %for.exiting_block
+
+for.exiting_block:
+ %cmp = icmp eq i64 %n, 42
+ br i1 %cmp, label %for.exit2, label %for.body
+
+for.body:
+ %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv
+ %0 = load i32, i32* %arrayidx, align 4
+ %add = add nsw i32 %0, %sum.02
+ %indvars.iv.next = add i64 %indvars.iv, 1
+ %exitcond = icmp eq i64 %indvars.iv.next, %n
+ br i1 %exitcond, label %for.end, label %header
+
+for.end: ; preds = %for.body
+ %sum.0.lcssa = phi i32 [ %add, %for.body ]
+ ret i32 %sum.0.lcssa
+
+for.exit2:
+ %retval = phi i32 [ %sum.02, %header ], [ 42, %for.exiting_block ]
+ ret i32 %retval
+}
+
+; test with two exiting and three exit blocks.
+; the non-latch exiting block has a switch.
+define void @test3(i64 %trip, i64 %add) {
+; CHECK-LABEL: test3
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[TRIP:%.*]], -1
+; CHECK-NEXT: [[XTRAITER:%.*]] = and i64 [[TRIP]], 7
+; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i64 [[TMP0]], 7
+; CHECK-NEXT: br i1 [[TMP1]], label %exit2.loopexit.unr-lcssa, label [[ENTRY_NEW:%.*]]
+; CHECK: entry.new:
+; CHECK-NEXT: %unroll_iter = sub i64 [[TRIP]], [[XTRAITER]]
+; CHECK-NEXT: br label [[LOOP_HEADER:%.*]]
+; CHECK-LABEL: loop_header:
+; CHECK-NEXT: %sum = phi i64 [ 0, %entry.new ], [ %sum.next.7, %loop_latch.7 ]
+; CHECK-NEXT: %niter = phi i64 [ %unroll_iter, %entry.new ], [ %niter.nsub.7, %loop_latch.7 ]
+; CHECK-LABEL: loop_exiting_bb1.7:
+; CHECK-NEXT: switch i64 %sum.next.6, label %loop_latch.7
+; CHECK-LABEL: loop_latch.7:
+; CHECK-NEXT: %sum.next.7 = add i64 %sum.next.6, %add
+; CHECK-NEXT: %niter.nsub.7 = add i64 %niter, -8
+; CHECK-NEXT: %niter.ncmp.7 = icmp eq i64 %niter.nsub.7, 0
+; CHECK-NEXT: br i1 %niter.ncmp.7, label %exit2.loopexit.unr-lcssa.loopexit, label %loop_header
+entry:
+ br label %loop_header
+
+loop_header:
+ %iv = phi i64 [ 0, %entry ], [ %iv_next, %loop_latch ]
+ %sum = phi i64 [ 0, %entry ], [ %sum.next, %loop_latch ]
+ br i1 undef, label %loop_latch, label %loop_exiting_bb1
+
+loop_exiting_bb1:
+ switch i64 %sum, label %loop_latch [
+ i64 24, label %exit1
+ i64 42, label %exit3
+ ]
+
+exit3:
+ ret void
+
+loop_latch:
+ %iv_next = add nuw nsw i64 %iv, 1
+ %sum.next = add i64 %sum, %add
+ %cmp = icmp ne i64 %iv_next, %trip
+ br i1 %cmp, label %loop_header, label %exit2.loopexit
+
+exit1:
+ ret void
+
+exit2.loopexit:
+ ret void
+}
+
+; FIXME: Support multiple exiting blocks to the same latch exit block.
+define i32 @test4(i32* nocapture %a, i64 %n, i1 %cond) {
+; CHECK-LABEL: test4
+; CHECK-NOT: .unr
+; CHECK-NOT: .epil
+entry:
+ br label %header
+
+header:
+ %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ]
+ %sum.02 = phi i32 [ %add, %for.body ], [ 0, %entry ]
+ br i1 %cond, label %for.end, label %for.exiting_block
+
+for.exiting_block:
+ %cmp = icmp eq i64 %n, 42
+ br i1 %cmp, label %for.exit2, label %for.body
+
+for.body: ; preds = %for.body, %entry
+ %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv
+ %0 = load i32, i32* %arrayidx, align 4
+ %add = add nsw i32 %0, %sum.02
+ %indvars.iv.next = add i64 %indvars.iv, 1
+ %exitcond = icmp eq i64 %indvars.iv.next, %n
+ br i1 %exitcond, label %for.end, label %header
+
+for.end: ; preds = %for.body, %entry
+ %sum.0.lcssa = phi i32 [ 0, %header ], [ %add, %for.body ]
+ ret i32 %sum.0.lcssa
+
+for.exit2:
+ ret i32 42
+}
+
+; two exiting and two exit blocks.
+; the non-latch exiting block has duplicate edges to the non-latch exit block.
+define i64 @test5(i64 %trip, i64 %add, i1 %cond) {
+; CHECK-LABEL: test5
+; CHECK-LABEL: exit1.loopexit:
+; CHECK-NEXT: %result.ph = phi i64 [ %ivy, %loop_exiting ], [ %ivy, %loop_exiting ], [ %ivy.1, %loop_exiting.1 ], [ %ivy.1, %loop_exiting.1 ], [ %ivy.2, %loop_exiting.2 ],
+; CHECK-NEXT: br label %exit1
+; CHECK-LABEL: exit1.loopexit2:
+; CHECK-NEXT: %ivy.epil = add i64 %iv.epil, %add
+; CHECK-NEXT: br label %exit1
+; CHECK-LABEL: exit1:
+; CHECK-NEXT: %result = phi i64 [ %result.ph, %exit1.loopexit ], [ %ivy.epil, %exit1.loopexit2 ]
+; CHECK-NEXT: ret i64 %result
+; CHECK-LABEL: loop_latch.7:
+; CHECK: %niter.nsub.7 = add i64 %niter, -8
+entry:
+ br label %loop_header
+
+loop_header:
+ %iv = phi i64 [ 0, %entry ], [ %iv_next, %loop_latch ]
+ %sum = phi i64 [ 0, %entry ], [ %sum.next, %loop_latch ]
+ br i1 %cond, label %loop_latch, label %loop_exiting
+
+loop_exiting:
+ %ivy = add i64 %iv, %add
+ switch i64 %sum, label %loop_latch [
+ i64 24, label %exit1
+ i64 42, label %exit1
+ ]
+
+loop_latch:
+ %iv_next = add nuw nsw i64 %iv, 1
+ %sum.next = add i64 %sum, %add
+ %cmp = icmp ne i64 %iv_next, %trip
+ br i1 %cmp, label %loop_header, label %latchexit
+
+exit1:
+ %result = phi i64 [ %ivy, %loop_exiting ], [ %ivy, %loop_exiting ]
+ ret i64 %result
+
+latchexit:
+ ret i64 %sum.next
+}
+
+; test when exit blocks have successors.
+define i32 @test6(i32* nocapture %a, i64 %n, i1 %cond, i32 %x) {
+; CHECK-LABEL: test6
+; CHECK-LABEL: for.exit2.loopexit:
+; CHECK-NEXT: %retval.ph = phi i32 [ 42, %for.exiting_block ], [ %sum.02, %header ], [ %add, %latch ], [ 42, %for.exiting_block.1 ], [ %add.1, %latch.1 ], [ 42, %for.exiting_block.2 ], [ %add.2, %latch.2 ],
+; CHECK-NEXT: br label %for.exit2
+; CHECK-LABEL: for.exit2.loopexit2:
+; CHECK-NEXT: %retval.ph3 = phi i32 [ 42, %for.exiting_block.epil ], [ %sum.02.epil, %header.epil ]
+; CHECK-NEXT: br label %for.exit2
+; CHECK-LABEL: for.exit2:
+; CHECK-NEXT: %retval = phi i32 [ %retval.ph, %for.exit2.loopexit ], [ %retval.ph3, %for.exit2.loopexit2 ]
+; CHECK-NEXT: br i1 %cond, label %exit_true, label %exit_false
+; CHECK-LABEL: latch.7:
+; CHECK: %niter.nsub.7 = add i64 %niter, -8
+entry:
+ br label %header
+
+header:
+ %indvars.iv = phi i64 [ %indvars.iv.next, %latch ], [ 0, %entry ]
+ %sum.02 = phi i32 [ %add, %latch ], [ 0, %entry ]
+ br i1 false, label %for.exit2, label %for.exiting_block
+
+for.exiting_block:
+ %cmp = icmp eq i64 %n, 42
+ br i1 %cmp, label %for.exit2, label %latch
+
+latch:
+ %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv
+ %load = load i32, i32* %arrayidx, align 4
+ %add = add nsw i32 %load, %sum.02
+ %indvars.iv.next = add i64 %indvars.iv, 1
+ %exitcond = icmp eq i64 %indvars.iv.next, %n
+ br i1 %exitcond, label %latch_exit, label %header
+
+latch_exit:
+ %sum.0.lcssa = phi i32 [ %add, %latch ]
+ ret i32 %sum.0.lcssa
+
+for.exit2:
+ %retval = phi i32 [ %sum.02, %header ], [ 42, %for.exiting_block ]
+ %addx = add i32 %retval, %x
+ br i1 %cond, label %exit_true, label %exit_false
+
+exit_true:
+ ret i32 %retval
+
+exit_false:
+ ret i32 %addx
+}