1 ; RUN: opt < %s -S -loop-simplify | FileCheck %s
2 ; RUN: opt < %s -S -passes=loop-simplify | FileCheck %s
4 ; This function should get a preheader inserted before bb3, that is jumped
7 ; CHECK-LABEL: define void @test(
9 br i1 true, label %bb1, label %bb2
14 ; CHECK-NEXT: br label %[[PH:.*]]
19 ; CHECK-NEXT: br label %[[PH]]
24 ; CHECK-NEXT: br label %bb3
27 ; CHECK-NEXT: br label %bb3
30 ; Test a case where we have multiple exit blocks as successors of a single loop
31 ; block that need to be made dedicated exit blocks. We also have multiple
32 ; exiting edges to one of the exit blocks that all should be rewritten.
33 define void @test_multiple_exits_from_single_block(i8 %a, i8* %b.ptr) {
34 ; CHECK-LABEL: define void @test_multiple_exits_from_single_block(
36 switch i8 %a, label %loop [
41 ; CHECK-NEXT: switch i8 %a, label %[[PH:.*]] [
42 ; CHECK-NEXT: i8 0, label %exit.a
43 ; CHECK-NEXT: i8 1, label %exit.b
47 %b = load volatile i8, i8* %b.ptr
48 switch i8 %b, label %loop [
58 ; CHECK-NEXT: br label %loop
61 ; CHECK-NEXT: %[[B:.*]] = load volatile i8, i8* %b.ptr
62 ; CHECK-NEXT: switch i8 %[[B]], label %[[BACKEDGE:.*]] [
63 ; CHECK-NEXT: i8 0, label %[[LOOPEXIT_A:.*]]
64 ; CHECK-NEXT: i8 1, label %[[LOOPEXIT_B:.*]]
65 ; CHECK-NEXT: i8 2, label %[[BACKEDGE]]
66 ; CHECK-NEXT: i8 3, label %[[LOOPEXIT_A]]
67 ; CHECK-NEXT: i8 4, label %[[BACKEDGE]]
68 ; CHECK-NEXT: i8 5, label %[[LOOPEXIT_A]]
69 ; CHECK-NEXT: i8 6, label %[[BACKEDGE]]
72 ; CHECK: [[BACKEDGE]]:
73 ; CHECK-NEXT: br label %loop
77 ; CHECK: [[LOOPEXIT_A]]:
78 ; CHECK-NEXT: br label %exit.a
81 ; CHECK-NEXT: ret void
85 ; CHECK: [[LOOPEXIT_B]]:
86 ; CHECK-NEXT: br label %exit.b
89 ; CHECK-NEXT: ret void
92 ; Check that we leave already dedicated exits alone when forming dedicated exit
94 define void @test_pre_existing_dedicated_exits(i1 %a, i1* %ptr) {
95 ; CHECK-LABEL: define void @test_pre_existing_dedicated_exits(
97 br i1 %a, label %loop.ph, label %non_dedicated_exit
99 ; CHECK-NEXT: br i1 %a, label %loop.ph, label %non_dedicated_exit
102 br label %loop.header
104 ; CHECK-NEXT: br label %loop.header
107 %c1 = load volatile i1, i1* %ptr
108 br i1 %c1, label %loop.body1, label %dedicated_exit1
109 ; CHECK: loop.header:
110 ; CHECK-NEXT: %[[C1:.*]] = load volatile i1, i1* %ptr
111 ; CHECK-NEXT: br i1 %[[C1]], label %loop.body1, label %dedicated_exit1
114 %c2 = load volatile i1, i1* %ptr
115 br i1 %c2, label %loop.body2, label %non_dedicated_exit
117 ; CHECK-NEXT: %[[C2:.*]] = load volatile i1, i1* %ptr
118 ; CHECK-NEXT: br i1 %[[C2]], label %loop.body2, label %[[LOOPEXIT:.*]]
121 %c3 = load volatile i1, i1* %ptr
122 br i1 %c3, label %loop.backedge, label %dedicated_exit2
124 ; CHECK-NEXT: %[[C3:.*]] = load volatile i1, i1* %ptr
125 ; CHECK-NEXT: br i1 %[[C3]], label %loop.backedge, label %dedicated_exit2
128 br label %loop.header
129 ; CHECK: loop.backedge:
130 ; CHECK-NEXT: br label %loop.header
134 ; Check that there isn't a split loop exit.
135 ; CHECK-NOT: br label %dedicated_exit1
137 ; CHECK: dedicated_exit1:
138 ; CHECK-NEXT: ret void
142 ; Check that there isn't a split loop exit.
143 ; CHECK-NOT: br label %dedicated_exit2
145 ; CHECK: dedicated_exit2:
146 ; CHECK-NEXT: ret void
150 ; CHECK: [[LOOPEXIT]]:
151 ; CHECK-NEXT: br label %non_dedicated_exit
153 ; CHECK: non_dedicated_exit:
154 ; CHECK-NEXT: ret void
157 ; Check that we form what dedicated exits we can even when some exits are
158 ; reached via indirectbr which precludes forming dedicated exits.
159 define void @test_form_some_dedicated_exits_despite_indirectbr(i8 %a, i8* %ptr, i8** %addr.ptr) {
160 ; CHECK-LABEL: define void @test_form_some_dedicated_exits_despite_indirectbr(
162 switch i8 %a, label %loop.ph [
168 ; CHECK-NEXT: switch i8 %a, label %loop.ph [
169 ; CHECK-NEXT: i8 0, label %exit.a
170 ; CHECK-NEXT: i8 1, label %exit.b
171 ; CHECK-NEXT: i8 2, label %exit.c
175 br label %loop.header
177 ; CHECK-NEXT: br label %loop.header
180 %addr1 = load volatile i8*, i8** %addr.ptr
181 indirectbr i8* %addr1, [label %loop.body1, label %exit.a]
182 ; CHECK: loop.header:
183 ; CHECK-NEXT: %[[ADDR1:.*]] = load volatile i8*, i8** %addr.ptr
184 ; CHECK-NEXT: indirectbr i8* %[[ADDR1]], [label %loop.body1, label %exit.a]
187 %b = load volatile i8, i8* %ptr
188 switch i8 %b, label %loop.body2 [
194 ; CHECK-NEXT: %[[B:.*]] = load volatile i8, i8* %ptr
195 ; CHECK-NEXT: switch i8 %[[B]], label %loop.body2 [
196 ; CHECK-NEXT: i8 0, label %exit.a
197 ; CHECK-NEXT: i8 1, label %[[LOOPEXIT:.*]]
198 ; CHECK-NEXT: i8 2, label %exit.c
202 %addr2 = load volatile i8*, i8** %addr.ptr
203 indirectbr i8* %addr2, [label %loop.backedge, label %exit.c]
205 ; CHECK-NEXT: %[[ADDR2:.*]] = load volatile i8*, i8** %addr.ptr
206 ; CHECK-NEXT: indirectbr i8* %[[ADDR2]], [label %loop.backedge, label %exit.c]
209 br label %loop.header
210 ; CHECK: loop.backedge:
211 ; CHECK-NEXT: br label %loop.header
215 ; Check that there isn't a split loop exit.
216 ; CHECK-NOT: br label %exit.a
219 ; CHECK-NEXT: ret void
223 ; CHECK: [[LOOPEXIT]]:
224 ; CHECK-NEXT: br label %exit.b
227 ; CHECK-NEXT: ret void
231 ; Check that there isn't a split loop exit.
232 ; CHECK-NOT: br label %exit.c
235 ; CHECK-NEXT: ret void