[ARM] Better OR's for MVE compares
[llvm-core.git] / test / Transforms / LoopSimplify / basictest.ll
blobe5fb7b9907bd421bfb7f0fdde2efd5a61636427f
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
5 ; to by bb1 & bb2
6 define void @test() {
7 ; CHECK-LABEL: define void @test(
8 entry:
9   br i1 true, label %bb1, label %bb2
11 bb1:
12   br label %bb3
13 ; CHECK:      bb1:
14 ; CHECK-NEXT:   br label %[[PH:.*]]
16 bb2:
17   br label %bb3
18 ; CHECK:      bb2:
19 ; CHECK-NEXT:   br label %[[PH]]
21 bb3:
22   br label %bb3
23 ; CHECK:      [[PH]]:
24 ; CHECK-NEXT:   br label %bb3
26 ; CHECK:      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(
35 entry:
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:   ]
46 loop:
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
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:   ]
72 ; CHECK:      [[BACKEDGE]]:
73 ; CHECK-NEXT:   br label %loop
75 exit.a:
76   ret void
77 ; CHECK:      [[LOOPEXIT_A]]:
78 ; CHECK-NEXT:   br label %exit.a
80 ; CHECK:      exit.a:
81 ; CHECK-NEXT:   ret void
83 exit.b:
84   ret void
85 ; CHECK:      [[LOOPEXIT_B]]:
86 ; CHECK-NEXT:   br label %exit.b
88 ; CHECK:      exit.b:
89 ; CHECK-NEXT:   ret void
92 ; Check that we leave already dedicated exits alone when forming dedicated exit
93 ; blocks.
94 define void @test_pre_existing_dedicated_exits(i1 %a, i1* %ptr) {
95 ; CHECK-LABEL: define void @test_pre_existing_dedicated_exits(
96 entry:
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
101 loop.ph:
102   br label %loop.header
103 ; CHECK:      loop.ph:
104 ; CHECK-NEXT:   br label %loop.header
106 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
113 loop.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:.*]]
120 loop.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
127 loop.backedge:
128   br label %loop.header
129 ; CHECK:      loop.backedge:
130 ; CHECK-NEXT:   br label %loop.header
132 dedicated_exit1:
133   ret void
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
140 dedicated_exit2:
141   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
148 non_dedicated_exit:
149   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(
161 entry:
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:   ]
174 loop.ph:
175   br label %loop.header
176 ; CHECK:      loop.ph:
177 ; CHECK-NEXT:   br label %loop.header
179 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]
186 loop.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:   ]
201 loop.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]
208 loop.backedge:
209   br label %loop.header
210 ; CHECK:      loop.backedge:
211 ; CHECK-NEXT:   br label %loop.header
213 exit.a:
214   ret void
215 ; Check that there isn't a split loop exit.
216 ; CHECK-NOT:    br label %exit.a
218 ; CHECK:      exit.a:
219 ; CHECK-NEXT:   ret void
221 exit.b:
222   ret void
223 ; CHECK:      [[LOOPEXIT]]:
224 ; CHECK-NEXT:   br label %exit.b
226 ; CHECK:      exit.b:
227 ; CHECK-NEXT:   ret void
229 exit.c:
230   ret void
231 ; Check that there isn't a split loop exit.
232 ; CHECK-NOT:    br label %exit.c
234 ; CHECK:      exit.c:
235 ; CHECK-NEXT:   ret void