1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -S -loop-simplify | FileCheck %s
3; RUN: opt < %s -S -passes=loop-simplify | FileCheck %s
4
5; This function should get a preheader inserted before bb3, that is jumped
6; to by bb1 & bb2
7define void @test() {
8; CHECK-LABEL: @test(
9; CHECK-NEXT:  entry:
10; CHECK-NEXT:    br i1 true, label [[BB1:%.*]], label [[BB2:%.*]]
11; CHECK:       bb1:
12; CHECK-NEXT:    br label [[BB3_PREHEADER:%.*]]
13; CHECK:       bb2:
14; CHECK-NEXT:    br label [[BB3_PREHEADER]]
15; CHECK:       bb3.preheader:
16; CHECK-NEXT:    br label [[BB3:%.*]]
17; CHECK:       bb3:
18; CHECK-NEXT:    br label [[BB3]]
19;
20entry:
21  br i1 true, label %bb1, label %bb2
22
23bb1:
24  br label %bb3
25
26bb2:
27  br label %bb3
28
29bb3:
30  br label %bb3
31}
32
33; Test a case where we have multiple exit blocks as successors of a single loop
34; block that need to be made dedicated exit blocks. We also have multiple
35; exiting edges to one of the exit blocks that all should be rewritten.
36define void @test_multiple_exits_from_single_block(i8 %a, i8* %b.ptr) {
37; CHECK-LABEL: @test_multiple_exits_from_single_block(
38; CHECK-NEXT:  entry:
39; CHECK-NEXT:    switch i8 [[A:%.*]], label [[LOOP_PREHEADER:%.*]] [
40; CHECK-NEXT:    i8 0, label [[EXIT_A:%.*]]
41; CHECK-NEXT:    i8 1, label [[EXIT_B:%.*]]
42; CHECK-NEXT:    ]
43; CHECK:       loop.preheader:
44; CHECK-NEXT:    br label [[LOOP:%.*]]
45; CHECK:       loop:
46; CHECK-NEXT:    [[B:%.*]] = load volatile i8, i8* [[B_PTR:%.*]]
47; CHECK-NEXT:    switch i8 [[B]], label [[LOOP_BACKEDGE:%.*]] [
48; CHECK-NEXT:    i8 0, label [[EXIT_A_LOOPEXIT:%.*]]
49; CHECK-NEXT:    i8 1, label [[EXIT_B_LOOPEXIT:%.*]]
50; CHECK-NEXT:    i8 2, label [[LOOP_BACKEDGE]]
51; CHECK-NEXT:    i8 3, label [[EXIT_A_LOOPEXIT]]
52; CHECK-NEXT:    i8 4, label [[LOOP_BACKEDGE]]
53; CHECK-NEXT:    i8 5, label [[EXIT_A_LOOPEXIT]]
54; CHECK-NEXT:    i8 6, label [[LOOP_BACKEDGE]]
55; CHECK-NEXT:    ]
56; CHECK:       loop.backedge:
57; CHECK-NEXT:    br label [[LOOP]]
58; CHECK:       exit.a.loopexit:
59; CHECK-NEXT:    br label [[EXIT_A]]
60; CHECK:       exit.a:
61; CHECK-NEXT:    ret void
62; CHECK:       exit.b.loopexit:
63; CHECK-NEXT:    br label [[EXIT_B]]
64; CHECK:       exit.b:
65; CHECK-NEXT:    ret void
66;
67entry:
68  switch i8 %a, label %loop [
69  i8 0, label %exit.a
70  i8 1, label %exit.b
71  ]
72
73loop:
74  %b = load volatile i8, i8* %b.ptr
75  switch i8 %b, label %loop [
76  i8 0, label %exit.a
77  i8 1, label %exit.b
78  i8 2, label %loop
79  i8 3, label %exit.a
80  i8 4, label %loop
81  i8 5, label %exit.a
82  i8 6, label %loop
83  ]
84
85exit.a:
86  ret void
87
88exit.b:
89  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: @test_pre_existing_dedicated_exits(
96; CHECK-NEXT:  entry:
97; CHECK-NEXT:    br i1 [[A:%.*]], label [[LOOP_PH:%.*]], label [[NON_DEDICATED_EXIT:%.*]]
98; CHECK:       loop.ph:
99; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
100; CHECK:       loop.header:
101; CHECK-NEXT:    [[C1:%.*]] = load volatile i1, i1* [[PTR:%.*]]
102; CHECK-NEXT:    br i1 [[C1]], label [[LOOP_BODY1:%.*]], label [[DEDICATED_EXIT1:%.*]]
103; CHECK:       loop.body1:
104; CHECK-NEXT:    [[C2:%.*]] = load volatile i1, i1* [[PTR]]
105; CHECK-NEXT:    br i1 [[C2]], label [[LOOP_BODY2:%.*]], label [[NON_DEDICATED_EXIT_LOOPEXIT:%.*]]
106; CHECK:       loop.body2:
107; CHECK-NEXT:    [[C3:%.*]] = load volatile i1, i1* [[PTR]]
108; CHECK-NEXT:    br i1 [[C3]], label [[LOOP_BACKEDGE:%.*]], label [[DEDICATED_EXIT2:%.*]]
109; CHECK:       loop.backedge:
110; CHECK-NEXT:    br label [[LOOP_HEADER]]
111; CHECK:       dedicated_exit1:
112; CHECK-NEXT:    ret void
113; CHECK:       dedicated_exit2:
114; CHECK-NEXT:    ret void
115; CHECK:       non_dedicated_exit.loopexit:
116; CHECK-NEXT:    br label [[NON_DEDICATED_EXIT]]
117; CHECK:       non_dedicated_exit:
118; CHECK-NEXT:    ret void
119;
120entry:
121  br i1 %a, label %loop.ph, label %non_dedicated_exit
122
123loop.ph:
124  br label %loop.header
125
126loop.header:
127  %c1 = load volatile i1, i1* %ptr
128  br i1 %c1, label %loop.body1, label %dedicated_exit1
129
130loop.body1:
131  %c2 = load volatile i1, i1* %ptr
132  br i1 %c2, label %loop.body2, label %non_dedicated_exit
133
134loop.body2:
135  %c3 = load volatile i1, i1* %ptr
136  br i1 %c3, label %loop.backedge, label %dedicated_exit2
137
138loop.backedge:
139  br label %loop.header
140
141dedicated_exit1:
142  ret void
143; Check that there isn't a split loop exit.
144
145dedicated_exit2:
146  ret void
147; Check that there isn't a split loop exit.
148
149non_dedicated_exit:
150  ret void
151}
152
153; Check that we form what dedicated exits we can even when some exits are
154; reached via indirectbr which precludes forming dedicated exits.
155define void @test_form_some_dedicated_exits_despite_indirectbr(i8 %a, i8* %ptr, i8** %addr.ptr) {
156; CHECK-LABEL: @test_form_some_dedicated_exits_despite_indirectbr(
157; CHECK-NEXT:  entry:
158; CHECK-NEXT:    switch i8 [[A:%.*]], label [[LOOP_PH:%.*]] [
159; CHECK-NEXT:    i8 0, label [[EXIT_A:%.*]]
160; CHECK-NEXT:    i8 1, label [[EXIT_B:%.*]]
161; CHECK-NEXT:    i8 2, label [[EXIT_C:%.*]]
162; CHECK-NEXT:    ]
163; CHECK:       loop.ph:
164; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
165; CHECK:       loop.header:
166; CHECK-NEXT:    [[ADDR1:%.*]] = load volatile i8*, i8** [[ADDR_PTR:%.*]]
167; CHECK-NEXT:    indirectbr i8* [[ADDR1]], [label [[LOOP_BODY1:%.*]], label %exit.a]
168; CHECK:       loop.body1:
169; CHECK-NEXT:    [[B:%.*]] = load volatile i8, i8* [[PTR:%.*]]
170; CHECK-NEXT:    switch i8 [[B]], label [[LOOP_BODY2:%.*]] [
171; CHECK-NEXT:    i8 0, label [[EXIT_A]]
172; CHECK-NEXT:    i8 1, label [[EXIT_B_LOOPEXIT:%.*]]
173; CHECK-NEXT:    i8 2, label [[EXIT_C]]
174; CHECK-NEXT:    ]
175; CHECK:       loop.body2:
176; CHECK-NEXT:    [[ADDR2:%.*]] = load volatile i8*, i8** [[ADDR_PTR]]
177; CHECK-NEXT:    indirectbr i8* [[ADDR2]], [label [[LOOP_BACKEDGE:%.*]], label %exit.c]
178; CHECK:       loop.backedge:
179; CHECK-NEXT:    br label [[LOOP_HEADER]]
180; CHECK:       exit.a:
181; CHECK-NEXT:    ret void
182; CHECK:       exit.b.loopexit:
183; CHECK-NEXT:    br label [[EXIT_B]]
184; CHECK:       exit.b:
185; CHECK-NEXT:    ret void
186; CHECK:       exit.c:
187; CHECK-NEXT:    ret void
188;
189entry:
190  switch i8 %a, label %loop.ph [
191  i8 0, label %exit.a
192  i8 1, label %exit.b
193  i8 2, label %exit.c
194  ]
195
196loop.ph:
197  br label %loop.header
198
199loop.header:
200  %addr1 = load volatile i8*, i8** %addr.ptr
201  indirectbr i8* %addr1, [label %loop.body1, label %exit.a]
202
203loop.body1:
204  %b = load volatile i8, i8* %ptr
205  switch i8 %b, label %loop.body2 [
206  i8 0, label %exit.a
207  i8 1, label %exit.b
208  i8 2, label %exit.c
209  ]
210
211loop.body2:
212  %addr2 = load volatile i8*, i8** %addr.ptr
213  indirectbr i8* %addr2, [label %loop.backedge, label %exit.c]
214
215loop.backedge:
216  br label %loop.header
217
218exit.a:
219  ret void
220; Check that there isn't a split loop exit.
221
222exit.b:
223  ret void
224
225exit.c:
226  ret void
227; Check that there isn't a split loop exit.
228}
229