summaryrefslogtreecommitdiffstats
path: root/llvm/test/Transforms/SimpleLoopUnswitch
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2018-06-25 23:32:54 +0000
committerChandler Carruth <chandlerc@gmail.com>2018-06-25 23:32:54 +0000
commit1652996fd619afd41a3b01441298f51b5f0128a1 (patch)
treec9a905d1e85e023cbcd2ec77551a21202dcfc658 /llvm/test/Transforms/SimpleLoopUnswitch
parent32447ff5b9592064d94a2fad5ffd71c5fcb35181 (diff)
downloadbcm5719-llvm-1652996fd619afd41a3b01441298f51b5f0128a1.tar.gz
bcm5719-llvm-1652996fd619afd41a3b01441298f51b5f0128a1.zip
[PM/LoopUnswitch] Teach the new unswitch to handle nontrivial
unswitching of switches. This works much like trivial unswitching of switches in that it reliably moves the switch out of the loop. Here we potentially clone the entire loop into each successor of the switch and re-point the cases at these clones. Due to the complexity of actually doing nontrivial unswitching, this patch doesn't create a dedicated routine for handling switches -- it would duplicate far too much code. Instead, it generalizes the existing routine to handle both branches and switches as it largely reduces to looping in a few places instead of doing something once. This actually improves the results in some cases with branches due to being much more careful about how dead regions of code are managed. With branches, because exactly one clone is created and there are exactly two edges considered, somewhat sloppy handling of the dead regions of code was sufficient in most cases. But with switches, there are much more complicated patterns of dead code and so I've had to move to a more robust model generally. We still do as much pruning of the dead code early as possible because that allows us to avoid even cloning the code. This also surfaced another problem with nontrivial unswitching before which is that we weren't as precise in reconstructing loops as we could have been. This seems to have been mostly harmless, but resulted in pointless LCSSA PHI nodes and other unnecessary cruft. With switches, we have to get this *right*, and everything benefits from it. While the testing may seem a bit light here because we only have two real cases with actual switches, they do a surprisingly good job of exercising numerous edge cases. Also, because we share the logic with branches, most of the changes in this patch are reasonably well covered by existing tests. The new unswitch now has all of the same fundamental power as the old one with the exception of the single unsound case of *partial* switch unswitching -- that really is just loop specialization and not unswitching at all. It doesn't fit into the canonicalization model in any way. We can add a loop specialization pass that runs late based on profile data if important test cases ever come up here. Differential Revision: https://reviews.llvm.org/D47683 llvm-svn: 335553
Diffstat (limited to 'llvm/test/Transforms/SimpleLoopUnswitch')
-rw-r--r--llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch.ll248
1 files changed, 193 insertions, 55 deletions
diff --git a/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch.ll b/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch.ll
index f17676028ac..a463cb68a07 100644
--- a/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch.ll
+++ b/llvm/test/Transforms/SimpleLoopUnswitch/nontrivial-unswitch.ll
@@ -387,7 +387,7 @@ loop_begin:
loop_b:
%b = load i32, i32* %b.ptr
br i1 %v, label %loop_begin, label %loop_exit
-; The 'loop_b' unswitched loop.
+; The original loop, now non-looping due to unswitching..
;
; CHECK: entry.split:
; CHECK-NEXT: br label %loop_begin
@@ -398,14 +398,13 @@ loop_b:
; CHECK-NEXT: br label %loop_exit.split
;
; CHECK: loop_exit.split:
-; CHECK-NEXT: %[[A_LCSSA:.*]] = phi i32 [ %[[A]], %loop_begin ]
; CHECK-NEXT: br label %loop_exit
loop_exit:
%ab.phi = phi i32 [ %b, %loop_b ], [ %a, %loop_begin ]
ret i32 %ab.phi
; CHECK: loop_exit:
-; CHECK-NEXT: %[[AB_PHI:.*]] = phi i32 [ %[[A_LCSSA]], %loop_exit.split ], [ %[[B_LCSSA]], %loop_exit.split.us ]
+; CHECK-NEXT: %[[AB_PHI:.*]] = phi i32 [ %[[A]], %loop_exit.split ], [ %[[B_LCSSA]], %loop_exit.split.us ]
; CHECK-NEXT: ret i32 %[[AB_PHI]]
}
@@ -458,8 +457,7 @@ loop_exit1:
call void @sink1(i32 %a.phi)
ret void
; CHECK: loop_exit1:
-; CHECK-NEXT: %[[A_PHI:.*]] = phi i32 [ %[[A_LCSSA]], %loop_exit1.split.us ]
-; CHECK-NEXT: call void @sink1(i32 %[[A_PHI]])
+; CHECK-NEXT: call void @sink1(i32 %[[A_LCSSA]])
; CHECK-NEXT: ret void
loop_exit2:
@@ -467,8 +465,8 @@ loop_exit2:
call void @sink2(i32 %b.phi)
ret void
; CHECK: loop_exit2:
-; CHECK-NEXT: %[[B_PHI:.*]] = phi i32 [ %[[B]], %loop_b ]
-; CHECK-NEXT: call void @sink2(i32 %[[B_PHI]])
+; CHECK-NEXT: %[[B_LCSSA:.*]] = phi i32 [ %[[B]], %loop_b ]
+; CHECK-NEXT: call void @sink2(i32 %[[B_LCSSA]])
; CHECK-NEXT: ret void
}
@@ -531,8 +529,7 @@ loop_exit2:
call void @sink2(i32 %b.phi)
ret void
; CHECK: loop_exit2:
-; CHECK-NEXT: %[[B_PHI:.*]] = phi i32 [ %[[B_LCSSA]], %loop_exit2.split.us ]
-; CHECK-NEXT: call void @sink2(i32 %[[B_PHI]])
+; CHECK-NEXT: call void @sink2(i32 %[[B_LCSSA]])
; CHECK-NEXT: ret void
}
@@ -587,8 +584,7 @@ loop_exit1:
call void @sink1(i32 %a.phi)
br label %exit
; CHECK: loop_exit1:
-; CHECK-NEXT: %[[A_PHI:.*]] = phi i32 [ %[[A_LCSSA]], %loop_exit1.split.us ]
-; CHECK-NEXT: call void @sink1(i32 %[[A_PHI]])
+; CHECK-NEXT: call void @sink1(i32 %[[A_LCSSA]])
; CHECK-NEXT: br label %exit
loop_exit2:
@@ -596,8 +592,8 @@ loop_exit2:
call void @sink2(i32 %b.phi)
br label %exit
; CHECK: loop_exit2:
-; CHECK-NEXT: %[[B_PHI:.*]] = phi i32 [ %[[B]], %loop_b ]
-; CHECK-NEXT: call void @sink2(i32 %[[B_PHI]])
+; CHECK-NEXT: %[[B_LCSSA:.*]] = phi i32 [ %[[B]], %loop_b ]
+; CHECK-NEXT: call void @sink2(i32 %[[B_LCSSA]])
; CHECK-NEXT: br label %exit
exit:
@@ -663,7 +659,7 @@ loop_latch:
%v2 = load i1, i1* %ptr
br i1 %v2, label %loop_begin, label %loop_exit
; CHECK: loop_latch:
-; CHECK-NEXT: %[[B_LCSSA:.*]] = phi i32 [ %[[B]], %inner_loop_b ]
+; CHECK-NEXT: %[[B_INNER_LCSSA:.*]] = phi i32 [ %[[B]], %inner_loop_b ]
; CHECK-NEXT: %[[V2:.*]] = load i1, i1* %ptr
; CHECK-NEXT: br i1 %[[V2]], label %loop_begin, label %loop_exit.loopexit1
@@ -671,15 +667,14 @@ loop_exit:
%ab.phi = phi i32 [ %a, %inner_loop_begin ], [ %b.phi, %loop_latch ]
ret i32 %ab.phi
; CHECK: loop_exit.loopexit:
-; CHECK-NEXT: %[[A_PHI:.*]] = phi i32 [ %[[A_LCSSA]], %loop_exit.loopexit.split.us ]
; CHECK-NEXT: br label %loop_exit
;
; CHECK: loop_exit.loopexit1:
-; CHECK-NEXT: %[[B_PHI:.*]] = phi i32 [ %[[B_LCSSA]], %loop_latch ]
+; CHECK-NEXT: %[[B_LCSSA:.*]] = phi i32 [ %[[B_INNER_LCSSA]], %loop_latch ]
; CHECK-NEXT: br label %loop_exit
;
; CHECK: loop_exit:
-; CHECK-NEXT: %[[AB_PHI:.*]] = phi i32 [ %[[A_PHI]], %loop_exit.loopexit ], [ %[[B_PHI]], %loop_exit.loopexit1 ]
+; CHECK-NEXT: %[[AB_PHI:.*]] = phi i32 [ %[[A_LCSSA]], %loop_exit.loopexit ], [ %[[B_LCSSA]], %loop_exit.loopexit1 ]
; CHECK-NEXT: ret i32 %[[AB_PHI]]
}
@@ -773,11 +768,10 @@ latch:
; CHECK-NEXT: br label %latch
;
; CHECK: latch:
-; CHECK-NEXT: %[[B_PHI:.*]] = phi i32 [ %[[B_INNER_LCSSA]], %loop_b_inner_exit ]
; CHECK-NEXT: br i1 %[[V]], label %loop_begin, label %loop_exit.split
;
; CHECK: loop_exit.split:
-; CHECK-NEXT: %[[B_LCSSA:.*]] = phi i32 [ %[[B_PHI]], %latch ]
+; CHECK-NEXT: %[[B_LCSSA:.*]] = phi i32 [ %[[B_INNER_LCSSA]], %latch ]
; CHECK-NEXT: br label %loop_exit
loop_exit:
@@ -1466,7 +1460,6 @@ inner_loop_exit:
%v = load i1, i1* %ptr
br i1 %v, label %loop_begin, label %loop_exit
; CHECK: inner_loop_exit:
-; CHECK-NEXT: %[[A_INNER_LCSSA:.*]] = phi i32 [ %[[A_INNER_LCSSA_US]], %inner_loop_exit.split.us ]
; CHECK-NEXT: %[[V:.*]] = load i1, i1* %ptr
; CHECK-NEXT: br i1 %[[V]], label %loop_begin, label %loop_exit
@@ -1474,7 +1467,7 @@ loop_exit:
%a.lcssa = phi i32 [ %a.inner_lcssa, %inner_loop_exit ]
ret i32 %a.lcssa
; CHECK: loop_exit:
-; CHECK-NEXT: %[[A_LCSSA:.*]] = phi i32 [ %[[A_INNER_LCSSA]], %inner_loop_exit ]
+; CHECK-NEXT: %[[A_LCSSA:.*]] = phi i32 [ %[[A_INNER_LCSSA_US]], %inner_loop_exit ]
; CHECK-NEXT: ret i32 %[[A_LCSSA]]
}
@@ -1555,7 +1548,7 @@ loop_exit:
ret i32 %a.lcssa
; CHECK: loop_exit:
; CHECK-NEXT: %[[A_PHI:.*]] = phi i32 [ %[[A_LCSSA]], %loop_exit.split ], [ %[[A_PHI_US]], %loop_exit.split.us ]
-; CHECK-NEXT: ret i32 %[[AB_PHI]]
+; CHECK-NEXT: ret i32 %[[A_PHI]]
}
; Test that requires re-forming dedicated exits for the original loop.
@@ -1635,7 +1628,7 @@ loop_exit:
ret i32 %a.lcssa
; CHECK: loop_exit:
; CHECK-NEXT: %[[A_PHI:.*]] = phi i32 [ %[[A_PHI_SPLIT]], %loop_exit.split ], [ %[[A_LCSSA_US]], %loop_exit.split.us ]
-; CHECK-NEXT: ret i32 %[[AB_PHI]]
+; CHECK-NEXT: ret i32 %[[A_PHI]]
}
; Check that if a cloned inner loop after unswitching doesn't loop and directly
@@ -1721,7 +1714,6 @@ loop_exit:
%a.lcssa = phi i32 [ %a, %inner_loop_begin ], [ %a.inner_lcssa, %inner_loop_exit ]
ret i32 %a.lcssa
; CHECK: loop_exit.loopexit:
-; CHECK-NEXT: %[[A_LCSSA_US:.*]] = phi i32 [ %[[A_INNER_LCSSA_US]], %loop_exit.loopexit.split.us ]
; CHECK-NEXT: br label %loop_exit
;
; CHECK: loop_exit.loopexit1:
@@ -1729,7 +1721,7 @@ loop_exit:
; CHECK-NEXT: br label %loop_exit
;
; CHECK: loop_exit:
-; CHECK-NEXT: %[[A_PHI:.*]] = phi i32 [ %[[A_LCSSA_US]], %loop_exit.loopexit ], [ %[[A_LCSSA]], %loop_exit.loopexit1 ]
+; CHECK-NEXT: %[[A_PHI:.*]] = phi i32 [ %[[A_INNER_LCSSA_US]], %loop_exit.loopexit ], [ %[[A_LCSSA]], %loop_exit.loopexit1 ]
; CHECK-NEXT: ret i32 %[[A_PHI]]
}
@@ -1802,7 +1794,6 @@ inner_loop_exit:
%v3 = load i1, i1* %ptr
br i1 %v3, label %loop_latch, label %loop_exit
; CHECK: inner_loop_exit:
-; CHECK-NEXT: %[[A_INNER_PHI:.*]] = phi i32 [ %[[A_INNER_LCSSA_US]], %inner_loop_exit.split.us ]
; CHECK-NEXT: %[[V:.*]] = load i1, i1* %ptr
; CHECK-NEXT: br i1 %[[V]], label %loop_latch, label %loop_exit.loopexit1
@@ -1819,7 +1810,7 @@ loop_exit:
; CHECK-NEXT: br label %loop_exit
;
; CHECK: loop_exit.loopexit1:
-; CHECK-NEXT: %[[A_LCSSA_US:.*]] = phi i32 [ %[[A_INNER_PHI]], %inner_loop_exit ]
+; CHECK-NEXT: %[[A_LCSSA_US:.*]] = phi i32 [ %[[A_INNER_LCSSA_US]], %inner_loop_exit ]
; CHECK-NEXT: br label %loop_exit
;
; CHECK: loop_exit:
@@ -1916,7 +1907,6 @@ inner_loop_exit:
%v4 = load i1, i1* %ptr
br i1 %v4, label %loop_begin, label %loop_exit
; CHECK: inner_loop_exit.loopexit:
-; CHECK-NEXT: %[[A_INNER_LCSSA_US:.*]] = phi i32 [ %[[A_INNER_INNER_LCSSA_US]], %inner_loop_exit.loopexit.split.us ]
; CHECK-NEXT: br label %inner_loop_exit
;
; CHECK: inner_loop_exit.loopexit1:
@@ -1924,7 +1914,7 @@ inner_loop_exit:
; CHECK-NEXT: br label %inner_loop_exit
;
; CHECK: inner_loop_exit:
-; CHECK-NEXT: %[[A_INNER_PHI:.*]] = phi i32 [ %[[A_INNER_LCSSA_US]], %inner_loop_exit.loopexit ], [ %[[A_INNER_LCSSA]], %inner_loop_exit.loopexit1 ]
+; CHECK-NEXT: %[[A_INNER_PHI:.*]] = phi i32 [ %[[A_INNER_INNER_LCSSA_US]], %inner_loop_exit.loopexit ], [ %[[A_INNER_LCSSA]], %inner_loop_exit.loopexit1 ]
; CHECK-NEXT: %[[V:.*]] = load i1, i1* %ptr
; CHECK-NEXT: br i1 %[[V]], label %loop_begin, label %loop_exit
@@ -2010,7 +2000,6 @@ inner_inner_loop_exit:
%v3 = load i1, i1* %ptr
br i1 %v3, label %inner_loop_latch, label %inner_loop_exit
; CHECK: inner_inner_loop_exit:
-; CHECK-NEXT: %[[A_INNER_INNER_PHI:.*]] = phi i32 [ %[[A_INNER_INNER_LCSSA_US]], %inner_inner_loop_exit.split.us ]
; CHECK-NEXT: %[[V:.*]] = load i1, i1* %ptr
; CHECK-NEXT: br i1 %[[V]], label %inner_loop_latch, label %inner_loop_exit.loopexit1
@@ -2028,7 +2017,7 @@ inner_loop_exit:
; CHECK-NEXT: br label %inner_loop_exit
;
; CHECK: inner_loop_exit.loopexit1:
-; CHECK-NEXT: %[[A_INNER_LCSSA_US:.*]] = phi i32 [ %[[A_INNER_INNER_PHI]], %inner_inner_loop_exit ]
+; CHECK-NEXT: %[[A_INNER_LCSSA_US:.*]] = phi i32 [ %[[A_INNER_INNER_LCSSA_US]], %inner_inner_loop_exit ]
; CHECK-NEXT: br label %inner_loop_exit
;
; CHECK: inner_loop_exit:
@@ -2296,56 +2285,96 @@ define i32 @test20(i32* %var, i32 %cond1, i32 %cond2) {
entry:
br label %loop_begin
; CHECK-NEXT: entry:
-; CHECK-NEXT: br label %loop_begin
+; CHECK-NEXT: switch i32 %cond2, label %[[ENTRY_SPLIT_EXIT:.*]] [
+; CHECK-NEXT: i32 0, label %[[ENTRY_SPLIT_A:.*]]
+; CHECK-NEXT: i32 1, label %[[ENTRY_SPLIT_A]]
+; CHECK-NEXT: i32 13, label %[[ENTRY_SPLIT_B:.*]]
+; CHECK-NEXT: i32 2, label %[[ENTRY_SPLIT_A]]
+; CHECK-NEXT: i32 42, label %[[ENTRY_SPLIT_C:.*]]
+; CHECK-NEXT: ]
loop_begin:
%var_val = load i32, i32* %var
- switch i32 %cond2, label %loop_a [
- i32 0, label %loop_b
- i32 1, label %loop_b
- i32 13, label %loop_c
- i32 2, label %loop_b
- i32 42, label %loop_exit
+ switch i32 %cond2, label %loop_exit [
+ i32 0, label %loop_a
+ i32 1, label %loop_a
+ i32 13, label %loop_b
+ i32 2, label %loop_a
+ i32 42, label %loop_c
]
-; CHECK: loop_begin:
-; CHECK-NEXT: %[[V:.*]] = load i32, i32* %var
-; CHECK-NEXT: switch i32 %cond2, label %loop_a [
-; CHECK-NEXT: i32 0, label %loop_b
-; CHECK-NEXT: i32 1, label %loop_b
-; CHECK-NEXT: i32 13, label %loop_c
-; CHECK-NEXT: i32 2, label %loop_b
-; CHECK-NEXT: i32 42, label %loop_exit
-; CHECK-NEXT: ]
loop_a:
call void @a()
br label %loop_latch
-; CHECK: loop_a:
+; Unswitched 'a' loop.
+;
+; CHECK: [[ENTRY_SPLIT_A]]:
+; CHECK-NEXT: br label %[[LOOP_BEGIN_A:.*]]
+;
+; CHECK: [[LOOP_BEGIN_A]]:
+; CHECK-NEXT: %{{.*}} = load i32, i32* %var
+; CHECK-NEXT: br label %[[LOOP_A:.*]]
+;
+; CHECK: [[LOOP_A]]:
; CHECK-NEXT: call void @a()
-; CHECK-NEXT: br label %loop_latch
+; CHECK-NEXT: br label %[[LOOP_LATCH_A:.*]]
+;
+; CHECK: [[LOOP_LATCH_A]]:
+; CHECK: br label %[[LOOP_BEGIN_A]]
loop_b:
call void @b()
br label %loop_latch
-; CHECK: loop_b:
+; Unswitched 'b' loop.
+;
+; CHECK: [[ENTRY_SPLIT_B]]:
+; CHECK-NEXT: br label %[[LOOP_BEGIN_B:.*]]
+;
+; CHECK: [[LOOP_BEGIN_B]]:
+; CHECK-NEXT: %{{.*}} = load i32, i32* %var
+; CHECK-NEXT: br label %[[LOOP_B:.*]]
+;
+; CHECK: [[LOOP_B]]:
; CHECK-NEXT: call void @b()
-; CHECK-NEXT: br label %loop_latch
+; CHECK-NEXT: br label %[[LOOP_LATCH_B:.*]]
+;
+; CHECK: [[LOOP_LATCH_B]]:
+; CHECK: br label %[[LOOP_BEGIN_B]]
loop_c:
call void @c() noreturn nounwind
br label %loop_latch
-; CHECK: loop_c:
+; Unswitched 'c' loop.
+;
+; CHECK: [[ENTRY_SPLIT_C]]:
+; CHECK-NEXT: br label %[[LOOP_BEGIN_C:.*]]
+;
+; CHECK: [[LOOP_BEGIN_C]]:
+; CHECK-NEXT: %{{.*}} = load i32, i32* %var
+; CHECK-NEXT: br label %[[LOOP_C:.*]]
+;
+; CHECK: [[LOOP_C]]:
; CHECK-NEXT: call void @c()
-; CHECK-NEXT: br label %loop_latch
+; CHECK-NEXT: br label %[[LOOP_LATCH_C:.*]]
+;
+; CHECK: [[LOOP_LATCH_C]]:
+; CHECK: br label %[[LOOP_BEGIN_C]]
loop_latch:
br label %loop_begin
-; CHECK: loop_latch:
-; CHECK-NEXT: br label %loop_begin
loop_exit:
%lcssa = phi i32 [ %var_val, %loop_begin ]
ret i32 %lcssa
+; Unswitched exit edge (no longer a loop).
+;
+; CHECK: [[ENTRY_SPLIT_EXIT]]:
+; CHECK-NEXT: br label %loop_begin
+;
+; CHECK: loop_begin:
+; CHECK-NEXT: %[[V:.*]] = load i32, i32* %var
+; CHECK-NEXT: br label %loop_exit
+;
; CHECK: loop_exit:
; CHECK-NEXT: %[[LCSSA:.*]] = phi i32 [ %[[V]], %loop_begin ]
; CHECK-NEXT: ret i32 %[[LCSSA]]
@@ -2824,3 +2853,112 @@ loop_exit:
; CHECK: loop_exit:
; CHECK-NEXT: ret
}
+
+; Non-trivial unswitching of a switch.
+define i32 @test27(i1* %ptr, i32 %cond) {
+; CHECK-LABEL: @test27(
+entry:
+ br label %loop_begin
+; CHECK-NEXT: entry:
+; CHECK-NEXT: switch i32 %cond, label %[[ENTRY_SPLIT_LATCH:.*]] [
+; CHECK-NEXT: i32 0, label %[[ENTRY_SPLIT_A:.*]]
+; CHECK-NEXT: i32 1, label %[[ENTRY_SPLIT_B:.*]]
+; CHECK-NEXT: i32 2, label %[[ENTRY_SPLIT_C:.*]]
+; CHECK-NEXT: ]
+
+loop_begin:
+ switch i32 %cond, label %latch [
+ i32 0, label %loop_a
+ i32 1, label %loop_b
+ i32 2, label %loop_c
+ ]
+
+loop_a:
+ call void @a()
+ br label %latch
+; Unswitched 'a' loop.
+;
+; CHECK: [[ENTRY_SPLIT_A]]:
+; CHECK-NEXT: br label %[[LOOP_BEGIN_A:.*]]
+;
+; CHECK: [[LOOP_BEGIN_A]]:
+; CHECK-NEXT: br label %[[LOOP_A:.*]]
+;
+; CHECK: [[LOOP_A]]:
+; CHECK-NEXT: call void @a()
+; CHECK-NEXT: br label %[[LOOP_LATCH_A:.*]]
+;
+; CHECK: [[LOOP_LATCH_A]]:
+; CHECK-NEXT: %[[V_A:.*]] = load i1, i1* %ptr
+; CHECK: br i1 %[[V_A]], label %[[LOOP_BEGIN_A]], label %[[LOOP_EXIT_A:.*]]
+;
+; CHECK: [[LOOP_EXIT_A]]:
+; CHECK-NEXT: br label %loop_exit
+
+loop_b:
+ call void @b()
+ br label %latch
+; Unswitched 'b' loop.
+;
+; CHECK: [[ENTRY_SPLIT_B]]:
+; CHECK-NEXT: br label %[[LOOP_BEGIN_B:.*]]
+;
+; CHECK: [[LOOP_BEGIN_B]]:
+; CHECK-NEXT: br label %[[LOOP_B:.*]]
+;
+; CHECK: [[LOOP_B]]:
+; CHECK-NEXT: call void @b()
+; CHECK-NEXT: br label %[[LOOP_LATCH_B:.*]]
+;
+; CHECK: [[LOOP_LATCH_B]]:
+; CHECK-NEXT: %[[V_B:.*]] = load i1, i1* %ptr
+; CHECK: br i1 %[[V_B]], label %[[LOOP_BEGIN_B]], label %[[LOOP_EXIT_B:.*]]
+;
+; CHECK: [[LOOP_EXIT_B]]:
+; CHECK-NEXT: br label %loop_exit
+
+loop_c:
+ call void @c()
+ br label %latch
+; Unswitched 'c' loop.
+;
+; CHECK: [[ENTRY_SPLIT_C]]:
+; CHECK-NEXT: br label %[[LOOP_BEGIN_C:.*]]
+;
+; CHECK: [[LOOP_BEGIN_C]]:
+; CHECK-NEXT: br label %[[LOOP_C:.*]]
+;
+; CHECK: [[LOOP_C]]:
+; CHECK-NEXT: call void @c()
+; CHECK-NEXT: br label %[[LOOP_LATCH_C:.*]]
+;
+; CHECK: [[LOOP_LATCH_C]]:
+; CHECK-NEXT: %[[V_C:.*]] = load i1, i1* %ptr
+; CHECK: br i1 %[[V_C]], label %[[LOOP_BEGIN_C]], label %[[LOOP_EXIT_C:.*]]
+;
+; CHECK: [[LOOP_EXIT_C]]:
+; CHECK-NEXT: br label %loop_exit
+
+latch:
+ %v = load i1, i1* %ptr
+ br i1 %v, label %loop_begin, label %loop_exit
+; Unswitched the 'latch' only loop.
+;
+; CHECK: [[ENTRY_SPLIT_LATCH]]:
+; CHECK-NEXT: br label %[[LOOP_BEGIN_LATCH:.*]]
+;
+; CHECK: [[LOOP_BEGIN_LATCH]]:
+; CHECK-NEXT: br label %[[LOOP_LATCH_LATCH:.*]]
+;
+; CHECK: [[LOOP_LATCH_LATCH]]:
+; CHECK-NEXT: %[[V_LATCH:.*]] = load i1, i1* %ptr
+; CHECK: br i1 %[[V_LATCH]], label %[[LOOP_BEGIN_LATCH]], label %[[LOOP_EXIT_LATCH:.*]]
+;
+; CHECK: [[LOOP_EXIT_LATCH]]:
+; CHECK-NEXT: br label %loop_exit
+
+loop_exit:
+ ret i32 0
+; CHECK: loop_exit:
+; CHECK-NEXT: ret i32 0
+} \ No newline at end of file
OpenPOWER on IntegriCloud