summaryrefslogtreecommitdiffstats
path: root/llvm/test/Transforms/LoopSimplify/basictest.ll
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/test/Transforms/LoopSimplify/basictest.ll')
-rw-r--r--llvm/test/Transforms/LoopSimplify/basictest.ll236
1 files changed, 236 insertions, 0 deletions
diff --git a/llvm/test/Transforms/LoopSimplify/basictest.ll b/llvm/test/Transforms/LoopSimplify/basictest.ll
new file mode 100644
index 00000000000..e5fb7b9907b
--- /dev/null
+++ b/llvm/test/Transforms/LoopSimplify/basictest.ll
@@ -0,0 +1,236 @@
+; RUN: opt < %s -S -loop-simplify | FileCheck %s
+; RUN: opt < %s -S -passes=loop-simplify | FileCheck %s
+
+; This function should get a preheader inserted before bb3, that is jumped
+; to by bb1 & bb2
+define void @test() {
+; CHECK-LABEL: define void @test(
+entry:
+ br i1 true, label %bb1, label %bb2
+
+bb1:
+ br label %bb3
+; CHECK: bb1:
+; CHECK-NEXT: br label %[[PH:.*]]
+
+bb2:
+ br label %bb3
+; CHECK: bb2:
+; CHECK-NEXT: br label %[[PH]]
+
+bb3:
+ br label %bb3
+; CHECK: [[PH]]:
+; CHECK-NEXT: br label %bb3
+;
+; CHECK: bb3:
+; CHECK-NEXT: br label %bb3
+}
+
+; Test a case where we have multiple exit blocks as successors of a single loop
+; block that need to be made dedicated exit blocks. We also have multiple
+; exiting edges to one of the exit blocks that all should be rewritten.
+define void @test_multiple_exits_from_single_block(i8 %a, i8* %b.ptr) {
+; CHECK-LABEL: define void @test_multiple_exits_from_single_block(
+entry:
+ switch i8 %a, label %loop [
+ i8 0, label %exit.a
+ i8 1, label %exit.b
+ ]
+; CHECK: entry:
+; CHECK-NEXT: switch i8 %a, label %[[PH:.*]] [
+; CHECK-NEXT: i8 0, label %exit.a
+; CHECK-NEXT: i8 1, label %exit.b
+; CHECK-NEXT: ]
+
+loop:
+ %b = load volatile i8, i8* %b.ptr
+ switch i8 %b, label %loop [
+ i8 0, label %exit.a
+ i8 1, label %exit.b
+ i8 2, label %loop
+ i8 3, label %exit.a
+ i8 4, label %loop
+ i8 5, label %exit.a
+ i8 6, label %loop
+ ]
+; CHECK: [[PH]]:
+; CHECK-NEXT: br label %loop
+;
+; CHECK: loop:
+; CHECK-NEXT: %[[B:.*]] = load volatile i8, i8* %b.ptr
+; CHECK-NEXT: switch i8 %[[B]], label %[[BACKEDGE:.*]] [
+; CHECK-NEXT: i8 0, label %[[LOOPEXIT_A:.*]]
+; CHECK-NEXT: i8 1, label %[[LOOPEXIT_B:.*]]
+; CHECK-NEXT: i8 2, label %[[BACKEDGE]]
+; CHECK-NEXT: i8 3, label %[[LOOPEXIT_A]]
+; CHECK-NEXT: i8 4, label %[[BACKEDGE]]
+; CHECK-NEXT: i8 5, label %[[LOOPEXIT_A]]
+; CHECK-NEXT: i8 6, label %[[BACKEDGE]]
+; CHECK-NEXT: ]
+;
+; CHECK: [[BACKEDGE]]:
+; CHECK-NEXT: br label %loop
+
+exit.a:
+ ret void
+; CHECK: [[LOOPEXIT_A]]:
+; CHECK-NEXT: br label %exit.a
+;
+; CHECK: exit.a:
+; CHECK-NEXT: ret void
+
+exit.b:
+ ret void
+; CHECK: [[LOOPEXIT_B]]:
+; CHECK-NEXT: br label %exit.b
+;
+; CHECK: exit.b:
+; CHECK-NEXT: ret void
+}
+
+; Check that we leave already dedicated exits alone when forming dedicated exit
+; blocks.
+define void @test_pre_existing_dedicated_exits(i1 %a, i1* %ptr) {
+; CHECK-LABEL: define void @test_pre_existing_dedicated_exits(
+entry:
+ br i1 %a, label %loop.ph, label %non_dedicated_exit
+; CHECK: entry:
+; CHECK-NEXT: br i1 %a, label %loop.ph, label %non_dedicated_exit
+
+loop.ph:
+ br label %loop.header
+; CHECK: loop.ph:
+; CHECK-NEXT: br label %loop.header
+
+loop.header:
+ %c1 = load volatile i1, i1* %ptr
+ br i1 %c1, label %loop.body1, label %dedicated_exit1
+; CHECK: loop.header:
+; CHECK-NEXT: %[[C1:.*]] = load volatile i1, i1* %ptr
+; CHECK-NEXT: br i1 %[[C1]], label %loop.body1, label %dedicated_exit1
+
+loop.body1:
+ %c2 = load volatile i1, i1* %ptr
+ br i1 %c2, label %loop.body2, label %non_dedicated_exit
+; CHECK: loop.body1:
+; CHECK-NEXT: %[[C2:.*]] = load volatile i1, i1* %ptr
+; CHECK-NEXT: br i1 %[[C2]], label %loop.body2, label %[[LOOPEXIT:.*]]
+
+loop.body2:
+ %c3 = load volatile i1, i1* %ptr
+ br i1 %c3, label %loop.backedge, label %dedicated_exit2
+; CHECK: loop.body2:
+; CHECK-NEXT: %[[C3:.*]] = load volatile i1, i1* %ptr
+; CHECK-NEXT: br i1 %[[C3]], label %loop.backedge, label %dedicated_exit2
+
+loop.backedge:
+ br label %loop.header
+; CHECK: loop.backedge:
+; CHECK-NEXT: br label %loop.header
+
+dedicated_exit1:
+ ret void
+; Check that there isn't a split loop exit.
+; CHECK-NOT: br label %dedicated_exit1
+;
+; CHECK: dedicated_exit1:
+; CHECK-NEXT: ret void
+
+dedicated_exit2:
+ ret void
+; Check that there isn't a split loop exit.
+; CHECK-NOT: br label %dedicated_exit2
+;
+; CHECK: dedicated_exit2:
+; CHECK-NEXT: ret void
+
+non_dedicated_exit:
+ ret void
+; CHECK: [[LOOPEXIT]]:
+; CHECK-NEXT: br label %non_dedicated_exit
+;
+; CHECK: non_dedicated_exit:
+; CHECK-NEXT: ret void
+}
+
+; Check that we form what dedicated exits we can even when some exits are
+; reached via indirectbr which precludes forming dedicated exits.
+define void @test_form_some_dedicated_exits_despite_indirectbr(i8 %a, i8* %ptr, i8** %addr.ptr) {
+; CHECK-LABEL: define void @test_form_some_dedicated_exits_despite_indirectbr(
+entry:
+ switch i8 %a, label %loop.ph [
+ i8 0, label %exit.a
+ i8 1, label %exit.b
+ i8 2, label %exit.c
+ ]
+; CHECK: entry:
+; CHECK-NEXT: switch i8 %a, label %loop.ph [
+; CHECK-NEXT: i8 0, label %exit.a
+; CHECK-NEXT: i8 1, label %exit.b
+; CHECK-NEXT: i8 2, label %exit.c
+; CHECK-NEXT: ]
+
+loop.ph:
+ br label %loop.header
+; CHECK: loop.ph:
+; CHECK-NEXT: br label %loop.header
+
+loop.header:
+ %addr1 = load volatile i8*, i8** %addr.ptr
+ indirectbr i8* %addr1, [label %loop.body1, label %exit.a]
+; CHECK: loop.header:
+; CHECK-NEXT: %[[ADDR1:.*]] = load volatile i8*, i8** %addr.ptr
+; CHECK-NEXT: indirectbr i8* %[[ADDR1]], [label %loop.body1, label %exit.a]
+
+loop.body1:
+ %b = load volatile i8, i8* %ptr
+ switch i8 %b, label %loop.body2 [
+ i8 0, label %exit.a
+ i8 1, label %exit.b
+ i8 2, label %exit.c
+ ]
+; CHECK: loop.body1:
+; CHECK-NEXT: %[[B:.*]] = load volatile i8, i8* %ptr
+; CHECK-NEXT: switch i8 %[[B]], label %loop.body2 [
+; CHECK-NEXT: i8 0, label %exit.a
+; CHECK-NEXT: i8 1, label %[[LOOPEXIT:.*]]
+; CHECK-NEXT: i8 2, label %exit.c
+; CHECK-NEXT: ]
+
+loop.body2:
+ %addr2 = load volatile i8*, i8** %addr.ptr
+ indirectbr i8* %addr2, [label %loop.backedge, label %exit.c]
+; CHECK: loop.body2:
+; CHECK-NEXT: %[[ADDR2:.*]] = load volatile i8*, i8** %addr.ptr
+; CHECK-NEXT: indirectbr i8* %[[ADDR2]], [label %loop.backedge, label %exit.c]
+
+loop.backedge:
+ br label %loop.header
+; CHECK: loop.backedge:
+; CHECK-NEXT: br label %loop.header
+
+exit.a:
+ ret void
+; Check that there isn't a split loop exit.
+; CHECK-NOT: br label %exit.a
+;
+; CHECK: exit.a:
+; CHECK-NEXT: ret void
+
+exit.b:
+ ret void
+; CHECK: [[LOOPEXIT]]:
+; CHECK-NEXT: br label %exit.b
+;
+; CHECK: exit.b:
+; CHECK-NEXT: ret void
+
+exit.c:
+ ret void
+; Check that there isn't a split loop exit.
+; CHECK-NOT: br label %exit.c
+;
+; CHECK: exit.c:
+; CHECK-NEXT: ret void
+}
OpenPOWER on IntegriCloud