1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -freeze-loop-unswitch-cond -passes='loop(simple-loop-unswitch<nontrivial>),verify<loops>' -S < %s | FileCheck %s
3 ; RUN: opt -freeze-loop-unswitch-cond -passes='loop-mssa(simple-loop-unswitch<nontrivial>),verify<loops>' -S < %s | FileCheck %s
4 ; RUN: opt -freeze-loop-unswitch-cond -passes='simple-loop-unswitch<nontrivial>' -verify-memoryssa -S < %s | FileCheck %s
11 declare void @sink1(i32)
12 declare void @sink2(i32)
13 declare void @sink3(i1)
14 declare void @sink4(i1)
17 declare i32 @cond.i32()
19 declare i32 @__CxxFrameHandler3(...)
21 define i32 @test1_freeze(ptr %ptr0, ptr %ptr1, ptr %ptr2) {
22 ; CHECK-LABEL: @test1_freeze(
24 ; CHECK-NEXT: [[COND1:%.*]] = load i1, ptr [[PTR1:%.*]], align 1
25 ; CHECK-NEXT: [[COND2:%.*]] = load i1, ptr [[PTR2:%.*]], align 1
26 ; CHECK-NEXT: br i1 [[COND1]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
27 ; CHECK: entry.split.us:
28 ; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]]
29 ; CHECK: loop_begin.us:
30 ; CHECK-NEXT: br label [[LOOP_A_US:%.*]]
32 ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @a()
33 ; CHECK-NEXT: br label [[LATCH_US:%.*]]
35 ; CHECK-NEXT: [[V_US:%.*]] = load i1, ptr [[PTR0:%.*]], align 1
36 ; CHECK-NEXT: br i1 [[V_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]]
37 ; CHECK: loop_exit.split.us:
38 ; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
40 ; CHECK-NEXT: [[COND2_FR:%.*]] = freeze i1 [[COND2]]
41 ; CHECK-NEXT: br i1 [[COND2_FR]], label [[ENTRY_SPLIT_SPLIT_US:%.*]], label [[ENTRY_SPLIT_SPLIT:%.*]]
42 ; CHECK: entry.split.split.us:
43 ; CHECK-NEXT: br label [[LOOP_BEGIN_US1:%.*]]
44 ; CHECK: loop_begin.us1:
45 ; CHECK-NEXT: br label [[LOOP_B_US:%.*]]
47 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @b()
48 ; CHECK-NEXT: br label [[LOOP_B_A_US:%.*]]
50 ; CHECK-NEXT: call void @sink3(i1 true)
51 ; CHECK-NEXT: br label [[LATCH_US2:%.*]]
53 ; CHECK-NEXT: [[V_US3:%.*]] = load i1, ptr [[PTR0]], align 1
54 ; CHECK-NEXT: br i1 [[V_US3]], label [[LOOP_BEGIN_US1]], label [[LOOP_EXIT_SPLIT_SPLIT_US:%.*]]
55 ; CHECK: loop_exit.split.split.us:
56 ; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT:%.*]]
57 ; CHECK: entry.split.split:
58 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
60 ; CHECK-NEXT: br label [[LOOP_B:%.*]]
62 ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @b()
63 ; CHECK-NEXT: br label [[LOOP_B_B:%.*]]
65 ; CHECK-NEXT: call void @sink4(i1 false)
66 ; CHECK-NEXT: br label [[LATCH:%.*]]
68 ; CHECK-NEXT: [[V:%.*]] = load i1, ptr [[PTR0]], align 1
69 ; CHECK-NEXT: br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT_SPLIT_SPLIT:%.*]]
70 ; CHECK: loop_exit.split.split:
71 ; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT]]
72 ; CHECK: loop_exit.split:
73 ; CHECK-NEXT: br label [[LOOP_EXIT]]
75 ; CHECK-NEXT: ret i32 0
78 %cond1 = load i1, ptr %ptr1
79 %cond2 = load i1, ptr %ptr2
83 br i1 %cond1, label %loop_a, label %loop_b
88 ; The 'loop_a' unswitched loop.
92 br i1 %cond2, label %loop_b_a, label %loop_b_b
93 ; The second unswitched condition.
96 call void @sink3(i1 %cond2)
98 ; The 'loop_b_a' unswitched loop.
99 ; %cond2 is replaced to true
102 call void @sink4(i1 %cond2)
104 ; The 'loop_b_b' unswitched loop.
105 ; %cond2 is replaced to false
108 %v = load i1, ptr %ptr0
109 br i1 %v, label %loop_begin, label %loop_exit
115 ; Test that when unswitching a deeply nested loop condition in a way that
116 ; produces a non-loop clone that can reach multiple exit blocks which are part
117 ; of different outer loops we correctly divide the cloned loop blocks between
118 ; the outer loops based on reachability.
119 define i32 @test7a(ptr %ptr, ptr %cond.ptr, ptr %a.ptr, ptr %b.ptr) {
120 ; CHECK-LABEL: @test7a(
122 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
124 ; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR:%.*]], align 4
125 ; CHECK-NEXT: br label [[INNER_LOOP_BEGIN:%.*]]
126 ; CHECK: inner_loop_begin:
127 ; CHECK-NEXT: [[A_PHI:%.*]] = phi i32 [ [[A]], [[LOOP_BEGIN]] ], [ [[A2:%.*]], [[INNER_INNER_LOOP_EXIT:%.*]] ]
128 ; CHECK-NEXT: [[COND:%.*]] = load i1, ptr [[COND_PTR:%.*]], align 1
129 ; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[B_PTR:%.*]], align 4
130 ; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]]
131 ; CHECK-NEXT: br i1 [[COND_FR]], label [[INNER_LOOP_BEGIN_SPLIT_US:%.*]], label [[INNER_LOOP_BEGIN_SPLIT:%.*]]
132 ; CHECK: inner_loop_begin.split.us:
133 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US:%.*]]
134 ; CHECK: inner_inner_loop_begin.us:
135 ; CHECK-NEXT: [[V1_US:%.*]] = load i1, ptr [[PTR:%.*]], align 1
136 ; CHECK-NEXT: br i1 [[V1_US]], label [[INNER_INNER_LOOP_A_US:%.*]], label [[INNER_INNER_LOOP_B_US:%.*]]
137 ; CHECK: inner_inner_loop_b.us:
138 ; CHECK-NEXT: [[V3_US:%.*]] = load i1, ptr [[PTR]], align 1
139 ; CHECK-NEXT: br i1 [[V3_US]], label [[INNER_INNER_LOOP_EXIT_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_C_US_LOOPEXIT:%.*]]
140 ; CHECK: inner_inner_loop_a.us:
141 ; CHECK-NEXT: [[A_PHI_LCSSA10:%.*]] = phi i32 [ [[A_PHI]], [[INNER_INNER_LOOP_BEGIN_US]] ]
142 ; CHECK-NEXT: [[B_LCSSA6:%.*]] = phi i32 [ [[B]], [[INNER_INNER_LOOP_BEGIN_US]] ]
143 ; CHECK-NEXT: [[V2_US:%.*]] = load i1, ptr [[PTR]], align 1
144 ; CHECK-NEXT: br i1 [[V2_US]], label [[LOOP_EXIT_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_C_US:%.*]]
145 ; CHECK: inner_inner_loop_c.us.loopexit:
146 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_C_US]]
147 ; CHECK: inner_inner_loop_c.us:
148 ; CHECK-NEXT: [[V4_US:%.*]] = load i1, ptr [[PTR]], align 1
149 ; CHECK-NEXT: br i1 [[V4_US]], label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_D_US:%.*]]
150 ; CHECK: inner_inner_loop_d.us:
151 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT_US]]
152 ; CHECK: inner_inner_loop_exit.split.us:
153 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_EXIT]]
154 ; CHECK: loop_exit.split.us:
155 ; CHECK-NEXT: [[A_LCSSA_US:%.*]] = phi i32 [ [[A_PHI_LCSSA10]], [[INNER_INNER_LOOP_A_US]] ]
156 ; CHECK-NEXT: [[B_LCSSA_US:%.*]] = phi i32 [ [[B_LCSSA6]], [[INNER_INNER_LOOP_A_US]] ]
157 ; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
158 ; CHECK: inner_loop_exit.loopexit.split.us:
159 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT:%.*]]
160 ; CHECK: inner_loop_begin.split:
161 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN:%.*]]
162 ; CHECK: inner_inner_loop_begin:
163 ; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR]], align 1
164 ; CHECK-NEXT: br i1 [[V1]], label [[INNER_INNER_LOOP_A:%.*]], label [[INNER_INNER_LOOP_B:%.*]]
165 ; CHECK: inner_inner_loop_a:
166 ; CHECK-NEXT: [[V2:%.*]] = load i1, ptr [[PTR]], align 1
167 ; CHECK-NEXT: br i1 [[V2]], label [[LOOP_EXIT_SPLIT:%.*]], label [[INNER_INNER_LOOP_C:%.*]]
168 ; CHECK: inner_inner_loop_b:
169 ; CHECK-NEXT: [[V3:%.*]] = load i1, ptr [[PTR]], align 1
170 ; CHECK-NEXT: br i1 [[V3]], label [[INNER_INNER_LOOP_EXIT_SPLIT:%.*]], label [[INNER_INNER_LOOP_C]]
171 ; CHECK: inner_inner_loop_c:
172 ; CHECK-NEXT: [[V4:%.*]] = load i1, ptr [[PTR]], align 1
173 ; CHECK-NEXT: br i1 [[V4]], label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT:%.*]], label [[INNER_INNER_LOOP_D:%.*]]
174 ; CHECK: inner_inner_loop_d:
175 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN]]
176 ; CHECK: inner_inner_loop_exit.split:
177 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_EXIT]]
178 ; CHECK: inner_inner_loop_exit:
179 ; CHECK-NEXT: [[A2]] = load i32, ptr [[A_PTR]], align 4
180 ; CHECK-NEXT: [[V5:%.*]] = load i1, ptr [[PTR]], align 1
181 ; CHECK-NEXT: br i1 [[V5]], label [[INNER_LOOP_EXIT_LOOPEXIT1:%.*]], label [[INNER_LOOP_BEGIN]]
182 ; CHECK: inner_loop_exit.loopexit.split:
183 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT]]
184 ; CHECK: inner_loop_exit.loopexit:
185 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT:%.*]]
186 ; CHECK: inner_loop_exit.loopexit1:
187 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT]]
188 ; CHECK: inner_loop_exit:
189 ; CHECK-NEXT: br label [[LOOP_BEGIN]]
190 ; CHECK: loop_exit.split:
191 ; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_PHI]], [[INNER_INNER_LOOP_A]] ]
192 ; CHECK-NEXT: [[B_LCSSA:%.*]] = phi i32 [ [[B]], [[INNER_INNER_LOOP_A]] ]
193 ; CHECK-NEXT: br label [[LOOP_EXIT]]
195 ; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[A_LCSSA]], [[LOOP_EXIT_SPLIT]] ], [ [[A_LCSSA_US]], [[LOOP_EXIT_SPLIT_US]] ]
196 ; CHECK-NEXT: [[DOTUS_PHI2:%.*]] = phi i32 [ [[B_LCSSA]], [[LOOP_EXIT_SPLIT]] ], [ [[B_LCSSA_US]], [[LOOP_EXIT_SPLIT_US]] ]
197 ; CHECK-NEXT: [[RESULT:%.*]] = add i32 [[DOTUS_PHI]], [[DOTUS_PHI2]]
198 ; CHECK-NEXT: ret i32 [[RESULT]]
204 %a = load i32, ptr %a.ptr
205 br label %inner_loop_begin
208 %a.phi = phi i32 [ %a, %loop_begin ], [ %a2, %inner_inner_loop_exit ]
209 %cond = load i1, ptr %cond.ptr
210 %b = load i32, ptr %b.ptr
211 br label %inner_inner_loop_begin
213 inner_inner_loop_begin:
214 %v1 = load i1, ptr %ptr
215 br i1 %v1, label %inner_inner_loop_a, label %inner_inner_loop_b
218 %v2 = load i1, ptr %ptr
219 br i1 %v2, label %loop_exit, label %inner_inner_loop_c
222 %v3 = load i1, ptr %ptr
223 br i1 %v3, label %inner_inner_loop_exit, label %inner_inner_loop_c
226 %v4 = load i1, ptr %ptr
227 br i1 %v4, label %inner_loop_exit, label %inner_inner_loop_d
230 br i1 %cond, label %inner_loop_exit, label %inner_inner_loop_begin
231 ; The cloned copy that always exits with the adjustments required to fix up
233 ; The original copy that continues to loop.
235 inner_inner_loop_exit:
236 %a2 = load i32, ptr %a.ptr
237 %v5 = load i1, ptr %ptr
238 br i1 %v5, label %inner_loop_exit, label %inner_loop_begin
244 %a.lcssa = phi i32 [ %a.phi, %inner_inner_loop_a ]
245 %b.lcssa = phi i32 [ %b, %inner_inner_loop_a ]
246 %result = add i32 %a.lcssa, %b.lcssa
250 ; Same pattern as @test7a but here the original loop becomes a non-loop that
251 ; can reach multiple exit blocks which are part of different outer loops.
252 define i32 @test7b(ptr %ptr, ptr %cond.ptr, ptr %a.ptr, ptr %b.ptr) {
253 ; CHECK-LABEL: @test7b(
255 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
257 ; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR:%.*]], align 4
258 ; CHECK-NEXT: br label [[INNER_LOOP_BEGIN:%.*]]
259 ; CHECK: inner_loop_begin:
260 ; CHECK-NEXT: [[A_PHI:%.*]] = phi i32 [ [[A]], [[LOOP_BEGIN]] ], [ [[A2:%.*]], [[INNER_INNER_LOOP_EXIT:%.*]] ]
261 ; CHECK-NEXT: [[COND:%.*]] = load i1, ptr [[COND_PTR:%.*]], align 1
262 ; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[B_PTR:%.*]], align 4
263 ; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]]
264 ; CHECK-NEXT: br i1 [[COND_FR]], label [[INNER_LOOP_BEGIN_SPLIT_US:%.*]], label [[INNER_LOOP_BEGIN_SPLIT:%.*]]
265 ; CHECK: inner_loop_begin.split.us:
266 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US:%.*]]
267 ; CHECK: inner_inner_loop_begin.us:
268 ; CHECK-NEXT: [[V1_US:%.*]] = load i1, ptr [[PTR:%.*]], align 1
269 ; CHECK-NEXT: br i1 [[V1_US]], label [[INNER_INNER_LOOP_A_US:%.*]], label [[INNER_INNER_LOOP_B_US:%.*]]
270 ; CHECK: inner_inner_loop_b.us:
271 ; CHECK-NEXT: [[V3_US:%.*]] = load i1, ptr [[PTR]], align 1
272 ; CHECK-NEXT: br i1 [[V3_US]], label [[INNER_INNER_LOOP_EXIT_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_C_US:%.*]]
273 ; CHECK: inner_inner_loop_a.us:
274 ; CHECK-NEXT: [[V2_US:%.*]] = load i1, ptr [[PTR]], align 1
275 ; CHECK-NEXT: br i1 [[V2_US]], label [[LOOP_EXIT_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_C_US]]
276 ; CHECK: inner_inner_loop_c.us:
277 ; CHECK-NEXT: [[V4_US:%.*]] = load i1, ptr [[PTR]], align 1
278 ; CHECK-NEXT: br i1 [[V4_US]], label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_D_US:%.*]]
279 ; CHECK: inner_inner_loop_d.us:
280 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US]]
281 ; CHECK: inner_inner_loop_exit.split.us:
282 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_EXIT]]
283 ; CHECK: loop_exit.split.us:
284 ; CHECK-NEXT: [[A_LCSSA_US:%.*]] = phi i32 [ [[A_PHI]], [[INNER_INNER_LOOP_A_US]] ]
285 ; CHECK-NEXT: [[B_LCSSA_US:%.*]] = phi i32 [ [[B]], [[INNER_INNER_LOOP_A_US]] ]
286 ; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
287 ; CHECK: inner_loop_exit.loopexit.split.us:
288 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT:%.*]]
289 ; CHECK: inner_loop_begin.split:
290 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN:%.*]]
291 ; CHECK: inner_inner_loop_begin:
292 ; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR]], align 1
293 ; CHECK-NEXT: br i1 [[V1]], label [[INNER_INNER_LOOP_A:%.*]], label [[INNER_INNER_LOOP_B:%.*]]
294 ; CHECK: inner_inner_loop_a:
295 ; CHECK-NEXT: [[A_PHI_LCSSA:%.*]] = phi i32 [ [[A_PHI]], [[INNER_INNER_LOOP_BEGIN]] ]
296 ; CHECK-NEXT: [[B_LCSSA3:%.*]] = phi i32 [ [[B]], [[INNER_INNER_LOOP_BEGIN]] ]
297 ; CHECK-NEXT: [[V2:%.*]] = load i1, ptr [[PTR]], align 1
298 ; CHECK-NEXT: br i1 [[V2]], label [[LOOP_EXIT_SPLIT:%.*]], label [[INNER_INNER_LOOP_C:%.*]]
299 ; CHECK: inner_inner_loop_b:
300 ; CHECK-NEXT: [[V3:%.*]] = load i1, ptr [[PTR]], align 1
301 ; CHECK-NEXT: br i1 [[V3]], label [[INNER_INNER_LOOP_EXIT_SPLIT:%.*]], label [[INNER_INNER_LOOP_C_LOOPEXIT:%.*]]
302 ; CHECK: inner_inner_loop_c.loopexit:
303 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_C]]
304 ; CHECK: inner_inner_loop_c:
305 ; CHECK-NEXT: [[V4:%.*]] = load i1, ptr [[PTR]], align 1
306 ; CHECK-NEXT: br i1 [[V4]], label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT:%.*]], label [[INNER_INNER_LOOP_D:%.*]]
307 ; CHECK: inner_inner_loop_d:
308 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT]]
309 ; CHECK: inner_inner_loop_exit.split:
310 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_EXIT]]
311 ; CHECK: inner_inner_loop_exit:
312 ; CHECK-NEXT: [[A2]] = load i32, ptr [[A_PTR]], align 4
313 ; CHECK-NEXT: [[V5:%.*]] = load i1, ptr [[PTR]], align 1
314 ; CHECK-NEXT: br i1 [[V5]], label [[INNER_LOOP_EXIT_LOOPEXIT1:%.*]], label [[INNER_LOOP_BEGIN]]
315 ; CHECK: inner_loop_exit.loopexit.split:
316 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT]]
317 ; CHECK: inner_loop_exit.loopexit:
318 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT:%.*]]
319 ; CHECK: inner_loop_exit.loopexit1:
320 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT]]
321 ; CHECK: inner_loop_exit:
322 ; CHECK-NEXT: br label [[LOOP_BEGIN]]
323 ; CHECK: loop_exit.split:
324 ; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_PHI_LCSSA]], [[INNER_INNER_LOOP_A]] ]
325 ; CHECK-NEXT: [[B_LCSSA:%.*]] = phi i32 [ [[B_LCSSA3]], [[INNER_INNER_LOOP_A]] ]
326 ; CHECK-NEXT: br label [[LOOP_EXIT]]
328 ; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[A_LCSSA]], [[LOOP_EXIT_SPLIT]] ], [ [[A_LCSSA_US]], [[LOOP_EXIT_SPLIT_US]] ]
329 ; CHECK-NEXT: [[DOTUS_PHI2:%.*]] = phi i32 [ [[B_LCSSA]], [[LOOP_EXIT_SPLIT]] ], [ [[B_LCSSA_US]], [[LOOP_EXIT_SPLIT_US]] ]
330 ; CHECK-NEXT: [[RESULT:%.*]] = add i32 [[DOTUS_PHI]], [[DOTUS_PHI2]]
331 ; CHECK-NEXT: ret i32 [[RESULT]]
337 %a = load i32, ptr %a.ptr
338 br label %inner_loop_begin
341 %a.phi = phi i32 [ %a, %loop_begin ], [ %a2, %inner_inner_loop_exit ]
342 %cond = load i1, ptr %cond.ptr
343 %b = load i32, ptr %b.ptr
344 br label %inner_inner_loop_begin
346 inner_inner_loop_begin:
347 %v1 = load i1, ptr %ptr
348 br i1 %v1, label %inner_inner_loop_a, label %inner_inner_loop_b
351 %v2 = load i1, ptr %ptr
352 br i1 %v2, label %loop_exit, label %inner_inner_loop_c
355 %v3 = load i1, ptr %ptr
356 br i1 %v3, label %inner_inner_loop_exit, label %inner_inner_loop_c
359 %v4 = load i1, ptr %ptr
360 br i1 %v4, label %inner_loop_exit, label %inner_inner_loop_d
363 br i1 %cond, label %inner_inner_loop_begin, label %inner_loop_exit
364 ; The cloned copy that continues looping.
365 ; The original copy that now always exits and needs adjustments for exit
368 inner_inner_loop_exit:
369 %a2 = load i32, ptr %a.ptr
370 %v5 = load i1, ptr %ptr
371 br i1 %v5, label %inner_loop_exit, label %inner_loop_begin
377 %a.lcssa = phi i32 [ %a.phi, %inner_inner_loop_a ]
378 %b.lcssa = phi i32 [ %b, %inner_inner_loop_a ]
379 %result = add i32 %a.lcssa, %b.lcssa
383 ; Test that when the exit block set of an inner loop changes to start at a less
384 ; high level of the loop nest we correctly hoist the loop up the nest.
385 define i32 @test8a(ptr %ptr, ptr %cond.ptr, ptr %a.ptr, ptr %b.ptr) {
386 ; CHECK-LABEL: @test8a(
388 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
390 ; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR:%.*]], align 4
391 ; CHECK-NEXT: br label [[INNER_LOOP_BEGIN:%.*]]
392 ; CHECK: inner_loop_begin:
393 ; CHECK-NEXT: [[A_PHI:%.*]] = phi i32 [ [[A]], [[LOOP_BEGIN]] ], [ [[A2:%.*]], [[INNER_INNER_LOOP_EXIT:%.*]] ]
394 ; CHECK-NEXT: [[COND:%.*]] = load i1, ptr [[COND_PTR:%.*]], align 1
395 ; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[B_PTR:%.*]], align 4
396 ; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]]
397 ; CHECK-NEXT: br i1 [[COND_FR]], label [[INNER_LOOP_BEGIN_SPLIT_US:%.*]], label [[INNER_LOOP_BEGIN_SPLIT:%.*]]
398 ; CHECK: inner_loop_begin.split.us:
399 ; CHECK-NEXT: [[A_PHI_LCSSA4:%.*]] = phi i32 [ [[A_PHI]], [[INNER_LOOP_BEGIN]] ]
400 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US:%.*]]
401 ; CHECK: inner_inner_loop_begin.us:
402 ; CHECK-NEXT: [[V1_US:%.*]] = load i1, ptr [[PTR:%.*]], align 1
403 ; CHECK-NEXT: br i1 [[V1_US]], label [[INNER_INNER_LOOP_A_US:%.*]], label [[INNER_INNER_LOOP_B_US:%.*]]
404 ; CHECK: inner_inner_loop_b.us:
405 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_LATCH_US:%.*]]
406 ; CHECK: inner_inner_loop_a.us:
407 ; CHECK-NEXT: [[V2_US:%.*]] = load i1, ptr [[PTR]], align 1
408 ; CHECK-NEXT: br i1 [[V2_US]], label [[INNER_INNER_LOOP_LATCH_US]], label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT_US:%.*]]
409 ; CHECK: inner_inner_loop_latch.us:
410 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US]]
411 ; CHECK: inner_loop_exit.loopexit.split.us:
412 ; CHECK-NEXT: [[A_PHI_LCSSA2_US:%.*]] = phi i32 [ [[A_PHI_LCSSA4]], [[INNER_INNER_LOOP_A_US]] ]
413 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT:%.*]]
414 ; CHECK: inner_loop_begin.split:
415 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN:%.*]]
416 ; CHECK: inner_inner_loop_begin:
417 ; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR]], align 1
418 ; CHECK-NEXT: br i1 [[V1]], label [[INNER_INNER_LOOP_A:%.*]], label [[INNER_INNER_LOOP_B:%.*]]
419 ; CHECK: inner_inner_loop_a:
420 ; CHECK-NEXT: [[V2:%.*]] = load i1, ptr [[PTR]], align 1
421 ; CHECK-NEXT: br i1 [[V2]], label [[INNER_INNER_LOOP_LATCH:%.*]], label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT:%.*]]
422 ; CHECK: inner_inner_loop_b:
423 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_EXIT]]
424 ; CHECK: inner_inner_loop_latch:
425 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN]]
426 ; CHECK: inner_inner_loop_exit:
427 ; CHECK-NEXT: [[A2]] = load i32, ptr [[A_PTR]], align 4
428 ; CHECK-NEXT: [[V4:%.*]] = load i1, ptr [[PTR]], align 1
429 ; CHECK-NEXT: br i1 [[V4]], label [[INNER_LOOP_EXIT_LOOPEXIT1:%.*]], label [[INNER_LOOP_BEGIN]]
430 ; CHECK: inner_loop_exit.loopexit.split:
431 ; CHECK-NEXT: [[A_PHI_LCSSA2:%.*]] = phi i32 [ [[A_PHI]], [[INNER_INNER_LOOP_A]] ]
432 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT]]
433 ; CHECK: inner_loop_exit.loopexit:
434 ; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[A_PHI_LCSSA2]], [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT]] ], [ [[A_PHI_LCSSA2_US]], [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT_US]] ]
435 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT:%.*]]
436 ; CHECK: inner_loop_exit.loopexit1:
437 ; CHECK-NEXT: [[A_PHI_LCSSA:%.*]] = phi i32 [ [[A_PHI]], [[INNER_INNER_LOOP_EXIT]] ]
438 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT]]
439 ; CHECK: inner_loop_exit:
440 ; CHECK-NEXT: [[A_PHI3:%.*]] = phi i32 [ [[A_PHI_LCSSA]], [[INNER_LOOP_EXIT_LOOPEXIT1]] ], [ [[DOTUS_PHI]], [[INNER_LOOP_EXIT_LOOPEXIT]] ]
441 ; CHECK-NEXT: [[V5:%.*]] = load i1, ptr [[PTR]], align 1
442 ; CHECK-NEXT: br i1 [[V5]], label [[LOOP_EXIT:%.*]], label [[LOOP_BEGIN]]
444 ; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_PHI3]], [[INNER_LOOP_EXIT]] ]
445 ; CHECK-NEXT: ret i32 [[A_LCSSA]]
451 %a = load i32, ptr %a.ptr
452 br label %inner_loop_begin
455 %a.phi = phi i32 [ %a, %loop_begin ], [ %a2, %inner_inner_loop_exit ]
456 %cond = load i1, ptr %cond.ptr
457 %b = load i32, ptr %b.ptr
458 br label %inner_inner_loop_begin
460 inner_inner_loop_begin:
461 %v1 = load i1, ptr %ptr
462 br i1 %v1, label %inner_inner_loop_a, label %inner_inner_loop_b
465 %v2 = load i1, ptr %ptr
466 br i1 %v2, label %inner_inner_loop_latch, label %inner_loop_exit
469 br i1 %cond, label %inner_inner_loop_latch, label %inner_inner_loop_exit
471 inner_inner_loop_latch:
472 br label %inner_inner_loop_begin
473 ; The cloned region is now an exit from the inner loop.
474 ; The original region exits the loop earlier.
476 inner_inner_loop_exit:
477 %a2 = load i32, ptr %a.ptr
478 %v4 = load i1, ptr %ptr
479 br i1 %v4, label %inner_loop_exit, label %inner_loop_begin
482 %v5 = load i1, ptr %ptr
483 br i1 %v5, label %loop_exit, label %loop_begin
486 %a.lcssa = phi i32 [ %a.phi, %inner_loop_exit ]
490 ; Same pattern as @test8a but where the original loop looses an exit block and
491 ; needs to be hoisted up the nest.
492 define i32 @test8b(ptr %ptr, ptr %cond.ptr, ptr %a.ptr, ptr %b.ptr) {
493 ; CHECK-LABEL: @test8b(
495 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
497 ; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR:%.*]], align 4
498 ; CHECK-NEXT: br label [[INNER_LOOP_BEGIN:%.*]]
499 ; CHECK: inner_loop_begin:
500 ; CHECK-NEXT: [[A_PHI:%.*]] = phi i32 [ [[A]], [[LOOP_BEGIN]] ], [ [[A2:%.*]], [[INNER_INNER_LOOP_EXIT:%.*]] ]
501 ; CHECK-NEXT: [[COND:%.*]] = load i1, ptr [[COND_PTR:%.*]], align 1
502 ; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[B_PTR:%.*]], align 4
503 ; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]]
504 ; CHECK-NEXT: br i1 [[COND_FR]], label [[INNER_LOOP_BEGIN_SPLIT_US:%.*]], label [[INNER_LOOP_BEGIN_SPLIT:%.*]]
505 ; CHECK: inner_loop_begin.split.us:
506 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US:%.*]]
507 ; CHECK: inner_inner_loop_begin.us:
508 ; CHECK-NEXT: [[V1_US:%.*]] = load i1, ptr [[PTR:%.*]], align 1
509 ; CHECK-NEXT: br i1 [[V1_US]], label [[INNER_INNER_LOOP_A_US:%.*]], label [[INNER_INNER_LOOP_B_US:%.*]]
510 ; CHECK: inner_inner_loop_b.us:
511 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_EXIT_SPLIT_US:%.*]]
512 ; CHECK: inner_inner_loop_a.us:
513 ; CHECK-NEXT: [[V2_US:%.*]] = load i1, ptr [[PTR]], align 1
514 ; CHECK-NEXT: br i1 [[V2_US]], label [[INNER_INNER_LOOP_LATCH_US:%.*]], label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT_US:%.*]]
515 ; CHECK: inner_inner_loop_latch.us:
516 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US]]
517 ; CHECK: inner_inner_loop_exit.split.us:
518 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_EXIT]]
519 ; CHECK: inner_loop_exit.loopexit.split.us:
520 ; CHECK-NEXT: [[A_PHI_LCSSA2_US:%.*]] = phi i32 [ [[A_PHI]], [[INNER_INNER_LOOP_A_US]] ]
521 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT:%.*]]
522 ; CHECK: inner_loop_begin.split:
523 ; CHECK-NEXT: [[A_PHI_LCSSA4:%.*]] = phi i32 [ [[A_PHI]], [[INNER_LOOP_BEGIN]] ]
524 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN:%.*]]
525 ; CHECK: inner_inner_loop_begin:
526 ; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR]], align 1
527 ; CHECK-NEXT: br i1 [[V1]], label [[INNER_INNER_LOOP_A:%.*]], label [[INNER_INNER_LOOP_B:%.*]]
528 ; CHECK: inner_inner_loop_a:
529 ; CHECK-NEXT: [[V2:%.*]] = load i1, ptr [[PTR]], align 1
530 ; CHECK-NEXT: br i1 [[V2]], label [[INNER_INNER_LOOP_LATCH:%.*]], label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT:%.*]]
531 ; CHECK: inner_inner_loop_b:
532 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_LATCH]]
533 ; CHECK: inner_inner_loop_latch:
534 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN]]
535 ; CHECK: inner_inner_loop_exit:
536 ; CHECK-NEXT: [[A2]] = load i32, ptr [[A_PTR]], align 4
537 ; CHECK-NEXT: [[V4:%.*]] = load i1, ptr [[PTR]], align 1
538 ; CHECK-NEXT: br i1 [[V4]], label [[INNER_LOOP_EXIT_LOOPEXIT1:%.*]], label [[INNER_LOOP_BEGIN]]
539 ; CHECK: inner_loop_exit.loopexit.split:
540 ; CHECK-NEXT: [[A_PHI_LCSSA2:%.*]] = phi i32 [ [[A_PHI_LCSSA4]], [[INNER_INNER_LOOP_A]] ]
541 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT]]
542 ; CHECK: inner_loop_exit.loopexit:
543 ; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[A_PHI_LCSSA2]], [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT]] ], [ [[A_PHI_LCSSA2_US]], [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT_US]] ]
544 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT:%.*]]
545 ; CHECK: inner_loop_exit.loopexit1:
546 ; CHECK-NEXT: [[A_PHI_LCSSA:%.*]] = phi i32 [ [[A_PHI]], [[INNER_INNER_LOOP_EXIT]] ]
547 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT]]
548 ; CHECK: inner_loop_exit:
549 ; CHECK-NEXT: [[A_PHI3:%.*]] = phi i32 [ [[A_PHI_LCSSA]], [[INNER_LOOP_EXIT_LOOPEXIT1]] ], [ [[DOTUS_PHI]], [[INNER_LOOP_EXIT_LOOPEXIT]] ]
550 ; CHECK-NEXT: [[V5:%.*]] = load i1, ptr [[PTR]], align 1
551 ; CHECK-NEXT: br i1 [[V5]], label [[LOOP_EXIT:%.*]], label [[LOOP_BEGIN]]
553 ; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_PHI3]], [[INNER_LOOP_EXIT]] ]
554 ; CHECK-NEXT: ret i32 [[A_LCSSA]]
560 %a = load i32, ptr %a.ptr
561 br label %inner_loop_begin
564 %a.phi = phi i32 [ %a, %loop_begin ], [ %a2, %inner_inner_loop_exit ]
565 %cond = load i1, ptr %cond.ptr
566 %b = load i32, ptr %b.ptr
567 br label %inner_inner_loop_begin
569 inner_inner_loop_begin:
570 %v1 = load i1, ptr %ptr
571 br i1 %v1, label %inner_inner_loop_a, label %inner_inner_loop_b
574 %v2 = load i1, ptr %ptr
575 br i1 %v2, label %inner_inner_loop_latch, label %inner_loop_exit
578 br i1 %cond, label %inner_inner_loop_exit, label %inner_inner_loop_latch
580 inner_inner_loop_latch:
581 br label %inner_inner_loop_begin
582 ; The cloned region is similar to before but with one earlier exit.
583 ; The original region is now an exit in the preheader.
585 inner_inner_loop_exit:
586 %a2 = load i32, ptr %a.ptr
587 %v4 = load i1, ptr %ptr
588 br i1 %v4, label %inner_loop_exit, label %inner_loop_begin
591 %v5 = load i1, ptr %ptr
592 br i1 %v5, label %loop_exit, label %loop_begin
595 %a.lcssa = phi i32 [ %a.phi, %inner_loop_exit ]
599 ; Test that requires re-forming dedicated exits for the cloned loop.
600 define i32 @test10a(ptr %ptr, i1 %cond, ptr %a.ptr) {
601 ; CHECK-LABEL: @test10a(
603 ; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND:%.*]]
604 ; CHECK-NEXT: br i1 [[COND_FR]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
605 ; CHECK: entry.split.us:
606 ; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]]
607 ; CHECK: loop_begin.us:
608 ; CHECK-NEXT: [[A_US:%.*]] = load i32, ptr [[A_PTR:%.*]], align 4
609 ; CHECK-NEXT: [[V1_US:%.*]] = load i1, ptr [[PTR:%.*]], align 1
610 ; CHECK-NEXT: br i1 [[V1_US]], label [[LOOP_A_US:%.*]], label [[LOOP_B_US:%.*]]
612 ; CHECK-NEXT: [[A_US_LCSSA:%.*]] = phi i32 [ [[A_US]], [[LOOP_BEGIN_US]] ]
613 ; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT_US:%.*]]
615 ; CHECK-NEXT: [[V2_US:%.*]] = load i1, ptr [[PTR]], align 1
616 ; CHECK-NEXT: br i1 [[V2_US]], label [[LOOP_EXIT_SPLIT_US_LOOPEXIT:%.*]], label [[LOOP_BEGIN_BACKEDGE_US:%.*]]
617 ; CHECK: loop_begin.backedge.us:
618 ; CHECK-NEXT: br label [[LOOP_BEGIN_US]]
619 ; CHECK: loop_exit.split.us.loopexit:
620 ; CHECK-NEXT: [[A_LCSSA_US_PH:%.*]] = phi i32 [ [[A_US]], [[LOOP_A_US]] ]
621 ; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT_US]]
622 ; CHECK: loop_exit.split.us:
623 ; CHECK-NEXT: [[A_LCSSA_US:%.*]] = phi i32 [ [[A_US_LCSSA]], [[LOOP_B_US]] ], [ [[A_LCSSA_US_PH]], [[LOOP_EXIT_SPLIT_US_LOOPEXIT]] ]
624 ; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
625 ; CHECK: entry.split:
626 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
628 ; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR]], align 4
629 ; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR]], align 1
630 ; CHECK-NEXT: br i1 [[V1]], label [[LOOP_A:%.*]], label [[LOOP_B:%.*]]
632 ; CHECK-NEXT: [[V2:%.*]] = load i1, ptr [[PTR]], align 1
633 ; CHECK-NEXT: br i1 [[V2]], label [[LOOP_EXIT_SPLIT:%.*]], label [[LOOP_BEGIN_BACKEDGE:%.*]]
634 ; CHECK: loop_begin.backedge:
635 ; CHECK-NEXT: br label [[LOOP_BEGIN]]
637 ; CHECK-NEXT: br label [[LOOP_BEGIN_BACKEDGE]]
638 ; CHECK: loop_exit.split:
639 ; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A]], [[LOOP_A]] ]
640 ; CHECK-NEXT: br label [[LOOP_EXIT]]
642 ; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[A_LCSSA]], [[LOOP_EXIT_SPLIT]] ], [ [[A_LCSSA_US]], [[LOOP_EXIT_SPLIT_US]] ]
643 ; CHECK-NEXT: ret i32 [[DOTUS_PHI]]
649 %a = load i32, ptr %a.ptr
650 %v1 = load i1, ptr %ptr
651 br i1 %v1, label %loop_a, label %loop_b
654 %v2 = load i1, ptr %ptr
655 br i1 %v2, label %loop_exit, label %loop_begin
658 br i1 %cond, label %loop_exit, label %loop_begin
659 ; The cloned loop with one edge as a direct exit.
661 ; The original loop without one 'loop_exit' edge.
664 %a.lcssa = phi i32 [ %a, %loop_a ], [ %a, %loop_b ]
668 ; Test that requires re-forming dedicated exits for the original loop.
669 define i32 @test10b(ptr %ptr, i1 %cond, ptr %a.ptr) {
670 ; CHECK-LABEL: @test10b(
672 ; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND:%.*]]
673 ; CHECK-NEXT: br i1 [[COND_FR]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
674 ; CHECK: entry.split.us:
675 ; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]]
676 ; CHECK: loop_begin.us:
677 ; CHECK-NEXT: [[A_US:%.*]] = load i32, ptr [[A_PTR:%.*]], align 4
678 ; CHECK-NEXT: [[V1_US:%.*]] = load i1, ptr [[PTR:%.*]], align 1
679 ; CHECK-NEXT: br i1 [[V1_US]], label [[LOOP_A_US:%.*]], label [[LOOP_B_US:%.*]]
681 ; CHECK-NEXT: br label [[LOOP_BEGIN_BACKEDGE_US:%.*]]
683 ; CHECK-NEXT: [[V2_US:%.*]] = load i1, ptr [[PTR]], align 1
684 ; CHECK-NEXT: br i1 [[V2_US]], label [[LOOP_BEGIN_BACKEDGE_US]], label [[LOOP_EXIT_SPLIT_US:%.*]]
685 ; CHECK: loop_begin.backedge.us:
686 ; CHECK-NEXT: br label [[LOOP_BEGIN_US]]
687 ; CHECK: loop_exit.split.us:
688 ; CHECK-NEXT: [[A_LCSSA_US:%.*]] = phi i32 [ [[A_US]], [[LOOP_A_US]] ]
689 ; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
690 ; CHECK: entry.split:
691 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
693 ; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR]], align 4
694 ; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR]], align 1
695 ; CHECK-NEXT: br i1 [[V1]], label [[LOOP_A:%.*]], label [[LOOP_B:%.*]]
697 ; CHECK-NEXT: [[V2:%.*]] = load i1, ptr [[PTR]], align 1
698 ; CHECK-NEXT: br i1 [[V2]], label [[LOOP_BEGIN_BACKEDGE:%.*]], label [[LOOP_EXIT_SPLIT_LOOPEXIT:%.*]]
699 ; CHECK: loop_begin.backedge:
700 ; CHECK-NEXT: br label [[LOOP_BEGIN]]
702 ; CHECK-NEXT: [[A_LCSSA1:%.*]] = phi i32 [ [[A]], [[LOOP_BEGIN]] ]
703 ; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT:%.*]]
704 ; CHECK: loop_exit.split.loopexit:
705 ; CHECK-NEXT: [[A_LCSSA_PH:%.*]] = phi i32 [ [[A]], [[LOOP_A]] ]
706 ; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT]]
707 ; CHECK: loop_exit.split:
708 ; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_LCSSA1]], [[LOOP_B]] ], [ [[A_LCSSA_PH]], [[LOOP_EXIT_SPLIT_LOOPEXIT]] ]
709 ; CHECK-NEXT: br label [[LOOP_EXIT]]
711 ; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[A_LCSSA]], [[LOOP_EXIT_SPLIT]] ], [ [[A_LCSSA_US]], [[LOOP_EXIT_SPLIT_US]] ]
712 ; CHECK-NEXT: ret i32 [[DOTUS_PHI]]
718 %a = load i32, ptr %a.ptr
719 %v1 = load i1, ptr %ptr
720 br i1 %v1, label %loop_a, label %loop_b
723 %v2 = load i1, ptr %ptr
724 br i1 %v2, label %loop_begin, label %loop_exit
727 br i1 %cond, label %loop_begin, label %loop_exit
728 ; The cloned loop without one of the exits.
730 ; The original loop without one 'loop_exit' edge.
733 %a.lcssa = phi i32 [ %a, %loop_a ], [ %a, %loop_b ]
737 ; Check that if a cloned inner loop after unswitching doesn't loop and directly
738 ; exits even an outer loop, we don't add the cloned preheader to the outer
739 ; loop and do add the needed LCSSA phi nodes for the new exit block from the
741 define i32 @test11a(ptr %ptr, ptr %cond.ptr, ptr %a.ptr, ptr %b.ptr) {
742 ; CHECK-LABEL: @test11a(
744 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
746 ; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[B_PTR:%.*]], align 4
747 ; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR:%.*]], align 1
748 ; CHECK-NEXT: br i1 [[V1]], label [[LOOP_LATCH:%.*]], label [[INNER_LOOP_PH:%.*]]
749 ; CHECK: inner_loop_ph:
750 ; CHECK-NEXT: [[COND:%.*]] = load i1, ptr [[COND_PTR:%.*]], align 1
751 ; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]]
752 ; CHECK-NEXT: br i1 [[COND_FR]], label [[INNER_LOOP_PH_SPLIT_US:%.*]], label [[INNER_LOOP_PH_SPLIT:%.*]]
753 ; CHECK: inner_loop_ph.split.us:
754 ; CHECK-NEXT: [[B_LCSSA:%.*]] = phi i32 [ [[B]], [[INNER_LOOP_PH]] ]
755 ; CHECK-NEXT: br label [[INNER_LOOP_BEGIN_US:%.*]]
756 ; CHECK: inner_loop_begin.us:
757 ; CHECK-NEXT: call void @sink1(i32 [[B_LCSSA]])
758 ; CHECK-NEXT: [[A_US:%.*]] = load i32, ptr [[A_PTR:%.*]], align 4
759 ; CHECK-NEXT: br label [[LOOP_EXIT_LOOPEXIT_SPLIT_US:%.*]]
760 ; CHECK: loop_exit.loopexit.split.us:
761 ; CHECK-NEXT: [[A_LCSSA2_US:%.*]] = phi i32 [ [[A_US]], [[INNER_LOOP_BEGIN_US]] ]
762 ; CHECK-NEXT: br label [[LOOP_EXIT_LOOPEXIT:%.*]]
763 ; CHECK: inner_loop_ph.split:
764 ; CHECK-NEXT: br label [[INNER_LOOP_BEGIN:%.*]]
765 ; CHECK: inner_loop_begin:
766 ; CHECK-NEXT: call void @sink1(i32 [[B]])
767 ; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR]], align 4
768 ; CHECK-NEXT: br label [[INNER_LOOP_A:%.*]]
769 ; CHECK: inner_loop_a:
770 ; CHECK-NEXT: [[V2:%.*]] = load i1, ptr [[PTR]], align 1
771 ; CHECK-NEXT: br i1 [[V2]], label [[INNER_LOOP_EXIT:%.*]], label [[INNER_LOOP_BEGIN]]
772 ; CHECK: inner_loop_exit:
773 ; CHECK-NEXT: [[A_INNER_LCSSA:%.*]] = phi i32 [ [[A]], [[INNER_LOOP_A]] ]
774 ; CHECK-NEXT: [[V3:%.*]] = load i1, ptr [[PTR]], align 1
775 ; CHECK-NEXT: br i1 [[V3]], label [[LOOP_LATCH]], label [[LOOP_EXIT_LOOPEXIT1:%.*]]
777 ; CHECK-NEXT: br label [[LOOP_BEGIN]]
778 ; CHECK: loop_exit.loopexit:
779 ; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
780 ; CHECK: loop_exit.loopexit1:
781 ; CHECK-NEXT: [[A_INNER_LCSSA_LCSSA:%.*]] = phi i32 [ [[A_INNER_LCSSA]], [[INNER_LOOP_EXIT]] ]
782 ; CHECK-NEXT: br label [[LOOP_EXIT]]
784 ; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_LCSSA2_US]], [[LOOP_EXIT_LOOPEXIT]] ], [ [[A_INNER_LCSSA_LCSSA]], [[LOOP_EXIT_LOOPEXIT1]] ]
785 ; CHECK-NEXT: ret i32 [[A_LCSSA]]
791 %b = load i32, ptr %b.ptr
792 %v1 = load i1, ptr %ptr
793 br i1 %v1, label %loop_latch, label %inner_loop_ph
796 %cond = load i1, ptr %cond.ptr
797 br label %inner_loop_begin
800 call void @sink1(i32 %b)
801 %a = load i32, ptr %a.ptr
802 br i1 %cond, label %loop_exit, label %inner_loop_a
805 %v2 = load i1, ptr %ptr
806 br i1 %v2, label %inner_loop_exit, label %inner_loop_begin
807 ; The cloned path doesn't actually loop and is an exit from the outer loop as
809 ; The original remains a loop losing the exit edge.
812 %a.inner_lcssa = phi i32 [ %a, %inner_loop_a ]
813 %v3 = load i1, ptr %ptr
814 br i1 %v3, label %loop_latch, label %loop_exit
820 %a.lcssa = phi i32 [ %a, %inner_loop_begin ], [ %a.inner_lcssa, %inner_loop_exit ]
824 ; Check that if the original inner loop after unswitching doesn't loop and
825 ; directly exits even an outer loop, we remove the original preheader from the
826 ; outer loop and add needed LCSSA phi nodes for the new exit block from the
828 define i32 @test11b(ptr %ptr, ptr %cond.ptr, ptr %a.ptr, ptr %b.ptr) {
829 ; CHECK-LABEL: @test11b(
831 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
833 ; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[B_PTR:%.*]], align 4
834 ; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR:%.*]], align 1
835 ; CHECK-NEXT: br i1 [[V1]], label [[LOOP_LATCH:%.*]], label [[INNER_LOOP_PH:%.*]]
836 ; CHECK: inner_loop_ph:
837 ; CHECK-NEXT: [[COND:%.*]] = load i1, ptr [[COND_PTR:%.*]], align 1
838 ; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]]
839 ; CHECK-NEXT: br i1 [[COND_FR]], label [[INNER_LOOP_PH_SPLIT_US:%.*]], label [[INNER_LOOP_PH_SPLIT:%.*]]
840 ; CHECK: inner_loop_ph.split.us:
841 ; CHECK-NEXT: br label [[INNER_LOOP_BEGIN_US:%.*]]
842 ; CHECK: inner_loop_begin.us:
843 ; CHECK-NEXT: call void @sink1(i32 [[B]])
844 ; CHECK-NEXT: [[A_US:%.*]] = load i32, ptr [[A_PTR:%.*]], align 4
845 ; CHECK-NEXT: br label [[INNER_LOOP_A_US:%.*]]
846 ; CHECK: inner_loop_a.us:
847 ; CHECK-NEXT: [[V2_US:%.*]] = load i1, ptr [[PTR]], align 1
848 ; CHECK-NEXT: br i1 [[V2_US]], label [[INNER_LOOP_EXIT_SPLIT_US:%.*]], label [[INNER_LOOP_BEGIN_US]]
849 ; CHECK: inner_loop_exit.split.us:
850 ; CHECK-NEXT: [[A_INNER_LCSSA_US:%.*]] = phi i32 [ [[A_US]], [[INNER_LOOP_A_US]] ]
851 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT:%.*]]
852 ; CHECK: inner_loop_ph.split:
853 ; CHECK-NEXT: [[B_LCSSA:%.*]] = phi i32 [ [[B]], [[INNER_LOOP_PH]] ]
854 ; CHECK-NEXT: br label [[INNER_LOOP_BEGIN:%.*]]
855 ; CHECK: inner_loop_begin:
856 ; CHECK-NEXT: call void @sink1(i32 [[B_LCSSA]])
857 ; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR]], align 4
858 ; CHECK-NEXT: br label [[LOOP_EXIT_LOOPEXIT:%.*]]
859 ; CHECK: inner_loop_exit:
860 ; CHECK-NEXT: [[V3:%.*]] = load i1, ptr [[PTR]], align 1
861 ; CHECK-NEXT: br i1 [[V3]], label [[LOOP_LATCH]], label [[LOOP_EXIT_LOOPEXIT1:%.*]]
863 ; CHECK-NEXT: br label [[LOOP_BEGIN]]
864 ; CHECK: loop_exit.loopexit:
865 ; CHECK-NEXT: [[A_LCSSA2:%.*]] = phi i32 [ [[A]], [[INNER_LOOP_BEGIN]] ]
866 ; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
867 ; CHECK: loop_exit.loopexit1:
868 ; CHECK-NEXT: [[A_INNER_LCSSA_LCSSA:%.*]] = phi i32 [ [[A_INNER_LCSSA_US]], [[INNER_LOOP_EXIT]] ]
869 ; CHECK-NEXT: br label [[LOOP_EXIT]]
871 ; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_LCSSA2]], [[LOOP_EXIT_LOOPEXIT]] ], [ [[A_INNER_LCSSA_LCSSA]], [[LOOP_EXIT_LOOPEXIT1]] ]
872 ; CHECK-NEXT: ret i32 [[A_LCSSA]]
878 %b = load i32, ptr %b.ptr
879 %v1 = load i1, ptr %ptr
880 br i1 %v1, label %loop_latch, label %inner_loop_ph
883 %cond = load i1, ptr %cond.ptr
884 br label %inner_loop_begin
887 call void @sink1(i32 %b)
888 %a = load i32, ptr %a.ptr
889 br i1 %cond, label %inner_loop_a, label %loop_exit
892 %v2 = load i1, ptr %ptr
893 br i1 %v2, label %inner_loop_exit, label %inner_loop_begin
894 ; The cloned path continues to loop without the exit out of the entire nest.
895 ; The original remains a loop losing the exit edge.
898 %a.inner_lcssa = phi i32 [ %a, %inner_loop_a ]
899 %v3 = load i1, ptr %ptr
900 br i1 %v3, label %loop_latch, label %loop_exit
906 %a.lcssa = phi i32 [ %a, %inner_loop_begin ], [ %a.inner_lcssa, %inner_loop_exit ]
910 ; Like test11a, but checking that when the whole thing is wrapped in yet
911 ; another loop, we correctly attribute the cloned preheader to that outermost
912 ; loop rather than only handling the case where the preheader is not in any loop
914 define i32 @test12a(ptr %ptr, ptr %cond.ptr, ptr %a.ptr, ptr %b.ptr) {
915 ; CHECK-LABEL: @test12a(
917 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
919 ; CHECK-NEXT: br label [[INNER_LOOP_BEGIN:%.*]]
920 ; CHECK: inner_loop_begin:
921 ; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[B_PTR:%.*]], align 4
922 ; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR:%.*]], align 1
923 ; CHECK-NEXT: br i1 [[V1]], label [[INNER_LOOP_LATCH:%.*]], label [[INNER_INNER_LOOP_PH:%.*]]
924 ; CHECK: inner_inner_loop_ph:
925 ; CHECK-NEXT: [[COND:%.*]] = load i1, ptr [[COND_PTR:%.*]], align 1
926 ; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]]
927 ; CHECK-NEXT: br i1 [[COND_FR]], label [[INNER_INNER_LOOP_PH_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_PH_SPLIT:%.*]]
928 ; CHECK: inner_inner_loop_ph.split.us:
929 ; CHECK-NEXT: [[B_LCSSA:%.*]] = phi i32 [ [[B]], [[INNER_INNER_LOOP_PH]] ]
930 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US:%.*]]
931 ; CHECK: inner_inner_loop_begin.us:
932 ; CHECK-NEXT: call void @sink1(i32 [[B_LCSSA]])
933 ; CHECK-NEXT: [[A_US:%.*]] = load i32, ptr [[A_PTR:%.*]], align 4
934 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT_US:%.*]]
935 ; CHECK: inner_loop_exit.loopexit.split.us:
936 ; CHECK-NEXT: [[A_LCSSA2_US:%.*]] = phi i32 [ [[A_US]], [[INNER_INNER_LOOP_BEGIN_US]] ]
937 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT:%.*]]
938 ; CHECK: inner_inner_loop_ph.split:
939 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN:%.*]]
940 ; CHECK: inner_inner_loop_begin:
941 ; CHECK-NEXT: call void @sink1(i32 [[B]])
942 ; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR]], align 4
943 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_A:%.*]]
944 ; CHECK: inner_inner_loop_a:
945 ; CHECK-NEXT: [[V2:%.*]] = load i1, ptr [[PTR]], align 1
946 ; CHECK-NEXT: br i1 [[V2]], label [[INNER_INNER_LOOP_EXIT:%.*]], label [[INNER_INNER_LOOP_BEGIN]]
947 ; CHECK: inner_inner_loop_exit:
948 ; CHECK-NEXT: [[A_INNER_INNER_LCSSA:%.*]] = phi i32 [ [[A]], [[INNER_INNER_LOOP_A]] ]
949 ; CHECK-NEXT: [[V3:%.*]] = load i1, ptr [[PTR]], align 1
950 ; CHECK-NEXT: br i1 [[V3]], label [[INNER_LOOP_LATCH]], label [[INNER_LOOP_EXIT_LOOPEXIT1:%.*]]
951 ; CHECK: inner_loop_latch:
952 ; CHECK-NEXT: br label [[INNER_LOOP_BEGIN]]
953 ; CHECK: inner_loop_exit.loopexit:
954 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT:%.*]]
955 ; CHECK: inner_loop_exit.loopexit1:
956 ; CHECK-NEXT: [[A_INNER_INNER_LCSSA_LCSSA:%.*]] = phi i32 [ [[A_INNER_INNER_LCSSA]], [[INNER_INNER_LOOP_EXIT]] ]
957 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT]]
958 ; CHECK: inner_loop_exit:
959 ; CHECK-NEXT: [[A_INNER_LCSSA:%.*]] = phi i32 [ [[A_LCSSA2_US]], [[INNER_LOOP_EXIT_LOOPEXIT]] ], [ [[A_INNER_INNER_LCSSA_LCSSA]], [[INNER_LOOP_EXIT_LOOPEXIT1]] ]
960 ; CHECK-NEXT: [[V4:%.*]] = load i1, ptr [[PTR]], align 1
961 ; CHECK-NEXT: br i1 [[V4]], label [[LOOP_BEGIN]], label [[LOOP_EXIT:%.*]]
963 ; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_INNER_LCSSA]], [[INNER_LOOP_EXIT]] ]
964 ; CHECK-NEXT: ret i32 [[A_LCSSA]]
970 br label %inner_loop_begin
973 %b = load i32, ptr %b.ptr
974 %v1 = load i1, ptr %ptr
975 br i1 %v1, label %inner_loop_latch, label %inner_inner_loop_ph
978 %cond = load i1, ptr %cond.ptr
979 br label %inner_inner_loop_begin
981 inner_inner_loop_begin:
982 call void @sink1(i32 %b)
983 %a = load i32, ptr %a.ptr
984 br i1 %cond, label %inner_loop_exit, label %inner_inner_loop_a
987 %v2 = load i1, ptr %ptr
988 br i1 %v2, label %inner_inner_loop_exit, label %inner_inner_loop_begin
989 ; The cloned path doesn't actually loop and is an exit from the outer loop as
991 ; The original remains a loop losing the exit edge.
993 inner_inner_loop_exit:
994 %a.inner_inner_lcssa = phi i32 [ %a, %inner_inner_loop_a ]
995 %v3 = load i1, ptr %ptr
996 br i1 %v3, label %inner_loop_latch, label %inner_loop_exit
999 br label %inner_loop_begin
1002 %a.inner_lcssa = phi i32 [ %a, %inner_inner_loop_begin ], [ %a.inner_inner_lcssa, %inner_inner_loop_exit ]
1003 %v4 = load i1, ptr %ptr
1004 br i1 %v4, label %loop_begin, label %loop_exit
1007 %a.lcssa = phi i32 [ %a.inner_lcssa, %inner_loop_exit ]
1011 ; Like test11b, but checking that when the whole thing is wrapped in yet
1012 ; another loop, we correctly sink the preheader to the outermost loop rather
1013 ; than only handling the case where the preheader is completely removed from
1015 define i32 @test12b(ptr %ptr, ptr %cond.ptr, ptr %a.ptr, ptr %b.ptr) {
1016 ; CHECK-LABEL: @test12b(
1017 ; CHECK-NEXT: entry:
1018 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
1019 ; CHECK: loop_begin:
1020 ; CHECK-NEXT: br label [[INNER_LOOP_BEGIN:%.*]]
1021 ; CHECK: inner_loop_begin:
1022 ; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[B_PTR:%.*]], align 4
1023 ; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR:%.*]], align 1
1024 ; CHECK-NEXT: br i1 [[V1]], label [[INNER_LOOP_LATCH:%.*]], label [[INNER_INNER_LOOP_PH:%.*]]
1025 ; CHECK: inner_inner_loop_ph:
1026 ; CHECK-NEXT: [[COND:%.*]] = load i1, ptr [[COND_PTR:%.*]], align 1
1027 ; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]]
1028 ; CHECK-NEXT: br i1 [[COND_FR]], label [[INNER_INNER_LOOP_PH_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_PH_SPLIT:%.*]]
1029 ; CHECK: inner_inner_loop_ph.split.us:
1030 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US:%.*]]
1031 ; CHECK: inner_inner_loop_begin.us:
1032 ; CHECK-NEXT: call void @sink1(i32 [[B]])
1033 ; CHECK-NEXT: [[A_US:%.*]] = load i32, ptr [[A_PTR:%.*]], align 4
1034 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_A_US:%.*]]
1035 ; CHECK: inner_inner_loop_a.us:
1036 ; CHECK-NEXT: [[V2_US:%.*]] = load i1, ptr [[PTR]], align 1
1037 ; CHECK-NEXT: br i1 [[V2_US]], label [[INNER_INNER_LOOP_EXIT_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_BEGIN_US]]
1038 ; CHECK: inner_inner_loop_exit.split.us:
1039 ; CHECK-NEXT: [[A_INNER_INNER_LCSSA_US:%.*]] = phi i32 [ [[A_US]], [[INNER_INNER_LOOP_A_US]] ]
1040 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_EXIT:%.*]]
1041 ; CHECK: inner_inner_loop_ph.split:
1042 ; CHECK-NEXT: [[B_LCSSA:%.*]] = phi i32 [ [[B]], [[INNER_INNER_LOOP_PH]] ]
1043 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN:%.*]]
1044 ; CHECK: inner_inner_loop_begin:
1045 ; CHECK-NEXT: call void @sink1(i32 [[B_LCSSA]])
1046 ; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR]], align 4
1047 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT:%.*]]
1048 ; CHECK: inner_inner_loop_exit:
1049 ; CHECK-NEXT: [[V3:%.*]] = load i1, ptr [[PTR]], align 1
1050 ; CHECK-NEXT: br i1 [[V3]], label [[INNER_LOOP_LATCH]], label [[INNER_LOOP_EXIT_LOOPEXIT1:%.*]]
1051 ; CHECK: inner_loop_latch:
1052 ; CHECK-NEXT: br label [[INNER_LOOP_BEGIN]]
1053 ; CHECK: inner_loop_exit.loopexit:
1054 ; CHECK-NEXT: [[A_LCSSA2:%.*]] = phi i32 [ [[A]], [[INNER_INNER_LOOP_BEGIN]] ]
1055 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT:%.*]]
1056 ; CHECK: inner_loop_exit.loopexit1:
1057 ; CHECK-NEXT: [[A_INNER_INNER_LCSSA_LCSSA:%.*]] = phi i32 [ [[A_INNER_INNER_LCSSA_US]], [[INNER_INNER_LOOP_EXIT]] ]
1058 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT]]
1059 ; CHECK: inner_loop_exit:
1060 ; CHECK-NEXT: [[A_INNER_LCSSA:%.*]] = phi i32 [ [[A_LCSSA2]], [[INNER_LOOP_EXIT_LOOPEXIT]] ], [ [[A_INNER_INNER_LCSSA_LCSSA]], [[INNER_LOOP_EXIT_LOOPEXIT1]] ]
1061 ; CHECK-NEXT: [[V4:%.*]] = load i1, ptr [[PTR]], align 1
1062 ; CHECK-NEXT: br i1 [[V4]], label [[LOOP_BEGIN]], label [[LOOP_EXIT:%.*]]
1064 ; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_INNER_LCSSA]], [[INNER_LOOP_EXIT]] ]
1065 ; CHECK-NEXT: ret i32 [[A_LCSSA]]
1068 br label %loop_begin
1071 br label %inner_loop_begin
1074 %b = load i32, ptr %b.ptr
1075 %v1 = load i1, ptr %ptr
1076 br i1 %v1, label %inner_loop_latch, label %inner_inner_loop_ph
1078 inner_inner_loop_ph:
1079 %cond = load i1, ptr %cond.ptr
1080 br label %inner_inner_loop_begin
1082 inner_inner_loop_begin:
1083 call void @sink1(i32 %b)
1084 %a = load i32, ptr %a.ptr
1085 br i1 %cond, label %inner_inner_loop_a, label %inner_loop_exit
1088 %v2 = load i1, ptr %ptr
1089 br i1 %v2, label %inner_inner_loop_exit, label %inner_inner_loop_begin
1090 ; The cloned path continues to loop without the exit out of the entire nest.
1091 ; The original remains a loop losing the exit edge.
1093 inner_inner_loop_exit:
1094 %a.inner_inner_lcssa = phi i32 [ %a, %inner_inner_loop_a ]
1095 %v3 = load i1, ptr %ptr
1096 br i1 %v3, label %inner_loop_latch, label %inner_loop_exit
1099 br label %inner_loop_begin
1102 %a.inner_lcssa = phi i32 [ %a, %inner_inner_loop_begin ], [ %a.inner_inner_lcssa, %inner_inner_loop_exit ]
1103 %v4 = load i1, ptr %ptr
1104 br i1 %v4, label %loop_begin, label %loop_exit
1107 %a.lcssa = phi i32 [ %a.inner_lcssa, %inner_loop_exit ]
1111 ; Test where the cloned loop has an inner loop that has to be traversed to form
1112 ; the cloned loop, and where this inner loop has multiple blocks, and where the
1113 ; exiting block that connects the inner loop to the cloned loop is not the header
1114 ; block. This ensures that we correctly handle interesting corner cases of
1115 ; traversing back to the header when establishing the cloned loop.
1116 define i32 @test13a(ptr %ptr, i1 %cond, ptr %a.ptr, ptr %b.ptr) {
1117 ; CHECK-LABEL: @test13a(
1118 ; CHECK-NEXT: entry:
1119 ; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND:%.*]]
1120 ; CHECK-NEXT: br i1 [[COND_FR]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
1121 ; CHECK: entry.split.us:
1122 ; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]]
1123 ; CHECK: loop_begin.us:
1124 ; CHECK-NEXT: [[A_US:%.*]] = load i32, ptr [[A_PTR:%.*]], align 4
1125 ; CHECK-NEXT: [[V1_US:%.*]] = load i1, ptr [[PTR:%.*]], align 1
1126 ; CHECK-NEXT: br i1 [[V1_US]], label [[LOOP_A_US:%.*]], label [[LOOP_B_US:%.*]]
1128 ; CHECK-NEXT: [[B_US:%.*]] = load i32, ptr [[B_PTR:%.*]], align 4
1129 ; CHECK-NEXT: br label [[LOOP_B_INNER_PH_US:%.*]]
1130 ; CHECK: loop_b_inner_ph.us:
1131 ; CHECK-NEXT: br label [[LOOP_B_INNER_HEADER_US:%.*]]
1132 ; CHECK: loop_b_inner_header.us:
1133 ; CHECK-NEXT: [[V3_US:%.*]] = load i1, ptr [[PTR]], align 1
1134 ; CHECK-NEXT: br i1 [[V3_US]], label [[LOOP_B_INNER_LATCH_US:%.*]], label [[LOOP_B_INNER_BODY_US:%.*]]
1135 ; CHECK: loop_b_inner_body.us:
1136 ; CHECK-NEXT: [[V4_US:%.*]] = load i1, ptr [[PTR]], align 1
1137 ; CHECK-NEXT: br i1 [[V4_US]], label [[LOOP_B_INNER_LATCH_US]], label [[LOOP_B_INNER_EXIT_US:%.*]]
1138 ; CHECK: loop_b_inner_exit.us:
1139 ; CHECK-NEXT: br label [[LOOP_LATCH_US:%.*]]
1140 ; CHECK: loop_b_inner_latch.us:
1141 ; CHECK-NEXT: br label [[LOOP_B_INNER_HEADER_US]]
1143 ; CHECK-NEXT: [[V2_US:%.*]] = load i1, ptr [[PTR]], align 1
1144 ; CHECK-NEXT: br i1 [[V2_US]], label [[LOOP_EXIT_SPLIT_US:%.*]], label [[LOOP_LATCH_US]]
1145 ; CHECK: loop_latch.us:
1146 ; CHECK-NEXT: br label [[LOOP_BEGIN_US]]
1147 ; CHECK: loop_exit.split.us:
1148 ; CHECK-NEXT: [[LCSSA_US:%.*]] = phi i32 [ [[A_US]], [[LOOP_A_US]] ]
1149 ; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
1150 ; CHECK: entry.split:
1151 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
1152 ; CHECK: loop_begin:
1153 ; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR]], align 4
1154 ; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR]], align 1
1155 ; CHECK-NEXT: br i1 [[V1]], label [[LOOP_A:%.*]], label [[LOOP_B:%.*]]
1157 ; CHECK-NEXT: [[V2:%.*]] = load i1, ptr [[PTR]], align 1
1158 ; CHECK-NEXT: br i1 [[V2]], label [[LOOP_EXIT_SPLIT_LOOPEXIT:%.*]], label [[LOOP_LATCH:%.*]]
1160 ; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[B_PTR]], align 4
1161 ; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT:%.*]]
1162 ; CHECK: loop_latch:
1163 ; CHECK-NEXT: br label [[LOOP_BEGIN]]
1164 ; CHECK: loop_exit.split.loopexit:
1165 ; CHECK-NEXT: [[LCSSA_PH:%.*]] = phi i32 [ [[A]], [[LOOP_A]] ]
1166 ; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT]]
1167 ; CHECK: loop_exit.split:
1168 ; CHECK-NEXT: [[LCSSA:%.*]] = phi i32 [ [[B]], [[LOOP_B]] ], [ [[LCSSA_PH]], [[LOOP_EXIT_SPLIT_LOOPEXIT]] ]
1169 ; CHECK-NEXT: br label [[LOOP_EXIT]]
1171 ; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[LCSSA]], [[LOOP_EXIT_SPLIT]] ], [ [[LCSSA_US]], [[LOOP_EXIT_SPLIT_US]] ]
1172 ; CHECK-NEXT: ret i32 [[DOTUS_PHI]]
1175 br label %loop_begin
1178 %a = load i32, ptr %a.ptr
1179 %v1 = load i1, ptr %ptr
1180 br i1 %v1, label %loop_a, label %loop_b
1183 %v2 = load i1, ptr %ptr
1184 br i1 %v2, label %loop_exit, label %loop_latch
1187 %b = load i32, ptr %b.ptr
1188 br i1 %cond, label %loop_b_inner_ph, label %loop_exit
1191 br label %loop_b_inner_header
1193 loop_b_inner_header:
1194 %v3 = load i1, ptr %ptr
1195 br i1 %v3, label %loop_b_inner_latch, label %loop_b_inner_body
1198 %v4 = load i1, ptr %ptr
1199 br i1 %v4, label %loop_b_inner_latch, label %loop_b_inner_exit
1202 br label %loop_b_inner_header
1205 br label %loop_latch
1208 br label %loop_begin
1209 ; The cloned loop contains an inner loop within it.
1210 ; And the original loop no longer contains an inner loop.
1213 %lcssa = phi i32 [ %a, %loop_a ], [ %b, %loop_b ]
1217 ; Test where the original loop has an inner loop that has to be traversed to
1218 ; rebuild the loop, and where this inner loop has multiple blocks, and where
1219 ; the exiting block that connects the inner loop to the original loop is not
1220 ; the header block. This ensures that we correctly handle interesting corner
1221 ; cases of traversing back to the header when re-establishing the original loop
1222 ; still exists after unswitching.
1223 define i32 @test13b(ptr %ptr, i1 %cond, ptr %a.ptr, ptr %b.ptr) {
1224 ; CHECK-LABEL: @test13b(
1225 ; CHECK-NEXT: entry:
1226 ; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND:%.*]]
1227 ; CHECK-NEXT: br i1 [[COND_FR]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
1228 ; CHECK: entry.split.us:
1229 ; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]]
1230 ; CHECK: loop_begin.us:
1231 ; CHECK-NEXT: [[A_US:%.*]] = load i32, ptr [[A_PTR:%.*]], align 4
1232 ; CHECK-NEXT: [[V1_US:%.*]] = load i1, ptr [[PTR:%.*]], align 1
1233 ; CHECK-NEXT: br i1 [[V1_US]], label [[LOOP_A_US:%.*]], label [[LOOP_B_US:%.*]]
1235 ; CHECK-NEXT: [[B_US:%.*]] = load i32, ptr [[B_PTR:%.*]], align 4
1236 ; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT_US:%.*]]
1238 ; CHECK-NEXT: [[V2_US:%.*]] = load i1, ptr [[PTR]], align 1
1239 ; CHECK-NEXT: br i1 [[V2_US]], label [[LOOP_EXIT_SPLIT_US_LOOPEXIT:%.*]], label [[LOOP_LATCH_US:%.*]]
1240 ; CHECK: loop_latch.us:
1241 ; CHECK-NEXT: br label [[LOOP_BEGIN_US]]
1242 ; CHECK: loop_exit.split.us.loopexit:
1243 ; CHECK-NEXT: [[LCSSA_US_PH:%.*]] = phi i32 [ [[A_US]], [[LOOP_A_US]] ]
1244 ; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT_US]]
1245 ; CHECK: loop_exit.split.us:
1246 ; CHECK-NEXT: [[LCSSA_US:%.*]] = phi i32 [ [[B_US]], [[LOOP_B_US]] ], [ [[LCSSA_US_PH]], [[LOOP_EXIT_SPLIT_US_LOOPEXIT]] ]
1247 ; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
1248 ; CHECK: entry.split:
1249 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
1250 ; CHECK: loop_begin:
1251 ; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR]], align 4
1252 ; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR]], align 1
1253 ; CHECK-NEXT: br i1 [[V1]], label [[LOOP_A:%.*]], label [[LOOP_B:%.*]]
1255 ; CHECK-NEXT: [[V2:%.*]] = load i1, ptr [[PTR]], align 1
1256 ; CHECK-NEXT: br i1 [[V2]], label [[LOOP_EXIT_SPLIT:%.*]], label [[LOOP_LATCH:%.*]]
1258 ; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[B_PTR]], align 4
1259 ; CHECK-NEXT: br label [[LOOP_B_INNER_PH:%.*]]
1260 ; CHECK: loop_b_inner_ph:
1261 ; CHECK-NEXT: br label [[LOOP_B_INNER_HEADER:%.*]]
1262 ; CHECK: loop_b_inner_header:
1263 ; CHECK-NEXT: [[V3:%.*]] = load i1, ptr [[PTR]], align 1
1264 ; CHECK-NEXT: br i1 [[V3]], label [[LOOP_B_INNER_LATCH:%.*]], label [[LOOP_B_INNER_BODY:%.*]]
1265 ; CHECK: loop_b_inner_body:
1266 ; CHECK-NEXT: [[V4:%.*]] = load i1, ptr [[PTR]], align 1
1267 ; CHECK-NEXT: br i1 [[V4]], label [[LOOP_B_INNER_LATCH]], label [[LOOP_B_INNER_EXIT:%.*]]
1268 ; CHECK: loop_b_inner_latch:
1269 ; CHECK-NEXT: br label [[LOOP_B_INNER_HEADER]]
1270 ; CHECK: loop_b_inner_exit:
1271 ; CHECK-NEXT: br label [[LOOP_LATCH]]
1272 ; CHECK: loop_latch:
1273 ; CHECK-NEXT: br label [[LOOP_BEGIN]]
1274 ; CHECK: loop_exit.split:
1275 ; CHECK-NEXT: [[LCSSA:%.*]] = phi i32 [ [[A]], [[LOOP_A]] ]
1276 ; CHECK-NEXT: br label [[LOOP_EXIT]]
1278 ; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[LCSSA]], [[LOOP_EXIT_SPLIT]] ], [ [[LCSSA_US]], [[LOOP_EXIT_SPLIT_US]] ]
1279 ; CHECK-NEXT: ret i32 [[DOTUS_PHI]]
1282 br label %loop_begin
1285 %a = load i32, ptr %a.ptr
1286 %v1 = load i1, ptr %ptr
1287 br i1 %v1, label %loop_a, label %loop_b
1290 %v2 = load i1, ptr %ptr
1291 br i1 %v2, label %loop_exit, label %loop_latch
1294 %b = load i32, ptr %b.ptr
1295 br i1 %cond, label %loop_exit, label %loop_b_inner_ph
1298 br label %loop_b_inner_header
1300 loop_b_inner_header:
1301 %v3 = load i1, ptr %ptr
1302 br i1 %v3, label %loop_b_inner_latch, label %loop_b_inner_body
1305 %v4 = load i1, ptr %ptr
1306 br i1 %v4, label %loop_b_inner_latch, label %loop_b_inner_exit
1309 br label %loop_b_inner_header
1312 br label %loop_latch
1315 br label %loop_begin
1316 ; The cloned loop doesn't contain an inner loop.
1317 ; But the original loop contains an inner loop that must be traversed.;
1320 %lcssa = phi i32 [ %a, %loop_a ], [ %b, %loop_b ]
1324 ; A test reduced out of 400.perlbench that when unswitching the `%stop`
1325 ; condition clones a loop nest outside of a containing loop. This excercises a
1326 ; different cloning path from our other test cases and in turn verifying the
1327 ; resulting structure can catch any failures to correctly clone these nested
1331 declare i32 @h(i32 %arg)
1333 ; Test that when we are unswitching and need to rebuild the loop block set we
1334 ; correctly skip past inner loops. We want to use the inner loop to efficiently
1335 ; skip whole subregions of the outer loop blocks but just because the header of
1336 ; the outer loop is also the preheader of an inner loop shouldn't confuse this
1338 define void @test23(i1 %arg, ptr %ptr) {
1339 ; CHECK-LABEL: @test23(
1340 ; CHECK-NEXT: entry:
1341 ; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i1 [[ARG:%.*]]
1342 ; CHECK-NEXT: br i1 [[ARG_FR]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
1343 ; CHECK: entry.split.us:
1344 ; CHECK-NEXT: br label [[OUTER_HEADER_US:%.*]]
1345 ; CHECK: outer.header.us:
1346 ; CHECK-NEXT: br label [[INNER_HEADER_US:%.*]]
1347 ; CHECK: inner.header.us:
1348 ; CHECK-NEXT: call void @f()
1349 ; CHECK-NEXT: br label [[INNER_LATCH_US:%.*]]
1350 ; CHECK: inner.latch.us:
1351 ; CHECK-NEXT: [[INNER_COND_US:%.*]] = load i1, ptr [[PTR:%.*]], align 1
1352 ; CHECK-NEXT: br i1 [[INNER_COND_US]], label [[INNER_HEADER_US]], label [[OUTER_BODY_US:%.*]]
1353 ; CHECK: outer.body.us:
1354 ; CHECK-NEXT: br label [[OUTER_BODY_LEFT_US:%.*]]
1355 ; CHECK: outer.body.left.us:
1356 ; CHECK-NEXT: call void @f()
1357 ; CHECK-NEXT: br label [[OUTER_LATCH_US:%.*]]
1358 ; CHECK: outer.latch.us:
1359 ; CHECK-NEXT: [[OUTER_COND_US:%.*]] = load i1, ptr [[PTR]], align 1
1360 ; CHECK-NEXT: br i1 [[OUTER_COND_US]], label [[OUTER_HEADER_US]], label [[EXIT_SPLIT_US:%.*]]
1361 ; CHECK: exit.split.us:
1362 ; CHECK-NEXT: br label [[EXIT:%.*]]
1363 ; CHECK: entry.split:
1364 ; CHECK-NEXT: br label [[OUTER_HEADER:%.*]]
1365 ; CHECK: outer.header:
1366 ; CHECK-NEXT: br label [[INNER_HEADER:%.*]]
1367 ; CHECK: inner.header:
1368 ; CHECK-NEXT: call void @f()
1369 ; CHECK-NEXT: br label [[INNER_LATCH:%.*]]
1370 ; CHECK: inner.latch:
1371 ; CHECK-NEXT: [[INNER_COND:%.*]] = load i1, ptr [[PTR]], align 1
1372 ; CHECK-NEXT: br i1 [[INNER_COND]], label [[INNER_HEADER]], label [[OUTER_BODY:%.*]]
1373 ; CHECK: outer.body:
1374 ; CHECK-NEXT: br label [[OUTER_BODY_RIGHT:%.*]]
1375 ; CHECK: outer.body.right:
1376 ; CHECK-NEXT: call void @g()
1377 ; CHECK-NEXT: br label [[OUTER_LATCH:%.*]]
1378 ; CHECK: outer.latch:
1379 ; CHECK-NEXT: [[OUTER_COND:%.*]] = load i1, ptr [[PTR]], align 1
1380 ; CHECK-NEXT: br i1 [[OUTER_COND]], label [[OUTER_HEADER]], label [[EXIT_SPLIT:%.*]]
1381 ; CHECK: exit.split:
1382 ; CHECK-NEXT: br label [[EXIT]]
1384 ; CHECK-NEXT: ret void
1387 br label %outer.header
1388 ; Just verify that we unswitched the correct bits. We should call `@f` twice in
1389 ; one unswitch and `@f` and then `@g` in the other.
1392 br label %inner.header
1396 br label %inner.latch
1399 %inner.cond = load i1, ptr %ptr
1400 br i1 %inner.cond, label %inner.header, label %outer.body
1403 br i1 %arg, label %outer.body.left, label %outer.body.right
1407 br label %outer.latch
1411 br label %outer.latch
1414 %outer.cond = load i1, ptr %ptr
1415 br i1 %outer.cond, label %outer.header, label %exit
1421 ; A test case designed to exercise unusual properties of switches: they
1422 ; can introduce multiple edges to successors. These need lots of special case
1423 ; handling as they get collapsed in many cases (domtree, the unswitch itself)
1424 ; but not in all cases (the PHI node operands).
1425 define i32 @test29(i32 %arg) {
1426 ; CHECK-LABEL: @test29(
1427 ; CHECK-NEXT: entry:
1428 ; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i32 [[ARG:%.*]]
1429 ; CHECK-NEXT: switch i32 [[ARG_FR]], label [[ENTRY_SPLIT:%.*]] [
1430 ; CHECK-NEXT: i32 0, label [[ENTRY_SPLIT_US:%.*]]
1431 ; CHECK-NEXT: i32 1, label [[ENTRY_SPLIT_US]]
1432 ; CHECK-NEXT: i32 2, label [[ENTRY_SPLIT_US1:%.*]]
1433 ; CHECK-NEXT: i32 3, label [[ENTRY_SPLIT]]
1435 ; CHECK: entry.split.us:
1436 ; CHECK-NEXT: br label [[HEADER_US:%.*]]
1438 ; CHECK-NEXT: [[TMP_US:%.*]] = call i32 @d()
1439 ; CHECK-NEXT: [[CMP1_US:%.*]] = icmp eq i32 [[TMP_US]], 0
1440 ; CHECK-NEXT: br i1 [[CMP1_US]], label [[BODY_A_US:%.*]], label [[DISPATCH_US:%.*]]
1441 ; CHECK: dispatch.us:
1442 ; CHECK-NEXT: br label [[BODY_A_US]]
1444 ; CHECK-NEXT: [[TMP_A_PHI_US:%.*]] = phi i32 [ 0, [[HEADER_US]] ], [ [[TMP_US]], [[DISPATCH_US]] ]
1445 ; CHECK-NEXT: [[TMP_A_US:%.*]] = call i32 @a()
1446 ; CHECK-NEXT: [[TMP_A_SUM_US:%.*]] = add i32 [[TMP_A_PHI_US]], [[TMP_A_US]]
1447 ; CHECK-NEXT: br label [[BODY_B_US:%.*]]
1449 ; CHECK-NEXT: [[TMP_B_PHI_US:%.*]] = phi i32 [ [[TMP_A_SUM_US]], [[BODY_A_US]] ]
1450 ; CHECK-NEXT: [[TMP_B_US:%.*]] = call i32 @b()
1451 ; CHECK-NEXT: [[TMP_B_SUM_US:%.*]] = add i32 [[TMP_B_PHI_US]], [[TMP_B_US]]
1452 ; CHECK-NEXT: br label [[BODY_C_US:%.*]]
1454 ; CHECK-NEXT: [[TMP_C_PHI_US:%.*]] = phi i32 [ [[TMP_B_SUM_US]], [[BODY_B_US]] ]
1455 ; CHECK-NEXT: [[TMP_C_US:%.*]] = call i32 @c()
1456 ; CHECK-NEXT: [[TMP_C_SUM_US:%.*]] = add i32 [[TMP_C_PHI_US]], [[TMP_C_US]]
1457 ; CHECK-NEXT: br label [[LATCH_US:%.*]]
1459 ; CHECK-NEXT: [[CMP2_US:%.*]] = icmp slt i32 [[TMP_C_SUM_US]], 42
1460 ; CHECK-NEXT: br i1 [[CMP2_US]], label [[HEADER_US]], label [[EXIT_SPLIT_US:%.*]]
1461 ; CHECK: exit.split.us:
1462 ; CHECK-NEXT: [[LCSSA_PHI_US:%.*]] = phi i32 [ [[TMP_C_SUM_US]], [[LATCH_US]] ]
1463 ; CHECK-NEXT: br label [[EXIT:%.*]]
1464 ; CHECK: entry.split.us1:
1465 ; CHECK-NEXT: br label [[HEADER_US2:%.*]]
1466 ; CHECK: header.us2:
1467 ; CHECK-NEXT: [[TMP_US3:%.*]] = call i32 @d()
1468 ; CHECK-NEXT: [[CMP1_US4:%.*]] = icmp eq i32 [[TMP_US3]], 0
1469 ; CHECK-NEXT: br i1 [[CMP1_US4]], label [[BODY_A_US6:%.*]], label [[DISPATCH_US5:%.*]]
1470 ; CHECK: dispatch.us5:
1471 ; CHECK-NEXT: br label [[BODY_B_US10:%.*]]
1472 ; CHECK: body.a.us6:
1473 ; CHECK-NEXT: [[TMP_A_PHI_US7:%.*]] = phi i32 [ 0, [[HEADER_US2]] ]
1474 ; CHECK-NEXT: [[TMP_A_US8:%.*]] = call i32 @a()
1475 ; CHECK-NEXT: [[TMP_A_SUM_US9:%.*]] = add i32 [[TMP_A_PHI_US7]], [[TMP_A_US8]]
1476 ; CHECK-NEXT: br label [[BODY_B_US10]]
1477 ; CHECK: body.b.us10:
1478 ; CHECK-NEXT: [[TMP_B_PHI_US11:%.*]] = phi i32 [ [[TMP_US3]], [[DISPATCH_US5]] ], [ [[TMP_A_SUM_US9]], [[BODY_A_US6]] ]
1479 ; CHECK-NEXT: [[TMP_B_US12:%.*]] = call i32 @b()
1480 ; CHECK-NEXT: [[TMP_B_SUM_US13:%.*]] = add i32 [[TMP_B_PHI_US11]], [[TMP_B_US12]]
1481 ; CHECK-NEXT: br label [[BODY_C_US14:%.*]]
1482 ; CHECK: body.c.us14:
1483 ; CHECK-NEXT: [[TMP_C_PHI_US15:%.*]] = phi i32 [ [[TMP_B_SUM_US13]], [[BODY_B_US10]] ]
1484 ; CHECK-NEXT: [[TMP_C_US16:%.*]] = call i32 @c()
1485 ; CHECK-NEXT: [[TMP_C_SUM_US17:%.*]] = add i32 [[TMP_C_PHI_US15]], [[TMP_C_US16]]
1486 ; CHECK-NEXT: br label [[LATCH_US18:%.*]]
1487 ; CHECK: latch.us18:
1488 ; CHECK-NEXT: [[CMP2_US19:%.*]] = icmp slt i32 [[TMP_C_SUM_US17]], 42
1489 ; CHECK-NEXT: br i1 [[CMP2_US19]], label [[HEADER_US2]], label [[EXIT_SPLIT_SPLIT_US:%.*]]
1490 ; CHECK: exit.split.split.us:
1491 ; CHECK-NEXT: [[LCSSA_PHI_US20:%.*]] = phi i32 [ [[TMP_C_SUM_US17]], [[LATCH_US18]] ]
1492 ; CHECK-NEXT: br label [[EXIT_SPLIT:%.*]]
1493 ; CHECK: entry.split:
1494 ; CHECK-NEXT: br label [[HEADER:%.*]]
1496 ; CHECK-NEXT: [[TMP:%.*]] = call i32 @d()
1497 ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[TMP]], 0
1498 ; CHECK-NEXT: br i1 [[CMP1]], label [[BODY_A:%.*]], label [[DISPATCH:%.*]]
1500 ; CHECK-NEXT: br label [[BODY_C:%.*]]
1502 ; CHECK-NEXT: [[TMP_A_PHI:%.*]] = phi i32 [ 0, [[HEADER]] ]
1503 ; CHECK-NEXT: [[TMP_A:%.*]] = call i32 @a()
1504 ; CHECK-NEXT: [[TMP_A_SUM:%.*]] = add i32 [[TMP_A_PHI]], [[TMP_A]]
1505 ; CHECK-NEXT: br label [[BODY_B:%.*]]
1507 ; CHECK-NEXT: [[TMP_B_PHI:%.*]] = phi i32 [ [[TMP_A_SUM]], [[BODY_A]] ]
1508 ; CHECK-NEXT: [[TMP_B:%.*]] = call i32 @b()
1509 ; CHECK-NEXT: [[TMP_B_SUM:%.*]] = add i32 [[TMP_B_PHI]], [[TMP_B]]
1510 ; CHECK-NEXT: br label [[BODY_C]]
1512 ; CHECK-NEXT: [[TMP_C_PHI:%.*]] = phi i32 [ [[TMP]], [[DISPATCH]] ], [ [[TMP_B_SUM]], [[BODY_B]] ]
1513 ; CHECK-NEXT: [[TMP_C:%.*]] = call i32 @c()
1514 ; CHECK-NEXT: [[TMP_C_SUM:%.*]] = add i32 [[TMP_C_PHI]], [[TMP_C]]
1515 ; CHECK-NEXT: br label [[LATCH:%.*]]
1517 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[TMP_C_SUM]], 42
1518 ; CHECK-NEXT: br i1 [[CMP2]], label [[HEADER]], label [[EXIT_SPLIT_SPLIT:%.*]]
1519 ; CHECK: exit.split.split:
1520 ; CHECK-NEXT: [[LCSSA_PHI:%.*]] = phi i32 [ [[TMP_C_SUM]], [[LATCH]] ]
1521 ; CHECK-NEXT: br label [[EXIT_SPLIT]]
1522 ; CHECK: exit.split:
1523 ; CHECK-NEXT: [[DOTUS_PHI21:%.*]] = phi i32 [ [[LCSSA_PHI]], [[EXIT_SPLIT_SPLIT]] ], [ [[LCSSA_PHI_US20]], [[EXIT_SPLIT_SPLIT_US]] ]
1524 ; CHECK-NEXT: br label [[EXIT]]
1526 ; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[DOTUS_PHI21]], [[EXIT_SPLIT]] ], [ [[LCSSA_PHI_US]], [[EXIT_SPLIT_US]] ]
1527 ; CHECK-NEXT: ret i32 [[DOTUS_PHI]]
1533 %tmp = call i32 @d()
1534 %cmp1 = icmp eq i32 %tmp, 0
1535 ; We set up a chain through all the successors of the switch that doesn't
1536 ; involve the switch so that we can have interesting PHI nodes in them.
1537 br i1 %cmp1, label %body.a, label %dispatch
1540 ; Switch with multiple successors. We arrange the last successor to be the
1541 ; default to make the test case easier to read. This has a duplicate edge
1542 ; both to the default destination (which is completely superfluous but
1543 ; technically valid IR) and to a regular successor.
1544 switch i32 %arg, label %body.c [
1545 i32 0, label %body.a
1546 i32 1, label %body.a
1547 i32 2, label %body.b
1548 i32 3, label %body.c
1552 %tmp.a.phi = phi i32 [ 0, %header ], [ %tmp, %dispatch ], [ %tmp, %dispatch ]
1553 %tmp.a = call i32 @a()
1554 %tmp.a.sum = add i32 %tmp.a.phi, %tmp.a
1556 ; Unswitched 'a' loop.
1559 %tmp.b.phi = phi i32 [ %tmp, %dispatch ], [ %tmp.a.sum, %body.a ]
1560 %tmp.b = call i32 @b()
1561 %tmp.b.sum = add i32 %tmp.b.phi, %tmp.b
1563 ; Unswitched 'b' loop.
1566 %tmp.c.phi = phi i32 [ %tmp, %dispatch ], [ %tmp, %dispatch ], [ %tmp.b.sum, %body.b ]
1567 %tmp.c = call i32 @c()
1568 %tmp.c.sum = add i32 %tmp.c.phi, %tmp.c
1570 ; Unswitched 'c' loop.
1573 %cmp2 = icmp slt i32 %tmp.c.sum, 42
1574 br i1 %cmp2, label %header, label %exit
1577 %lcssa.phi = phi i32 [ %tmp.c.sum, %latch ]
1582 ; Similar to @test29 but designed to have one of the duplicate edges be
1583 ; a loop exit edge as those can in some cases be special. Among other things,
1584 ; this includes an LCSSA phi with multiple entries despite being a dedicated
1586 define i32 @test30(i32 %arg) {
1587 ; CHECK-LABEL: @test30(
1588 ; CHECK-NEXT: entry:
1589 ; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i32 [[ARG:%.*]]
1590 ; CHECK-NEXT: switch i32 [[ARG_FR]], label [[ENTRY_SPLIT:%.*]] [
1591 ; CHECK-NEXT: i32 -1, label [[ENTRY_SPLIT]]
1592 ; CHECK-NEXT: i32 0, label [[ENTRY_SPLIT_US:%.*]]
1593 ; CHECK-NEXT: i32 1, label [[ENTRY_SPLIT_US1:%.*]]
1594 ; CHECK-NEXT: i32 2, label [[ENTRY_SPLIT_US1]]
1596 ; CHECK: entry.split.us:
1597 ; CHECK-NEXT: br label [[HEADER_US:%.*]]
1599 ; CHECK-NEXT: [[TMP_US:%.*]] = call i32 @d()
1600 ; CHECK-NEXT: [[CMP1_US:%.*]] = icmp eq i32 [[TMP_US]], 0
1601 ; CHECK-NEXT: br i1 [[CMP1_US]], label [[BODY_A_US:%.*]], label [[DISPATCH_US:%.*]]
1602 ; CHECK: dispatch.us:
1603 ; CHECK-NEXT: br label [[BODY_A_US]]
1605 ; CHECK-NEXT: [[TMP_A_PHI_US:%.*]] = phi i32 [ 0, [[HEADER_US]] ], [ [[TMP_US]], [[DISPATCH_US]] ]
1606 ; CHECK-NEXT: [[TMP_A_US:%.*]] = call i32 @a()
1607 ; CHECK-NEXT: [[TMP_A_SUM_US:%.*]] = add i32 [[TMP_A_PHI_US]], [[TMP_A_US]]
1608 ; CHECK-NEXT: br label [[BODY_B_US:%.*]]
1610 ; CHECK-NEXT: [[TMP_B_PHI_US:%.*]] = phi i32 [ [[TMP_A_SUM_US]], [[BODY_A_US]] ]
1611 ; CHECK-NEXT: [[TMP_B_US:%.*]] = call i32 @b()
1612 ; CHECK-NEXT: [[TMP_B_SUM_US:%.*]] = add i32 [[TMP_B_PHI_US]], [[TMP_B_US]]
1613 ; CHECK-NEXT: br label [[LATCH_US:%.*]]
1615 ; CHECK-NEXT: [[CMP2_US:%.*]] = icmp slt i32 [[TMP_B_SUM_US]], 42
1616 ; CHECK-NEXT: br i1 [[CMP2_US]], label [[HEADER_US]], label [[LOOP_EXIT2_SPLIT_US:%.*]]
1617 ; CHECK: loop.exit2.split.us:
1618 ; CHECK-NEXT: [[L2_PHI_US:%.*]] = phi i32 [ [[TMP_B_SUM_US]], [[LATCH_US]] ]
1619 ; CHECK-NEXT: br label [[LOOP_EXIT2:%.*]]
1620 ; CHECK: entry.split.us1:
1621 ; CHECK-NEXT: br label [[HEADER_US2:%.*]]
1622 ; CHECK: header.us2:
1623 ; CHECK-NEXT: [[TMP_US3:%.*]] = call i32 @d()
1624 ; CHECK-NEXT: [[CMP1_US4:%.*]] = icmp eq i32 [[TMP_US3]], 0
1625 ; CHECK-NEXT: br i1 [[CMP1_US4]], label [[BODY_A_US6:%.*]], label [[DISPATCH_US5:%.*]]
1626 ; CHECK: dispatch.us5:
1627 ; CHECK-NEXT: br label [[BODY_B_US10:%.*]]
1628 ; CHECK: body.a.us6:
1629 ; CHECK-NEXT: [[TMP_A_PHI_US7:%.*]] = phi i32 [ 0, [[HEADER_US2]] ]
1630 ; CHECK-NEXT: [[TMP_A_US8:%.*]] = call i32 @a()
1631 ; CHECK-NEXT: [[TMP_A_SUM_US9:%.*]] = add i32 [[TMP_A_PHI_US7]], [[TMP_A_US8]]
1632 ; CHECK-NEXT: br label [[BODY_B_US10]]
1633 ; CHECK: body.b.us10:
1634 ; CHECK-NEXT: [[TMP_B_PHI_US11:%.*]] = phi i32 [ [[TMP_US3]], [[DISPATCH_US5]] ], [ [[TMP_A_SUM_US9]], [[BODY_A_US6]] ]
1635 ; CHECK-NEXT: [[TMP_B_US12:%.*]] = call i32 @b()
1636 ; CHECK-NEXT: [[TMP_B_SUM_US13:%.*]] = add i32 [[TMP_B_PHI_US11]], [[TMP_B_US12]]
1637 ; CHECK-NEXT: br label [[LATCH_US14:%.*]]
1638 ; CHECK: latch.us14:
1639 ; CHECK-NEXT: [[CMP2_US15:%.*]] = icmp slt i32 [[TMP_B_SUM_US13]], 42
1640 ; CHECK-NEXT: br i1 [[CMP2_US15]], label [[HEADER_US2]], label [[LOOP_EXIT2_SPLIT_SPLIT_US:%.*]]
1641 ; CHECK: loop.exit2.split.split.us:
1642 ; CHECK-NEXT: [[L2_PHI_US16:%.*]] = phi i32 [ [[TMP_B_SUM_US13]], [[LATCH_US14]] ]
1643 ; CHECK-NEXT: br label [[LOOP_EXIT2_SPLIT:%.*]]
1644 ; CHECK: entry.split:
1645 ; CHECK-NEXT: br label [[HEADER:%.*]]
1647 ; CHECK-NEXT: [[TMP:%.*]] = call i32 @d()
1648 ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[TMP]], 0
1649 ; CHECK-NEXT: br i1 [[CMP1]], label [[BODY_A:%.*]], label [[DISPATCH:%.*]]
1651 ; CHECK-NEXT: [[TMP_LCSSA:%.*]] = phi i32 [ [[TMP]], [[HEADER]] ]
1652 ; CHECK-NEXT: br label [[LOOP_EXIT1:%.*]]
1654 ; CHECK-NEXT: [[TMP_A_PHI:%.*]] = phi i32 [ 0, [[HEADER]] ]
1655 ; CHECK-NEXT: [[TMP_A:%.*]] = call i32 @a()
1656 ; CHECK-NEXT: [[TMP_A_SUM:%.*]] = add i32 [[TMP_A_PHI]], [[TMP_A]]
1657 ; CHECK-NEXT: br label [[BODY_B:%.*]]
1659 ; CHECK-NEXT: [[TMP_B_PHI:%.*]] = phi i32 [ [[TMP_A_SUM]], [[BODY_A]] ]
1660 ; CHECK-NEXT: [[TMP_B:%.*]] = call i32 @b()
1661 ; CHECK-NEXT: [[TMP_B_SUM:%.*]] = add i32 [[TMP_B_PHI]], [[TMP_B]]
1662 ; CHECK-NEXT: br label [[LATCH:%.*]]
1664 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[TMP_B_SUM]], 42
1665 ; CHECK-NEXT: br i1 [[CMP2]], label [[HEADER]], label [[LOOP_EXIT2_SPLIT_SPLIT:%.*]]
1666 ; CHECK: loop.exit1:
1667 ; CHECK-NEXT: [[L1_PHI:%.*]] = phi i32 [ [[TMP_LCSSA]], [[DISPATCH]] ]
1668 ; CHECK-NEXT: br label [[EXIT:%.*]]
1669 ; CHECK: loop.exit2.split.split:
1670 ; CHECK-NEXT: [[L2_PHI:%.*]] = phi i32 [ [[TMP_B_SUM]], [[LATCH]] ]
1671 ; CHECK-NEXT: br label [[LOOP_EXIT2_SPLIT]]
1672 ; CHECK: loop.exit2.split:
1673 ; CHECK-NEXT: [[DOTUS_PHI17:%.*]] = phi i32 [ [[L2_PHI]], [[LOOP_EXIT2_SPLIT_SPLIT]] ], [ [[L2_PHI_US16]], [[LOOP_EXIT2_SPLIT_SPLIT_US]] ]
1674 ; CHECK-NEXT: br label [[LOOP_EXIT2]]
1675 ; CHECK: loop.exit2:
1676 ; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[DOTUS_PHI17]], [[LOOP_EXIT2_SPLIT]] ], [ [[L2_PHI_US]], [[LOOP_EXIT2_SPLIT_US]] ]
1677 ; CHECK-NEXT: br label [[EXIT]]
1679 ; CHECK-NEXT: [[L_PHI:%.*]] = phi i32 [ [[L1_PHI]], [[LOOP_EXIT1]] ], [ [[DOTUS_PHI]], [[LOOP_EXIT2]] ]
1680 ; CHECK-NEXT: ret i32 [[L_PHI]]
1686 %tmp = call i32 @d()
1687 %cmp1 = icmp eq i32 %tmp, 0
1688 br i1 %cmp1, label %body.a, label %dispatch
1691 switch i32 %arg, label %loop.exit1 [
1692 i32 -1, label %loop.exit1
1693 i32 0, label %body.a
1694 i32 1, label %body.b
1695 i32 2, label %body.b
1699 %tmp.a.phi = phi i32 [ 0, %header ], [ %tmp, %dispatch ]
1700 %tmp.a = call i32 @a()
1701 %tmp.a.sum = add i32 %tmp.a.phi, %tmp.a
1703 ; Unswitched 'a' loop.
1706 %tmp.b.phi = phi i32 [ %tmp, %dispatch ], [ %tmp, %dispatch ], [ %tmp.a.sum, %body.a ]
1707 %tmp.b = call i32 @b()
1708 %tmp.b.sum = add i32 %tmp.b.phi, %tmp.b
1710 ; Unswitched 'b' loop.
1713 %cmp2 = icmp slt i32 %tmp.b.sum, 42
1714 br i1 %cmp2, label %header, label %loop.exit2
1717 %l1.phi = phi i32 [ %tmp, %dispatch ], [ %tmp, %dispatch ]
1719 ; Unswitched 'exit' loop.
1722 %l2.phi = phi i32 [ %tmp.b.sum, %latch ]
1726 %l.phi = phi i32 [ %l1.phi, %loop.exit1 ], [ %l2.phi, %loop.exit2 ]
1730 ; Unswitch will not actually change the loop nest from:
1732 define void @hoist_inner_loop0() {
1733 ; CHECK-LABEL: @hoist_inner_loop0(
1734 ; CHECK-NEXT: entry:
1735 ; CHECK-NEXT: br label [[A_HEADER:%.*]]
1737 ; CHECK-NEXT: br label [[B_HEADER:%.*]]
1739 ; CHECK-NEXT: [[V1:%.*]] = call i1 @cond()
1740 ; CHECK-NEXT: [[V1_FR:%.*]] = freeze i1 [[V1]]
1741 ; CHECK-NEXT: br i1 [[V1_FR]], label [[B_HEADER_SPLIT_US:%.*]], label [[B_HEADER_SPLIT:%.*]]
1742 ; CHECK: b.header.split.us:
1743 ; CHECK-NEXT: br label [[C_HEADER_US:%.*]]
1744 ; CHECK: c.header.us:
1745 ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @c()
1746 ; CHECK-NEXT: br label [[B_LATCH_SPLIT_US:%.*]]
1747 ; CHECK: b.latch.split.us:
1748 ; CHECK-NEXT: br label [[B_LATCH:%.*]]
1749 ; CHECK: b.header.split:
1750 ; CHECK-NEXT: br label [[C_HEADER:%.*]]
1752 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @c()
1753 ; CHECK-NEXT: br label [[C_LATCH:%.*]]
1755 ; CHECK-NEXT: [[V2:%.*]] = call i1 @cond()
1756 ; CHECK-NEXT: br i1 [[V2]], label [[C_HEADER]], label [[B_LATCH_SPLIT:%.*]]
1757 ; CHECK: b.latch.split:
1758 ; CHECK-NEXT: br label [[B_LATCH]]
1760 ; CHECK-NEXT: [[V3:%.*]] = call i1 @cond()
1761 ; CHECK-NEXT: br i1 [[V3]], label [[B_HEADER]], label [[A_LATCH:%.*]]
1763 ; CHECK-NEXT: br label [[A_HEADER]]
1765 ; CHECK-NEXT: ret void
1774 %v1 = call i1 @cond()
1779 br i1 %v1, label %b.latch, label %c.latch
1782 %v2 = call i1 @cond()
1783 br i1 %v2, label %c.header, label %b.latch
1786 %v3 = call i1 @cond()
1787 br i1 %v3, label %b.header, label %a.latch
1796 ; Unswitch will transform the loop nest from:
1800 define void @hoist_inner_loop1(ptr %ptr) {
1801 ; CHECK-LABEL: @hoist_inner_loop1(
1802 ; CHECK-NEXT: entry:
1803 ; CHECK-NEXT: br label [[A_HEADER:%.*]]
1805 ; CHECK-NEXT: [[X_A:%.*]] = load i32, ptr [[PTR:%.*]], align 4
1806 ; CHECK-NEXT: br label [[B_HEADER:%.*]]
1808 ; CHECK-NEXT: [[X_B:%.*]] = load i32, ptr [[PTR]], align 4
1809 ; CHECK-NEXT: [[V1:%.*]] = call i1 @cond()
1810 ; CHECK-NEXT: [[V1_FR:%.*]] = freeze i1 [[V1]]
1811 ; CHECK-NEXT: br i1 [[V1_FR]], label [[B_HEADER_SPLIT_US:%.*]], label [[B_HEADER_SPLIT:%.*]]
1812 ; CHECK: b.header.split.us:
1813 ; CHECK-NEXT: br label [[C_HEADER_US:%.*]]
1814 ; CHECK: c.header.us:
1815 ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @c()
1816 ; CHECK-NEXT: br label [[B_LATCH_SPLIT_US:%.*]]
1817 ; CHECK: b.latch.split.us:
1818 ; CHECK-NEXT: br label [[B_LATCH:%.*]]
1819 ; CHECK: b.header.split:
1820 ; CHECK-NEXT: [[X_B_LCSSA:%.*]] = phi i32 [ [[X_B]], [[B_HEADER]] ]
1821 ; CHECK-NEXT: br label [[C_HEADER:%.*]]
1823 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @c()
1824 ; CHECK-NEXT: br label [[C_LATCH:%.*]]
1826 ; CHECK-NEXT: store i32 [[X_A]], ptr [[PTR]], align 4
1827 ; CHECK-NEXT: store i32 [[X_B_LCSSA]], ptr [[PTR]], align 4
1828 ; CHECK-NEXT: [[V2:%.*]] = call i1 @cond()
1829 ; CHECK-NEXT: br i1 [[V2]], label [[C_HEADER]], label [[A_EXIT_C:%.*]]
1831 ; CHECK-NEXT: [[V3:%.*]] = call i1 @cond()
1832 ; CHECK-NEXT: br i1 [[V3]], label [[B_HEADER]], label [[A_EXIT_B:%.*]]
1834 ; CHECK-NEXT: br label [[A_LATCH:%.*]]
1836 ; CHECK-NEXT: br label [[A_LATCH]]
1838 ; CHECK-NEXT: br label [[A_HEADER]]
1840 ; CHECK-NEXT: ret void
1846 %x.a = load i32, ptr %ptr
1850 %x.b = load i32, ptr %ptr
1851 %v1 = call i1 @cond()
1856 br i1 %v1, label %b.latch, label %c.latch
1859 ; Use values from other loops to check LCSSA form.
1860 store i32 %x.a, ptr %ptr
1861 store i32 %x.b, ptr %ptr
1862 %v2 = call i1 @cond()
1863 br i1 %v2, label %c.header, label %a.exit.c
1866 %v3 = call i1 @cond()
1867 br i1 %v3, label %b.header, label %a.exit.b
1882 ; Unswitch will transform the loop nest from:
1886 define void @hoist_inner_loop2(ptr %ptr) {
1887 ; CHECK-LABEL: @hoist_inner_loop2(
1888 ; CHECK-NEXT: entry:
1889 ; CHECK-NEXT: br label [[A_HEADER:%.*]]
1891 ; CHECK-NEXT: [[X_A:%.*]] = load i32, ptr [[PTR:%.*]], align 4
1892 ; CHECK-NEXT: br label [[B_HEADER:%.*]]
1894 ; CHECK-NEXT: [[X_B:%.*]] = load i32, ptr [[PTR]], align 4
1895 ; CHECK-NEXT: [[V1:%.*]] = call i1 @cond()
1896 ; CHECK-NEXT: [[V1_FR:%.*]] = freeze i1 [[V1]]
1897 ; CHECK-NEXT: br i1 [[V1_FR]], label [[B_HEADER_SPLIT_US:%.*]], label [[B_HEADER_SPLIT:%.*]]
1898 ; CHECK: b.header.split.us:
1899 ; CHECK-NEXT: br label [[C_HEADER_US:%.*]]
1900 ; CHECK: c.header.us:
1901 ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @c()
1902 ; CHECK-NEXT: br label [[B_LATCH_SPLIT_US:%.*]]
1903 ; CHECK: b.latch.split.us:
1904 ; CHECK-NEXT: br label [[B_LATCH:%.*]]
1905 ; CHECK: b.header.split:
1906 ; CHECK-NEXT: [[X_A_LCSSA:%.*]] = phi i32 [ [[X_A]], [[B_HEADER]] ]
1907 ; CHECK-NEXT: [[X_B_LCSSA:%.*]] = phi i32 [ [[X_B]], [[B_HEADER]] ]
1908 ; CHECK-NEXT: br label [[C_HEADER:%.*]]
1910 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @c()
1911 ; CHECK-NEXT: br label [[C_LATCH:%.*]]
1913 ; CHECK-NEXT: store i32 [[X_A_LCSSA]], ptr [[PTR]], align 4
1914 ; CHECK-NEXT: store i32 [[X_B_LCSSA]], ptr [[PTR]], align 4
1915 ; CHECK-NEXT: [[V2:%.*]] = call i1 @cond()
1916 ; CHECK-NEXT: br i1 [[V2]], label [[C_HEADER]], label [[EXIT:%.*]]
1918 ; CHECK-NEXT: [[V3:%.*]] = call i1 @cond()
1919 ; CHECK-NEXT: br i1 [[V3]], label [[B_HEADER]], label [[A_LATCH:%.*]]
1921 ; CHECK-NEXT: br label [[A_HEADER]]
1923 ; CHECK-NEXT: ret void
1929 %x.a = load i32, ptr %ptr
1933 %x.b = load i32, ptr %ptr
1934 %v1 = call i1 @cond()
1939 br i1 %v1, label %b.latch, label %c.latch
1942 ; Use values from other loops to check LCSSA form.
1943 store i32 %x.a, ptr %ptr
1944 store i32 %x.b, ptr %ptr
1945 %v2 = call i1 @cond()
1946 br i1 %v2, label %c.header, label %exit
1949 %v3 = call i1 @cond()
1950 br i1 %v3, label %b.header, label %a.latch
1959 ; Same as @hoist_inner_loop2 but with a nested loop inside the hoisted loop.
1960 ; Unswitch will transform the loop nest from:
1964 define void @hoist_inner_loop3(ptr %ptr) {
1965 ; CHECK-LABEL: @hoist_inner_loop3(
1966 ; CHECK-NEXT: entry:
1967 ; CHECK-NEXT: br label [[A_HEADER:%.*]]
1969 ; CHECK-NEXT: [[X_A:%.*]] = load i32, ptr [[PTR:%.*]], align 4
1970 ; CHECK-NEXT: br label [[B_HEADER:%.*]]
1972 ; CHECK-NEXT: [[X_B:%.*]] = load i32, ptr [[PTR]], align 4
1973 ; CHECK-NEXT: [[V1:%.*]] = call i1 @cond()
1974 ; CHECK-NEXT: [[V1_FR:%.*]] = freeze i1 [[V1]]
1975 ; CHECK-NEXT: br i1 [[V1_FR]], label [[B_HEADER_SPLIT_US:%.*]], label [[B_HEADER_SPLIT:%.*]]
1976 ; CHECK: b.header.split.us:
1977 ; CHECK-NEXT: br label [[C_HEADER_US:%.*]]
1978 ; CHECK: c.header.us:
1979 ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @c()
1980 ; CHECK-NEXT: br label [[B_LATCH_SPLIT_US:%.*]]
1981 ; CHECK: b.latch.split.us:
1982 ; CHECK-NEXT: br label [[B_LATCH:%.*]]
1983 ; CHECK: b.header.split:
1984 ; CHECK-NEXT: [[X_A_LCSSA:%.*]] = phi i32 [ [[X_A]], [[B_HEADER]] ]
1985 ; CHECK-NEXT: [[X_B_LCSSA:%.*]] = phi i32 [ [[X_B]], [[B_HEADER]] ]
1986 ; CHECK-NEXT: br label [[C_HEADER:%.*]]
1988 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @c()
1989 ; CHECK-NEXT: br label [[C_BODY:%.*]]
1991 ; CHECK-NEXT: [[X_C:%.*]] = load i32, ptr [[PTR]], align 4
1992 ; CHECK-NEXT: br label [[D_HEADER:%.*]]
1994 ; CHECK-NEXT: store i32 [[X_A_LCSSA]], ptr [[PTR]], align 4
1995 ; CHECK-NEXT: store i32 [[X_B_LCSSA]], ptr [[PTR]], align 4
1996 ; CHECK-NEXT: store i32 [[X_C]], ptr [[PTR]], align 4
1997 ; CHECK-NEXT: [[V2:%.*]] = call i1 @cond()
1998 ; CHECK-NEXT: br i1 [[V2]], label [[D_HEADER]], label [[C_LATCH:%.*]]
2000 ; CHECK-NEXT: [[V3:%.*]] = call i1 @cond()
2001 ; CHECK-NEXT: br i1 [[V3]], label [[C_HEADER]], label [[EXIT:%.*]]
2003 ; CHECK-NEXT: [[V4:%.*]] = call i1 @cond()
2004 ; CHECK-NEXT: br i1 [[V4]], label [[B_HEADER]], label [[A_LATCH:%.*]]
2006 ; CHECK-NEXT: br label [[A_HEADER]]
2008 ; CHECK-NEXT: ret void
2014 %x.a = load i32, ptr %ptr
2018 %x.b = load i32, ptr %ptr
2019 %v1 = call i1 @cond()
2024 br i1 %v1, label %b.latch, label %c.body
2027 %x.c = load i32, ptr %ptr
2031 ; Use values from other loops to check LCSSA form.
2032 store i32 %x.a, ptr %ptr
2033 store i32 %x.b, ptr %ptr
2034 store i32 %x.c, ptr %ptr
2035 %v2 = call i1 @cond()
2036 br i1 %v2, label %d.header, label %c.latch
2039 %v3 = call i1 @cond()
2040 br i1 %v3, label %c.header, label %exit
2043 %v4 = call i1 @cond()
2044 br i1 %v4, label %b.header, label %a.latch
2053 ; This test is designed to exercise checking multiple remaining exits from the
2054 ; loop being unswitched.
2055 ; Unswitch will transform the loop nest from:
2059 define void @hoist_inner_loop4() {
2060 ; CHECK-LABEL: @hoist_inner_loop4(
2061 ; CHECK-NEXT: entry:
2062 ; CHECK-NEXT: br label [[A_HEADER:%.*]]
2064 ; CHECK-NEXT: br label [[B_HEADER:%.*]]
2066 ; CHECK-NEXT: br label [[C_HEADER:%.*]]
2068 ; CHECK-NEXT: [[V1:%.*]] = call i1 @cond()
2069 ; CHECK-NEXT: [[V1_FR:%.*]] = freeze i1 [[V1]]
2070 ; CHECK-NEXT: br i1 [[V1_FR]], label [[C_HEADER_SPLIT_US:%.*]], label [[C_HEADER_SPLIT:%.*]]
2071 ; CHECK: c.header.split.us:
2072 ; CHECK-NEXT: br label [[D_HEADER_US:%.*]]
2073 ; CHECK: d.header.us:
2074 ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @d()
2075 ; CHECK-NEXT: br label [[C_LATCH_SPLIT_US:%.*]]
2076 ; CHECK: c.latch.split.us:
2077 ; CHECK-NEXT: br label [[C_LATCH:%.*]]
2078 ; CHECK: c.header.split:
2079 ; CHECK-NEXT: br label [[D_HEADER:%.*]]
2081 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @d()
2082 ; CHECK-NEXT: br label [[D_EXITING1:%.*]]
2083 ; CHECK: d.exiting1:
2084 ; CHECK-NEXT: [[V2:%.*]] = call i1 @cond()
2085 ; CHECK-NEXT: br i1 [[V2]], label [[D_EXITING2:%.*]], label [[A_LATCH:%.*]]
2086 ; CHECK: d.exiting2:
2087 ; CHECK-NEXT: [[V3:%.*]] = call i1 @cond()
2088 ; CHECK-NEXT: br i1 [[V3]], label [[D_EXITING3:%.*]], label [[LOOPEXIT_D:%.*]]
2089 ; CHECK: d.exiting3:
2090 ; CHECK-NEXT: [[V4:%.*]] = call i1 @cond()
2091 ; CHECK-NEXT: br i1 [[V4]], label [[D_LATCH:%.*]], label [[B_LATCH:%.*]]
2093 ; CHECK-NEXT: br label [[D_HEADER]]
2095 ; CHECK-NEXT: [[V5:%.*]] = call i1 @cond()
2096 ; CHECK-NEXT: br i1 [[V5]], label [[C_HEADER]], label [[LOOPEXIT_C:%.*]]
2098 ; CHECK-NEXT: br label [[B_HEADER]]
2100 ; CHECK-NEXT: br label [[A_HEADER]]
2101 ; CHECK: loopexit.d:
2102 ; CHECK-NEXT: br label [[EXIT:%.*]]
2103 ; CHECK: loopexit.c:
2104 ; CHECK-NEXT: br label [[EXIT]]
2106 ; CHECK-NEXT: ret void
2118 %v1 = call i1 @cond()
2123 br i1 %v1, label %c.latch, label %d.exiting1
2126 %v2 = call i1 @cond()
2127 br i1 %v2, label %d.exiting2, label %a.latch
2130 %v3 = call i1 @cond()
2131 br i1 %v3, label %d.exiting3, label %loopexit.d
2134 %v4 = call i1 @cond()
2135 br i1 %v4, label %d.latch, label %b.latch
2141 %v5 = call i1 @cond()
2142 br i1 %v5, label %c.header, label %loopexit.c
2160 ; Unswitch will transform the loop nest from:
2164 define void @hoist_inner_loop5(ptr %ptr) {
2165 ; CHECK-LABEL: @hoist_inner_loop5(
2166 ; CHECK-NEXT: entry:
2167 ; CHECK-NEXT: br label [[A_HEADER:%.*]]
2169 ; CHECK-NEXT: [[X_A:%.*]] = load i32, ptr [[PTR:%.*]], align 4
2170 ; CHECK-NEXT: br label [[B_HEADER:%.*]]
2172 ; CHECK-NEXT: [[X_B:%.*]] = load i32, ptr [[PTR]], align 4
2173 ; CHECK-NEXT: br label [[C_HEADER:%.*]]
2175 ; CHECK-NEXT: [[X_C:%.*]] = load i32, ptr [[PTR]], align 4
2176 ; CHECK-NEXT: [[V1:%.*]] = call i1 @cond()
2177 ; CHECK-NEXT: [[V1_FR:%.*]] = freeze i1 [[V1]]
2178 ; CHECK-NEXT: br i1 [[V1_FR]], label [[C_HEADER_SPLIT_US:%.*]], label [[C_HEADER_SPLIT:%.*]]
2179 ; CHECK: c.header.split.us:
2180 ; CHECK-NEXT: br label [[D_HEADER_US:%.*]]
2181 ; CHECK: d.header.us:
2182 ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @d()
2183 ; CHECK-NEXT: br label [[C_LATCH_SPLIT_US:%.*]]
2184 ; CHECK: c.latch.split.us:
2185 ; CHECK-NEXT: br label [[C_LATCH:%.*]]
2186 ; CHECK: c.header.split:
2187 ; CHECK-NEXT: [[X_B_LCSSA:%.*]] = phi i32 [ [[X_B]], [[C_HEADER]] ]
2188 ; CHECK-NEXT: [[X_C_LCSSA:%.*]] = phi i32 [ [[X_C]], [[C_HEADER]] ]
2189 ; CHECK-NEXT: br label [[D_HEADER:%.*]]
2191 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @d()
2192 ; CHECK-NEXT: br label [[D_LATCH:%.*]]
2194 ; CHECK-NEXT: store i32 [[X_A]], ptr [[PTR]], align 4
2195 ; CHECK-NEXT: store i32 [[X_B_LCSSA]], ptr [[PTR]], align 4
2196 ; CHECK-NEXT: store i32 [[X_C_LCSSA]], ptr [[PTR]], align 4
2197 ; CHECK-NEXT: [[V2:%.*]] = call i1 @cond()
2198 ; CHECK-NEXT: br i1 [[V2]], label [[D_HEADER]], label [[A_LATCH:%.*]]
2200 ; CHECK-NEXT: [[V3:%.*]] = call i1 @cond()
2201 ; CHECK-NEXT: br i1 [[V3]], label [[C_HEADER]], label [[B_LATCH:%.*]]
2203 ; CHECK-NEXT: br label [[B_HEADER]]
2205 ; CHECK-NEXT: br label [[A_HEADER]]
2207 ; CHECK-NEXT: ret void
2213 %x.a = load i32, ptr %ptr
2217 %x.b = load i32, ptr %ptr
2221 %x.c = load i32, ptr %ptr
2222 %v1 = call i1 @cond()
2227 br i1 %v1, label %c.latch, label %d.latch
2230 ; Use values from other loops to check LCSSA form.
2231 store i32 %x.a, ptr %ptr
2232 store i32 %x.b, ptr %ptr
2233 store i32 %x.c, ptr %ptr
2234 %v2 = call i1 @cond()
2235 br i1 %v2, label %d.header, label %a.latch
2238 %v3 = call i1 @cond()
2239 br i1 %v3, label %c.header, label %b.latch
2251 define void @hoist_inner_loop_switch(ptr %ptr) {
2252 ; CHECK-LABEL: @hoist_inner_loop_switch(
2253 ; CHECK-NEXT: entry:
2254 ; CHECK-NEXT: br label [[A_HEADER:%.*]]
2256 ; CHECK-NEXT: [[X_A:%.*]] = load i32, ptr [[PTR:%.*]], align 4
2257 ; CHECK-NEXT: br label [[B_HEADER:%.*]]
2259 ; CHECK-NEXT: [[X_B:%.*]] = load i32, ptr [[PTR]], align 4
2260 ; CHECK-NEXT: [[V1:%.*]] = call i32 @cond.i32()
2261 ; CHECK-NEXT: [[V1_FR:%.*]] = freeze i32 [[V1]]
2262 ; CHECK-NEXT: switch i32 [[V1_FR]], label [[B_HEADER_SPLIT:%.*]] [
2263 ; CHECK-NEXT: i32 1, label [[B_HEADER_SPLIT_US:%.*]]
2264 ; CHECK-NEXT: i32 2, label [[B_HEADER_SPLIT_US]]
2265 ; CHECK-NEXT: i32 3, label [[B_HEADER_SPLIT_US]]
2267 ; CHECK: b.header.split.us:
2268 ; CHECK-NEXT: br label [[C_HEADER_US:%.*]]
2269 ; CHECK: c.header.us:
2270 ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @c()
2271 ; CHECK-NEXT: br label [[B_LATCH_SPLIT_US:%.*]]
2272 ; CHECK: b.latch.split.us:
2273 ; CHECK-NEXT: br label [[B_LATCH:%.*]]
2274 ; CHECK: b.header.split:
2275 ; CHECK-NEXT: [[X_A_LCSSA:%.*]] = phi i32 [ [[X_A]], [[B_HEADER]] ]
2276 ; CHECK-NEXT: [[X_B_LCSSA:%.*]] = phi i32 [ [[X_B]], [[B_HEADER]] ]
2277 ; CHECK-NEXT: br label [[C_HEADER:%.*]]
2279 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @c()
2280 ; CHECK-NEXT: br label [[C_LATCH:%.*]]
2282 ; CHECK-NEXT: store i32 [[X_A_LCSSA]], ptr [[PTR]], align 4
2283 ; CHECK-NEXT: store i32 [[X_B_LCSSA]], ptr [[PTR]], align 4
2284 ; CHECK-NEXT: [[V2:%.*]] = call i1 @cond()
2285 ; CHECK-NEXT: br i1 [[V2]], label [[C_HEADER]], label [[EXIT:%.*]]
2287 ; CHECK-NEXT: [[V3:%.*]] = call i1 @cond()
2288 ; CHECK-NEXT: br i1 [[V3]], label [[B_HEADER]], label [[A_LATCH:%.*]]
2290 ; CHECK-NEXT: br label [[A_HEADER]]
2292 ; CHECK-NEXT: ret void
2298 %x.a = load i32, ptr %ptr
2302 %x.b = load i32, ptr %ptr
2303 %v1 = call i32 @cond.i32()
2308 switch i32 %v1, label %c.latch [
2309 i32 1, label %b.latch
2310 i32 2, label %b.latch
2311 i32 3, label %b.latch
2315 ; Use values from other loops to check LCSSA form.
2316 store i32 %x.a, ptr %ptr
2317 store i32 %x.b, ptr %ptr
2318 %v2 = call i1 @cond()
2319 br i1 %v2, label %c.header, label %exit
2322 %v3 = call i1 @cond()
2323 br i1 %v3, label %b.header, label %a.latch
2332 define i32 @test_partial_unswitch_all_conds_guaranteed_non_poison(i1 noundef %c.1, i1 noundef %c.2) {
2333 ; CHECK-LABEL: @test_partial_unswitch_all_conds_guaranteed_non_poison(
2334 ; CHECK-NEXT: entry:
2335 ; CHECK-NEXT: [[TMP0:%.*]] = and i1 [[C_1:%.*]], [[C_2:%.*]]
2336 ; CHECK-NEXT: br i1 [[TMP0]], label [[ENTRY_SPLIT:%.*]], label [[ENTRY_SPLIT_US:%.*]]
2337 ; CHECK: entry.split.us:
2338 ; CHECK-NEXT: br label [[LOOP_US:%.*]]
2340 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @a()
2341 ; CHECK-NEXT: br label [[EXIT_SPLIT_US:%.*]]
2342 ; CHECK: exit.split.us:
2343 ; CHECK-NEXT: br label [[EXIT:%.*]]
2344 ; CHECK: entry.split:
2345 ; CHECK-NEXT: br label [[LOOP:%.*]]
2347 ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @a()
2348 ; CHECK-NEXT: [[SEL:%.*]] = select i1 true, i1 true, i1 false
2349 ; CHECK-NEXT: br i1 [[SEL]], label [[LOOP]], label [[EXIT_SPLIT:%.*]]
2350 ; CHECK: exit.split:
2351 ; CHECK-NEXT: br label [[EXIT]]
2353 ; CHECK-NEXT: ret i32 0
2360 %sel = select i1 %c.1, i1 %c.2, i1 false
2361 br i1 %sel, label %loop, label %exit