xref: /llvm-project/llvm/test/Transforms/LoopUnroll/peel-multiple-unreachable-exits.ll (revision ef992b60798b6cd2c50b25351bfc392e319896b7)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=loop-unroll -S %s | FileCheck %s
3
4declare void @foo()
5
6define void @peel_unreachable_exit_and_latch_exit(ptr %ptr, i32 %N, i32 %x) {
7; CHECK-LABEL: @peel_unreachable_exit_and_latch_exit(
8; CHECK-NEXT:  entry:
9; CHECK-NEXT:    br label [[LOOP_HEADER_PEEL_BEGIN:%.*]]
10; CHECK:       loop.header.peel.begin:
11; CHECK-NEXT:    br label [[LOOP_HEADER_PEEL:%.*]]
12; CHECK:       loop.header.peel:
13; CHECK-NEXT:    [[C_PEEL:%.*]] = icmp ult i32 1, 2
14; CHECK-NEXT:    br i1 [[C_PEEL]], label [[THEN_PEEL:%.*]], label [[ELSE_PEEL:%.*]]
15; CHECK:       else.peel:
16; CHECK-NEXT:    [[C_2_PEEL:%.*]] = icmp eq i32 1, [[X:%.*]]
17; CHECK-NEXT:    br i1 [[C_2_PEEL]], label [[UNREACHABLE_EXIT:%.*]], label [[LOOP_LATCH_PEEL:%.*]]
18; CHECK:       then.peel:
19; CHECK-NEXT:    br label [[LOOP_LATCH_PEEL]]
20; CHECK:       loop.latch.peel:
21; CHECK-NEXT:    [[M_PEEL:%.*]] = phi i32 [ 0, [[THEN_PEEL]] ], [ [[X]], [[ELSE_PEEL]] ]
22; CHECK-NEXT:    [[GEP_PEEL:%.*]] = getelementptr i32, ptr [[PTR:%.*]], i32 1
23; CHECK-NEXT:    store i32 [[M_PEEL]], ptr [[GEP_PEEL]], align 4
24; CHECK-NEXT:    [[IV_NEXT_PEEL:%.*]] = add nuw nsw i32 1, 1
25; CHECK-NEXT:    [[C_3_PEEL:%.*]] = icmp ult i32 1, 1000
26; CHECK-NEXT:    br i1 [[C_3_PEEL]], label [[LOOP_HEADER_PEEL_NEXT:%.*]], label [[EXIT:%.*]]
27; CHECK:       loop.header.peel.next:
28; CHECK-NEXT:    br label [[LOOP_HEADER_PEEL_NEXT1:%.*]]
29; CHECK:       loop.header.peel.next1:
30; CHECK-NEXT:    br label [[ENTRY_PEEL_NEWPH:%.*]]
31; CHECK:       entry.peel.newph:
32; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
33; CHECK:       loop.header:
34; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[IV_NEXT_PEEL]], [[ENTRY_PEEL_NEWPH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
35; CHECK-NEXT:    br i1 false, label [[THEN:%.*]], label [[ELSE:%.*]]
36; CHECK:       then:
37; CHECK-NEXT:    br label [[LOOP_LATCH]]
38; CHECK:       else:
39; CHECK-NEXT:    [[C_2:%.*]] = icmp eq i32 [[IV]], [[X]]
40; CHECK-NEXT:    br i1 [[C_2]], label [[UNREACHABLE_EXIT_LOOPEXIT:%.*]], label [[LOOP_LATCH]]
41; CHECK:       loop.latch:
42; CHECK-NEXT:    [[M:%.*]] = phi i32 [ 0, [[THEN]] ], [ [[X]], [[ELSE]] ]
43; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i32, ptr [[PTR]], i32 [[IV]]
44; CHECK-NEXT:    store i32 [[M]], ptr [[GEP]], align 4
45; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
46; CHECK-NEXT:    [[C_3:%.*]] = icmp ult i32 [[IV]], 1000
47; CHECK-NEXT:    br i1 [[C_3]], label [[LOOP_HEADER]], label [[EXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP0:![0-9]+]]
48; CHECK:       exit.loopexit:
49; CHECK-NEXT:    br label [[EXIT]]
50; CHECK:       exit:
51; CHECK-NEXT:    ret void
52; CHECK:       unreachable.exit.loopexit:
53; CHECK-NEXT:    br label [[UNREACHABLE_EXIT]]
54; CHECK:       unreachable.exit:
55; CHECK-NEXT:    call void @foo()
56; CHECK-NEXT:    unreachable
57;
58entry:
59  br label %loop.header
60
61loop.header:
62  %iv = phi i32 [ 1, %entry ], [ %iv.next, %loop.latch ]
63  %c = icmp ult i32 %iv, 2
64  br i1 %c, label %then, label %else
65
66then:
67  br label %loop.latch
68
69else:
70  %c.2 = icmp eq i32 %iv, %x
71  br i1 %c.2, label %unreachable.exit, label %loop.latch
72
73loop.latch:
74  %m = phi i32 [ 0, %then ], [ %x, %else ]
75  %gep = getelementptr i32, ptr %ptr, i32 %iv
76  store i32 %m, ptr %gep
77  %iv.next = add nuw nsw i32  %iv, 1
78  %c.3 = icmp ult i32 %iv, 1000
79  br i1 %c.3, label %loop.header, label %exit
80
81exit:
82  ret void
83
84unreachable.exit:
85  call void @foo()
86  unreachable
87}
88
89define void @peel_unreachable_exit_and_header_exit(ptr %ptr, i32 %N, i32 %x) {
90; CHECK-LABEL: @peel_unreachable_exit_and_header_exit(
91; CHECK-NEXT:  entry:
92; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
93; CHECK:       loop.header:
94; CHECK-NEXT:    br i1 true, label [[EXIT:%.*]], label [[ELSE:%.*]]
95; CHECK:       else:
96; CHECK-NEXT:    [[C_2:%.*]] = icmp eq i32 1, [[X:%.*]]
97; CHECK-NEXT:    br i1 [[C_2]], label [[UNREACHABLE_EXIT:%.*]], label [[LOOP_LATCH:%.*]]
98; CHECK:       loop.latch:
99; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i32, ptr [[PTR:%.*]], i32 1
100; CHECK-NEXT:    store i32 [[X]], ptr [[GEP]], align 4
101; CHECK-NEXT:    unreachable
102; CHECK:       exit:
103; CHECK-NEXT:    ret void
104; CHECK:       unreachable.exit:
105; CHECK-NEXT:    call void @foo()
106; CHECK-NEXT:    unreachable
107;
108entry:
109  br label %loop.header
110
111loop.header:
112  %iv = phi i32 [ 1, %entry ], [ %iv.next, %loop.latch ]
113  %c = icmp ult i32 %iv, 1000
114  br i1 %c, label %exit, label %else
115
116else:
117  %c.2 = icmp eq i32 %iv, %x
118  br i1 %c.2, label %unreachable.exit, label %loop.latch
119
120loop.latch:
121  %gep = getelementptr i32, ptr %ptr, i32 %iv
122  store i32 %x, ptr %gep
123  %iv.next = add nuw nsw i32  %iv, 1
124  br label %loop.header
125
126exit:
127  ret void
128
129unreachable.exit:
130  call void @foo()
131  unreachable
132}
133
134define void @peel_unreachable_and_multiple_reachable_exits(ptr %ptr, i32 %N, i32 %x) {
135; CHECK-LABEL: @peel_unreachable_and_multiple_reachable_exits(
136; CHECK-NEXT:  entry:
137; CHECK-NEXT:    br label [[LOOP_HEADER_PEEL_BEGIN:%.*]]
138; CHECK:       loop.header.peel.begin:
139; CHECK-NEXT:    br label [[LOOP_HEADER_PEEL:%.*]]
140; CHECK:       loop.header.peel:
141; CHECK-NEXT:    [[C_PEEL:%.*]] = icmp ult i32 1, 2
142; CHECK-NEXT:    br i1 [[C_PEEL]], label [[THEN_PEEL:%.*]], label [[ELSE_PEEL:%.*]]
143; CHECK:       else.peel:
144; CHECK-NEXT:    [[C_3_PEEL:%.*]] = icmp eq i32 1, [[X:%.*]]
145; CHECK-NEXT:    br i1 [[C_3_PEEL]], label [[UNREACHABLE_EXIT:%.*]], label [[LOOP_LATCH_PEEL:%.*]]
146; CHECK:       then.peel:
147; CHECK-NEXT:    [[C_2_PEEL:%.*]] = icmp sgt i32 1, [[X]]
148; CHECK-NEXT:    br i1 [[C_2_PEEL]], label [[EXIT:%.*]], label [[LOOP_LATCH_PEEL]]
149; CHECK:       loop.latch.peel:
150; CHECK-NEXT:    [[M_PEEL:%.*]] = phi i32 [ 0, [[THEN_PEEL]] ], [ [[X]], [[ELSE_PEEL]] ]
151; CHECK-NEXT:    [[GEP_PEEL:%.*]] = getelementptr i32, ptr [[PTR:%.*]], i32 1
152; CHECK-NEXT:    store i32 [[M_PEEL]], ptr [[GEP_PEEL]], align 4
153; CHECK-NEXT:    [[IV_NEXT_PEEL:%.*]] = add nuw nsw i32 1, 1
154; CHECK-NEXT:    [[C_4_PEEL:%.*]] = icmp ult i32 1, 1000
155; CHECK-NEXT:    br i1 [[C_4_PEEL]], label [[LOOP_HEADER_PEEL_NEXT:%.*]], label [[EXIT]]
156; CHECK:       loop.header.peel.next:
157; CHECK-NEXT:    br label [[LOOP_HEADER_PEEL_NEXT1:%.*]]
158; CHECK:       loop.header.peel.next1:
159; CHECK-NEXT:    br label [[ENTRY_PEEL_NEWPH:%.*]]
160; CHECK:       entry.peel.newph:
161; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
162; CHECK:       loop.header:
163; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[IV_NEXT_PEEL]], [[ENTRY_PEEL_NEWPH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
164; CHECK-NEXT:    br i1 false, label [[THEN:%.*]], label [[ELSE:%.*]]
165; CHECK:       then:
166; CHECK-NEXT:    br i1 true, label [[EXIT_LOOPEXIT:%.*]], label [[LOOP_LATCH]]
167; CHECK:       else:
168; CHECK-NEXT:    [[C_3:%.*]] = icmp eq i32 [[IV]], [[X]]
169; CHECK-NEXT:    br i1 [[C_3]], label [[UNREACHABLE_EXIT_LOOPEXIT:%.*]], label [[LOOP_LATCH]]
170; CHECK:       loop.latch:
171; CHECK-NEXT:    [[M:%.*]] = phi i32 [ 0, [[THEN]] ], [ [[X]], [[ELSE]] ]
172; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i32, ptr [[PTR]], i32 [[IV]]
173; CHECK-NEXT:    store i32 [[M]], ptr [[GEP]], align 4
174; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
175; CHECK-NEXT:    [[C_4:%.*]] = icmp ult i32 [[IV]], 1000
176; CHECK-NEXT:    br i1 [[C_4]], label [[LOOP_HEADER]], label [[EXIT_LOOPEXIT]], !llvm.loop [[LOOP2:![0-9]+]]
177; CHECK:       exit.loopexit:
178; CHECK-NEXT:    br label [[EXIT]]
179; CHECK:       exit:
180; CHECK-NEXT:    ret void
181; CHECK:       unreachable.exit.loopexit:
182; CHECK-NEXT:    br label [[UNREACHABLE_EXIT]]
183; CHECK:       unreachable.exit:
184; CHECK-NEXT:    call void @foo()
185; CHECK-NEXT:    unreachable
186;
187entry:
188  br label %loop.header
189
190loop.header:
191  %iv = phi i32 [ 1, %entry ], [ %iv.next, %loop.latch ]
192  %c = icmp ult i32 %iv, 2
193  br i1 %c, label %then, label %else
194
195then:
196  %c.2 = icmp sgt i32 %iv, %x
197  br i1 %c.2, label %exit, label %loop.latch
198
199else:
200  %c.3 = icmp eq i32 %iv, %x
201  br i1 %c.3, label %unreachable.exit, label %loop.latch
202
203loop.latch:
204  %m = phi i32 [ 0, %then ], [ %x, %else ]
205  %gep = getelementptr i32, ptr %ptr, i32 %iv
206  store i32 %m, ptr %gep
207  %iv.next = add nuw nsw i32  %iv, 1
208  %c.4 = icmp ult i32 %iv, 1000
209  br i1 %c.4, label %loop.header, label %exit
210
211exit:
212  ret void
213
214unreachable.exit:
215  call void @foo()
216  unreachable
217}
218
219define void @peel_exits_to_blocks_branch_to_unreachable_block(ptr %ptr, i32 %N, i32 %x, i1 %c.1) {
220; CHECK-LABEL: @peel_exits_to_blocks_branch_to_unreachable_block(
221; CHECK-NEXT:  entry:
222; CHECK-NEXT:    br label [[LOOP_HEADER_PEEL_BEGIN:%.*]]
223; CHECK:       loop.header.peel.begin:
224; CHECK-NEXT:    br label [[LOOP_HEADER_PEEL:%.*]]
225; CHECK:       loop.header.peel:
226; CHECK-NEXT:    [[C_PEEL:%.*]] = icmp ult i32 1, 2
227; CHECK-NEXT:    br i1 [[C_PEEL]], label [[THEN_PEEL:%.*]], label [[ELSE_PEEL:%.*]]
228; CHECK:       else.peel:
229; CHECK-NEXT:    [[C_2_PEEL:%.*]] = icmp eq i32 1, [[X:%.*]]
230; CHECK-NEXT:    br i1 [[C_2_PEEL]], label [[EXIT_2:%.*]], label [[LOOP_LATCH_PEEL:%.*]]
231; CHECK:       then.peel:
232; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[EXIT_1:%.*]], label [[LOOP_LATCH_PEEL]]
233; CHECK:       loop.latch.peel:
234; CHECK-NEXT:    [[M_PEEL:%.*]] = phi i32 [ 0, [[THEN_PEEL]] ], [ [[X]], [[ELSE_PEEL]] ]
235; CHECK-NEXT:    [[GEP_PEEL:%.*]] = getelementptr i32, ptr [[PTR:%.*]], i32 1
236; CHECK-NEXT:    store i32 [[M_PEEL]], ptr [[GEP_PEEL]], align 4
237; CHECK-NEXT:    [[IV_NEXT_PEEL:%.*]] = add nuw nsw i32 1, 1
238; CHECK-NEXT:    [[C_3_PEEL:%.*]] = icmp ult i32 1, 1000
239; CHECK-NEXT:    br i1 [[C_3_PEEL]], label [[LOOP_HEADER_PEEL_NEXT:%.*]], label [[EXIT:%.*]]
240; CHECK:       loop.header.peel.next:
241; CHECK-NEXT:    br label [[LOOP_HEADER_PEEL_NEXT1:%.*]]
242; CHECK:       loop.header.peel.next1:
243; CHECK-NEXT:    br label [[ENTRY_PEEL_NEWPH:%.*]]
244; CHECK:       entry.peel.newph:
245; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
246; CHECK:       loop.header:
247; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[IV_NEXT_PEEL]], [[ENTRY_PEEL_NEWPH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
248; CHECK-NEXT:    br i1 false, label [[THEN:%.*]], label [[ELSE:%.*]]
249; CHECK:       then:
250; CHECK-NEXT:    br i1 [[C_1]], label [[EXIT_1_LOOPEXIT:%.*]], label [[LOOP_LATCH]]
251; CHECK:       else:
252; CHECK-NEXT:    [[C_2:%.*]] = icmp eq i32 [[IV]], [[X]]
253; CHECK-NEXT:    br i1 [[C_2]], label [[EXIT_2_LOOPEXIT:%.*]], label [[LOOP_LATCH]]
254; CHECK:       loop.latch:
255; CHECK-NEXT:    [[M:%.*]] = phi i32 [ 0, [[THEN]] ], [ [[X]], [[ELSE]] ]
256; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i32, ptr [[PTR]], i32 [[IV]]
257; CHECK-NEXT:    store i32 [[M]], ptr [[GEP]], align 4
258; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
259; CHECK-NEXT:    [[C_3:%.*]] = icmp ult i32 [[IV]], 1000
260; CHECK-NEXT:    br i1 [[C_3]], label [[LOOP_HEADER]], label [[EXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP3:![0-9]+]]
261; CHECK:       exit.loopexit:
262; CHECK-NEXT:    br label [[EXIT]]
263; CHECK:       exit:
264; CHECK-NEXT:    ret void
265; CHECK:       exit.1.loopexit:
266; CHECK-NEXT:    br label [[EXIT_1]]
267; CHECK:       exit.1:
268; CHECK-NEXT:    call void @foo()
269; CHECK-NEXT:    br label [[UNREACHABLE_TERM:%.*]]
270; CHECK:       exit.2.loopexit:
271; CHECK-NEXT:    br label [[EXIT_2]]
272; CHECK:       exit.2:
273; CHECK-NEXT:    call void @bar()
274; CHECK-NEXT:    br label [[UNREACHABLE_TERM]]
275; CHECK:       unreachable.term:
276; CHECK-NEXT:    call void @baz()
277; CHECK-NEXT:    unreachable
278;
279entry:
280  br label %loop.header
281
282loop.header:
283  %iv = phi i32 [ 1, %entry ], [ %iv.next, %loop.latch ]
284  %c = icmp ult i32 %iv, 2
285  br i1 %c, label %then, label %else
286
287then:
288  br i1 %c.1, label %exit.1, label %loop.latch
289
290else:
291  %c.2 = icmp eq i32 %iv, %x
292  br i1 %c.2, label %exit.2, label %loop.latch
293
294loop.latch:
295  %m = phi i32 [ 0, %then ], [ %x, %else ]
296  %gep = getelementptr i32, ptr %ptr, i32 %iv
297  store i32 %m, ptr %gep
298  %iv.next = add nuw nsw i32  %iv, 1
299  %c.3 = icmp ult i32 %iv, 1000
300  br i1 %c.3, label %loop.header, label %exit
301
302exit:
303  ret void
304
305exit.1:
306  call void @foo()
307  br label %unreachable.term
308
309exit.2:
310  call void @bar()
311  br label %unreachable.term
312
313unreachable.term:
314  call void @baz()
315  unreachable
316}
317
318define void @peel_exits_to_blocks_branch_to_unreachable_block_with_invariant_load(ptr %ptr, i32 %N, i32 %x, i1 %c.1, i32 %y, ptr %size_ptr) {
319; CHECK-LABEL: @peel_exits_to_blocks_branch_to_unreachable_block_with_invariant_load(
320; CHECK-NEXT:  entry:
321; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
322; CHECK:       loop.header:
323; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
324; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[Y:%.*]]
325; CHECK-NEXT:    br i1 [[C]], label [[THEN:%.*]], label [[ELSE:%.*]]
326; CHECK:       then:
327; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[EXIT_1:%.*]], label [[LOOP_LATCH]]
328; CHECK:       else:
329; CHECK-NEXT:    [[C_2:%.*]] = icmp eq i32 [[IV]], [[X:%.*]]
330; CHECK-NEXT:    br i1 [[C_2]], label [[EXIT_2:%.*]], label [[LOOP_LATCH]]
331; CHECK:       loop.latch:
332; CHECK-NEXT:    [[M:%.*]] = phi i32 [ 0, [[THEN]] ], [ [[X]], [[ELSE]] ]
333; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i32, ptr [[PTR:%.*]], i32 [[IV]]
334; CHECK-NEXT:    store i32 [[M]], ptr [[GEP]], align 4
335; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
336; CHECK-NEXT:    [[SIZE:%.*]] = load i32, ptr [[SIZE_PTR:%.*]], align 4
337; CHECK-NEXT:    [[C_3:%.*]] = icmp ult i32 [[IV_NEXT]], [[SIZE]]
338; CHECK-NEXT:    br i1 [[C_3]], label [[LOOP_HEADER]], label [[EXIT:%.*]]
339; CHECK:       exit:
340; CHECK-NEXT:    ret void
341; CHECK:       exit.1:
342; CHECK-NEXT:    call void @foo()
343; CHECK-NEXT:    br label [[UNREACHABLE_TERM:%.*]]
344; CHECK:       exit.2:
345; CHECK-NEXT:    call void @bar()
346; CHECK-NEXT:    br label [[UNREACHABLE_TERM]]
347; CHECK:       unreachable.term:
348; CHECK-NEXT:    call void @baz()
349; CHECK-NEXT:    unreachable
350;
351entry:
352  br label %loop.header
353
354loop.header:
355  %iv = phi i32 [ 1, %entry ], [ %iv.next, %loop.latch ]
356  %c = icmp ult i32 %iv, %y
357  br i1 %c, label %then, label %else
358
359then:
360  br i1 %c.1, label %exit.1, label %loop.latch
361
362else:
363  %c.2 = icmp eq i32 %iv, %x
364  br i1 %c.2, label %exit.2, label %loop.latch
365
366loop.latch:
367  %m = phi i32 [ 0, %then ], [ %x, %else ]
368  %gep = getelementptr i32, ptr %ptr, i32 %iv
369  store i32 %m, ptr %gep
370  %iv.next = add nuw nsw i32 %iv, 1
371  %size = load i32, ptr %size_ptr, align 4
372  %c.3 = icmp ult i32 %iv.next, %size
373  br i1 %c.3, label %loop.header, label %exit
374
375exit:
376  ret void
377
378exit.1:
379  call void @foo()
380  br label %unreachable.term
381
382exit.2:
383  call void @bar()
384  br label %unreachable.term
385
386unreachable.term:
387  call void @baz()
388  unreachable
389}
390
391define void @peel_exits_to_blocks_branch_to_unreachable_block_with_profile(ptr %ptr, i32 %N, i32 %x, i1 %c.1) !prof !0 {
392; CHECK-LABEL: @peel_exits_to_blocks_branch_to_unreachable_block_with_profile(
393; CHECK-NEXT:  entry:
394; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
395; CHECK:       loop.header:
396; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
397; CHECK-NEXT:    [[C:%.*]] = icmp ult i32 [[IV]], [[N:%.*]]
398; CHECK-NEXT:    br i1 [[C]], label [[THEN:%.*]], label [[ELSE:%.*]], !prof [[PROF5:![0-9]+]]
399; CHECK:       then:
400; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[EXIT_1:%.*]], label [[LOOP_LATCH]]
401; CHECK:       else:
402; CHECK-NEXT:    [[C_2:%.*]] = icmp eq i32 [[IV]], [[X:%.*]]
403; CHECK-NEXT:    br i1 [[C_2]], label [[EXIT_2:%.*]], label [[LOOP_LATCH]]
404; CHECK:       loop.latch:
405; CHECK-NEXT:    [[M:%.*]] = phi i32 [ 0, [[THEN]] ], [ [[X]], [[ELSE]] ]
406; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i32, ptr [[PTR:%.*]], i32 [[IV]]
407; CHECK-NEXT:    store i32 [[M]], ptr [[GEP]], align 4
408; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
409; CHECK-NEXT:    [[C_3:%.*]] = icmp ult i32 [[IV_NEXT]], [[N]]
410; CHECK-NEXT:    br i1 [[C_3]], label [[LOOP_HEADER]], label [[EXIT:%.*]], !prof [[PROF5]]
411; CHECK:       exit:
412; CHECK-NEXT:    ret void
413; CHECK:       exit.1:
414; CHECK-NEXT:    call void @foo()
415; CHECK-NEXT:    br label [[UNREACHABLE_TERM:%.*]]
416; CHECK:       exit.2:
417; CHECK-NEXT:    call void @bar()
418; CHECK-NEXT:    br label [[UNREACHABLE_TERM]]
419; CHECK:       unreachable.term:
420; CHECK-NEXT:    call void @baz()
421; CHECK-NEXT:    unreachable
422;
423entry:
424  br label %loop.header
425
426loop.header:
427  %iv = phi i32 [ 1, %entry ], [ %iv.next, %loop.latch ]
428  %c = icmp ult i32 %iv, %N
429  br i1 %c, label %then, label %else, !prof !1
430
431then:
432  br i1 %c.1, label %exit.1, label %loop.latch
433
434else:
435  %c.2 = icmp eq i32 %iv, %x
436  br i1 %c.2, label %exit.2, label %loop.latch
437
438loop.latch:
439  %m = phi i32 [ 0, %then ], [ %x, %else ]
440  %gep = getelementptr i32, ptr %ptr, i32 %iv
441  store i32 %m, ptr %gep
442  %iv.next = add nuw nsw i32  %iv, 1
443  %c.3 = icmp ult i32 %iv.next, %N
444  br i1 %c.3, label %loop.header, label %exit, !prof !2
445
446exit:
447  ret void
448
449exit.1:
450  call void @foo()
451  br label %unreachable.term
452
453exit.2:
454  call void @bar()
455  br label %unreachable.term
456
457unreachable.term:
458  call void @baz()
459  unreachable
460}
461
462declare void @bar()
463declare void @baz()
464
465!0 = !{!"function_entry_count", i64 32768}
466!1 = !{!"branch_weights", i32 0, i32 1}
467!2 = !{!"branch_weights", i32 0, i32 1}
468