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 -verify-memoryssa < %s | FileCheck %s
10 declare void @sink1(i32)
11 declare void @sink2(i32)
12 declare void @sink3(i1)
13 declare void @sink4(i1)
16 declare i32 @cond.i32()
18 declare i32 @__CxxFrameHandler3(...)
20 define i32 @test1_freeze(ptr %ptr0, ptr %ptr1, ptr %ptr2) {
21 ; CHECK-LABEL: @test1_freeze(
23 ; CHECK-NEXT: [[COND1:%.*]] = load i1, ptr [[PTR1:%.*]], align 1
24 ; CHECK-NEXT: [[COND2:%.*]] = load i1, ptr [[PTR2:%.*]], align 1
25 ; CHECK-NEXT: br i1 [[COND1]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
26 ; CHECK: entry.split.us:
27 ; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]]
28 ; CHECK: loop_begin.us:
29 ; CHECK-NEXT: br label [[LOOP_A_US:%.*]]
31 ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @a()
32 ; CHECK-NEXT: br label [[LATCH_US:%.*]]
34 ; CHECK-NEXT: [[V_US:%.*]] = load i1, ptr [[PTR0:%.*]], align 1
35 ; CHECK-NEXT: br i1 [[V_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]]
36 ; CHECK: loop_exit.split.us:
37 ; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
39 ; CHECK-NEXT: [[COND2_FR:%.*]] = freeze i1 [[COND2]]
40 ; CHECK-NEXT: br i1 [[COND2_FR]], label [[ENTRY_SPLIT_SPLIT_US:%.*]], label [[ENTRY_SPLIT_SPLIT:%.*]]
41 ; CHECK: entry.split.split.us:
42 ; CHECK-NEXT: br label [[LOOP_BEGIN_US1:%.*]]
43 ; CHECK: loop_begin.us1:
44 ; CHECK-NEXT: br label [[LOOP_B_US:%.*]]
46 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @b()
47 ; CHECK-NEXT: br label [[LOOP_B_A_US:%.*]]
49 ; CHECK-NEXT: call void @sink3(i1 true)
50 ; CHECK-NEXT: br label [[LATCH_US2:%.*]]
52 ; CHECK-NEXT: [[V_US3:%.*]] = load i1, ptr [[PTR0]], align 1
53 ; CHECK-NEXT: br i1 [[V_US3]], label [[LOOP_BEGIN_US1]], label [[LOOP_EXIT_SPLIT_SPLIT_US:%.*]]
54 ; CHECK: loop_exit.split.split.us:
55 ; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT:%.*]]
56 ; CHECK: entry.split.split:
57 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
59 ; CHECK-NEXT: br label [[LOOP_B:%.*]]
61 ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @b()
62 ; CHECK-NEXT: br label [[LOOP_B_B:%.*]]
64 ; CHECK-NEXT: call void @sink4(i1 false)
65 ; CHECK-NEXT: br label [[LATCH:%.*]]
67 ; CHECK-NEXT: [[V:%.*]] = load i1, ptr [[PTR0]], align 1
68 ; CHECK-NEXT: br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT_SPLIT_SPLIT:%.*]]
69 ; CHECK: loop_exit.split.split:
70 ; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT]]
71 ; CHECK: loop_exit.split:
72 ; CHECK-NEXT: br label [[LOOP_EXIT]]
74 ; CHECK-NEXT: ret i32 0
77 %cond1 = load i1, ptr %ptr1
78 %cond2 = load i1, ptr %ptr2
82 br i1 %cond1, label %loop_a, label %loop_b
87 ; The 'loop_a' unswitched loop.
91 br i1 %cond2, label %loop_b_a, label %loop_b_b
92 ; The second unswitched condition.
95 call void @sink3(i1 %cond2)
97 ; The 'loop_b_a' unswitched loop.
98 ; %cond2 is replaced to true
101 call void @sink4(i1 %cond2)
103 ; The 'loop_b_b' unswitched loop.
104 ; %cond2 is replaced to false
107 %v = load i1, ptr %ptr0
108 br i1 %v, label %loop_begin, label %loop_exit
114 ; Test that when unswitching a deeply nested loop condition in a way that
115 ; produces a non-loop clone that can reach multiple exit blocks which are part
116 ; of different outer loops we correctly divide the cloned loop blocks between
117 ; the outer loops based on reachability.
118 define i32 @test7a(ptr %ptr, ptr %cond.ptr, ptr %a.ptr, ptr %b.ptr) {
119 ; CHECK-LABEL: @test7a(
121 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
123 ; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR:%.*]], align 4
124 ; CHECK-NEXT: br label [[INNER_LOOP_BEGIN:%.*]]
125 ; CHECK: inner_loop_begin:
126 ; CHECK-NEXT: [[A_PHI:%.*]] = phi i32 [ [[A]], [[LOOP_BEGIN]] ], [ [[A2:%.*]], [[INNER_INNER_LOOP_EXIT:%.*]] ]
127 ; CHECK-NEXT: [[COND:%.*]] = load i1, ptr [[COND_PTR:%.*]], align 1
128 ; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[B_PTR:%.*]], align 4
129 ; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]]
130 ; CHECK-NEXT: br i1 [[COND_FR]], label [[INNER_LOOP_BEGIN_SPLIT_US:%.*]], label [[INNER_LOOP_BEGIN_SPLIT:%.*]]
131 ; CHECK: inner_loop_begin.split.us:
132 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US:%.*]]
133 ; CHECK: inner_inner_loop_begin.us:
134 ; CHECK-NEXT: [[V1_US:%.*]] = load i1, ptr [[PTR:%.*]], align 1
135 ; CHECK-NEXT: br i1 [[V1_US]], label [[INNER_INNER_LOOP_A_US:%.*]], label [[INNER_INNER_LOOP_B_US:%.*]]
136 ; CHECK: inner_inner_loop_b.us:
137 ; CHECK-NEXT: [[V3_US:%.*]] = load i1, ptr [[PTR]], align 1
138 ; CHECK-NEXT: br i1 [[V3_US]], label [[INNER_INNER_LOOP_EXIT_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_C_US_LOOPEXIT:%.*]]
139 ; CHECK: inner_inner_loop_a.us:
140 ; CHECK-NEXT: [[A_PHI_LCSSA10:%.*]] = phi i32 [ [[A_PHI]], [[INNER_INNER_LOOP_BEGIN_US]] ]
141 ; CHECK-NEXT: [[B_LCSSA6:%.*]] = phi i32 [ [[B]], [[INNER_INNER_LOOP_BEGIN_US]] ]
142 ; CHECK-NEXT: [[V2_US:%.*]] = load i1, ptr [[PTR]], align 1
143 ; CHECK-NEXT: br i1 [[V2_US]], label [[LOOP_EXIT_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_C_US:%.*]]
144 ; CHECK: inner_inner_loop_c.us.loopexit:
145 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_C_US]]
146 ; CHECK: inner_inner_loop_c.us:
147 ; CHECK-NEXT: [[V4_US:%.*]] = load i1, ptr [[PTR]], align 1
148 ; CHECK-NEXT: br i1 [[V4_US]], label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_D_US:%.*]]
149 ; CHECK: inner_inner_loop_d.us:
150 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT_US]]
151 ; CHECK: inner_inner_loop_exit.split.us:
152 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_EXIT]]
153 ; CHECK: loop_exit.split.us:
154 ; CHECK-NEXT: [[A_LCSSA_US:%.*]] = phi i32 [ [[A_PHI_LCSSA10]], [[INNER_INNER_LOOP_A_US]] ]
155 ; CHECK-NEXT: [[B_LCSSA_US:%.*]] = phi i32 [ [[B_LCSSA6]], [[INNER_INNER_LOOP_A_US]] ]
156 ; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
157 ; CHECK: inner_loop_exit.loopexit.split.us:
158 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT:%.*]]
159 ; CHECK: inner_loop_begin.split:
160 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN:%.*]]
161 ; CHECK: inner_inner_loop_begin:
162 ; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR]], align 1
163 ; CHECK-NEXT: br i1 [[V1]], label [[INNER_INNER_LOOP_A:%.*]], label [[INNER_INNER_LOOP_B:%.*]]
164 ; CHECK: inner_inner_loop_a:
165 ; CHECK-NEXT: [[V2:%.*]] = load i1, ptr [[PTR]], align 1
166 ; CHECK-NEXT: br i1 [[V2]], label [[LOOP_EXIT_SPLIT:%.*]], label [[INNER_INNER_LOOP_C:%.*]]
167 ; CHECK: inner_inner_loop_b:
168 ; CHECK-NEXT: [[V3:%.*]] = load i1, ptr [[PTR]], align 1
169 ; CHECK-NEXT: br i1 [[V3]], label [[INNER_INNER_LOOP_EXIT_SPLIT:%.*]], label [[INNER_INNER_LOOP_C]]
170 ; CHECK: inner_inner_loop_c:
171 ; CHECK-NEXT: [[V4:%.*]] = load i1, ptr [[PTR]], align 1
172 ; CHECK-NEXT: br i1 [[V4]], label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT:%.*]], label [[INNER_INNER_LOOP_D:%.*]]
173 ; CHECK: inner_inner_loop_d:
174 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN]]
175 ; CHECK: inner_inner_loop_exit.split:
176 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_EXIT]]
177 ; CHECK: inner_inner_loop_exit:
178 ; CHECK-NEXT: [[A2]] = load i32, ptr [[A_PTR]], align 4
179 ; CHECK-NEXT: [[V5:%.*]] = load i1, ptr [[PTR]], align 1
180 ; CHECK-NEXT: br i1 [[V5]], label [[INNER_LOOP_EXIT_LOOPEXIT1:%.*]], label [[INNER_LOOP_BEGIN]]
181 ; CHECK: inner_loop_exit.loopexit.split:
182 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT]]
183 ; CHECK: inner_loop_exit.loopexit:
184 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT:%.*]]
185 ; CHECK: inner_loop_exit.loopexit1:
186 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT]]
187 ; CHECK: inner_loop_exit:
188 ; CHECK-NEXT: br label [[LOOP_BEGIN]]
189 ; CHECK: loop_exit.split:
190 ; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_PHI]], [[INNER_INNER_LOOP_A]] ]
191 ; CHECK-NEXT: [[B_LCSSA:%.*]] = phi i32 [ [[B]], [[INNER_INNER_LOOP_A]] ]
192 ; CHECK-NEXT: br label [[LOOP_EXIT]]
194 ; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[A_LCSSA]], [[LOOP_EXIT_SPLIT]] ], [ [[A_LCSSA_US]], [[LOOP_EXIT_SPLIT_US]] ]
195 ; CHECK-NEXT: [[DOTUS_PHI2:%.*]] = phi i32 [ [[B_LCSSA]], [[LOOP_EXIT_SPLIT]] ], [ [[B_LCSSA_US]], [[LOOP_EXIT_SPLIT_US]] ]
196 ; CHECK-NEXT: [[RESULT:%.*]] = add i32 [[DOTUS_PHI]], [[DOTUS_PHI2]]
197 ; CHECK-NEXT: ret i32 [[RESULT]]
203 %a = load i32, ptr %a.ptr
204 br label %inner_loop_begin
207 %a.phi = phi i32 [ %a, %loop_begin ], [ %a2, %inner_inner_loop_exit ]
208 %cond = load i1, ptr %cond.ptr
209 %b = load i32, ptr %b.ptr
210 br label %inner_inner_loop_begin
212 inner_inner_loop_begin:
213 %v1 = load i1, ptr %ptr
214 br i1 %v1, label %inner_inner_loop_a, label %inner_inner_loop_b
217 %v2 = load i1, ptr %ptr
218 br i1 %v2, label %loop_exit, label %inner_inner_loop_c
221 %v3 = load i1, ptr %ptr
222 br i1 %v3, label %inner_inner_loop_exit, label %inner_inner_loop_c
225 %v4 = load i1, ptr %ptr
226 br i1 %v4, label %inner_loop_exit, label %inner_inner_loop_d
229 br i1 %cond, label %inner_loop_exit, label %inner_inner_loop_begin
230 ; The cloned copy that always exits with the adjustments required to fix up
232 ; The original copy that continues to loop.
234 inner_inner_loop_exit:
235 %a2 = load i32, ptr %a.ptr
236 %v5 = load i1, ptr %ptr
237 br i1 %v5, label %inner_loop_exit, label %inner_loop_begin
243 %a.lcssa = phi i32 [ %a.phi, %inner_inner_loop_a ]
244 %b.lcssa = phi i32 [ %b, %inner_inner_loop_a ]
245 %result = add i32 %a.lcssa, %b.lcssa
249 ; Same pattern as @test7a but here the original loop becomes a non-loop that
250 ; can reach multiple exit blocks which are part of different outer loops.
251 define i32 @test7b(ptr %ptr, ptr %cond.ptr, ptr %a.ptr, ptr %b.ptr) {
252 ; CHECK-LABEL: @test7b(
254 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
256 ; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR:%.*]], align 4
257 ; CHECK-NEXT: br label [[INNER_LOOP_BEGIN:%.*]]
258 ; CHECK: inner_loop_begin:
259 ; CHECK-NEXT: [[A_PHI:%.*]] = phi i32 [ [[A]], [[LOOP_BEGIN]] ], [ [[A2:%.*]], [[INNER_INNER_LOOP_EXIT:%.*]] ]
260 ; CHECK-NEXT: [[COND:%.*]] = load i1, ptr [[COND_PTR:%.*]], align 1
261 ; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[B_PTR:%.*]], align 4
262 ; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]]
263 ; CHECK-NEXT: br i1 [[COND_FR]], label [[INNER_LOOP_BEGIN_SPLIT_US:%.*]], label [[INNER_LOOP_BEGIN_SPLIT:%.*]]
264 ; CHECK: inner_loop_begin.split.us:
265 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US:%.*]]
266 ; CHECK: inner_inner_loop_begin.us:
267 ; CHECK-NEXT: [[V1_US:%.*]] = load i1, ptr [[PTR:%.*]], align 1
268 ; CHECK-NEXT: br i1 [[V1_US]], label [[INNER_INNER_LOOP_A_US:%.*]], label [[INNER_INNER_LOOP_B_US:%.*]]
269 ; CHECK: inner_inner_loop_b.us:
270 ; CHECK-NEXT: [[V3_US:%.*]] = load i1, ptr [[PTR]], align 1
271 ; CHECK-NEXT: br i1 [[V3_US]], label [[INNER_INNER_LOOP_EXIT_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_C_US:%.*]]
272 ; CHECK: inner_inner_loop_a.us:
273 ; CHECK-NEXT: [[V2_US:%.*]] = load i1, ptr [[PTR]], align 1
274 ; CHECK-NEXT: br i1 [[V2_US]], label [[LOOP_EXIT_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_C_US]]
275 ; CHECK: inner_inner_loop_c.us:
276 ; CHECK-NEXT: [[V4_US:%.*]] = load i1, ptr [[PTR]], align 1
277 ; CHECK-NEXT: br i1 [[V4_US]], label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_D_US:%.*]]
278 ; CHECK: inner_inner_loop_d.us:
279 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US]]
280 ; CHECK: inner_inner_loop_exit.split.us:
281 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_EXIT]]
282 ; CHECK: loop_exit.split.us:
283 ; CHECK-NEXT: [[A_LCSSA_US:%.*]] = phi i32 [ [[A_PHI]], [[INNER_INNER_LOOP_A_US]] ]
284 ; CHECK-NEXT: [[B_LCSSA_US:%.*]] = phi i32 [ [[B]], [[INNER_INNER_LOOP_A_US]] ]
285 ; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
286 ; CHECK: inner_loop_exit.loopexit.split.us:
287 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT:%.*]]
288 ; CHECK: inner_loop_begin.split:
289 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN:%.*]]
290 ; CHECK: inner_inner_loop_begin:
291 ; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR]], align 1
292 ; CHECK-NEXT: br i1 [[V1]], label [[INNER_INNER_LOOP_A:%.*]], label [[INNER_INNER_LOOP_B:%.*]]
293 ; CHECK: inner_inner_loop_a:
294 ; CHECK-NEXT: [[A_PHI_LCSSA:%.*]] = phi i32 [ [[A_PHI]], [[INNER_INNER_LOOP_BEGIN]] ]
295 ; CHECK-NEXT: [[B_LCSSA3:%.*]] = phi i32 [ [[B]], [[INNER_INNER_LOOP_BEGIN]] ]
296 ; CHECK-NEXT: [[V2:%.*]] = load i1, ptr [[PTR]], align 1
297 ; CHECK-NEXT: br i1 [[V2]], label [[LOOP_EXIT_SPLIT:%.*]], label [[INNER_INNER_LOOP_C:%.*]]
298 ; CHECK: inner_inner_loop_b:
299 ; CHECK-NEXT: [[V3:%.*]] = load i1, ptr [[PTR]], align 1
300 ; CHECK-NEXT: br i1 [[V3]], label [[INNER_INNER_LOOP_EXIT_SPLIT:%.*]], label [[INNER_INNER_LOOP_C_LOOPEXIT:%.*]]
301 ; CHECK: inner_inner_loop_c.loopexit:
302 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_C]]
303 ; CHECK: inner_inner_loop_c:
304 ; CHECK-NEXT: [[V4:%.*]] = load i1, ptr [[PTR]], align 1
305 ; CHECK-NEXT: br i1 [[V4]], label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT:%.*]], label [[INNER_INNER_LOOP_D:%.*]]
306 ; CHECK: inner_inner_loop_d:
307 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT]]
308 ; CHECK: inner_inner_loop_exit.split:
309 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_EXIT]]
310 ; CHECK: inner_inner_loop_exit:
311 ; CHECK-NEXT: [[A2]] = load i32, ptr [[A_PTR]], align 4
312 ; CHECK-NEXT: [[V5:%.*]] = load i1, ptr [[PTR]], align 1
313 ; CHECK-NEXT: br i1 [[V5]], label [[INNER_LOOP_EXIT_LOOPEXIT1:%.*]], label [[INNER_LOOP_BEGIN]]
314 ; CHECK: inner_loop_exit.loopexit.split:
315 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT]]
316 ; CHECK: inner_loop_exit.loopexit:
317 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT:%.*]]
318 ; CHECK: inner_loop_exit.loopexit1:
319 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT]]
320 ; CHECK: inner_loop_exit:
321 ; CHECK-NEXT: br label [[LOOP_BEGIN]]
322 ; CHECK: loop_exit.split:
323 ; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_PHI_LCSSA]], [[INNER_INNER_LOOP_A]] ]
324 ; CHECK-NEXT: [[B_LCSSA:%.*]] = phi i32 [ [[B_LCSSA3]], [[INNER_INNER_LOOP_A]] ]
325 ; CHECK-NEXT: br label [[LOOP_EXIT]]
327 ; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[A_LCSSA]], [[LOOP_EXIT_SPLIT]] ], [ [[A_LCSSA_US]], [[LOOP_EXIT_SPLIT_US]] ]
328 ; CHECK-NEXT: [[DOTUS_PHI2:%.*]] = phi i32 [ [[B_LCSSA]], [[LOOP_EXIT_SPLIT]] ], [ [[B_LCSSA_US]], [[LOOP_EXIT_SPLIT_US]] ]
329 ; CHECK-NEXT: [[RESULT:%.*]] = add i32 [[DOTUS_PHI]], [[DOTUS_PHI2]]
330 ; CHECK-NEXT: ret i32 [[RESULT]]
336 %a = load i32, ptr %a.ptr
337 br label %inner_loop_begin
340 %a.phi = phi i32 [ %a, %loop_begin ], [ %a2, %inner_inner_loop_exit ]
341 %cond = load i1, ptr %cond.ptr
342 %b = load i32, ptr %b.ptr
343 br label %inner_inner_loop_begin
345 inner_inner_loop_begin:
346 %v1 = load i1, ptr %ptr
347 br i1 %v1, label %inner_inner_loop_a, label %inner_inner_loop_b
350 %v2 = load i1, ptr %ptr
351 br i1 %v2, label %loop_exit, label %inner_inner_loop_c
354 %v3 = load i1, ptr %ptr
355 br i1 %v3, label %inner_inner_loop_exit, label %inner_inner_loop_c
358 %v4 = load i1, ptr %ptr
359 br i1 %v4, label %inner_loop_exit, label %inner_inner_loop_d
362 br i1 %cond, label %inner_inner_loop_begin, label %inner_loop_exit
363 ; The cloned copy that continues looping.
364 ; The original copy that now always exits and needs adjustments for exit
367 inner_inner_loop_exit:
368 %a2 = load i32, ptr %a.ptr
369 %v5 = load i1, ptr %ptr
370 br i1 %v5, label %inner_loop_exit, label %inner_loop_begin
376 %a.lcssa = phi i32 [ %a.phi, %inner_inner_loop_a ]
377 %b.lcssa = phi i32 [ %b, %inner_inner_loop_a ]
378 %result = add i32 %a.lcssa, %b.lcssa
382 ; Test that when the exit block set of an inner loop changes to start at a less
383 ; high level of the loop nest we correctly hoist the loop up the nest.
384 define i32 @test8a(ptr %ptr, ptr %cond.ptr, ptr %a.ptr, ptr %b.ptr) {
385 ; CHECK-LABEL: @test8a(
387 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
389 ; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR:%.*]], align 4
390 ; CHECK-NEXT: br label [[INNER_LOOP_BEGIN:%.*]]
391 ; CHECK: inner_loop_begin:
392 ; CHECK-NEXT: [[A_PHI:%.*]] = phi i32 [ [[A]], [[LOOP_BEGIN]] ], [ [[A2:%.*]], [[INNER_INNER_LOOP_EXIT:%.*]] ]
393 ; CHECK-NEXT: [[COND:%.*]] = load i1, ptr [[COND_PTR:%.*]], align 1
394 ; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[B_PTR:%.*]], align 4
395 ; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]]
396 ; CHECK-NEXT: br i1 [[COND_FR]], label [[INNER_LOOP_BEGIN_SPLIT_US:%.*]], label [[INNER_LOOP_BEGIN_SPLIT:%.*]]
397 ; CHECK: inner_loop_begin.split.us:
398 ; CHECK-NEXT: [[A_PHI_LCSSA4:%.*]] = phi i32 [ [[A_PHI]], [[INNER_LOOP_BEGIN]] ]
399 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US:%.*]]
400 ; CHECK: inner_inner_loop_begin.us:
401 ; CHECK-NEXT: [[V1_US:%.*]] = load i1, ptr [[PTR:%.*]], align 1
402 ; CHECK-NEXT: br i1 [[V1_US]], label [[INNER_INNER_LOOP_A_US:%.*]], label [[INNER_INNER_LOOP_B_US:%.*]]
403 ; CHECK: inner_inner_loop_b.us:
404 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_LATCH_US:%.*]]
405 ; CHECK: inner_inner_loop_a.us:
406 ; CHECK-NEXT: [[V2_US:%.*]] = load i1, ptr [[PTR]], align 1
407 ; CHECK-NEXT: br i1 [[V2_US]], label [[INNER_INNER_LOOP_LATCH_US]], label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT_US:%.*]]
408 ; CHECK: inner_inner_loop_latch.us:
409 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US]]
410 ; CHECK: inner_loop_exit.loopexit.split.us:
411 ; CHECK-NEXT: [[A_PHI_LCSSA2_US:%.*]] = phi i32 [ [[A_PHI_LCSSA4]], [[INNER_INNER_LOOP_A_US]] ]
412 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT:%.*]]
413 ; CHECK: inner_loop_begin.split:
414 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN:%.*]]
415 ; CHECK: inner_inner_loop_begin:
416 ; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR]], align 1
417 ; CHECK-NEXT: br i1 [[V1]], label [[INNER_INNER_LOOP_A:%.*]], label [[INNER_INNER_LOOP_B:%.*]]
418 ; CHECK: inner_inner_loop_a:
419 ; CHECK-NEXT: [[V2:%.*]] = load i1, ptr [[PTR]], align 1
420 ; CHECK-NEXT: br i1 [[V2]], label [[INNER_INNER_LOOP_LATCH:%.*]], label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT:%.*]]
421 ; CHECK: inner_inner_loop_b:
422 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_EXIT]]
423 ; CHECK: inner_inner_loop_latch:
424 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN]]
425 ; CHECK: inner_inner_loop_exit:
426 ; CHECK-NEXT: [[A2]] = load i32, ptr [[A_PTR]], align 4
427 ; CHECK-NEXT: [[V4:%.*]] = load i1, ptr [[PTR]], align 1
428 ; CHECK-NEXT: br i1 [[V4]], label [[INNER_LOOP_EXIT_LOOPEXIT1:%.*]], label [[INNER_LOOP_BEGIN]]
429 ; CHECK: inner_loop_exit.loopexit.split:
430 ; CHECK-NEXT: [[A_PHI_LCSSA2:%.*]] = phi i32 [ [[A_PHI]], [[INNER_INNER_LOOP_A]] ]
431 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT]]
432 ; CHECK: inner_loop_exit.loopexit:
433 ; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[A_PHI_LCSSA2]], [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT]] ], [ [[A_PHI_LCSSA2_US]], [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT_US]] ]
434 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT:%.*]]
435 ; CHECK: inner_loop_exit.loopexit1:
436 ; CHECK-NEXT: [[A_PHI_LCSSA:%.*]] = phi i32 [ [[A_PHI]], [[INNER_INNER_LOOP_EXIT]] ]
437 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT]]
438 ; CHECK: inner_loop_exit:
439 ; CHECK-NEXT: [[A_PHI3:%.*]] = phi i32 [ [[A_PHI_LCSSA]], [[INNER_LOOP_EXIT_LOOPEXIT1]] ], [ [[DOTUS_PHI]], [[INNER_LOOP_EXIT_LOOPEXIT]] ]
440 ; CHECK-NEXT: [[V5:%.*]] = load i1, ptr [[PTR]], align 1
441 ; CHECK-NEXT: br i1 [[V5]], label [[LOOP_EXIT:%.*]], label [[LOOP_BEGIN]]
443 ; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_PHI3]], [[INNER_LOOP_EXIT]] ]
444 ; CHECK-NEXT: ret i32 [[A_LCSSA]]
450 %a = load i32, ptr %a.ptr
451 br label %inner_loop_begin
454 %a.phi = phi i32 [ %a, %loop_begin ], [ %a2, %inner_inner_loop_exit ]
455 %cond = load i1, ptr %cond.ptr
456 %b = load i32, ptr %b.ptr
457 br label %inner_inner_loop_begin
459 inner_inner_loop_begin:
460 %v1 = load i1, ptr %ptr
461 br i1 %v1, label %inner_inner_loop_a, label %inner_inner_loop_b
464 %v2 = load i1, ptr %ptr
465 br i1 %v2, label %inner_inner_loop_latch, label %inner_loop_exit
468 br i1 %cond, label %inner_inner_loop_latch, label %inner_inner_loop_exit
470 inner_inner_loop_latch:
471 br label %inner_inner_loop_begin
472 ; The cloned region is now an exit from the inner loop.
473 ; The original region exits the loop earlier.
475 inner_inner_loop_exit:
476 %a2 = load i32, ptr %a.ptr
477 %v4 = load i1, ptr %ptr
478 br i1 %v4, label %inner_loop_exit, label %inner_loop_begin
481 %v5 = load i1, ptr %ptr
482 br i1 %v5, label %loop_exit, label %loop_begin
485 %a.lcssa = phi i32 [ %a.phi, %inner_loop_exit ]
489 ; Same pattern as @test8a but where the original loop looses an exit block and
490 ; needs to be hoisted up the nest.
491 define i32 @test8b(ptr %ptr, ptr %cond.ptr, ptr %a.ptr, ptr %b.ptr) {
492 ; CHECK-LABEL: @test8b(
494 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
496 ; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR:%.*]], align 4
497 ; CHECK-NEXT: br label [[INNER_LOOP_BEGIN:%.*]]
498 ; CHECK: inner_loop_begin:
499 ; CHECK-NEXT: [[A_PHI:%.*]] = phi i32 [ [[A]], [[LOOP_BEGIN]] ], [ [[A2:%.*]], [[INNER_INNER_LOOP_EXIT:%.*]] ]
500 ; CHECK-NEXT: [[COND:%.*]] = load i1, ptr [[COND_PTR:%.*]], align 1
501 ; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[B_PTR:%.*]], align 4
502 ; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]]
503 ; CHECK-NEXT: br i1 [[COND_FR]], label [[INNER_LOOP_BEGIN_SPLIT_US:%.*]], label [[INNER_LOOP_BEGIN_SPLIT:%.*]]
504 ; CHECK: inner_loop_begin.split.us:
505 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US:%.*]]
506 ; CHECK: inner_inner_loop_begin.us:
507 ; CHECK-NEXT: [[V1_US:%.*]] = load i1, ptr [[PTR:%.*]], align 1
508 ; CHECK-NEXT: br i1 [[V1_US]], label [[INNER_INNER_LOOP_A_US:%.*]], label [[INNER_INNER_LOOP_B_US:%.*]]
509 ; CHECK: inner_inner_loop_b.us:
510 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_EXIT_SPLIT_US:%.*]]
511 ; CHECK: inner_inner_loop_a.us:
512 ; CHECK-NEXT: [[V2_US:%.*]] = load i1, ptr [[PTR]], align 1
513 ; CHECK-NEXT: br i1 [[V2_US]], label [[INNER_INNER_LOOP_LATCH_US:%.*]], label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT_US:%.*]]
514 ; CHECK: inner_inner_loop_latch.us:
515 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US]]
516 ; CHECK: inner_inner_loop_exit.split.us:
517 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_EXIT]]
518 ; CHECK: inner_loop_exit.loopexit.split.us:
519 ; CHECK-NEXT: [[A_PHI_LCSSA2_US:%.*]] = phi i32 [ [[A_PHI]], [[INNER_INNER_LOOP_A_US]] ]
520 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT:%.*]]
521 ; CHECK: inner_loop_begin.split:
522 ; CHECK-NEXT: [[A_PHI_LCSSA4:%.*]] = phi i32 [ [[A_PHI]], [[INNER_LOOP_BEGIN]] ]
523 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN:%.*]]
524 ; CHECK: inner_inner_loop_begin:
525 ; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR]], align 1
526 ; CHECK-NEXT: br i1 [[V1]], label [[INNER_INNER_LOOP_A:%.*]], label [[INNER_INNER_LOOP_B:%.*]]
527 ; CHECK: inner_inner_loop_a:
528 ; CHECK-NEXT: [[V2:%.*]] = load i1, ptr [[PTR]], align 1
529 ; CHECK-NEXT: br i1 [[V2]], label [[INNER_INNER_LOOP_LATCH:%.*]], label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT:%.*]]
530 ; CHECK: inner_inner_loop_b:
531 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_LATCH]]
532 ; CHECK: inner_inner_loop_latch:
533 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN]]
534 ; CHECK: inner_inner_loop_exit:
535 ; CHECK-NEXT: [[A2]] = load i32, ptr [[A_PTR]], align 4
536 ; CHECK-NEXT: [[V4:%.*]] = load i1, ptr [[PTR]], align 1
537 ; CHECK-NEXT: br i1 [[V4]], label [[INNER_LOOP_EXIT_LOOPEXIT1:%.*]], label [[INNER_LOOP_BEGIN]]
538 ; CHECK: inner_loop_exit.loopexit.split:
539 ; CHECK-NEXT: [[A_PHI_LCSSA2:%.*]] = phi i32 [ [[A_PHI_LCSSA4]], [[INNER_INNER_LOOP_A]] ]
540 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT]]
541 ; CHECK: inner_loop_exit.loopexit:
542 ; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[A_PHI_LCSSA2]], [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT]] ], [ [[A_PHI_LCSSA2_US]], [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT_US]] ]
543 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT:%.*]]
544 ; CHECK: inner_loop_exit.loopexit1:
545 ; CHECK-NEXT: [[A_PHI_LCSSA:%.*]] = phi i32 [ [[A_PHI]], [[INNER_INNER_LOOP_EXIT]] ]
546 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT]]
547 ; CHECK: inner_loop_exit:
548 ; CHECK-NEXT: [[A_PHI3:%.*]] = phi i32 [ [[A_PHI_LCSSA]], [[INNER_LOOP_EXIT_LOOPEXIT1]] ], [ [[DOTUS_PHI]], [[INNER_LOOP_EXIT_LOOPEXIT]] ]
549 ; CHECK-NEXT: [[V5:%.*]] = load i1, ptr [[PTR]], align 1
550 ; CHECK-NEXT: br i1 [[V5]], label [[LOOP_EXIT:%.*]], label [[LOOP_BEGIN]]
552 ; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_PHI3]], [[INNER_LOOP_EXIT]] ]
553 ; CHECK-NEXT: ret i32 [[A_LCSSA]]
559 %a = load i32, ptr %a.ptr
560 br label %inner_loop_begin
563 %a.phi = phi i32 [ %a, %loop_begin ], [ %a2, %inner_inner_loop_exit ]
564 %cond = load i1, ptr %cond.ptr
565 %b = load i32, ptr %b.ptr
566 br label %inner_inner_loop_begin
568 inner_inner_loop_begin:
569 %v1 = load i1, ptr %ptr
570 br i1 %v1, label %inner_inner_loop_a, label %inner_inner_loop_b
573 %v2 = load i1, ptr %ptr
574 br i1 %v2, label %inner_inner_loop_latch, label %inner_loop_exit
577 br i1 %cond, label %inner_inner_loop_exit, label %inner_inner_loop_latch
579 inner_inner_loop_latch:
580 br label %inner_inner_loop_begin
581 ; The cloned region is similar to before but with one earlier exit.
582 ; The original region is now an exit in the preheader.
584 inner_inner_loop_exit:
585 %a2 = load i32, ptr %a.ptr
586 %v4 = load i1, ptr %ptr
587 br i1 %v4, label %inner_loop_exit, label %inner_loop_begin
590 %v5 = load i1, ptr %ptr
591 br i1 %v5, label %loop_exit, label %loop_begin
594 %a.lcssa = phi i32 [ %a.phi, %inner_loop_exit ]
598 ; Test that requires re-forming dedicated exits for the cloned loop.
599 define i32 @test10a(ptr %ptr, i1 %cond, ptr %a.ptr) {
600 ; CHECK-LABEL: @test10a(
602 ; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND:%.*]]
603 ; CHECK-NEXT: br i1 [[COND_FR]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
604 ; CHECK: entry.split.us:
605 ; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]]
606 ; CHECK: loop_begin.us:
607 ; CHECK-NEXT: [[A_US:%.*]] = load i32, ptr [[A_PTR:%.*]], align 4
608 ; CHECK-NEXT: [[V1_US:%.*]] = load i1, ptr [[PTR:%.*]], align 1
609 ; CHECK-NEXT: br i1 [[V1_US]], label [[LOOP_A_US:%.*]], label [[LOOP_B_US:%.*]]
611 ; CHECK-NEXT: [[A_US_LCSSA:%.*]] = phi i32 [ [[A_US]], [[LOOP_BEGIN_US]] ]
612 ; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT_US:%.*]]
614 ; CHECK-NEXT: [[V2_US:%.*]] = load i1, ptr [[PTR]], align 1
615 ; CHECK-NEXT: br i1 [[V2_US]], label [[LOOP_EXIT_SPLIT_US_LOOPEXIT:%.*]], label [[LOOP_BEGIN_BACKEDGE_US:%.*]]
616 ; CHECK: loop_begin.backedge.us:
617 ; CHECK-NEXT: br label [[LOOP_BEGIN_US]]
618 ; CHECK: loop_exit.split.us.loopexit:
619 ; CHECK-NEXT: [[A_LCSSA_US_PH:%.*]] = phi i32 [ [[A_US]], [[LOOP_A_US]] ]
620 ; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT_US]]
621 ; CHECK: loop_exit.split.us:
622 ; CHECK-NEXT: [[A_LCSSA_US:%.*]] = phi i32 [ [[A_US_LCSSA]], [[LOOP_B_US]] ], [ [[A_LCSSA_US_PH]], [[LOOP_EXIT_SPLIT_US_LOOPEXIT]] ]
623 ; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
624 ; CHECK: entry.split:
625 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
627 ; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR]], align 4
628 ; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR]], align 1
629 ; CHECK-NEXT: br i1 [[V1]], label [[LOOP_A:%.*]], label [[LOOP_B:%.*]]
631 ; CHECK-NEXT: [[V2:%.*]] = load i1, ptr [[PTR]], align 1
632 ; CHECK-NEXT: br i1 [[V2]], label [[LOOP_EXIT_SPLIT:%.*]], label [[LOOP_BEGIN_BACKEDGE:%.*]]
633 ; CHECK: loop_begin.backedge:
634 ; CHECK-NEXT: br label [[LOOP_BEGIN]]
636 ; CHECK-NEXT: br label [[LOOP_BEGIN_BACKEDGE]]
637 ; CHECK: loop_exit.split:
638 ; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A]], [[LOOP_A]] ]
639 ; CHECK-NEXT: br label [[LOOP_EXIT]]
641 ; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[A_LCSSA]], [[LOOP_EXIT_SPLIT]] ], [ [[A_LCSSA_US]], [[LOOP_EXIT_SPLIT_US]] ]
642 ; CHECK-NEXT: ret i32 [[DOTUS_PHI]]
648 %a = load i32, ptr %a.ptr
649 %v1 = load i1, ptr %ptr
650 br i1 %v1, label %loop_a, label %loop_b
653 %v2 = load i1, ptr %ptr
654 br i1 %v2, label %loop_exit, label %loop_begin
657 br i1 %cond, label %loop_exit, label %loop_begin
658 ; The cloned loop with one edge as a direct exit.
660 ; The original loop without one 'loop_exit' edge.
663 %a.lcssa = phi i32 [ %a, %loop_a ], [ %a, %loop_b ]
667 ; Test that requires re-forming dedicated exits for the original loop.
668 define i32 @test10b(ptr %ptr, i1 %cond, ptr %a.ptr) {
669 ; CHECK-LABEL: @test10b(
671 ; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND:%.*]]
672 ; CHECK-NEXT: br i1 [[COND_FR]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
673 ; CHECK: entry.split.us:
674 ; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]]
675 ; CHECK: loop_begin.us:
676 ; CHECK-NEXT: [[A_US:%.*]] = load i32, ptr [[A_PTR:%.*]], align 4
677 ; CHECK-NEXT: [[V1_US:%.*]] = load i1, ptr [[PTR:%.*]], align 1
678 ; CHECK-NEXT: br i1 [[V1_US]], label [[LOOP_A_US:%.*]], label [[LOOP_B_US:%.*]]
680 ; CHECK-NEXT: br label [[LOOP_BEGIN_BACKEDGE_US:%.*]]
682 ; CHECK-NEXT: [[V2_US:%.*]] = load i1, ptr [[PTR]], align 1
683 ; CHECK-NEXT: br i1 [[V2_US]], label [[LOOP_BEGIN_BACKEDGE_US]], label [[LOOP_EXIT_SPLIT_US:%.*]]
684 ; CHECK: loop_begin.backedge.us:
685 ; CHECK-NEXT: br label [[LOOP_BEGIN_US]]
686 ; CHECK: loop_exit.split.us:
687 ; CHECK-NEXT: [[A_LCSSA_US:%.*]] = phi i32 [ [[A_US]], [[LOOP_A_US]] ]
688 ; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
689 ; CHECK: entry.split:
690 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
692 ; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR]], align 4
693 ; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR]], align 1
694 ; CHECK-NEXT: br i1 [[V1]], label [[LOOP_A:%.*]], label [[LOOP_B:%.*]]
696 ; CHECK-NEXT: [[V2:%.*]] = load i1, ptr [[PTR]], align 1
697 ; CHECK-NEXT: br i1 [[V2]], label [[LOOP_BEGIN_BACKEDGE:%.*]], label [[LOOP_EXIT_SPLIT_LOOPEXIT:%.*]]
698 ; CHECK: loop_begin.backedge:
699 ; CHECK-NEXT: br label [[LOOP_BEGIN]]
701 ; CHECK-NEXT: [[A_LCSSA1:%.*]] = phi i32 [ [[A]], [[LOOP_BEGIN]] ]
702 ; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT:%.*]]
703 ; CHECK: loop_exit.split.loopexit:
704 ; CHECK-NEXT: [[A_LCSSA_PH:%.*]] = phi i32 [ [[A]], [[LOOP_A]] ]
705 ; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT]]
706 ; CHECK: loop_exit.split:
707 ; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_LCSSA1]], [[LOOP_B]] ], [ [[A_LCSSA_PH]], [[LOOP_EXIT_SPLIT_LOOPEXIT]] ]
708 ; CHECK-NEXT: br label [[LOOP_EXIT]]
710 ; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[A_LCSSA]], [[LOOP_EXIT_SPLIT]] ], [ [[A_LCSSA_US]], [[LOOP_EXIT_SPLIT_US]] ]
711 ; CHECK-NEXT: ret i32 [[DOTUS_PHI]]
717 %a = load i32, ptr %a.ptr
718 %v1 = load i1, ptr %ptr
719 br i1 %v1, label %loop_a, label %loop_b
722 %v2 = load i1, ptr %ptr
723 br i1 %v2, label %loop_begin, label %loop_exit
726 br i1 %cond, label %loop_begin, label %loop_exit
727 ; The cloned loop without one of the exits.
729 ; The original loop without one 'loop_exit' edge.
732 %a.lcssa = phi i32 [ %a, %loop_a ], [ %a, %loop_b ]
736 ; Check that if a cloned inner loop after unswitching doesn't loop and directly
737 ; exits even an outer loop, we don't add the cloned preheader to the outer
738 ; loop and do add the needed LCSSA phi nodes for the new exit block from the
740 define i32 @test11a(ptr %ptr, ptr %cond.ptr, ptr %a.ptr, ptr %b.ptr) {
741 ; CHECK-LABEL: @test11a(
743 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
745 ; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[B_PTR:%.*]], align 4
746 ; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR:%.*]], align 1
747 ; CHECK-NEXT: br i1 [[V1]], label [[LOOP_LATCH:%.*]], label [[INNER_LOOP_PH:%.*]]
748 ; CHECK: inner_loop_ph:
749 ; CHECK-NEXT: [[COND:%.*]] = load i1, ptr [[COND_PTR:%.*]], align 1
750 ; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]]
751 ; CHECK-NEXT: br i1 [[COND_FR]], label [[INNER_LOOP_PH_SPLIT_US:%.*]], label [[INNER_LOOP_PH_SPLIT:%.*]]
752 ; CHECK: inner_loop_ph.split.us:
753 ; CHECK-NEXT: [[B_LCSSA:%.*]] = phi i32 [ [[B]], [[INNER_LOOP_PH]] ]
754 ; CHECK-NEXT: br label [[INNER_LOOP_BEGIN_US:%.*]]
755 ; CHECK: inner_loop_begin.us:
756 ; CHECK-NEXT: call void @sink1(i32 [[B_LCSSA]])
757 ; CHECK-NEXT: [[A_US:%.*]] = load i32, ptr [[A_PTR:%.*]], align 4
758 ; CHECK-NEXT: br label [[LOOP_EXIT_LOOPEXIT_SPLIT_US:%.*]]
759 ; CHECK: loop_exit.loopexit.split.us:
760 ; CHECK-NEXT: [[A_LCSSA2_US:%.*]] = phi i32 [ [[A_US]], [[INNER_LOOP_BEGIN_US]] ]
761 ; CHECK-NEXT: br label [[LOOP_EXIT_LOOPEXIT:%.*]]
762 ; CHECK: inner_loop_ph.split:
763 ; CHECK-NEXT: br label [[INNER_LOOP_BEGIN:%.*]]
764 ; CHECK: inner_loop_begin:
765 ; CHECK-NEXT: call void @sink1(i32 [[B]])
766 ; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR]], align 4
767 ; CHECK-NEXT: br label [[INNER_LOOP_A:%.*]]
768 ; CHECK: inner_loop_a:
769 ; CHECK-NEXT: [[V2:%.*]] = load i1, ptr [[PTR]], align 1
770 ; CHECK-NEXT: br i1 [[V2]], label [[INNER_LOOP_EXIT:%.*]], label [[INNER_LOOP_BEGIN]]
771 ; CHECK: inner_loop_exit:
772 ; CHECK-NEXT: [[A_INNER_LCSSA:%.*]] = phi i32 [ [[A]], [[INNER_LOOP_A]] ]
773 ; CHECK-NEXT: [[V3:%.*]] = load i1, ptr [[PTR]], align 1
774 ; CHECK-NEXT: br i1 [[V3]], label [[LOOP_LATCH]], label [[LOOP_EXIT_LOOPEXIT1:%.*]]
776 ; CHECK-NEXT: br label [[LOOP_BEGIN]]
777 ; CHECK: loop_exit.loopexit:
778 ; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
779 ; CHECK: loop_exit.loopexit1:
780 ; CHECK-NEXT: [[A_INNER_LCSSA_LCSSA:%.*]] = phi i32 [ [[A_INNER_LCSSA]], [[INNER_LOOP_EXIT]] ]
781 ; CHECK-NEXT: br label [[LOOP_EXIT]]
783 ; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_LCSSA2_US]], [[LOOP_EXIT_LOOPEXIT]] ], [ [[A_INNER_LCSSA_LCSSA]], [[LOOP_EXIT_LOOPEXIT1]] ]
784 ; CHECK-NEXT: ret i32 [[A_LCSSA]]
790 %b = load i32, ptr %b.ptr
791 %v1 = load i1, ptr %ptr
792 br i1 %v1, label %loop_latch, label %inner_loop_ph
795 %cond = load i1, ptr %cond.ptr
796 br label %inner_loop_begin
799 call void @sink1(i32 %b)
800 %a = load i32, ptr %a.ptr
801 br i1 %cond, label %loop_exit, label %inner_loop_a
804 %v2 = load i1, ptr %ptr
805 br i1 %v2, label %inner_loop_exit, label %inner_loop_begin
806 ; The cloned path doesn't actually loop and is an exit from the outer loop as
808 ; The original remains a loop losing the exit edge.
811 %a.inner_lcssa = phi i32 [ %a, %inner_loop_a ]
812 %v3 = load i1, ptr %ptr
813 br i1 %v3, label %loop_latch, label %loop_exit
819 %a.lcssa = phi i32 [ %a, %inner_loop_begin ], [ %a.inner_lcssa, %inner_loop_exit ]
823 ; Check that if the original inner loop after unswitching doesn't loop and
824 ; directly exits even an outer loop, we remove the original preheader from the
825 ; outer loop and add needed LCSSA phi nodes for the new exit block from the
827 define i32 @test11b(ptr %ptr, ptr %cond.ptr, ptr %a.ptr, ptr %b.ptr) {
828 ; CHECK-LABEL: @test11b(
830 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
832 ; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[B_PTR:%.*]], align 4
833 ; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR:%.*]], align 1
834 ; CHECK-NEXT: br i1 [[V1]], label [[LOOP_LATCH:%.*]], label [[INNER_LOOP_PH:%.*]]
835 ; CHECK: inner_loop_ph:
836 ; CHECK-NEXT: [[COND:%.*]] = load i1, ptr [[COND_PTR:%.*]], align 1
837 ; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]]
838 ; CHECK-NEXT: br i1 [[COND_FR]], label [[INNER_LOOP_PH_SPLIT_US:%.*]], label [[INNER_LOOP_PH_SPLIT:%.*]]
839 ; CHECK: inner_loop_ph.split.us:
840 ; CHECK-NEXT: br label [[INNER_LOOP_BEGIN_US:%.*]]
841 ; CHECK: inner_loop_begin.us:
842 ; CHECK-NEXT: call void @sink1(i32 [[B]])
843 ; CHECK-NEXT: [[A_US:%.*]] = load i32, ptr [[A_PTR:%.*]], align 4
844 ; CHECK-NEXT: br label [[INNER_LOOP_A_US:%.*]]
845 ; CHECK: inner_loop_a.us:
846 ; CHECK-NEXT: [[V2_US:%.*]] = load i1, ptr [[PTR]], align 1
847 ; CHECK-NEXT: br i1 [[V2_US]], label [[INNER_LOOP_EXIT_SPLIT_US:%.*]], label [[INNER_LOOP_BEGIN_US]]
848 ; CHECK: inner_loop_exit.split.us:
849 ; CHECK-NEXT: [[A_INNER_LCSSA_US:%.*]] = phi i32 [ [[A_US]], [[INNER_LOOP_A_US]] ]
850 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT:%.*]]
851 ; CHECK: inner_loop_ph.split:
852 ; CHECK-NEXT: [[B_LCSSA:%.*]] = phi i32 [ [[B]], [[INNER_LOOP_PH]] ]
853 ; CHECK-NEXT: br label [[INNER_LOOP_BEGIN:%.*]]
854 ; CHECK: inner_loop_begin:
855 ; CHECK-NEXT: call void @sink1(i32 [[B_LCSSA]])
856 ; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR]], align 4
857 ; CHECK-NEXT: br label [[LOOP_EXIT_LOOPEXIT:%.*]]
858 ; CHECK: inner_loop_exit:
859 ; CHECK-NEXT: [[V3:%.*]] = load i1, ptr [[PTR]], align 1
860 ; CHECK-NEXT: br i1 [[V3]], label [[LOOP_LATCH]], label [[LOOP_EXIT_LOOPEXIT1:%.*]]
862 ; CHECK-NEXT: br label [[LOOP_BEGIN]]
863 ; CHECK: loop_exit.loopexit:
864 ; CHECK-NEXT: [[A_LCSSA2:%.*]] = phi i32 [ [[A]], [[INNER_LOOP_BEGIN]] ]
865 ; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
866 ; CHECK: loop_exit.loopexit1:
867 ; CHECK-NEXT: [[A_INNER_LCSSA_LCSSA:%.*]] = phi i32 [ [[A_INNER_LCSSA_US]], [[INNER_LOOP_EXIT]] ]
868 ; CHECK-NEXT: br label [[LOOP_EXIT]]
870 ; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_LCSSA2]], [[LOOP_EXIT_LOOPEXIT]] ], [ [[A_INNER_LCSSA_LCSSA]], [[LOOP_EXIT_LOOPEXIT1]] ]
871 ; CHECK-NEXT: ret i32 [[A_LCSSA]]
877 %b = load i32, ptr %b.ptr
878 %v1 = load i1, ptr %ptr
879 br i1 %v1, label %loop_latch, label %inner_loop_ph
882 %cond = load i1, ptr %cond.ptr
883 br label %inner_loop_begin
886 call void @sink1(i32 %b)
887 %a = load i32, ptr %a.ptr
888 br i1 %cond, label %inner_loop_a, label %loop_exit
891 %v2 = load i1, ptr %ptr
892 br i1 %v2, label %inner_loop_exit, label %inner_loop_begin
893 ; The cloned path continues to loop without the exit out of the entire nest.
894 ; The original remains a loop losing the exit edge.
897 %a.inner_lcssa = phi i32 [ %a, %inner_loop_a ]
898 %v3 = load i1, ptr %ptr
899 br i1 %v3, label %loop_latch, label %loop_exit
905 %a.lcssa = phi i32 [ %a, %inner_loop_begin ], [ %a.inner_lcssa, %inner_loop_exit ]
909 ; Like test11a, but checking that when the whole thing is wrapped in yet
910 ; another loop, we correctly attribute the cloned preheader to that outermost
911 ; loop rather than only handling the case where the preheader is not in any loop
913 define i32 @test12a(ptr %ptr, ptr %cond.ptr, ptr %a.ptr, ptr %b.ptr) {
914 ; CHECK-LABEL: @test12a(
916 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
918 ; CHECK-NEXT: br label [[INNER_LOOP_BEGIN:%.*]]
919 ; CHECK: inner_loop_begin:
920 ; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[B_PTR:%.*]], align 4
921 ; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR:%.*]], align 1
922 ; CHECK-NEXT: br i1 [[V1]], label [[INNER_LOOP_LATCH:%.*]], label [[INNER_INNER_LOOP_PH:%.*]]
923 ; CHECK: inner_inner_loop_ph:
924 ; CHECK-NEXT: [[COND:%.*]] = load i1, ptr [[COND_PTR:%.*]], align 1
925 ; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]]
926 ; CHECK-NEXT: br i1 [[COND_FR]], label [[INNER_INNER_LOOP_PH_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_PH_SPLIT:%.*]]
927 ; CHECK: inner_inner_loop_ph.split.us:
928 ; CHECK-NEXT: [[B_LCSSA:%.*]] = phi i32 [ [[B]], [[INNER_INNER_LOOP_PH]] ]
929 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US:%.*]]
930 ; CHECK: inner_inner_loop_begin.us:
931 ; CHECK-NEXT: call void @sink1(i32 [[B_LCSSA]])
932 ; CHECK-NEXT: [[A_US:%.*]] = load i32, ptr [[A_PTR:%.*]], align 4
933 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT_SPLIT_US:%.*]]
934 ; CHECK: inner_loop_exit.loopexit.split.us:
935 ; CHECK-NEXT: [[A_LCSSA2_US:%.*]] = phi i32 [ [[A_US]], [[INNER_INNER_LOOP_BEGIN_US]] ]
936 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT:%.*]]
937 ; CHECK: inner_inner_loop_ph.split:
938 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN:%.*]]
939 ; CHECK: inner_inner_loop_begin:
940 ; CHECK-NEXT: call void @sink1(i32 [[B]])
941 ; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR]], align 4
942 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_A:%.*]]
943 ; CHECK: inner_inner_loop_a:
944 ; CHECK-NEXT: [[V2:%.*]] = load i1, ptr [[PTR]], align 1
945 ; CHECK-NEXT: br i1 [[V2]], label [[INNER_INNER_LOOP_EXIT:%.*]], label [[INNER_INNER_LOOP_BEGIN]]
946 ; CHECK: inner_inner_loop_exit:
947 ; CHECK-NEXT: [[A_INNER_INNER_LCSSA:%.*]] = phi i32 [ [[A]], [[INNER_INNER_LOOP_A]] ]
948 ; CHECK-NEXT: [[V3:%.*]] = load i1, ptr [[PTR]], align 1
949 ; CHECK-NEXT: br i1 [[V3]], label [[INNER_LOOP_LATCH]], label [[INNER_LOOP_EXIT_LOOPEXIT1:%.*]]
950 ; CHECK: inner_loop_latch:
951 ; CHECK-NEXT: br label [[INNER_LOOP_BEGIN]]
952 ; CHECK: inner_loop_exit.loopexit:
953 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT:%.*]]
954 ; CHECK: inner_loop_exit.loopexit1:
955 ; CHECK-NEXT: [[A_INNER_INNER_LCSSA_LCSSA:%.*]] = phi i32 [ [[A_INNER_INNER_LCSSA]], [[INNER_INNER_LOOP_EXIT]] ]
956 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT]]
957 ; CHECK: inner_loop_exit:
958 ; CHECK-NEXT: [[A_INNER_LCSSA:%.*]] = phi i32 [ [[A_LCSSA2_US]], [[INNER_LOOP_EXIT_LOOPEXIT]] ], [ [[A_INNER_INNER_LCSSA_LCSSA]], [[INNER_LOOP_EXIT_LOOPEXIT1]] ]
959 ; CHECK-NEXT: [[V4:%.*]] = load i1, ptr [[PTR]], align 1
960 ; CHECK-NEXT: br i1 [[V4]], label [[LOOP_BEGIN]], label [[LOOP_EXIT:%.*]]
962 ; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_INNER_LCSSA]], [[INNER_LOOP_EXIT]] ]
963 ; CHECK-NEXT: ret i32 [[A_LCSSA]]
969 br label %inner_loop_begin
972 %b = load i32, ptr %b.ptr
973 %v1 = load i1, ptr %ptr
974 br i1 %v1, label %inner_loop_latch, label %inner_inner_loop_ph
977 %cond = load i1, ptr %cond.ptr
978 br label %inner_inner_loop_begin
980 inner_inner_loop_begin:
981 call void @sink1(i32 %b)
982 %a = load i32, ptr %a.ptr
983 br i1 %cond, label %inner_loop_exit, label %inner_inner_loop_a
986 %v2 = load i1, ptr %ptr
987 br i1 %v2, label %inner_inner_loop_exit, label %inner_inner_loop_begin
988 ; The cloned path doesn't actually loop and is an exit from the outer loop as
990 ; The original remains a loop losing the exit edge.
992 inner_inner_loop_exit:
993 %a.inner_inner_lcssa = phi i32 [ %a, %inner_inner_loop_a ]
994 %v3 = load i1, ptr %ptr
995 br i1 %v3, label %inner_loop_latch, label %inner_loop_exit
998 br label %inner_loop_begin
1001 %a.inner_lcssa = phi i32 [ %a, %inner_inner_loop_begin ], [ %a.inner_inner_lcssa, %inner_inner_loop_exit ]
1002 %v4 = load i1, ptr %ptr
1003 br i1 %v4, label %loop_begin, label %loop_exit
1006 %a.lcssa = phi i32 [ %a.inner_lcssa, %inner_loop_exit ]
1010 ; Like test11b, but checking that when the whole thing is wrapped in yet
1011 ; another loop, we correctly sink the preheader to the outermost loop rather
1012 ; than only handling the case where the preheader is completely removed from
1014 define i32 @test12b(ptr %ptr, ptr %cond.ptr, ptr %a.ptr, ptr %b.ptr) {
1015 ; CHECK-LABEL: @test12b(
1016 ; CHECK-NEXT: entry:
1017 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
1018 ; CHECK: loop_begin:
1019 ; CHECK-NEXT: br label [[INNER_LOOP_BEGIN:%.*]]
1020 ; CHECK: inner_loop_begin:
1021 ; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[B_PTR:%.*]], align 4
1022 ; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR:%.*]], align 1
1023 ; CHECK-NEXT: br i1 [[V1]], label [[INNER_LOOP_LATCH:%.*]], label [[INNER_INNER_LOOP_PH:%.*]]
1024 ; CHECK: inner_inner_loop_ph:
1025 ; CHECK-NEXT: [[COND:%.*]] = load i1, ptr [[COND_PTR:%.*]], align 1
1026 ; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND]]
1027 ; CHECK-NEXT: br i1 [[COND_FR]], label [[INNER_INNER_LOOP_PH_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_PH_SPLIT:%.*]]
1028 ; CHECK: inner_inner_loop_ph.split.us:
1029 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN_US:%.*]]
1030 ; CHECK: inner_inner_loop_begin.us:
1031 ; CHECK-NEXT: call void @sink1(i32 [[B]])
1032 ; CHECK-NEXT: [[A_US:%.*]] = load i32, ptr [[A_PTR:%.*]], align 4
1033 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_A_US:%.*]]
1034 ; CHECK: inner_inner_loop_a.us:
1035 ; CHECK-NEXT: [[V2_US:%.*]] = load i1, ptr [[PTR]], align 1
1036 ; CHECK-NEXT: br i1 [[V2_US]], label [[INNER_INNER_LOOP_EXIT_SPLIT_US:%.*]], label [[INNER_INNER_LOOP_BEGIN_US]]
1037 ; CHECK: inner_inner_loop_exit.split.us:
1038 ; CHECK-NEXT: [[A_INNER_INNER_LCSSA_US:%.*]] = phi i32 [ [[A_US]], [[INNER_INNER_LOOP_A_US]] ]
1039 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_EXIT:%.*]]
1040 ; CHECK: inner_inner_loop_ph.split:
1041 ; CHECK-NEXT: [[B_LCSSA:%.*]] = phi i32 [ [[B]], [[INNER_INNER_LOOP_PH]] ]
1042 ; CHECK-NEXT: br label [[INNER_INNER_LOOP_BEGIN:%.*]]
1043 ; CHECK: inner_inner_loop_begin:
1044 ; CHECK-NEXT: call void @sink1(i32 [[B_LCSSA]])
1045 ; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR]], align 4
1046 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT_LOOPEXIT:%.*]]
1047 ; CHECK: inner_inner_loop_exit:
1048 ; CHECK-NEXT: [[V3:%.*]] = load i1, ptr [[PTR]], align 1
1049 ; CHECK-NEXT: br i1 [[V3]], label [[INNER_LOOP_LATCH]], label [[INNER_LOOP_EXIT_LOOPEXIT1:%.*]]
1050 ; CHECK: inner_loop_latch:
1051 ; CHECK-NEXT: br label [[INNER_LOOP_BEGIN]]
1052 ; CHECK: inner_loop_exit.loopexit:
1053 ; CHECK-NEXT: [[A_LCSSA2:%.*]] = phi i32 [ [[A]], [[INNER_INNER_LOOP_BEGIN]] ]
1054 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT:%.*]]
1055 ; CHECK: inner_loop_exit.loopexit1:
1056 ; CHECK-NEXT: [[A_INNER_INNER_LCSSA_LCSSA:%.*]] = phi i32 [ [[A_INNER_INNER_LCSSA_US]], [[INNER_INNER_LOOP_EXIT]] ]
1057 ; CHECK-NEXT: br label [[INNER_LOOP_EXIT]]
1058 ; CHECK: inner_loop_exit:
1059 ; CHECK-NEXT: [[A_INNER_LCSSA:%.*]] = phi i32 [ [[A_LCSSA2]], [[INNER_LOOP_EXIT_LOOPEXIT]] ], [ [[A_INNER_INNER_LCSSA_LCSSA]], [[INNER_LOOP_EXIT_LOOPEXIT1]] ]
1060 ; CHECK-NEXT: [[V4:%.*]] = load i1, ptr [[PTR]], align 1
1061 ; CHECK-NEXT: br i1 [[V4]], label [[LOOP_BEGIN]], label [[LOOP_EXIT:%.*]]
1063 ; CHECK-NEXT: [[A_LCSSA:%.*]] = phi i32 [ [[A_INNER_LCSSA]], [[INNER_LOOP_EXIT]] ]
1064 ; CHECK-NEXT: ret i32 [[A_LCSSA]]
1067 br label %loop_begin
1070 br label %inner_loop_begin
1073 %b = load i32, ptr %b.ptr
1074 %v1 = load i1, ptr %ptr
1075 br i1 %v1, label %inner_loop_latch, label %inner_inner_loop_ph
1077 inner_inner_loop_ph:
1078 %cond = load i1, ptr %cond.ptr
1079 br label %inner_inner_loop_begin
1081 inner_inner_loop_begin:
1082 call void @sink1(i32 %b)
1083 %a = load i32, ptr %a.ptr
1084 br i1 %cond, label %inner_inner_loop_a, label %inner_loop_exit
1087 %v2 = load i1, ptr %ptr
1088 br i1 %v2, label %inner_inner_loop_exit, label %inner_inner_loop_begin
1089 ; The cloned path continues to loop without the exit out of the entire nest.
1090 ; The original remains a loop losing the exit edge.
1092 inner_inner_loop_exit:
1093 %a.inner_inner_lcssa = phi i32 [ %a, %inner_inner_loop_a ]
1094 %v3 = load i1, ptr %ptr
1095 br i1 %v3, label %inner_loop_latch, label %inner_loop_exit
1098 br label %inner_loop_begin
1101 %a.inner_lcssa = phi i32 [ %a, %inner_inner_loop_begin ], [ %a.inner_inner_lcssa, %inner_inner_loop_exit ]
1102 %v4 = load i1, ptr %ptr
1103 br i1 %v4, label %loop_begin, label %loop_exit
1106 %a.lcssa = phi i32 [ %a.inner_lcssa, %inner_loop_exit ]
1110 ; Test where the cloned loop has an inner loop that has to be traversed to form
1111 ; the cloned loop, and where this inner loop has multiple blocks, and where the
1112 ; exiting block that connects the inner loop to the cloned loop is not the header
1113 ; block. This ensures that we correctly handle interesting corner cases of
1114 ; traversing back to the header when establishing the cloned loop.
1115 define i32 @test13a(ptr %ptr, i1 %cond, ptr %a.ptr, ptr %b.ptr) {
1116 ; CHECK-LABEL: @test13a(
1117 ; CHECK-NEXT: entry:
1118 ; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND:%.*]]
1119 ; CHECK-NEXT: br i1 [[COND_FR]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
1120 ; CHECK: entry.split.us:
1121 ; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]]
1122 ; CHECK: loop_begin.us:
1123 ; CHECK-NEXT: [[A_US:%.*]] = load i32, ptr [[A_PTR:%.*]], align 4
1124 ; CHECK-NEXT: [[V1_US:%.*]] = load i1, ptr [[PTR:%.*]], align 1
1125 ; CHECK-NEXT: br i1 [[V1_US]], label [[LOOP_A_US:%.*]], label [[LOOP_B_US:%.*]]
1127 ; CHECK-NEXT: [[B_US:%.*]] = load i32, ptr [[B_PTR:%.*]], align 4
1128 ; CHECK-NEXT: br label [[LOOP_B_INNER_PH_US:%.*]]
1129 ; CHECK: loop_b_inner_ph.us:
1130 ; CHECK-NEXT: br label [[LOOP_B_INNER_HEADER_US:%.*]]
1131 ; CHECK: loop_b_inner_header.us:
1132 ; CHECK-NEXT: [[V3_US:%.*]] = load i1, ptr [[PTR]], align 1
1133 ; CHECK-NEXT: br i1 [[V3_US]], label [[LOOP_B_INNER_LATCH_US:%.*]], label [[LOOP_B_INNER_BODY_US:%.*]]
1134 ; CHECK: loop_b_inner_body.us:
1135 ; CHECK-NEXT: [[V4_US:%.*]] = load i1, ptr [[PTR]], align 1
1136 ; CHECK-NEXT: br i1 [[V4_US]], label [[LOOP_B_INNER_LATCH_US]], label [[LOOP_B_INNER_EXIT_US:%.*]]
1137 ; CHECK: loop_b_inner_exit.us:
1138 ; CHECK-NEXT: br label [[LOOP_LATCH_US:%.*]]
1139 ; CHECK: loop_b_inner_latch.us:
1140 ; CHECK-NEXT: br label [[LOOP_B_INNER_HEADER_US]]
1142 ; CHECK-NEXT: [[V2_US:%.*]] = load i1, ptr [[PTR]], align 1
1143 ; CHECK-NEXT: br i1 [[V2_US]], label [[LOOP_EXIT_SPLIT_US:%.*]], label [[LOOP_LATCH_US]]
1144 ; CHECK: loop_latch.us:
1145 ; CHECK-NEXT: br label [[LOOP_BEGIN_US]]
1146 ; CHECK: loop_exit.split.us:
1147 ; CHECK-NEXT: [[LCSSA_US:%.*]] = phi i32 [ [[A_US]], [[LOOP_A_US]] ]
1148 ; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
1149 ; CHECK: entry.split:
1150 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
1151 ; CHECK: loop_begin:
1152 ; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR]], align 4
1153 ; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR]], align 1
1154 ; CHECK-NEXT: br i1 [[V1]], label [[LOOP_A:%.*]], label [[LOOP_B:%.*]]
1156 ; CHECK-NEXT: [[V2:%.*]] = load i1, ptr [[PTR]], align 1
1157 ; CHECK-NEXT: br i1 [[V2]], label [[LOOP_EXIT_SPLIT_LOOPEXIT:%.*]], label [[LOOP_LATCH:%.*]]
1159 ; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[B_PTR]], align 4
1160 ; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT:%.*]]
1161 ; CHECK: loop_latch:
1162 ; CHECK-NEXT: br label [[LOOP_BEGIN]]
1163 ; CHECK: loop_exit.split.loopexit:
1164 ; CHECK-NEXT: [[LCSSA_PH:%.*]] = phi i32 [ [[A]], [[LOOP_A]] ]
1165 ; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT]]
1166 ; CHECK: loop_exit.split:
1167 ; CHECK-NEXT: [[LCSSA:%.*]] = phi i32 [ [[B]], [[LOOP_B]] ], [ [[LCSSA_PH]], [[LOOP_EXIT_SPLIT_LOOPEXIT]] ]
1168 ; CHECK-NEXT: br label [[LOOP_EXIT]]
1170 ; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[LCSSA]], [[LOOP_EXIT_SPLIT]] ], [ [[LCSSA_US]], [[LOOP_EXIT_SPLIT_US]] ]
1171 ; CHECK-NEXT: ret i32 [[DOTUS_PHI]]
1174 br label %loop_begin
1177 %a = load i32, ptr %a.ptr
1178 %v1 = load i1, ptr %ptr
1179 br i1 %v1, label %loop_a, label %loop_b
1182 %v2 = load i1, ptr %ptr
1183 br i1 %v2, label %loop_exit, label %loop_latch
1186 %b = load i32, ptr %b.ptr
1187 br i1 %cond, label %loop_b_inner_ph, label %loop_exit
1190 br label %loop_b_inner_header
1192 loop_b_inner_header:
1193 %v3 = load i1, ptr %ptr
1194 br i1 %v3, label %loop_b_inner_latch, label %loop_b_inner_body
1197 %v4 = load i1, ptr %ptr
1198 br i1 %v4, label %loop_b_inner_latch, label %loop_b_inner_exit
1201 br label %loop_b_inner_header
1204 br label %loop_latch
1207 br label %loop_begin
1208 ; The cloned loop contains an inner loop within it.
1209 ; And the original loop no longer contains an inner loop.
1212 %lcssa = phi i32 [ %a, %loop_a ], [ %b, %loop_b ]
1216 ; Test where the original loop has an inner loop that has to be traversed to
1217 ; rebuild the loop, and where this inner loop has multiple blocks, and where
1218 ; the exiting block that connects the inner loop to the original loop is not
1219 ; the header block. This ensures that we correctly handle interesting corner
1220 ; cases of traversing back to the header when re-establishing the original loop
1221 ; still exists after unswitching.
1222 define i32 @test13b(ptr %ptr, i1 %cond, ptr %a.ptr, ptr %b.ptr) {
1223 ; CHECK-LABEL: @test13b(
1224 ; CHECK-NEXT: entry:
1225 ; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND:%.*]]
1226 ; CHECK-NEXT: br i1 [[COND_FR]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
1227 ; CHECK: entry.split.us:
1228 ; CHECK-NEXT: br label [[LOOP_BEGIN_US:%.*]]
1229 ; CHECK: loop_begin.us:
1230 ; CHECK-NEXT: [[A_US:%.*]] = load i32, ptr [[A_PTR:%.*]], align 4
1231 ; CHECK-NEXT: [[V1_US:%.*]] = load i1, ptr [[PTR:%.*]], align 1
1232 ; CHECK-NEXT: br i1 [[V1_US]], label [[LOOP_A_US:%.*]], label [[LOOP_B_US:%.*]]
1234 ; CHECK-NEXT: [[B_US:%.*]] = load i32, ptr [[B_PTR:%.*]], align 4
1235 ; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT_US:%.*]]
1237 ; CHECK-NEXT: [[V2_US:%.*]] = load i1, ptr [[PTR]], align 1
1238 ; CHECK-NEXT: br i1 [[V2_US]], label [[LOOP_EXIT_SPLIT_US_LOOPEXIT:%.*]], label [[LOOP_LATCH_US:%.*]]
1239 ; CHECK: loop_latch.us:
1240 ; CHECK-NEXT: br label [[LOOP_BEGIN_US]]
1241 ; CHECK: loop_exit.split.us.loopexit:
1242 ; CHECK-NEXT: [[LCSSA_US_PH:%.*]] = phi i32 [ [[A_US]], [[LOOP_A_US]] ]
1243 ; CHECK-NEXT: br label [[LOOP_EXIT_SPLIT_US]]
1244 ; CHECK: loop_exit.split.us:
1245 ; CHECK-NEXT: [[LCSSA_US:%.*]] = phi i32 [ [[B_US]], [[LOOP_B_US]] ], [ [[LCSSA_US_PH]], [[LOOP_EXIT_SPLIT_US_LOOPEXIT]] ]
1246 ; CHECK-NEXT: br label [[LOOP_EXIT:%.*]]
1247 ; CHECK: entry.split:
1248 ; CHECK-NEXT: br label [[LOOP_BEGIN:%.*]]
1249 ; CHECK: loop_begin:
1250 ; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[A_PTR]], align 4
1251 ; CHECK-NEXT: [[V1:%.*]] = load i1, ptr [[PTR]], align 1
1252 ; CHECK-NEXT: br i1 [[V1]], label [[LOOP_A:%.*]], label [[LOOP_B:%.*]]
1254 ; CHECK-NEXT: [[V2:%.*]] = load i1, ptr [[PTR]], align 1
1255 ; CHECK-NEXT: br i1 [[V2]], label [[LOOP_EXIT_SPLIT:%.*]], label [[LOOP_LATCH:%.*]]
1257 ; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[B_PTR]], align 4
1258 ; CHECK-NEXT: br label [[LOOP_B_INNER_PH:%.*]]
1259 ; CHECK: loop_b_inner_ph:
1260 ; CHECK-NEXT: br label [[LOOP_B_INNER_HEADER:%.*]]
1261 ; CHECK: loop_b_inner_header:
1262 ; CHECK-NEXT: [[V3:%.*]] = load i1, ptr [[PTR]], align 1
1263 ; CHECK-NEXT: br i1 [[V3]], label [[LOOP_B_INNER_LATCH:%.*]], label [[LOOP_B_INNER_BODY:%.*]]
1264 ; CHECK: loop_b_inner_body:
1265 ; CHECK-NEXT: [[V4:%.*]] = load i1, ptr [[PTR]], align 1
1266 ; CHECK-NEXT: br i1 [[V4]], label [[LOOP_B_INNER_LATCH]], label [[LOOP_B_INNER_EXIT:%.*]]
1267 ; CHECK: loop_b_inner_latch:
1268 ; CHECK-NEXT: br label [[LOOP_B_INNER_HEADER]]
1269 ; CHECK: loop_b_inner_exit:
1270 ; CHECK-NEXT: br label [[LOOP_LATCH]]
1271 ; CHECK: loop_latch:
1272 ; CHECK-NEXT: br label [[LOOP_BEGIN]]
1273 ; CHECK: loop_exit.split:
1274 ; CHECK-NEXT: [[LCSSA:%.*]] = phi i32 [ [[A]], [[LOOP_A]] ]
1275 ; CHECK-NEXT: br label [[LOOP_EXIT]]
1277 ; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[LCSSA]], [[LOOP_EXIT_SPLIT]] ], [ [[LCSSA_US]], [[LOOP_EXIT_SPLIT_US]] ]
1278 ; CHECK-NEXT: ret i32 [[DOTUS_PHI]]
1281 br label %loop_begin
1284 %a = load i32, ptr %a.ptr
1285 %v1 = load i1, ptr %ptr
1286 br i1 %v1, label %loop_a, label %loop_b
1289 %v2 = load i1, ptr %ptr
1290 br i1 %v2, label %loop_exit, label %loop_latch
1293 %b = load i32, ptr %b.ptr
1294 br i1 %cond, label %loop_exit, label %loop_b_inner_ph
1297 br label %loop_b_inner_header
1299 loop_b_inner_header:
1300 %v3 = load i1, ptr %ptr
1301 br i1 %v3, label %loop_b_inner_latch, label %loop_b_inner_body
1304 %v4 = load i1, ptr %ptr
1305 br i1 %v4, label %loop_b_inner_latch, label %loop_b_inner_exit
1308 br label %loop_b_inner_header
1311 br label %loop_latch
1314 br label %loop_begin
1315 ; The cloned loop doesn't contain an inner loop.
1316 ; But the original loop contains an inner loop that must be traversed.;
1319 %lcssa = phi i32 [ %a, %loop_a ], [ %b, %loop_b ]
1323 ; A test reduced out of 400.perlbench that when unswitching the `%stop`
1324 ; condition clones a loop nest outside of a containing loop. This excercises a
1325 ; different cloning path from our other test cases and in turn verifying the
1326 ; resulting structure can catch any failures to correctly clone these nested
1330 declare i32 @h(i32 %arg)
1332 ; Test that when we are unswitching and need to rebuild the loop block set we
1333 ; correctly skip past inner loops. We want to use the inner loop to efficiently
1334 ; skip whole subregions of the outer loop blocks but just because the header of
1335 ; the outer loop is also the preheader of an inner loop shouldn't confuse this
1337 define void @test23(i1 %arg, ptr %ptr) {
1338 ; CHECK-LABEL: @test23(
1339 ; CHECK-NEXT: entry:
1340 ; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i1 [[ARG:%.*]]
1341 ; CHECK-NEXT: br i1 [[ARG_FR]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
1342 ; CHECK: entry.split.us:
1343 ; CHECK-NEXT: br label [[OUTER_HEADER_US:%.*]]
1344 ; CHECK: outer.header.us:
1345 ; CHECK-NEXT: br label [[INNER_HEADER_US:%.*]]
1346 ; CHECK: inner.header.us:
1347 ; CHECK-NEXT: call void @f()
1348 ; CHECK-NEXT: br label [[INNER_LATCH_US:%.*]]
1349 ; CHECK: inner.latch.us:
1350 ; CHECK-NEXT: [[INNER_COND_US:%.*]] = load i1, ptr [[PTR:%.*]], align 1
1351 ; CHECK-NEXT: br i1 [[INNER_COND_US]], label [[INNER_HEADER_US]], label [[OUTER_BODY_US:%.*]]
1352 ; CHECK: outer.body.us:
1353 ; CHECK-NEXT: br label [[OUTER_BODY_LEFT_US:%.*]]
1354 ; CHECK: outer.body.left.us:
1355 ; CHECK-NEXT: call void @f()
1356 ; CHECK-NEXT: br label [[OUTER_LATCH_US:%.*]]
1357 ; CHECK: outer.latch.us:
1358 ; CHECK-NEXT: [[OUTER_COND_US:%.*]] = load i1, ptr [[PTR]], align 1
1359 ; CHECK-NEXT: br i1 [[OUTER_COND_US]], label [[OUTER_HEADER_US]], label [[EXIT_SPLIT_US:%.*]]
1360 ; CHECK: exit.split.us:
1361 ; CHECK-NEXT: br label [[EXIT:%.*]]
1362 ; CHECK: entry.split:
1363 ; CHECK-NEXT: br label [[OUTER_HEADER:%.*]]
1364 ; CHECK: outer.header:
1365 ; CHECK-NEXT: br label [[INNER_HEADER:%.*]]
1366 ; CHECK: inner.header:
1367 ; CHECK-NEXT: call void @f()
1368 ; CHECK-NEXT: br label [[INNER_LATCH:%.*]]
1369 ; CHECK: inner.latch:
1370 ; CHECK-NEXT: [[INNER_COND:%.*]] = load i1, ptr [[PTR]], align 1
1371 ; CHECK-NEXT: br i1 [[INNER_COND]], label [[INNER_HEADER]], label [[OUTER_BODY:%.*]]
1372 ; CHECK: outer.body:
1373 ; CHECK-NEXT: br label [[OUTER_BODY_RIGHT:%.*]]
1374 ; CHECK: outer.body.right:
1375 ; CHECK-NEXT: call void @g()
1376 ; CHECK-NEXT: br label [[OUTER_LATCH:%.*]]
1377 ; CHECK: outer.latch:
1378 ; CHECK-NEXT: [[OUTER_COND:%.*]] = load i1, ptr [[PTR]], align 1
1379 ; CHECK-NEXT: br i1 [[OUTER_COND]], label [[OUTER_HEADER]], label [[EXIT_SPLIT:%.*]]
1380 ; CHECK: exit.split:
1381 ; CHECK-NEXT: br label [[EXIT]]
1383 ; CHECK-NEXT: ret void
1386 br label %outer.header
1387 ; Just verify that we unswitched the correct bits. We should call `@f` twice in
1388 ; one unswitch and `@f` and then `@g` in the other.
1391 br label %inner.header
1395 br label %inner.latch
1398 %inner.cond = load i1, ptr %ptr
1399 br i1 %inner.cond, label %inner.header, label %outer.body
1402 br i1 %arg, label %outer.body.left, label %outer.body.right
1406 br label %outer.latch
1410 br label %outer.latch
1413 %outer.cond = load i1, ptr %ptr
1414 br i1 %outer.cond, label %outer.header, label %exit
1420 ; A test case designed to exercise unusual properties of switches: they
1421 ; can introduce multiple edges to successors. These need lots of special case
1422 ; handling as they get collapsed in many cases (domtree, the unswitch itself)
1423 ; but not in all cases (the PHI node operands).
1424 define i32 @test29(i32 %arg) {
1425 ; CHECK-LABEL: @test29(
1426 ; CHECK-NEXT: entry:
1427 ; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i32 [[ARG:%.*]]
1428 ; CHECK-NEXT: switch i32 [[ARG_FR]], label [[ENTRY_SPLIT:%.*]] [
1429 ; CHECK-NEXT: i32 0, label [[ENTRY_SPLIT_US:%.*]]
1430 ; CHECK-NEXT: i32 1, label [[ENTRY_SPLIT_US]]
1431 ; CHECK-NEXT: i32 2, label [[ENTRY_SPLIT_US1:%.*]]
1432 ; CHECK-NEXT: i32 3, label [[ENTRY_SPLIT]]
1434 ; CHECK: entry.split.us:
1435 ; CHECK-NEXT: br label [[HEADER_US:%.*]]
1437 ; CHECK-NEXT: [[TMP_US:%.*]] = call i32 @d()
1438 ; CHECK-NEXT: [[CMP1_US:%.*]] = icmp eq i32 [[TMP_US]], 0
1439 ; CHECK-NEXT: br i1 [[CMP1_US]], label [[BODY_A_US:%.*]], label [[DISPATCH_US:%.*]]
1440 ; CHECK: dispatch.us:
1441 ; CHECK-NEXT: br label [[BODY_A_US]]
1443 ; CHECK-NEXT: [[TMP_A_PHI_US:%.*]] = phi i32 [ 0, [[HEADER_US]] ], [ [[TMP_US]], [[DISPATCH_US]] ]
1444 ; CHECK-NEXT: [[TMP_A_US:%.*]] = call i32 @a()
1445 ; CHECK-NEXT: [[TMP_A_SUM_US:%.*]] = add i32 [[TMP_A_PHI_US]], [[TMP_A_US]]
1446 ; CHECK-NEXT: br label [[BODY_B_US:%.*]]
1448 ; CHECK-NEXT: [[TMP_B_PHI_US:%.*]] = phi i32 [ [[TMP_A_SUM_US]], [[BODY_A_US]] ]
1449 ; CHECK-NEXT: [[TMP_B_US:%.*]] = call i32 @b()
1450 ; CHECK-NEXT: [[TMP_B_SUM_US:%.*]] = add i32 [[TMP_B_PHI_US]], [[TMP_B_US]]
1451 ; CHECK-NEXT: br label [[BODY_C_US:%.*]]
1453 ; CHECK-NEXT: [[TMP_C_PHI_US:%.*]] = phi i32 [ [[TMP_B_SUM_US]], [[BODY_B_US]] ]
1454 ; CHECK-NEXT: [[TMP_C_US:%.*]] = call i32 @c()
1455 ; CHECK-NEXT: [[TMP_C_SUM_US:%.*]] = add i32 [[TMP_C_PHI_US]], [[TMP_C_US]]
1456 ; CHECK-NEXT: br label [[LATCH_US:%.*]]
1458 ; CHECK-NEXT: [[CMP2_US:%.*]] = icmp slt i32 [[TMP_C_SUM_US]], 42
1459 ; CHECK-NEXT: br i1 [[CMP2_US]], label [[HEADER_US]], label [[EXIT_SPLIT_US:%.*]]
1460 ; CHECK: exit.split.us:
1461 ; CHECK-NEXT: [[LCSSA_PHI_US:%.*]] = phi i32 [ [[TMP_C_SUM_US]], [[LATCH_US]] ]
1462 ; CHECK-NEXT: br label [[EXIT:%.*]]
1463 ; CHECK: entry.split.us1:
1464 ; CHECK-NEXT: br label [[HEADER_US2:%.*]]
1465 ; CHECK: header.us2:
1466 ; CHECK-NEXT: [[TMP_US3:%.*]] = call i32 @d()
1467 ; CHECK-NEXT: [[CMP1_US4:%.*]] = icmp eq i32 [[TMP_US3]], 0
1468 ; CHECK-NEXT: br i1 [[CMP1_US4]], label [[BODY_A_US6:%.*]], label [[DISPATCH_US5:%.*]]
1469 ; CHECK: dispatch.us5:
1470 ; CHECK-NEXT: br label [[BODY_B_US10:%.*]]
1471 ; CHECK: body.a.us6:
1472 ; CHECK-NEXT: [[TMP_A_PHI_US7:%.*]] = phi i32 [ 0, [[HEADER_US2]] ]
1473 ; CHECK-NEXT: [[TMP_A_US8:%.*]] = call i32 @a()
1474 ; CHECK-NEXT: [[TMP_A_SUM_US9:%.*]] = add i32 [[TMP_A_PHI_US7]], [[TMP_A_US8]]
1475 ; CHECK-NEXT: br label [[BODY_B_US10]]
1476 ; CHECK: body.b.us10:
1477 ; CHECK-NEXT: [[TMP_B_PHI_US11:%.*]] = phi i32 [ [[TMP_US3]], [[DISPATCH_US5]] ], [ [[TMP_A_SUM_US9]], [[BODY_A_US6]] ]
1478 ; CHECK-NEXT: [[TMP_B_US12:%.*]] = call i32 @b()
1479 ; CHECK-NEXT: [[TMP_B_SUM_US13:%.*]] = add i32 [[TMP_B_PHI_US11]], [[TMP_B_US12]]
1480 ; CHECK-NEXT: br label [[BODY_C_US14:%.*]]
1481 ; CHECK: body.c.us14:
1482 ; CHECK-NEXT: [[TMP_C_PHI_US15:%.*]] = phi i32 [ [[TMP_B_SUM_US13]], [[BODY_B_US10]] ]
1483 ; CHECK-NEXT: [[TMP_C_US16:%.*]] = call i32 @c()
1484 ; CHECK-NEXT: [[TMP_C_SUM_US17:%.*]] = add i32 [[TMP_C_PHI_US15]], [[TMP_C_US16]]
1485 ; CHECK-NEXT: br label [[LATCH_US18:%.*]]
1486 ; CHECK: latch.us18:
1487 ; CHECK-NEXT: [[CMP2_US19:%.*]] = icmp slt i32 [[TMP_C_SUM_US17]], 42
1488 ; CHECK-NEXT: br i1 [[CMP2_US19]], label [[HEADER_US2]], label [[EXIT_SPLIT_SPLIT_US:%.*]]
1489 ; CHECK: exit.split.split.us:
1490 ; CHECK-NEXT: [[LCSSA_PHI_US20:%.*]] = phi i32 [ [[TMP_C_SUM_US17]], [[LATCH_US18]] ]
1491 ; CHECK-NEXT: br label [[EXIT_SPLIT:%.*]]
1492 ; CHECK: entry.split:
1493 ; CHECK-NEXT: br label [[HEADER:%.*]]
1495 ; CHECK-NEXT: [[TMP:%.*]] = call i32 @d()
1496 ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[TMP]], 0
1497 ; CHECK-NEXT: br i1 [[CMP1]], label [[BODY_A:%.*]], label [[DISPATCH:%.*]]
1499 ; CHECK-NEXT: br label [[BODY_C:%.*]]
1501 ; CHECK-NEXT: [[TMP_A_PHI:%.*]] = phi i32 [ 0, [[HEADER]] ]
1502 ; CHECK-NEXT: [[TMP_A:%.*]] = call i32 @a()
1503 ; CHECK-NEXT: [[TMP_A_SUM:%.*]] = add i32 [[TMP_A_PHI]], [[TMP_A]]
1504 ; CHECK-NEXT: br label [[BODY_B:%.*]]
1506 ; CHECK-NEXT: [[TMP_B_PHI:%.*]] = phi i32 [ [[TMP_A_SUM]], [[BODY_A]] ]
1507 ; CHECK-NEXT: [[TMP_B:%.*]] = call i32 @b()
1508 ; CHECK-NEXT: [[TMP_B_SUM:%.*]] = add i32 [[TMP_B_PHI]], [[TMP_B]]
1509 ; CHECK-NEXT: br label [[BODY_C]]
1511 ; CHECK-NEXT: [[TMP_C_PHI:%.*]] = phi i32 [ [[TMP]], [[DISPATCH]] ], [ [[TMP_B_SUM]], [[BODY_B]] ]
1512 ; CHECK-NEXT: [[TMP_C:%.*]] = call i32 @c()
1513 ; CHECK-NEXT: [[TMP_C_SUM:%.*]] = add i32 [[TMP_C_PHI]], [[TMP_C]]
1514 ; CHECK-NEXT: br label [[LATCH:%.*]]
1516 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[TMP_C_SUM]], 42
1517 ; CHECK-NEXT: br i1 [[CMP2]], label [[HEADER]], label [[EXIT_SPLIT_SPLIT:%.*]]
1518 ; CHECK: exit.split.split:
1519 ; CHECK-NEXT: [[LCSSA_PHI:%.*]] = phi i32 [ [[TMP_C_SUM]], [[LATCH]] ]
1520 ; CHECK-NEXT: br label [[EXIT_SPLIT]]
1521 ; CHECK: exit.split:
1522 ; CHECK-NEXT: [[DOTUS_PHI21:%.*]] = phi i32 [ [[LCSSA_PHI]], [[EXIT_SPLIT_SPLIT]] ], [ [[LCSSA_PHI_US20]], [[EXIT_SPLIT_SPLIT_US]] ]
1523 ; CHECK-NEXT: br label [[EXIT]]
1525 ; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[DOTUS_PHI21]], [[EXIT_SPLIT]] ], [ [[LCSSA_PHI_US]], [[EXIT_SPLIT_US]] ]
1526 ; CHECK-NEXT: ret i32 [[DOTUS_PHI]]
1532 %tmp = call i32 @d()
1533 %cmp1 = icmp eq i32 %tmp, 0
1534 ; We set up a chain through all the successors of the switch that doesn't
1535 ; involve the switch so that we can have interesting PHI nodes in them.
1536 br i1 %cmp1, label %body.a, label %dispatch
1539 ; Switch with multiple successors. We arrange the last successor to be the
1540 ; default to make the test case easier to read. This has a duplicate edge
1541 ; both to the default destination (which is completely superfluous but
1542 ; technically valid IR) and to a regular successor.
1543 switch i32 %arg, label %body.c [
1544 i32 0, label %body.a
1545 i32 1, label %body.a
1546 i32 2, label %body.b
1547 i32 3, label %body.c
1551 %tmp.a.phi = phi i32 [ 0, %header ], [ %tmp, %dispatch ], [ %tmp, %dispatch ]
1552 %tmp.a = call i32 @a()
1553 %tmp.a.sum = add i32 %tmp.a.phi, %tmp.a
1555 ; Unswitched 'a' loop.
1558 %tmp.b.phi = phi i32 [ %tmp, %dispatch ], [ %tmp.a.sum, %body.a ]
1559 %tmp.b = call i32 @b()
1560 %tmp.b.sum = add i32 %tmp.b.phi, %tmp.b
1562 ; Unswitched 'b' loop.
1565 %tmp.c.phi = phi i32 [ %tmp, %dispatch ], [ %tmp, %dispatch ], [ %tmp.b.sum, %body.b ]
1566 %tmp.c = call i32 @c()
1567 %tmp.c.sum = add i32 %tmp.c.phi, %tmp.c
1569 ; Unswitched 'c' loop.
1572 %cmp2 = icmp slt i32 %tmp.c.sum, 42
1573 br i1 %cmp2, label %header, label %exit
1576 %lcssa.phi = phi i32 [ %tmp.c.sum, %latch ]
1581 ; Similar to @test29 but designed to have one of the duplicate edges be
1582 ; a loop exit edge as those can in some cases be special. Among other things,
1583 ; this includes an LCSSA phi with multiple entries despite being a dedicated
1585 define i32 @test30(i32 %arg) {
1586 ; CHECK-LABEL: @test30(
1587 ; CHECK-NEXT: entry:
1588 ; CHECK-NEXT: [[ARG_FR:%.*]] = freeze i32 [[ARG:%.*]]
1589 ; CHECK-NEXT: switch i32 [[ARG_FR]], label [[ENTRY_SPLIT:%.*]] [
1590 ; CHECK-NEXT: i32 -1, label [[ENTRY_SPLIT]]
1591 ; CHECK-NEXT: i32 0, label [[ENTRY_SPLIT_US:%.*]]
1592 ; CHECK-NEXT: i32 1, label [[ENTRY_SPLIT_US1:%.*]]
1593 ; CHECK-NEXT: i32 2, label [[ENTRY_SPLIT_US1]]
1595 ; CHECK: entry.split.us:
1596 ; CHECK-NEXT: br label [[HEADER_US:%.*]]
1598 ; CHECK-NEXT: [[TMP_US:%.*]] = call i32 @d()
1599 ; CHECK-NEXT: [[CMP1_US:%.*]] = icmp eq i32 [[TMP_US]], 0
1600 ; CHECK-NEXT: br i1 [[CMP1_US]], label [[BODY_A_US:%.*]], label [[DISPATCH_US:%.*]]
1601 ; CHECK: dispatch.us:
1602 ; CHECK-NEXT: br label [[BODY_A_US]]
1604 ; CHECK-NEXT: [[TMP_A_PHI_US:%.*]] = phi i32 [ 0, [[HEADER_US]] ], [ [[TMP_US]], [[DISPATCH_US]] ]
1605 ; CHECK-NEXT: [[TMP_A_US:%.*]] = call i32 @a()
1606 ; CHECK-NEXT: [[TMP_A_SUM_US:%.*]] = add i32 [[TMP_A_PHI_US]], [[TMP_A_US]]
1607 ; CHECK-NEXT: br label [[BODY_B_US:%.*]]
1609 ; CHECK-NEXT: [[TMP_B_PHI_US:%.*]] = phi i32 [ [[TMP_A_SUM_US]], [[BODY_A_US]] ]
1610 ; CHECK-NEXT: [[TMP_B_US:%.*]] = call i32 @b()
1611 ; CHECK-NEXT: [[TMP_B_SUM_US:%.*]] = add i32 [[TMP_B_PHI_US]], [[TMP_B_US]]
1612 ; CHECK-NEXT: br label [[LATCH_US:%.*]]
1614 ; CHECK-NEXT: [[CMP2_US:%.*]] = icmp slt i32 [[TMP_B_SUM_US]], 42
1615 ; CHECK-NEXT: br i1 [[CMP2_US]], label [[HEADER_US]], label [[LOOP_EXIT2_SPLIT_US:%.*]]
1616 ; CHECK: loop.exit2.split.us:
1617 ; CHECK-NEXT: [[L2_PHI_US:%.*]] = phi i32 [ [[TMP_B_SUM_US]], [[LATCH_US]] ]
1618 ; CHECK-NEXT: br label [[LOOP_EXIT2:%.*]]
1619 ; CHECK: entry.split.us1:
1620 ; CHECK-NEXT: br label [[HEADER_US2:%.*]]
1621 ; CHECK: header.us2:
1622 ; CHECK-NEXT: [[TMP_US3:%.*]] = call i32 @d()
1623 ; CHECK-NEXT: [[CMP1_US4:%.*]] = icmp eq i32 [[TMP_US3]], 0
1624 ; CHECK-NEXT: br i1 [[CMP1_US4]], label [[BODY_A_US6:%.*]], label [[DISPATCH_US5:%.*]]
1625 ; CHECK: dispatch.us5:
1626 ; CHECK-NEXT: br label [[BODY_B_US10:%.*]]
1627 ; CHECK: body.a.us6:
1628 ; CHECK-NEXT: [[TMP_A_PHI_US7:%.*]] = phi i32 [ 0, [[HEADER_US2]] ]
1629 ; CHECK-NEXT: [[TMP_A_US8:%.*]] = call i32 @a()
1630 ; CHECK-NEXT: [[TMP_A_SUM_US9:%.*]] = add i32 [[TMP_A_PHI_US7]], [[TMP_A_US8]]
1631 ; CHECK-NEXT: br label [[BODY_B_US10]]
1632 ; CHECK: body.b.us10:
1633 ; CHECK-NEXT: [[TMP_B_PHI_US11:%.*]] = phi i32 [ [[TMP_US3]], [[DISPATCH_US5]] ], [ [[TMP_A_SUM_US9]], [[BODY_A_US6]] ]
1634 ; CHECK-NEXT: [[TMP_B_US12:%.*]] = call i32 @b()
1635 ; CHECK-NEXT: [[TMP_B_SUM_US13:%.*]] = add i32 [[TMP_B_PHI_US11]], [[TMP_B_US12]]
1636 ; CHECK-NEXT: br label [[LATCH_US14:%.*]]
1637 ; CHECK: latch.us14:
1638 ; CHECK-NEXT: [[CMP2_US15:%.*]] = icmp slt i32 [[TMP_B_SUM_US13]], 42
1639 ; CHECK-NEXT: br i1 [[CMP2_US15]], label [[HEADER_US2]], label [[LOOP_EXIT2_SPLIT_SPLIT_US:%.*]]
1640 ; CHECK: loop.exit2.split.split.us:
1641 ; CHECK-NEXT: [[L2_PHI_US16:%.*]] = phi i32 [ [[TMP_B_SUM_US13]], [[LATCH_US14]] ]
1642 ; CHECK-NEXT: br label [[LOOP_EXIT2_SPLIT:%.*]]
1643 ; CHECK: entry.split:
1644 ; CHECK-NEXT: br label [[HEADER:%.*]]
1646 ; CHECK-NEXT: [[TMP:%.*]] = call i32 @d()
1647 ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[TMP]], 0
1648 ; CHECK-NEXT: br i1 [[CMP1]], label [[BODY_A:%.*]], label [[DISPATCH:%.*]]
1650 ; CHECK-NEXT: [[TMP_LCSSA:%.*]] = phi i32 [ [[TMP]], [[HEADER]] ]
1651 ; CHECK-NEXT: br label [[LOOP_EXIT1:%.*]]
1653 ; CHECK-NEXT: [[TMP_A_PHI:%.*]] = phi i32 [ 0, [[HEADER]] ]
1654 ; CHECK-NEXT: [[TMP_A:%.*]] = call i32 @a()
1655 ; CHECK-NEXT: [[TMP_A_SUM:%.*]] = add i32 [[TMP_A_PHI]], [[TMP_A]]
1656 ; CHECK-NEXT: br label [[BODY_B:%.*]]
1658 ; CHECK-NEXT: [[TMP_B_PHI:%.*]] = phi i32 [ [[TMP_A_SUM]], [[BODY_A]] ]
1659 ; CHECK-NEXT: [[TMP_B:%.*]] = call i32 @b()
1660 ; CHECK-NEXT: [[TMP_B_SUM:%.*]] = add i32 [[TMP_B_PHI]], [[TMP_B]]
1661 ; CHECK-NEXT: br label [[LATCH:%.*]]
1663 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[TMP_B_SUM]], 42
1664 ; CHECK-NEXT: br i1 [[CMP2]], label [[HEADER]], label [[LOOP_EXIT2_SPLIT_SPLIT:%.*]]
1665 ; CHECK: loop.exit1:
1666 ; CHECK-NEXT: [[L1_PHI:%.*]] = phi i32 [ [[TMP_LCSSA]], [[DISPATCH]] ]
1667 ; CHECK-NEXT: br label [[EXIT:%.*]]
1668 ; CHECK: loop.exit2.split.split:
1669 ; CHECK-NEXT: [[L2_PHI:%.*]] = phi i32 [ [[TMP_B_SUM]], [[LATCH]] ]
1670 ; CHECK-NEXT: br label [[LOOP_EXIT2_SPLIT]]
1671 ; CHECK: loop.exit2.split:
1672 ; CHECK-NEXT: [[DOTUS_PHI17:%.*]] = phi i32 [ [[L2_PHI]], [[LOOP_EXIT2_SPLIT_SPLIT]] ], [ [[L2_PHI_US16]], [[LOOP_EXIT2_SPLIT_SPLIT_US]] ]
1673 ; CHECK-NEXT: br label [[LOOP_EXIT2]]
1674 ; CHECK: loop.exit2:
1675 ; CHECK-NEXT: [[DOTUS_PHI:%.*]] = phi i32 [ [[DOTUS_PHI17]], [[LOOP_EXIT2_SPLIT]] ], [ [[L2_PHI_US]], [[LOOP_EXIT2_SPLIT_US]] ]
1676 ; CHECK-NEXT: br label [[EXIT]]
1678 ; CHECK-NEXT: [[L_PHI:%.*]] = phi i32 [ [[L1_PHI]], [[LOOP_EXIT1]] ], [ [[DOTUS_PHI]], [[LOOP_EXIT2]] ]
1679 ; CHECK-NEXT: ret i32 [[L_PHI]]
1685 %tmp = call i32 @d()
1686 %cmp1 = icmp eq i32 %tmp, 0
1687 br i1 %cmp1, label %body.a, label %dispatch
1690 switch i32 %arg, label %loop.exit1 [
1691 i32 -1, label %loop.exit1
1692 i32 0, label %body.a
1693 i32 1, label %body.b
1694 i32 2, label %body.b
1698 %tmp.a.phi = phi i32 [ 0, %header ], [ %tmp, %dispatch ]
1699 %tmp.a = call i32 @a()
1700 %tmp.a.sum = add i32 %tmp.a.phi, %tmp.a
1702 ; Unswitched 'a' loop.
1705 %tmp.b.phi = phi i32 [ %tmp, %dispatch ], [ %tmp, %dispatch ], [ %tmp.a.sum, %body.a ]
1706 %tmp.b = call i32 @b()
1707 %tmp.b.sum = add i32 %tmp.b.phi, %tmp.b
1709 ; Unswitched 'b' loop.
1712 %cmp2 = icmp slt i32 %tmp.b.sum, 42
1713 br i1 %cmp2, label %header, label %loop.exit2
1716 %l1.phi = phi i32 [ %tmp, %dispatch ], [ %tmp, %dispatch ]
1718 ; Unswitched 'exit' loop.
1721 %l2.phi = phi i32 [ %tmp.b.sum, %latch ]
1725 %l.phi = phi i32 [ %l1.phi, %loop.exit1 ], [ %l2.phi, %loop.exit2 ]
1729 ; Unswitch will not actually change the loop nest from:
1731 define void @hoist_inner_loop0() {
1732 ; CHECK-LABEL: @hoist_inner_loop0(
1733 ; CHECK-NEXT: entry:
1734 ; CHECK-NEXT: br label [[A_HEADER:%.*]]
1736 ; CHECK-NEXT: br label [[B_HEADER:%.*]]
1738 ; CHECK-NEXT: [[V1:%.*]] = call i1 @cond()
1739 ; CHECK-NEXT: [[V1_FR:%.*]] = freeze i1 [[V1]]
1740 ; CHECK-NEXT: br i1 [[V1_FR]], label [[B_HEADER_SPLIT_US:%.*]], label [[B_HEADER_SPLIT:%.*]]
1741 ; CHECK: b.header.split.us:
1742 ; CHECK-NEXT: br label [[C_HEADER_US:%.*]]
1743 ; CHECK: c.header.us:
1744 ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @c()
1745 ; CHECK-NEXT: br label [[B_LATCH_SPLIT_US:%.*]]
1746 ; CHECK: b.latch.split.us:
1747 ; CHECK-NEXT: br label [[B_LATCH:%.*]]
1748 ; CHECK: b.header.split:
1749 ; CHECK-NEXT: br label [[C_HEADER:%.*]]
1751 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @c()
1752 ; CHECK-NEXT: br label [[C_LATCH:%.*]]
1754 ; CHECK-NEXT: [[V2:%.*]] = call i1 @cond()
1755 ; CHECK-NEXT: br i1 [[V2]], label [[C_HEADER]], label [[B_LATCH_SPLIT:%.*]]
1756 ; CHECK: b.latch.split:
1757 ; CHECK-NEXT: br label [[B_LATCH]]
1759 ; CHECK-NEXT: [[V3:%.*]] = call i1 @cond()
1760 ; CHECK-NEXT: br i1 [[V3]], label [[B_HEADER]], label [[A_LATCH:%.*]]
1762 ; CHECK-NEXT: br label [[A_HEADER]]
1764 ; CHECK-NEXT: ret void
1773 %v1 = call i1 @cond()
1778 br i1 %v1, label %b.latch, label %c.latch
1781 %v2 = call i1 @cond()
1782 br i1 %v2, label %c.header, label %b.latch
1785 %v3 = call i1 @cond()
1786 br i1 %v3, label %b.header, label %a.latch
1795 ; Unswitch will transform the loop nest from:
1799 define void @hoist_inner_loop1(ptr %ptr) {
1800 ; CHECK-LABEL: @hoist_inner_loop1(
1801 ; CHECK-NEXT: entry:
1802 ; CHECK-NEXT: br label [[A_HEADER:%.*]]
1804 ; CHECK-NEXT: [[X_A:%.*]] = load i32, ptr [[PTR:%.*]], align 4
1805 ; CHECK-NEXT: br label [[B_HEADER:%.*]]
1807 ; CHECK-NEXT: [[X_B:%.*]] = load i32, ptr [[PTR]], align 4
1808 ; CHECK-NEXT: [[V1:%.*]] = call i1 @cond()
1809 ; CHECK-NEXT: [[V1_FR:%.*]] = freeze i1 [[V1]]
1810 ; CHECK-NEXT: br i1 [[V1_FR]], label [[B_HEADER_SPLIT_US:%.*]], label [[B_HEADER_SPLIT:%.*]]
1811 ; CHECK: b.header.split.us:
1812 ; CHECK-NEXT: br label [[C_HEADER_US:%.*]]
1813 ; CHECK: c.header.us:
1814 ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @c()
1815 ; CHECK-NEXT: br label [[B_LATCH_SPLIT_US:%.*]]
1816 ; CHECK: b.latch.split.us:
1817 ; CHECK-NEXT: br label [[B_LATCH:%.*]]
1818 ; CHECK: b.header.split:
1819 ; CHECK-NEXT: [[X_B_LCSSA:%.*]] = phi i32 [ [[X_B]], [[B_HEADER]] ]
1820 ; CHECK-NEXT: br label [[C_HEADER:%.*]]
1822 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @c()
1823 ; CHECK-NEXT: br label [[C_LATCH:%.*]]
1825 ; CHECK-NEXT: store i32 [[X_A]], ptr [[PTR]], align 4
1826 ; CHECK-NEXT: store i32 [[X_B_LCSSA]], ptr [[PTR]], align 4
1827 ; CHECK-NEXT: [[V2:%.*]] = call i1 @cond()
1828 ; CHECK-NEXT: br i1 [[V2]], label [[C_HEADER]], label [[A_EXIT_C:%.*]]
1830 ; CHECK-NEXT: [[V3:%.*]] = call i1 @cond()
1831 ; CHECK-NEXT: br i1 [[V3]], label [[B_HEADER]], label [[A_EXIT_B:%.*]]
1833 ; CHECK-NEXT: br label [[A_LATCH:%.*]]
1835 ; CHECK-NEXT: br label [[A_LATCH]]
1837 ; CHECK-NEXT: br label [[A_HEADER]]
1839 ; CHECK-NEXT: ret void
1845 %x.a = load i32, ptr %ptr
1849 %x.b = load i32, ptr %ptr
1850 %v1 = call i1 @cond()
1855 br i1 %v1, label %b.latch, label %c.latch
1858 ; Use values from other loops to check LCSSA form.
1859 store i32 %x.a, ptr %ptr
1860 store i32 %x.b, ptr %ptr
1861 %v2 = call i1 @cond()
1862 br i1 %v2, label %c.header, label %a.exit.c
1865 %v3 = call i1 @cond()
1866 br i1 %v3, label %b.header, label %a.exit.b
1881 ; Unswitch will transform the loop nest from:
1885 define void @hoist_inner_loop2(ptr %ptr) {
1886 ; CHECK-LABEL: @hoist_inner_loop2(
1887 ; CHECK-NEXT: entry:
1888 ; CHECK-NEXT: br label [[A_HEADER:%.*]]
1890 ; CHECK-NEXT: [[X_A:%.*]] = load i32, ptr [[PTR:%.*]], align 4
1891 ; CHECK-NEXT: br label [[B_HEADER:%.*]]
1893 ; CHECK-NEXT: [[X_B:%.*]] = load i32, ptr [[PTR]], align 4
1894 ; CHECK-NEXT: [[V1:%.*]] = call i1 @cond()
1895 ; CHECK-NEXT: [[V1_FR:%.*]] = freeze i1 [[V1]]
1896 ; CHECK-NEXT: br i1 [[V1_FR]], label [[B_HEADER_SPLIT_US:%.*]], label [[B_HEADER_SPLIT:%.*]]
1897 ; CHECK: b.header.split.us:
1898 ; CHECK-NEXT: br label [[C_HEADER_US:%.*]]
1899 ; CHECK: c.header.us:
1900 ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @c()
1901 ; CHECK-NEXT: br label [[B_LATCH_SPLIT_US:%.*]]
1902 ; CHECK: b.latch.split.us:
1903 ; CHECK-NEXT: br label [[B_LATCH:%.*]]
1904 ; CHECK: b.header.split:
1905 ; CHECK-NEXT: [[X_A_LCSSA:%.*]] = phi i32 [ [[X_A]], [[B_HEADER]] ]
1906 ; CHECK-NEXT: [[X_B_LCSSA:%.*]] = phi i32 [ [[X_B]], [[B_HEADER]] ]
1907 ; CHECK-NEXT: br label [[C_HEADER:%.*]]
1909 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @c()
1910 ; CHECK-NEXT: br label [[C_LATCH:%.*]]
1912 ; CHECK-NEXT: store i32 [[X_A_LCSSA]], ptr [[PTR]], align 4
1913 ; CHECK-NEXT: store i32 [[X_B_LCSSA]], ptr [[PTR]], align 4
1914 ; CHECK-NEXT: [[V2:%.*]] = call i1 @cond()
1915 ; CHECK-NEXT: br i1 [[V2]], label [[C_HEADER]], label [[EXIT:%.*]]
1917 ; CHECK-NEXT: [[V3:%.*]] = call i1 @cond()
1918 ; CHECK-NEXT: br i1 [[V3]], label [[B_HEADER]], label [[A_LATCH:%.*]]
1920 ; CHECK-NEXT: br label [[A_HEADER]]
1922 ; CHECK-NEXT: ret void
1928 %x.a = load i32, ptr %ptr
1932 %x.b = load i32, ptr %ptr
1933 %v1 = call i1 @cond()
1938 br i1 %v1, label %b.latch, label %c.latch
1941 ; Use values from other loops to check LCSSA form.
1942 store i32 %x.a, ptr %ptr
1943 store i32 %x.b, ptr %ptr
1944 %v2 = call i1 @cond()
1945 br i1 %v2, label %c.header, label %exit
1948 %v3 = call i1 @cond()
1949 br i1 %v3, label %b.header, label %a.latch
1958 ; Same as @hoist_inner_loop2 but with a nested loop inside the hoisted loop.
1959 ; Unswitch will transform the loop nest from:
1963 define void @hoist_inner_loop3(ptr %ptr) {
1964 ; CHECK-LABEL: @hoist_inner_loop3(
1965 ; CHECK-NEXT: entry:
1966 ; CHECK-NEXT: br label [[A_HEADER:%.*]]
1968 ; CHECK-NEXT: [[X_A:%.*]] = load i32, ptr [[PTR:%.*]], align 4
1969 ; CHECK-NEXT: br label [[B_HEADER:%.*]]
1971 ; CHECK-NEXT: [[X_B:%.*]] = load i32, ptr [[PTR]], align 4
1972 ; CHECK-NEXT: [[V1:%.*]] = call i1 @cond()
1973 ; CHECK-NEXT: [[V1_FR:%.*]] = freeze i1 [[V1]]
1974 ; CHECK-NEXT: br i1 [[V1_FR]], label [[B_HEADER_SPLIT_US:%.*]], label [[B_HEADER_SPLIT:%.*]]
1975 ; CHECK: b.header.split.us:
1976 ; CHECK-NEXT: br label [[C_HEADER_US:%.*]]
1977 ; CHECK: c.header.us:
1978 ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @c()
1979 ; CHECK-NEXT: br label [[B_LATCH_SPLIT_US:%.*]]
1980 ; CHECK: b.latch.split.us:
1981 ; CHECK-NEXT: br label [[B_LATCH:%.*]]
1982 ; CHECK: b.header.split:
1983 ; CHECK-NEXT: [[X_A_LCSSA:%.*]] = phi i32 [ [[X_A]], [[B_HEADER]] ]
1984 ; CHECK-NEXT: [[X_B_LCSSA:%.*]] = phi i32 [ [[X_B]], [[B_HEADER]] ]
1985 ; CHECK-NEXT: br label [[C_HEADER:%.*]]
1987 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @c()
1988 ; CHECK-NEXT: br label [[C_BODY:%.*]]
1990 ; CHECK-NEXT: [[X_C:%.*]] = load i32, ptr [[PTR]], align 4
1991 ; CHECK-NEXT: br label [[D_HEADER:%.*]]
1993 ; CHECK-NEXT: store i32 [[X_A_LCSSA]], ptr [[PTR]], align 4
1994 ; CHECK-NEXT: store i32 [[X_B_LCSSA]], ptr [[PTR]], align 4
1995 ; CHECK-NEXT: store i32 [[X_C]], ptr [[PTR]], align 4
1996 ; CHECK-NEXT: [[V2:%.*]] = call i1 @cond()
1997 ; CHECK-NEXT: br i1 [[V2]], label [[D_HEADER]], label [[C_LATCH:%.*]]
1999 ; CHECK-NEXT: [[V3:%.*]] = call i1 @cond()
2000 ; CHECK-NEXT: br i1 [[V3]], label [[C_HEADER]], label [[EXIT:%.*]]
2002 ; CHECK-NEXT: [[V4:%.*]] = call i1 @cond()
2003 ; CHECK-NEXT: br i1 [[V4]], label [[B_HEADER]], label [[A_LATCH:%.*]]
2005 ; CHECK-NEXT: br label [[A_HEADER]]
2007 ; CHECK-NEXT: ret void
2013 %x.a = load i32, ptr %ptr
2017 %x.b = load i32, ptr %ptr
2018 %v1 = call i1 @cond()
2023 br i1 %v1, label %b.latch, label %c.body
2026 %x.c = load i32, ptr %ptr
2030 ; Use values from other loops to check LCSSA form.
2031 store i32 %x.a, ptr %ptr
2032 store i32 %x.b, ptr %ptr
2033 store i32 %x.c, ptr %ptr
2034 %v2 = call i1 @cond()
2035 br i1 %v2, label %d.header, label %c.latch
2038 %v3 = call i1 @cond()
2039 br i1 %v3, label %c.header, label %exit
2042 %v4 = call i1 @cond()
2043 br i1 %v4, label %b.header, label %a.latch
2052 ; This test is designed to exercise checking multiple remaining exits from the
2053 ; loop being unswitched.
2054 ; Unswitch will transform the loop nest from:
2058 define void @hoist_inner_loop4() {
2059 ; CHECK-LABEL: @hoist_inner_loop4(
2060 ; CHECK-NEXT: entry:
2061 ; CHECK-NEXT: br label [[A_HEADER:%.*]]
2063 ; CHECK-NEXT: br label [[B_HEADER:%.*]]
2065 ; CHECK-NEXT: br label [[C_HEADER:%.*]]
2067 ; CHECK-NEXT: [[V1:%.*]] = call i1 @cond()
2068 ; CHECK-NEXT: [[V1_FR:%.*]] = freeze i1 [[V1]]
2069 ; CHECK-NEXT: br i1 [[V1_FR]], label [[C_HEADER_SPLIT_US:%.*]], label [[C_HEADER_SPLIT:%.*]]
2070 ; CHECK: c.header.split.us:
2071 ; CHECK-NEXT: br label [[D_HEADER_US:%.*]]
2072 ; CHECK: d.header.us:
2073 ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @d()
2074 ; CHECK-NEXT: br label [[C_LATCH_SPLIT_US:%.*]]
2075 ; CHECK: c.latch.split.us:
2076 ; CHECK-NEXT: br label [[C_LATCH:%.*]]
2077 ; CHECK: c.header.split:
2078 ; CHECK-NEXT: br label [[D_HEADER:%.*]]
2080 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @d()
2081 ; CHECK-NEXT: br label [[D_EXITING1:%.*]]
2082 ; CHECK: d.exiting1:
2083 ; CHECK-NEXT: [[V2:%.*]] = call i1 @cond()
2084 ; CHECK-NEXT: br i1 [[V2]], label [[D_EXITING2:%.*]], label [[A_LATCH:%.*]]
2085 ; CHECK: d.exiting2:
2086 ; CHECK-NEXT: [[V3:%.*]] = call i1 @cond()
2087 ; CHECK-NEXT: br i1 [[V3]], label [[D_EXITING3:%.*]], label [[LOOPEXIT_D:%.*]]
2088 ; CHECK: d.exiting3:
2089 ; CHECK-NEXT: [[V4:%.*]] = call i1 @cond()
2090 ; CHECK-NEXT: br i1 [[V4]], label [[D_LATCH:%.*]], label [[B_LATCH:%.*]]
2092 ; CHECK-NEXT: br label [[D_HEADER]]
2094 ; CHECK-NEXT: [[V5:%.*]] = call i1 @cond()
2095 ; CHECK-NEXT: br i1 [[V5]], label [[C_HEADER]], label [[LOOPEXIT_C:%.*]]
2097 ; CHECK-NEXT: br label [[B_HEADER]]
2099 ; CHECK-NEXT: br label [[A_HEADER]]
2100 ; CHECK: loopexit.d:
2101 ; CHECK-NEXT: br label [[EXIT:%.*]]
2102 ; CHECK: loopexit.c:
2103 ; CHECK-NEXT: br label [[EXIT]]
2105 ; CHECK-NEXT: ret void
2117 %v1 = call i1 @cond()
2122 br i1 %v1, label %c.latch, label %d.exiting1
2125 %v2 = call i1 @cond()
2126 br i1 %v2, label %d.exiting2, label %a.latch
2129 %v3 = call i1 @cond()
2130 br i1 %v3, label %d.exiting3, label %loopexit.d
2133 %v4 = call i1 @cond()
2134 br i1 %v4, label %d.latch, label %b.latch
2140 %v5 = call i1 @cond()
2141 br i1 %v5, label %c.header, label %loopexit.c
2159 ; Unswitch will transform the loop nest from:
2163 define void @hoist_inner_loop5(ptr %ptr) {
2164 ; CHECK-LABEL: @hoist_inner_loop5(
2165 ; CHECK-NEXT: entry:
2166 ; CHECK-NEXT: br label [[A_HEADER:%.*]]
2168 ; CHECK-NEXT: [[X_A:%.*]] = load i32, ptr [[PTR:%.*]], align 4
2169 ; CHECK-NEXT: br label [[B_HEADER:%.*]]
2171 ; CHECK-NEXT: [[X_B:%.*]] = load i32, ptr [[PTR]], align 4
2172 ; CHECK-NEXT: br label [[C_HEADER:%.*]]
2174 ; CHECK-NEXT: [[X_C:%.*]] = load i32, ptr [[PTR]], align 4
2175 ; CHECK-NEXT: [[V1:%.*]] = call i1 @cond()
2176 ; CHECK-NEXT: [[V1_FR:%.*]] = freeze i1 [[V1]]
2177 ; CHECK-NEXT: br i1 [[V1_FR]], label [[C_HEADER_SPLIT_US:%.*]], label [[C_HEADER_SPLIT:%.*]]
2178 ; CHECK: c.header.split.us:
2179 ; CHECK-NEXT: br label [[D_HEADER_US:%.*]]
2180 ; CHECK: d.header.us:
2181 ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @d()
2182 ; CHECK-NEXT: br label [[C_LATCH_SPLIT_US:%.*]]
2183 ; CHECK: c.latch.split.us:
2184 ; CHECK-NEXT: br label [[C_LATCH:%.*]]
2185 ; CHECK: c.header.split:
2186 ; CHECK-NEXT: [[X_B_LCSSA:%.*]] = phi i32 [ [[X_B]], [[C_HEADER]] ]
2187 ; CHECK-NEXT: [[X_C_LCSSA:%.*]] = phi i32 [ [[X_C]], [[C_HEADER]] ]
2188 ; CHECK-NEXT: br label [[D_HEADER:%.*]]
2190 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @d()
2191 ; CHECK-NEXT: br label [[D_LATCH:%.*]]
2193 ; CHECK-NEXT: store i32 [[X_A]], ptr [[PTR]], align 4
2194 ; CHECK-NEXT: store i32 [[X_B_LCSSA]], ptr [[PTR]], align 4
2195 ; CHECK-NEXT: store i32 [[X_C_LCSSA]], ptr [[PTR]], align 4
2196 ; CHECK-NEXT: [[V2:%.*]] = call i1 @cond()
2197 ; CHECK-NEXT: br i1 [[V2]], label [[D_HEADER]], label [[A_LATCH:%.*]]
2199 ; CHECK-NEXT: [[V3:%.*]] = call i1 @cond()
2200 ; CHECK-NEXT: br i1 [[V3]], label [[C_HEADER]], label [[B_LATCH:%.*]]
2202 ; CHECK-NEXT: br label [[B_HEADER]]
2204 ; CHECK-NEXT: br label [[A_HEADER]]
2206 ; CHECK-NEXT: ret void
2212 %x.a = load i32, ptr %ptr
2216 %x.b = load i32, ptr %ptr
2220 %x.c = load i32, ptr %ptr
2221 %v1 = call i1 @cond()
2226 br i1 %v1, label %c.latch, label %d.latch
2229 ; Use values from other loops to check LCSSA form.
2230 store i32 %x.a, ptr %ptr
2231 store i32 %x.b, ptr %ptr
2232 store i32 %x.c, ptr %ptr
2233 %v2 = call i1 @cond()
2234 br i1 %v2, label %d.header, label %a.latch
2237 %v3 = call i1 @cond()
2238 br i1 %v3, label %c.header, label %b.latch
2250 define void @hoist_inner_loop_switch(ptr %ptr) {
2251 ; CHECK-LABEL: @hoist_inner_loop_switch(
2252 ; CHECK-NEXT: entry:
2253 ; CHECK-NEXT: br label [[A_HEADER:%.*]]
2255 ; CHECK-NEXT: [[X_A:%.*]] = load i32, ptr [[PTR:%.*]], align 4
2256 ; CHECK-NEXT: br label [[B_HEADER:%.*]]
2258 ; CHECK-NEXT: [[X_B:%.*]] = load i32, ptr [[PTR]], align 4
2259 ; CHECK-NEXT: [[V1:%.*]] = call i32 @cond.i32()
2260 ; CHECK-NEXT: [[V1_FR:%.*]] = freeze i32 [[V1]]
2261 ; CHECK-NEXT: switch i32 [[V1_FR]], label [[B_HEADER_SPLIT:%.*]] [
2262 ; CHECK-NEXT: i32 1, label [[B_HEADER_SPLIT_US:%.*]]
2263 ; CHECK-NEXT: i32 2, label [[B_HEADER_SPLIT_US]]
2264 ; CHECK-NEXT: i32 3, label [[B_HEADER_SPLIT_US]]
2266 ; CHECK: b.header.split.us:
2267 ; CHECK-NEXT: br label [[C_HEADER_US:%.*]]
2268 ; CHECK: c.header.us:
2269 ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @c()
2270 ; CHECK-NEXT: br label [[B_LATCH_SPLIT_US:%.*]]
2271 ; CHECK: b.latch.split.us:
2272 ; CHECK-NEXT: br label [[B_LATCH:%.*]]
2273 ; CHECK: b.header.split:
2274 ; CHECK-NEXT: [[X_A_LCSSA:%.*]] = phi i32 [ [[X_A]], [[B_HEADER]] ]
2275 ; CHECK-NEXT: [[X_B_LCSSA:%.*]] = phi i32 [ [[X_B]], [[B_HEADER]] ]
2276 ; CHECK-NEXT: br label [[C_HEADER:%.*]]
2278 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @c()
2279 ; CHECK-NEXT: br label [[C_LATCH:%.*]]
2281 ; CHECK-NEXT: store i32 [[X_A_LCSSA]], ptr [[PTR]], align 4
2282 ; CHECK-NEXT: store i32 [[X_B_LCSSA]], ptr [[PTR]], align 4
2283 ; CHECK-NEXT: [[V2:%.*]] = call i1 @cond()
2284 ; CHECK-NEXT: br i1 [[V2]], label [[C_HEADER]], label [[EXIT:%.*]]
2286 ; CHECK-NEXT: [[V3:%.*]] = call i1 @cond()
2287 ; CHECK-NEXT: br i1 [[V3]], label [[B_HEADER]], label [[A_LATCH:%.*]]
2289 ; CHECK-NEXT: br label [[A_HEADER]]
2291 ; CHECK-NEXT: ret void
2297 %x.a = load i32, ptr %ptr
2301 %x.b = load i32, ptr %ptr
2302 %v1 = call i32 @cond.i32()
2307 switch i32 %v1, label %c.latch [
2308 i32 1, label %b.latch
2309 i32 2, label %b.latch
2310 i32 3, label %b.latch
2314 ; Use values from other loops to check LCSSA form.
2315 store i32 %x.a, ptr %ptr
2316 store i32 %x.b, ptr %ptr
2317 %v2 = call i1 @cond()
2318 br i1 %v2, label %c.header, label %exit
2321 %v3 = call i1 @cond()
2322 br i1 %v3, label %b.header, label %a.latch
2331 define i32 @test_partial_unswitch_all_conds_guaranteed_non_poison(i1 noundef %c.1, i1 noundef %c.2) {
2332 ; CHECK-LABEL: @test_partial_unswitch_all_conds_guaranteed_non_poison(
2333 ; CHECK-NEXT: entry:
2334 ; CHECK-NEXT: [[TMP0:%.*]] = and i1 [[C_1:%.*]], [[C_2:%.*]]
2335 ; CHECK-NEXT: br i1 [[TMP0]], label [[ENTRY_SPLIT:%.*]], label [[ENTRY_SPLIT_US:%.*]]
2336 ; CHECK: entry.split.us:
2337 ; CHECK-NEXT: br label [[LOOP_US:%.*]]
2339 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @a()
2340 ; CHECK-NEXT: br label [[EXIT_SPLIT_US:%.*]]
2341 ; CHECK: exit.split.us:
2342 ; CHECK-NEXT: br label [[EXIT:%.*]]
2343 ; CHECK: entry.split:
2344 ; CHECK-NEXT: br label [[LOOP:%.*]]
2346 ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @a()
2347 ; CHECK-NEXT: [[SEL:%.*]] = select i1 true, i1 true, i1 false
2348 ; CHECK-NEXT: br i1 [[SEL]], label [[LOOP]], label [[EXIT_SPLIT:%.*]]
2349 ; CHECK: exit.split:
2350 ; CHECK-NEXT: br label [[EXIT]]
2352 ; CHECK-NEXT: ret i32 0
2359 %sel = select i1 %c.1, i1 %c.2, i1 false
2360 br i1 %sel, label %loop, label %exit