• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -mtriple=thumbv8m.main -simple-loop-unswitch -enable-nontrivial-unswitch -unswitch-threshold=5 -S -o - %s | FileCheck %s
3
4declare void @a()
5declare void @b()
6declare void @x()
7
8define void @test_no_unswitch(i1* %ptr, i1 %cond) {
9; CHECK-LABEL: @test_no_unswitch(
10; CHECK-NEXT:  entry:
11; CHECK-NEXT:    br label [[LOOP_BEGIN:%.*]]
12; CHECK:       loop_begin:
13; CHECK-NEXT:    call void @x()
14; CHECK-NEXT:    call void @x()
15; CHECK-NEXT:    call void @x()
16; CHECK-NEXT:    call void @x()
17; CHECK-NEXT:    br i1 [[COND:%.*]], label [[LOOP_A:%.*]], label [[LOOP_B:%.*]]
18; CHECK:       loop_a:
19; CHECK-NEXT:    call void @a()
20; CHECK-NEXT:    br label [[LOOP_LATCH:%.*]]
21; CHECK:       loop_b:
22; CHECK-NEXT:    call void @b()
23; CHECK-NEXT:    br label [[LOOP_LATCH]]
24; CHECK:       loop_latch:
25; CHECK-NEXT:    [[V:%.*]] = load i1, i1* [[PTR:%.*]], align 1
26; CHECK-NEXT:    br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT:%.*]]
27; CHECK:       loop_exit:
28; CHECK-NEXT:    ret void
29;
30entry:
31  br label %loop_begin
32loop_begin:
33  call void @x()
34  call void @x()
35  call void @x()
36  call void @x()
37  br i1 %cond, label %loop_a, label %loop_b
38
39loop_a:
40  call void @a()
41  br label %loop_latch
42
43loop_b:
44  call void @b()
45  br label %loop_latch
46
47loop_latch:
48  %v = load i1, i1* %ptr
49  br i1 %v, label %loop_begin, label %loop_exit
50
51loop_exit:
52  ret void
53}
54
55define void @test_unswitch(i1* %ptr, i1 %cond) {
56; CHECK-LABEL: @test_unswitch(
57; CHECK-NEXT:  entry:
58; CHECK-NEXT:    br i1 [[COND:%.*]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
59; CHECK:       entry.split.us:
60; CHECK-NEXT:    br label [[LOOP_BEGIN_US:%.*]]
61; CHECK:       loop_begin.us:
62; CHECK-NEXT:    call void @x()
63; CHECK-NEXT:    br label [[LOOP_A_US:%.*]]
64; CHECK:       loop_a.us:
65; CHECK-NEXT:    call void @a()
66; CHECK-NEXT:    br label [[LOOP_LATCH_US:%.*]]
67; CHECK:       loop_latch.us:
68; CHECK-NEXT:    [[V_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1
69; CHECK-NEXT:    br i1 [[V_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]]
70; CHECK:       loop_exit.split.us:
71; CHECK-NEXT:    br label [[LOOP_EXIT:%.*]]
72; CHECK:       entry.split:
73; CHECK-NEXT:    br label [[LOOP_BEGIN:%.*]]
74; CHECK:       loop_begin:
75; CHECK-NEXT:    call void @x()
76; CHECK-NEXT:    br label [[LOOP_B:%.*]]
77; CHECK:       loop_b:
78; CHECK-NEXT:    call void @b()
79; CHECK-NEXT:    br label [[LOOP_LATCH:%.*]]
80; CHECK:       loop_latch:
81; CHECK-NEXT:    [[V:%.*]] = load i1, i1* [[PTR]], align 1
82; CHECK-NEXT:    br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT_SPLIT:%.*]]
83; CHECK:       loop_exit.split:
84; CHECK-NEXT:    br label [[LOOP_EXIT]]
85; CHECK:       loop_exit:
86; CHECK-NEXT:    ret void
87;
88entry:
89  br label %loop_begin
90
91loop_begin:
92  call void @x()
93  br i1 %cond, label %loop_a, label %loop_b
94
95loop_a:
96  call void @a()
97  br label %loop_latch
98
99loop_b:
100  call void @b()
101  br label %loop_latch
102
103loop_latch:
104  %v = load i1, i1* %ptr
105  br i1 %v, label %loop_begin, label %loop_exit
106
107loop_exit:
108  ret void
109}
110
111define void @test_unswitch_minsize(i1* %ptr, i1 %cond) #0 {
112; CHECK-LABEL: @test_unswitch_minsize(
113; CHECK-NEXT:  entry:
114; CHECK-NEXT:    br i1 [[COND:%.*]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
115; CHECK:       entry.split.us:
116; CHECK-NEXT:    br label [[LOOP_BEGIN_US:%.*]]
117; CHECK:       loop_begin.us:
118; CHECK-NEXT:    call void @x()
119; CHECK-NEXT:    br label [[LOOP_A_US:%.*]]
120; CHECK:       loop_a.us:
121; CHECK-NEXT:    call void @a()
122; CHECK-NEXT:    br label [[LOOP_LATCH_US:%.*]]
123; CHECK:       loop_latch.us:
124; CHECK-NEXT:    [[V_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1
125; CHECK-NEXT:    br i1 [[V_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]]
126; CHECK:       loop_exit.split.us:
127; CHECK-NEXT:    br label [[LOOP_EXIT:%.*]]
128; CHECK:       entry.split:
129; CHECK-NEXT:    br label [[LOOP_BEGIN:%.*]]
130; CHECK:       loop_begin:
131; CHECK-NEXT:    call void @x()
132; CHECK-NEXT:    br label [[LOOP_B:%.*]]
133; CHECK:       loop_b:
134; CHECK-NEXT:    call void @b()
135; CHECK-NEXT:    br label [[LOOP_LATCH:%.*]]
136; CHECK:       loop_latch:
137; CHECK-NEXT:    [[V:%.*]] = load i1, i1* [[PTR]], align 1
138; CHECK-NEXT:    br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT_SPLIT:%.*]]
139; CHECK:       loop_exit.split:
140; CHECK-NEXT:    br label [[LOOP_EXIT]]
141; CHECK:       loop_exit:
142; CHECK-NEXT:    ret void
143;
144entry:
145  br label %loop_begin
146
147loop_begin:
148  call void @x()
149  br i1 %cond, label %loop_a, label %loop_b
150
151loop_a:
152  call void @a()
153  br label %loop_latch
154
155loop_b:
156  call void @b()
157  br label %loop_latch
158
159loop_latch:
160  %v = load i1, i1* %ptr
161  br i1 %v, label %loop_begin, label %loop_exit
162
163loop_exit:
164  ret void
165}
166
167define void @test_unswitch_non_dup_code(i1* %ptr, i1 %cond) {
168; CHECK-LABEL: @test_unswitch_non_dup_code(
169; CHECK-NEXT:  entry:
170; CHECK-NEXT:    br i1 [[COND:%.*]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
171; CHECK:       entry.split.us:
172; CHECK-NEXT:    br label [[LOOP_BEGIN_US:%.*]]
173; CHECK:       loop_begin.us:
174; CHECK-NEXT:    call void @x()
175; CHECK-NEXT:    br label [[LOOP_A_US:%.*]]
176; CHECK:       loop_a.us:
177; CHECK-NEXT:    call void @a()
178; CHECK-NEXT:    call void @a()
179; CHECK-NEXT:    call void @a()
180; CHECK-NEXT:    call void @a()
181; CHECK-NEXT:    br label [[LOOP_LATCH_US:%.*]]
182; CHECK:       loop_latch.us:
183; CHECK-NEXT:    [[V_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1
184; CHECK-NEXT:    br i1 [[V_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]]
185; CHECK:       loop_exit.split.us:
186; CHECK-NEXT:    br label [[LOOP_EXIT:%.*]]
187; CHECK:       entry.split:
188; CHECK-NEXT:    br label [[LOOP_BEGIN:%.*]]
189; CHECK:       loop_begin:
190; CHECK-NEXT:    call void @x()
191; CHECK-NEXT:    br label [[LOOP_B:%.*]]
192; CHECK:       loop_b:
193; CHECK-NEXT:    call void @b()
194; CHECK-NEXT:    call void @b()
195; CHECK-NEXT:    call void @b()
196; CHECK-NEXT:    call void @b()
197; CHECK-NEXT:    br label [[LOOP_LATCH:%.*]]
198; CHECK:       loop_latch:
199; CHECK-NEXT:    [[V:%.*]] = load i1, i1* [[PTR]], align 1
200; CHECK-NEXT:    br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT_SPLIT:%.*]]
201; CHECK:       loop_exit.split:
202; CHECK-NEXT:    br label [[LOOP_EXIT]]
203; CHECK:       loop_exit:
204; CHECK-NEXT:    ret void
205;
206entry:
207  br label %loop_begin
208
209loop_begin:
210  call void @x()
211  br i1 %cond, label %loop_a, label %loop_b
212
213loop_a:
214  call void @a()
215  call void @a()
216  call void @a()
217  call void @a()
218  br label %loop_latch
219
220loop_b:
221  call void @b()
222  call void @b()
223  call void @b()
224  call void @b()
225  br label %loop_latch
226
227loop_latch:
228  %v = load i1, i1* %ptr
229  br i1 %v, label %loop_begin, label %loop_exit
230
231loop_exit:
232  ret void
233}
234
235define void @test_unswitch_non_dup_code_minsize(i1* %ptr, i1 %cond) #0 {
236; CHECK-LABEL: @test_unswitch_non_dup_code_minsize(
237; CHECK-NEXT:  entry:
238; CHECK-NEXT:    br i1 [[COND:%.*]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
239; CHECK:       entry.split.us:
240; CHECK-NEXT:    br label [[LOOP_BEGIN_US:%.*]]
241; CHECK:       loop_begin.us:
242; CHECK-NEXT:    call void @x()
243; CHECK-NEXT:    br label [[LOOP_A_US:%.*]]
244; CHECK:       loop_a.us:
245; CHECK-NEXT:    call void @a()
246; CHECK-NEXT:    call void @a()
247; CHECK-NEXT:    call void @a()
248; CHECK-NEXT:    call void @a()
249; CHECK-NEXT:    br label [[LOOP_LATCH_US:%.*]]
250; CHECK:       loop_latch.us:
251; CHECK-NEXT:    [[V_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1
252; CHECK-NEXT:    br i1 [[V_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]]
253; CHECK:       loop_exit.split.us:
254; CHECK-NEXT:    br label [[LOOP_EXIT:%.*]]
255; CHECK:       entry.split:
256; CHECK-NEXT:    br label [[LOOP_BEGIN:%.*]]
257; CHECK:       loop_begin:
258; CHECK-NEXT:    call void @x()
259; CHECK-NEXT:    br label [[LOOP_B:%.*]]
260; CHECK:       loop_b:
261; CHECK-NEXT:    call void @b()
262; CHECK-NEXT:    call void @b()
263; CHECK-NEXT:    call void @b()
264; CHECK-NEXT:    call void @b()
265; CHECK-NEXT:    br label [[LOOP_LATCH:%.*]]
266; CHECK:       loop_latch:
267; CHECK-NEXT:    [[V:%.*]] = load i1, i1* [[PTR]], align 1
268; CHECK-NEXT:    br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT_SPLIT:%.*]]
269; CHECK:       loop_exit.split:
270; CHECK-NEXT:    br label [[LOOP_EXIT]]
271; CHECK:       loop_exit:
272; CHECK-NEXT:    ret void
273;
274entry:
275  br label %loop_begin
276
277loop_begin:
278  call void @x()
279  br i1 %cond, label %loop_a, label %loop_b
280
281loop_a:
282  call void @a()
283  call void @a()
284  call void @a()
285  call void @a()
286  br label %loop_latch
287
288loop_b:
289  call void @b()
290  call void @b()
291  call void @b()
292  call void @b()
293  br label %loop_latch
294
295loop_latch:
296  %v = load i1, i1* %ptr
297  br i1 %v, label %loop_begin, label %loop_exit
298
299loop_exit:
300  ret void
301}
302
303define void @test_unswitch_non_dup_code_in_cfg(i1* %ptr, i1 %cond) {
304; CHECK-LABEL: @test_unswitch_non_dup_code_in_cfg(
305; CHECK-NEXT:  entry:
306; CHECK-NEXT:    br i1 [[COND:%.*]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
307; CHECK:       entry.split.us:
308; CHECK-NEXT:    br label [[LOOP_BEGIN_US:%.*]]
309; CHECK:       loop_begin.us:
310; CHECK-NEXT:    call void @x()
311; CHECK-NEXT:    br label [[LOOP_A_US:%.*]]
312; CHECK:       loop_a.us:
313; CHECK-NEXT:    [[V1_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1
314; CHECK-NEXT:    br i1 [[V1_US]], label [[LOOP_A_A_US:%.*]], label [[LOOP_A_B_US:%.*]]
315; CHECK:       loop_a_b.us:
316; CHECK-NEXT:    call void @a()
317; CHECK-NEXT:    br label [[LOOP_LATCH_US:%.*]]
318; CHECK:       loop_a_a.us:
319; CHECK-NEXT:    call void @a()
320; CHECK-NEXT:    br label [[LOOP_LATCH_US]]
321; CHECK:       loop_latch.us:
322; CHECK-NEXT:    [[V3_US:%.*]] = load i1, i1* [[PTR]], align 1
323; CHECK-NEXT:    br i1 [[V3_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]]
324; CHECK:       loop_exit.split.us:
325; CHECK-NEXT:    br label [[LOOP_EXIT:%.*]]
326; CHECK:       entry.split:
327; CHECK-NEXT:    br label [[LOOP_BEGIN:%.*]]
328; CHECK:       loop_begin:
329; CHECK-NEXT:    call void @x()
330; CHECK-NEXT:    br label [[LOOP_B:%.*]]
331; CHECK:       loop_b:
332; CHECK-NEXT:    [[V2:%.*]] = load i1, i1* [[PTR]], align 1
333; CHECK-NEXT:    br i1 [[V2]], label [[LOOP_B_A:%.*]], label [[LOOP_B_B:%.*]]
334; CHECK:       loop_b_a:
335; CHECK-NEXT:    call void @b()
336; CHECK-NEXT:    br label [[LOOP_LATCH:%.*]]
337; CHECK:       loop_b_b:
338; CHECK-NEXT:    call void @b()
339; CHECK-NEXT:    br label [[LOOP_LATCH]]
340; CHECK:       loop_latch:
341; CHECK-NEXT:    [[V3:%.*]] = load i1, i1* [[PTR]], align 1
342; CHECK-NEXT:    br i1 [[V3]], label [[LOOP_BEGIN]], label [[LOOP_EXIT_SPLIT:%.*]]
343; CHECK:       loop_exit.split:
344; CHECK-NEXT:    br label [[LOOP_EXIT]]
345; CHECK:       loop_exit:
346; CHECK-NEXT:    ret void
347;
348entry:
349  br label %loop_begin
350
351loop_begin:
352  call void @x()
353  br i1 %cond, label %loop_a, label %loop_b
354
355loop_a:
356  %v1 = load i1, i1* %ptr
357  br i1 %v1, label %loop_a_a, label %loop_a_b
358
359loop_a_a:
360  call void @a()
361  br label %loop_latch
362
363loop_a_b:
364  call void @a()
365  br label %loop_latch
366
367loop_b:
368  %v2 = load i1, i1* %ptr
369  br i1 %v2, label %loop_b_a, label %loop_b_b
370
371loop_b_a:
372  call void @b()
373  br label %loop_latch
374
375loop_b_b:
376  call void @b()
377  br label %loop_latch
378
379loop_latch:
380  %v3 = load i1, i1* %ptr
381  br i1 %v3, label %loop_begin, label %loop_exit
382
383loop_exit:
384  ret void
385}
386
387define void @test_unswitch_non_dup_code_in_cfg_minsize(i1* %ptr, i1 %cond) #0 {
388; CHECK-LABEL: @test_unswitch_non_dup_code_in_cfg_minsize(
389; CHECK-NEXT:  entry:
390; CHECK-NEXT:    br i1 [[COND:%.*]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
391; CHECK:       entry.split.us:
392; CHECK-NEXT:    br label [[LOOP_BEGIN_US:%.*]]
393; CHECK:       loop_begin.us:
394; CHECK-NEXT:    call void @x()
395; CHECK-NEXT:    br label [[LOOP_A_US:%.*]]
396; CHECK:       loop_a.us:
397; CHECK-NEXT:    [[V1_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1
398; CHECK-NEXT:    br i1 [[V1_US]], label [[LOOP_A_A_US:%.*]], label [[LOOP_A_B_US:%.*]]
399; CHECK:       loop_a_b.us:
400; CHECK-NEXT:    call void @a()
401; CHECK-NEXT:    br label [[LOOP_LATCH_US:%.*]]
402; CHECK:       loop_a_a.us:
403; CHECK-NEXT:    call void @a()
404; CHECK-NEXT:    br label [[LOOP_LATCH_US]]
405; CHECK:       loop_latch.us:
406; CHECK-NEXT:    [[V3_US:%.*]] = load i1, i1* [[PTR]], align 1
407; CHECK-NEXT:    br i1 [[V3_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]]
408; CHECK:       loop_exit.split.us:
409; CHECK-NEXT:    br label [[LOOP_EXIT:%.*]]
410; CHECK:       entry.split:
411; CHECK-NEXT:    br label [[LOOP_BEGIN:%.*]]
412; CHECK:       loop_begin:
413; CHECK-NEXT:    call void @x()
414; CHECK-NEXT:    br label [[LOOP_B:%.*]]
415; CHECK:       loop_b:
416; CHECK-NEXT:    [[V2:%.*]] = load i1, i1* [[PTR]], align 1
417; CHECK-NEXT:    br i1 [[V2]], label [[LOOP_B_A:%.*]], label [[LOOP_B_B:%.*]]
418; CHECK:       loop_b_a:
419; CHECK-NEXT:    call void @b()
420; CHECK-NEXT:    br label [[LOOP_LATCH:%.*]]
421; CHECK:       loop_b_b:
422; CHECK-NEXT:    call void @b()
423; CHECK-NEXT:    br label [[LOOP_LATCH]]
424; CHECK:       loop_latch:
425; CHECK-NEXT:    [[V3:%.*]] = load i1, i1* [[PTR]], align 1
426; CHECK-NEXT:    br i1 [[V3]], label [[LOOP_BEGIN]], label [[LOOP_EXIT_SPLIT:%.*]]
427; CHECK:       loop_exit.split:
428; CHECK-NEXT:    br label [[LOOP_EXIT]]
429; CHECK:       loop_exit:
430; CHECK-NEXT:    ret void
431;
432entry:
433  br label %loop_begin
434
435loop_begin:
436  call void @x()
437  br i1 %cond, label %loop_a, label %loop_b
438
439loop_a:
440  %v1 = load i1, i1* %ptr
441  br i1 %v1, label %loop_a_a, label %loop_a_b
442
443loop_a_a:
444  call void @a()
445  br label %loop_latch
446
447loop_a_b:
448  call void @a()
449  br label %loop_latch
450
451loop_b:
452  %v2 = load i1, i1* %ptr
453  br i1 %v2, label %loop_b_a, label %loop_b_b
454
455loop_b_a:
456  call void @b()
457  br label %loop_latch
458
459loop_b_b:
460  call void @b()
461  br label %loop_latch
462
463loop_latch:
464  %v3 = load i1, i1* %ptr
465  br i1 %v3, label %loop_begin, label %loop_exit
466
467loop_exit:
468  ret void
469}
470
471define void @test_no_unswitch_non_dup_code(i1* %ptr, i1 %cond) {
472; CHECK-LABEL: @test_no_unswitch_non_dup_code(
473; CHECK-NEXT:  entry:
474; CHECK-NEXT:    br label [[LOOP_BEGIN:%.*]]
475; CHECK:       loop_begin:
476; CHECK-NEXT:    call void @x()
477; CHECK-NEXT:    br i1 [[COND:%.*]], label [[LOOP_A:%.*]], label [[LOOP_B:%.*]]
478; CHECK:       loop_a:
479; CHECK-NEXT:    [[V1:%.*]] = load i1, i1* [[PTR:%.*]], align 1
480; CHECK-NEXT:    br i1 [[V1]], label [[LOOP_A_A:%.*]], label [[LOOP_A_B:%.*]]
481; CHECK:       loop_a_a:
482; CHECK-NEXT:    call void @a()
483; CHECK-NEXT:    br label [[LOOP_LATCH:%.*]]
484; CHECK:       loop_a_b:
485; CHECK-NEXT:    call void @a()
486; CHECK-NEXT:    br label [[LOOP_LATCH]]
487; CHECK:       loop_b:
488; CHECK-NEXT:    [[V2:%.*]] = load i1, i1* [[PTR]], align 1
489; CHECK-NEXT:    br i1 [[V2]], label [[LOOP_B_A:%.*]], label [[LOOP_B_B:%.*]]
490; CHECK:       loop_b_a:
491; CHECK-NEXT:    call void @b()
492; CHECK-NEXT:    br label [[LOOP_LATCH]]
493; CHECK:       loop_b_b:
494; CHECK-NEXT:    call void @b()
495; CHECK-NEXT:    br label [[LOOP_LATCH]]
496; CHECK:       loop_latch:
497; CHECK-NEXT:    call void @x()
498; CHECK-NEXT:    call void @x()
499; CHECK-NEXT:    [[V:%.*]] = load i1, i1* [[PTR]], align 1
500; CHECK-NEXT:    br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT:%.*]]
501; CHECK:       loop_exit:
502; CHECK-NEXT:    ret void
503;
504entry:
505  br label %loop_begin
506
507loop_begin:
508  call void @x()
509  br i1 %cond, label %loop_a, label %loop_b
510
511loop_a:
512  %v1 = load i1, i1* %ptr
513  br i1 %v1, label %loop_a_a, label %loop_a_b
514
515loop_a_a:
516  call void @a()
517  br label %loop_latch
518
519loop_a_b:
520  call void @a()
521  br label %loop_latch
522
523loop_b:
524  %v2 = load i1, i1* %ptr
525  br i1 %v2, label %loop_b_a, label %loop_b_b
526
527loop_b_a:
528  call void @b()
529  br label %loop_latch
530
531loop_b_b:
532  call void @b()
533  br label %loop_latch
534
535loop_latch:
536  call void @x()
537  call void @x()
538  %v = load i1, i1* %ptr
539  br i1 %v, label %loop_begin, label %loop_exit
540
541loop_exit:
542  ret void
543}
544
545define void @test_unswitch_large_exit(i1* %ptr, i1 %cond) {
546; CHECK-LABEL: @test_unswitch_large_exit(
547; CHECK-NEXT:  entry:
548; CHECK-NEXT:    br i1 [[COND:%.*]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
549; CHECK:       entry.split.us:
550; CHECK-NEXT:    br label [[LOOP_BEGIN_US:%.*]]
551; CHECK:       loop_begin.us:
552; CHECK-NEXT:    call void @x()
553; CHECK-NEXT:    br label [[LOOP_A_US:%.*]]
554; CHECK:       loop_a.us:
555; CHECK-NEXT:    call void @a()
556; CHECK-NEXT:    br label [[LOOP_LATCH_US:%.*]]
557; CHECK:       loop_latch.us:
558; CHECK-NEXT:    [[V_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1
559; CHECK-NEXT:    br i1 [[V_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]]
560; CHECK:       loop_exit.split.us:
561; CHECK-NEXT:    br label [[LOOP_EXIT:%.*]]
562; CHECK:       entry.split:
563; CHECK-NEXT:    br label [[LOOP_BEGIN:%.*]]
564; CHECK:       loop_begin:
565; CHECK-NEXT:    call void @x()
566; CHECK-NEXT:    br label [[LOOP_B:%.*]]
567; CHECK:       loop_b:
568; CHECK-NEXT:    call void @b()
569; CHECK-NEXT:    br label [[LOOP_LATCH:%.*]]
570; CHECK:       loop_latch:
571; CHECK-NEXT:    [[V:%.*]] = load i1, i1* [[PTR]], align 1
572; CHECK-NEXT:    br i1 [[V]], label [[LOOP_BEGIN]], label [[LOOP_EXIT_SPLIT:%.*]]
573; CHECK:       loop_exit.split:
574; CHECK-NEXT:    br label [[LOOP_EXIT]]
575; CHECK:       loop_exit:
576; CHECK-NEXT:    call void @x()
577; CHECK-NEXT:    call void @x()
578; CHECK-NEXT:    call void @x()
579; CHECK-NEXT:    call void @x()
580; CHECK-NEXT:    ret void
581;
582entry:
583  br label %loop_begin
584
585loop_begin:
586  call void @x()
587  br i1 %cond, label %loop_a, label %loop_b
588
589loop_a:
590  call void @a()
591  br label %loop_latch
592
593loop_b:
594  call void @b()
595  br label %loop_latch
596
597loop_latch:
598  %v = load i1, i1* %ptr
599  br i1 %v, label %loop_begin, label %loop_exit
600
601loop_exit:
602  call void @x()
603  call void @x()
604  call void @x()
605  call void @x()
606  ret void
607}
608
609define void @test_unswitch_dedicated_exiting(i1* %ptr, i1 %cond) {
610; CHECK-LABEL: @test_unswitch_dedicated_exiting(
611; CHECK-NEXT:  entry:
612; CHECK-NEXT:    br i1 [[COND:%.*]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
613; CHECK:       entry.split.us:
614; CHECK-NEXT:    br label [[LOOP_BEGIN_US:%.*]]
615; CHECK:       loop_begin.us:
616; CHECK-NEXT:    call void @x()
617; CHECK-NEXT:    br label [[LOOP_A_US:%.*]]
618; CHECK:       loop_a.us:
619; CHECK-NEXT:    call void @a()
620; CHECK-NEXT:    br label [[LOOP_LATCH_US:%.*]]
621; CHECK:       loop_latch.us:
622; CHECK-NEXT:    [[V_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1
623; CHECK-NEXT:    br i1 [[V_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]]
624; CHECK:       loop_exit.split.us:
625; CHECK-NEXT:    br label [[LOOP_EXIT:%.*]]
626; CHECK:       entry.split:
627; CHECK-NEXT:    br label [[LOOP_BEGIN:%.*]]
628; CHECK:       loop_begin:
629; CHECK-NEXT:    call void @x()
630; CHECK-NEXT:    br label [[LOOP_B_EXIT:%.*]]
631; CHECK:       loop_b_exit:
632; CHECK-NEXT:    call void @b()
633; CHECK-NEXT:    call void @b()
634; CHECK-NEXT:    call void @b()
635; CHECK-NEXT:    call void @b()
636; CHECK-NEXT:    ret void
637; CHECK:       loop_exit:
638; CHECK-NEXT:    ret void
639;
640entry:
641  br label %loop_begin
642
643loop_begin:
644  call void @x()
645  br i1 %cond, label %loop_a, label %loop_b_exit
646
647loop_a:
648  call void @a()
649  br label %loop_latch
650
651loop_b_exit:
652  call void @b()
653  call void @b()
654  call void @b()
655  call void @b()
656  ret void
657
658loop_latch:
659  %v = load i1, i1* %ptr
660  br i1 %v, label %loop_begin, label %loop_exit
661
662loop_exit:
663  ret void
664}
665
666define void @test_unswitch_dedicated_exiting_minsize(i1* %ptr, i1 %cond) #0 {
667; CHECK-LABEL: @test_unswitch_dedicated_exiting_minsize(
668; CHECK-NEXT:  entry:
669; CHECK-NEXT:    br i1 [[COND:%.*]], label [[ENTRY_SPLIT_US:%.*]], label [[ENTRY_SPLIT:%.*]]
670; CHECK:       entry.split.us:
671; CHECK-NEXT:    br label [[LOOP_BEGIN_US:%.*]]
672; CHECK:       loop_begin.us:
673; CHECK-NEXT:    call void @x()
674; CHECK-NEXT:    br label [[LOOP_A_US:%.*]]
675; CHECK:       loop_a.us:
676; CHECK-NEXT:    call void @a()
677; CHECK-NEXT:    br label [[LOOP_LATCH_US:%.*]]
678; CHECK:       loop_latch.us:
679; CHECK-NEXT:    [[V_US:%.*]] = load i1, i1* [[PTR:%.*]], align 1
680; CHECK-NEXT:    br i1 [[V_US]], label [[LOOP_BEGIN_US]], label [[LOOP_EXIT_SPLIT_US:%.*]]
681; CHECK:       loop_exit.split.us:
682; CHECK-NEXT:    br label [[LOOP_EXIT:%.*]]
683; CHECK:       entry.split:
684; CHECK-NEXT:    br label [[LOOP_BEGIN:%.*]]
685; CHECK:       loop_begin:
686; CHECK-NEXT:    call void @x()
687; CHECK-NEXT:    br label [[LOOP_B_EXIT:%.*]]
688; CHECK:       loop_b_exit:
689; CHECK-NEXT:    call void @b()
690; CHECK-NEXT:    call void @b()
691; CHECK-NEXT:    call void @b()
692; CHECK-NEXT:    call void @b()
693; CHECK-NEXT:    ret void
694; CHECK:       loop_exit:
695; CHECK-NEXT:    ret void
696;
697entry:
698  br label %loop_begin
699
700loop_begin:
701  call void @x()
702  br i1 %cond, label %loop_a, label %loop_b_exit
703
704loop_a:
705  call void @a()
706  br label %loop_latch
707
708loop_b_exit:
709  call void @b()
710  call void @b()
711  call void @b()
712  call void @b()
713  ret void
714
715loop_latch:
716  %v = load i1, i1* %ptr
717  br i1 %v, label %loop_begin, label %loop_exit
718
719loop_exit:
720  ret void
721}
722
723attributes #0 = { minsize optsize }
724