blob: e5fb7b9907bd421bfb7f0fdde2efd5a61636427f [file] [log] [blame]
Chandler Carruth73367b62017-06-25 22:24:02 +00001; RUN: opt < %s -S -loop-simplify | FileCheck %s
2; RUN: opt < %s -S -passes=loop-simplify | FileCheck %s
Chris Lattnerb009cea2002-09-26 19:50:11 +00003
Chandler Carruth73367b62017-06-25 22:24:02 +00004; This function should get a preheader inserted before bb3, that is jumped
5; to by bb1 & bb2
Tanya Lattner8bf97c22008-03-25 04:26:08 +00006define void @test() {
Chandler Carruth73367b62017-06-25 22:24:02 +00007; CHECK-LABEL: define void @test(
8entry:
9 br i1 true, label %bb1, label %bb2
10
11bb1:
12 br label %bb3
13; CHECK: bb1:
14; CHECK-NEXT: br label %[[PH:.*]]
15
16bb2:
17 br label %bb3
18; CHECK: bb2:
19; CHECK-NEXT: br label %[[PH]]
20
21bb3:
22 br label %bb3
23; CHECK: [[PH]]:
24; CHECK-NEXT: br label %bb3
25;
26; CHECK: bb3:
27; CHECK-NEXT: br label %bb3
Tanya Lattner8bf97c22008-03-25 04:26:08 +000028}
29
Chandler Carruth73367b62017-06-25 22:24:02 +000030; 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.
33define void @test_multiple_exits_from_single_block(i8 %a, i8* %b.ptr) {
34; CHECK-LABEL: define void @test_multiple_exits_from_single_block(
35entry:
36 switch i8 %a, label %loop [
37 i8 0, label %exit.a
38 i8 1, label %exit.b
39 ]
40; CHECK: entry:
41; CHECK-NEXT: switch i8 %a, label %[[PH:.*]] [
42; CHECK-NEXT: i8 0, label %exit.a
43; CHECK-NEXT: i8 1, label %exit.b
44; CHECK-NEXT: ]
45
46loop:
47 %b = load volatile i8, i8* %b.ptr
48 switch i8 %b, label %loop [
49 i8 0, label %exit.a
50 i8 1, label %exit.b
51 i8 2, label %loop
52 i8 3, label %exit.a
53 i8 4, label %loop
54 i8 5, label %exit.a
55 i8 6, label %loop
56 ]
57; CHECK: [[PH]]:
58; CHECK-NEXT: br label %loop
59;
60; CHECK: 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]]
70; CHECK-NEXT: ]
71;
72; CHECK: [[BACKEDGE]]:
73; CHECK-NEXT: br label %loop
74
75exit.a:
76 ret void
77; CHECK: [[LOOPEXIT_A]]:
78; CHECK-NEXT: br label %exit.a
79;
80; CHECK: exit.a:
81; CHECK-NEXT: ret void
82
83exit.b:
84 ret void
85; CHECK: [[LOOPEXIT_B]]:
86; CHECK-NEXT: br label %exit.b
87;
88; CHECK: exit.b:
89; CHECK-NEXT: ret void
90}
91
92; Check that we leave already dedicated exits alone when forming dedicated exit
93; blocks.
94define void @test_pre_existing_dedicated_exits(i1 %a, i1* %ptr) {
95; CHECK-LABEL: define void @test_pre_existing_dedicated_exits(
96entry:
97 br i1 %a, label %loop.ph, label %non_dedicated_exit
98; CHECK: entry:
99; CHECK-NEXT: br i1 %a, label %loop.ph, label %non_dedicated_exit
100
101loop.ph:
102 br label %loop.header
103; CHECK: loop.ph:
104; CHECK-NEXT: br label %loop.header
105
106loop.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
112
113loop.body1:
114 %c2 = load volatile i1, i1* %ptr
115 br i1 %c2, label %loop.body2, label %non_dedicated_exit
116; CHECK: loop.body1:
117; CHECK-NEXT: %[[C2:.*]] = load volatile i1, i1* %ptr
118; CHECK-NEXT: br i1 %[[C2]], label %loop.body2, label %[[LOOPEXIT:.*]]
119
120loop.body2:
121 %c3 = load volatile i1, i1* %ptr
122 br i1 %c3, label %loop.backedge, label %dedicated_exit2
123; CHECK: loop.body2:
124; CHECK-NEXT: %[[C3:.*]] = load volatile i1, i1* %ptr
125; CHECK-NEXT: br i1 %[[C3]], label %loop.backedge, label %dedicated_exit2
126
127loop.backedge:
128 br label %loop.header
129; CHECK: loop.backedge:
130; CHECK-NEXT: br label %loop.header
131
132dedicated_exit1:
133 ret void
134; Check that there isn't a split loop exit.
135; CHECK-NOT: br label %dedicated_exit1
136;
137; CHECK: dedicated_exit1:
138; CHECK-NEXT: ret void
139
140dedicated_exit2:
141 ret void
142; Check that there isn't a split loop exit.
143; CHECK-NOT: br label %dedicated_exit2
144;
145; CHECK: dedicated_exit2:
146; CHECK-NEXT: ret void
147
148non_dedicated_exit:
149 ret void
150; CHECK: [[LOOPEXIT]]:
151; CHECK-NEXT: br label %non_dedicated_exit
152;
153; CHECK: non_dedicated_exit:
154; CHECK-NEXT: ret void
155}
Chandler Carruth4a000882017-06-25 22:45:31 +0000156
157; Check that we form what dedicated exits we can even when some exits are
158; reached via indirectbr which precludes forming dedicated exits.
159define 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(
161entry:
162 switch i8 %a, label %loop.ph [
163 i8 0, label %exit.a
164 i8 1, label %exit.b
165 i8 2, label %exit.c
166 ]
167; CHECK: entry:
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
172; CHECK-NEXT: ]
173
174loop.ph:
175 br label %loop.header
176; CHECK: loop.ph:
177; CHECK-NEXT: br label %loop.header
178
179loop.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]
185
186loop.body1:
187 %b = load volatile i8, i8* %ptr
188 switch i8 %b, label %loop.body2 [
189 i8 0, label %exit.a
190 i8 1, label %exit.b
191 i8 2, label %exit.c
192 ]
193; CHECK: loop.body1:
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
199; CHECK-NEXT: ]
200
201loop.body2:
202 %addr2 = load volatile i8*, i8** %addr.ptr
203 indirectbr i8* %addr2, [label %loop.backedge, label %exit.c]
204; CHECK: loop.body2:
205; CHECK-NEXT: %[[ADDR2:.*]] = load volatile i8*, i8** %addr.ptr
206; CHECK-NEXT: indirectbr i8* %[[ADDR2]], [label %loop.backedge, label %exit.c]
207
208loop.backedge:
209 br label %loop.header
210; CHECK: loop.backedge:
211; CHECK-NEXT: br label %loop.header
212
213exit.a:
214 ret void
215; Check that there isn't a split loop exit.
216; CHECK-NOT: br label %exit.a
217;
218; CHECK: exit.a:
219; CHECK-NEXT: ret void
220
221exit.b:
222 ret void
223; CHECK: [[LOOPEXIT]]:
224; CHECK-NEXT: br label %exit.b
225;
226; CHECK: exit.b:
227; CHECK-NEXT: ret void
228
229exit.c:
230 ret void
231; Check that there isn't a split loop exit.
232; CHECK-NOT: br label %exit.c
233;
234; CHECK: exit.c:
235; CHECK-NEXT: ret void
236}