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 i32 @peel_readonly_to_make_loads_derefenceable(ptr %ptr, i32 %N, ptr %inv, i1 %c.1) {
7; CHECK-LABEL: @peel_readonly_to_make_loads_derefenceable(
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:    br i1 [[C_1:%.*]], label [[THEN_PEEL:%.*]], label [[UNREACHABLE_EXIT:%.*]]
14; CHECK:       then.peel:
15; CHECK-NEXT:    [[I_PEEL:%.*]] = load i32, ptr [[INV:%.*]], align 4
16; CHECK-NEXT:    [[C_2_PEEL:%.*]] = icmp ult i32 [[I_PEEL]], 2
17; CHECK-NEXT:    br i1 [[C_2_PEEL]], label [[LOOP_LATCH_PEEL:%.*]], label [[UNREACHABLE_EXIT]]
18; CHECK:       loop.latch.peel:
19; CHECK-NEXT:    [[GEP_PEEL:%.*]] = getelementptr i32, ptr [[PTR:%.*]], i32 1
20; CHECK-NEXT:    [[LV_PEEL:%.*]] = load i32, ptr [[GEP_PEEL]], align 4
21; CHECK-NEXT:    [[SUM_NEXT_PEEL:%.*]] = add i32 0, [[LV_PEEL]]
22; CHECK-NEXT:    [[IV_NEXT_PEEL:%.*]] = add nuw nsw i32 1, 1
23; CHECK-NEXT:    [[C_3_PEEL:%.*]] = icmp ult i32 1, 1000
24; CHECK-NEXT:    br i1 [[C_3_PEEL]], label [[LOOP_HEADER_PEEL_NEXT:%.*]], label [[EXIT:%.*]]
25; CHECK:       loop.header.peel.next:
26; CHECK-NEXT:    br label [[LOOP_HEADER_PEEL_NEXT1:%.*]]
27; CHECK:       loop.header.peel.next1:
28; CHECK-NEXT:    br label [[ENTRY_PEEL_NEWPH:%.*]]
29; CHECK:       entry.peel.newph:
30; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
31; CHECK:       loop.header:
32; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[IV_NEXT_PEEL]], [[ENTRY_PEEL_NEWPH]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
33; CHECK-NEXT:    [[SUM:%.*]] = phi i32 [ [[SUM_NEXT_PEEL]], [[ENTRY_PEEL_NEWPH]] ], [ [[SUM_NEXT:%.*]], [[LOOP_LATCH]] ]
34; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[UNREACHABLE_EXIT_LOOPEXIT:%.*]]
35; CHECK:       then:
36; CHECK-NEXT:    [[I:%.*]] = load i32, ptr [[INV]], align 4
37; CHECK-NEXT:    [[C_2:%.*]] = icmp ult i32 [[I]], 2
38; CHECK-NEXT:    br i1 [[C_2]], label [[LOOP_LATCH]], label [[UNREACHABLE_EXIT_LOOPEXIT]]
39; CHECK:       loop.latch:
40; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i32, ptr [[PTR]], i32 [[IV]]
41; CHECK-NEXT:    [[LV:%.*]] = load i32, ptr [[GEP]], align 4
42; CHECK-NEXT:    [[SUM_NEXT]] = add i32 [[SUM]], [[LV]]
43; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
44; CHECK-NEXT:    [[C_3:%.*]] = icmp ult i32 [[IV]], 1000
45; CHECK-NEXT:    br i1 [[C_3]], label [[LOOP_HEADER]], label [[EXIT_LOOPEXIT:%.*]], !llvm.loop [[LOOP0:![0-9]+]]
46; CHECK:       exit.loopexit:
47; CHECK-NEXT:    [[SUM_NEXT_LCSSA_PH:%.*]] = phi i32 [ [[SUM_NEXT]], [[LOOP_LATCH]] ]
48; CHECK-NEXT:    br label [[EXIT]]
49; CHECK:       exit:
50; CHECK-NEXT:    [[SUM_NEXT_LCSSA:%.*]] = phi i32 [ [[SUM_NEXT_PEEL]], [[LOOP_LATCH_PEEL]] ], [ [[SUM_NEXT_LCSSA_PH]], [[EXIT_LOOPEXIT]] ]
51; CHECK-NEXT:    ret i32 [[SUM_NEXT_LCSSA]]
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  %sum = phi i32 [ 0, %entry ], [ %sum.next, %loop.latch ]
64  br i1 %c.1, label %then, label %unreachable.exit
65
66then:
67  %i = load i32, ptr %inv
68  %c.2 = icmp ult i32 %i, 2
69  br i1 %c.2, label %loop.latch, label %unreachable.exit
70
71loop.latch:
72  %gep = getelementptr i32, ptr %ptr, i32 %iv
73  %lv = load i32, ptr %gep
74  %sum.next = add i32 %sum, %lv
75  %iv.next = add nuw nsw i32  %iv, 1
76  %c.3 = icmp ult i32 %iv, 1000
77  br i1 %c.3, label %loop.header, label %exit
78
79exit:
80  ret i32 %sum.next
81
82unreachable.exit:
83  call void @foo()
84  unreachable
85}
86
87define i32 @peel_readonly_to_make_loads_derefenceable_exits_lead_to_unreachable(ptr %ptr, i32 %N, ptr %inv, i1 %c.1) {
88; CHECK-LABEL: @peel_readonly_to_make_loads_derefenceable_exits_lead_to_unreachable(
89; CHECK-NEXT:  entry:
90; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
91; CHECK:       loop.header:
92; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
93; CHECK-NEXT:    [[SUM:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[SUM_NEXT:%.*]], [[LOOP_LATCH]] ]
94; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[EXIT_2:%.*]]
95; CHECK:       then:
96; CHECK-NEXT:    [[I:%.*]] = load i32, ptr [[INV:%.*]], align 4
97; CHECK-NEXT:    [[C_2:%.*]] = icmp ult i32 [[I]], 2
98; CHECK-NEXT:    br i1 [[C_2]], label [[THEN_2:%.*]], label [[EXIT_2]]
99; CHECK:       then.2:
100; CHECK-NEXT:    [[C_4:%.*]] = icmp ult i32 [[I]], 4
101; CHECK-NEXT:    br i1 [[C_4]], label [[LOOP_LATCH]], label [[EXIT_3:%.*]]
102; CHECK:       loop.latch:
103; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i32, ptr [[PTR:%.*]], i32 [[IV]]
104; CHECK-NEXT:    [[LV:%.*]] = load i32, ptr [[GEP]], align 4
105; CHECK-NEXT:    [[SUM_NEXT]] = add i32 [[SUM]], [[LV]]
106; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
107; CHECK-NEXT:    [[C_3:%.*]] = icmp ult i32 [[IV]], 1000
108; CHECK-NEXT:    br i1 [[C_3]], label [[LOOP_HEADER]], label [[EXIT:%.*]]
109; CHECK:       exit:
110; CHECK-NEXT:    [[SUM_NEXT_LCSSA:%.*]] = phi i32 [ [[SUM_NEXT]], [[LOOP_LATCH]] ]
111; CHECK-NEXT:    ret i32 [[SUM_NEXT_LCSSA]]
112; CHECK:       exit.2:
113; CHECK-NEXT:    br label [[UNREACHABLE_BB:%.*]]
114; CHECK:       exit.3:
115; CHECK-NEXT:    br label [[UNREACHABLE_BB]]
116; CHECK:       unreachable.bb:
117; CHECK-NEXT:    call void @foo()
118; CHECK-NEXT:    unreachable
119;
120entry:
121  br label %loop.header
122
123loop.header:
124  %iv = phi i32 [ 1, %entry ], [ %iv.next, %loop.latch ]
125  %sum = phi i32 [ 0, %entry ], [ %sum.next, %loop.latch ]
126  br i1 %c.1, label %then, label %exit.2
127
128then:
129  %i = load i32, ptr %inv
130  %c.2 = icmp ult i32 %i, 2
131  br i1 %c.2, label %then.2, label %exit.2
132
133then.2:
134  %c.4 = icmp ult i32 %i, 4
135  br i1 %c.4, label %loop.latch, label %exit.3
136
137loop.latch:
138  %gep = getelementptr i32, ptr %ptr, i32 %iv
139  %lv = load i32, ptr %gep
140  %sum.next = add i32 %sum, %lv
141  %iv.next = add nuw nsw i32  %iv, 1
142  %c.3 = icmp ult i32 %iv, 1000
143  br i1 %c.3, label %loop.header, label %exit
144
145exit:
146  ret i32 %sum.next
147
148exit.2:
149  br label %unreachable.bb
150
151exit.3:
152  br label %unreachable.bb
153
154unreachable.bb:
155  call void @foo()
156  unreachable
157}
158
159define i32 @do_not_peel_readonly_load_in_header(ptr %ptr, i32 %N, ptr %inv, i1 %c.1) {
160; CHECK-LABEL: @do_not_peel_readonly_load_in_header(
161; CHECK-NEXT:  entry:
162; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
163; CHECK:       loop.header:
164; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
165; CHECK-NEXT:    [[SUM:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[SUM_NEXT:%.*]], [[LOOP_LATCH]] ]
166; CHECK-NEXT:    [[I:%.*]] = load i32, ptr [[INV:%.*]], align 4
167; CHECK-NEXT:    [[C_2:%.*]] = icmp ult i32 [[I]], 2
168; CHECK-NEXT:    br i1 [[C_2]], label [[THEN:%.*]], label [[UNREACHABLE_EXIT:%.*]]
169; CHECK:       then:
170; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[LOOP_LATCH]], label [[UNREACHABLE_EXIT]]
171; CHECK:       loop.latch:
172; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i32, ptr [[PTR:%.*]], i32 [[IV]]
173; CHECK-NEXT:    [[LV:%.*]] = load i32, ptr [[GEP]], align 4
174; CHECK-NEXT:    [[SUM_NEXT]] = add i32 [[SUM]], [[LV]]
175; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
176; CHECK-NEXT:    [[C_3:%.*]] = icmp ult i32 [[IV]], 1000
177; CHECK-NEXT:    br i1 [[C_3]], label [[LOOP_HEADER]], label [[EXIT:%.*]]
178; CHECK:       exit:
179; CHECK-NEXT:    [[SUM_NEXT_LCSSA:%.*]] = phi i32 [ [[SUM_NEXT]], [[LOOP_LATCH]] ]
180; CHECK-NEXT:    ret i32 [[SUM_NEXT_LCSSA]]
181; CHECK:       unreachable.exit:
182; CHECK-NEXT:    call void @foo()
183; CHECK-NEXT:    unreachable
184;
185entry:
186  br label %loop.header
187
188loop.header:
189  %iv = phi i32 [ 1, %entry ], [ %iv.next, %loop.latch ]
190  %sum = phi i32 [ 0, %entry ], [ %sum.next, %loop.latch ]
191  %i = load i32, ptr %inv
192  %c.2 = icmp ult i32 %i, 2
193  br i1 %c.2, label %then, label %unreachable.exit
194
195then:
196  br i1 %c.1, label %loop.latch, label %unreachable.exit
197
198loop.latch:
199  %gep = getelementptr i32, ptr %ptr, i32 %iv
200  %lv = load i32, ptr %gep
201  %sum.next = add i32 %sum, %lv
202  %iv.next = add nuw nsw i32  %iv, 1
203  %c.3 = icmp ult i32 %iv, 1000
204  br i1 %c.3, label %loop.header, label %exit
205
206exit:
207  ret i32 %sum.next
208
209unreachable.exit:
210  call void @foo()
211  unreachable
212}
213
214define i32 @do_not_peel_readonly_but_wont_turn_dereferenceable(ptr %ptr, i32 %N, i32 %x, ptr %inv) {
215; CHECK-LABEL: @do_not_peel_readonly_but_wont_turn_dereferenceable(
216; CHECK-NEXT:  entry:
217; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
218; CHECK:       loop.header:
219; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
220; CHECK-NEXT:    [[SUM:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[SUM_NEXT:%.*]], [[LOOP_LATCH]] ]
221; CHECK-NEXT:    [[C_1:%.*]] = icmp eq i32 [[IV]], [[X:%.*]]
222; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[ELSE:%.*]]
223; CHECK:       then:
224; CHECK-NEXT:    [[I:%.*]] = load i32, ptr [[INV:%.*]], align 4
225; CHECK-NEXT:    [[C_2:%.*]] = icmp eq i32 [[I]], 20
226; CHECK-NEXT:    br i1 [[C_2]], label [[UNREACHABLE_EXIT:%.*]], label [[LOOP_LATCH]]
227; CHECK:       else:
228; CHECK-NEXT:    br label [[LOOP_LATCH]]
229; CHECK:       loop.latch:
230; CHECK-NEXT:    [[P:%.*]] = phi i32 [ [[I]], [[THEN]] ], [ 0, [[ELSE]] ]
231; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i32, ptr [[PTR:%.*]], i32 [[IV]]
232; CHECK-NEXT:    [[LV:%.*]] = load i32, ptr [[GEP]], align 4
233; CHECK-NEXT:    [[ADD_1:%.*]] = add i32 [[LV]], [[P]]
234; CHECK-NEXT:    [[SUM_NEXT]] = add i32 [[SUM]], [[ADD_1]]
235; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
236; CHECK-NEXT:    [[C_3:%.*]] = icmp ult i32 [[IV]], 1000
237; CHECK-NEXT:    br i1 [[C_3]], label [[LOOP_HEADER]], label [[EXIT:%.*]]
238; CHECK:       exit:
239; CHECK-NEXT:    [[SUM_NEXT_LCSSA:%.*]] = phi i32 [ [[SUM_NEXT]], [[LOOP_LATCH]] ]
240; CHECK-NEXT:    ret i32 [[SUM_NEXT_LCSSA]]
241; CHECK:       unreachable.exit:
242; CHECK-NEXT:    call void @foo()
243; CHECK-NEXT:    unreachable
244;
245entry:
246  br label %loop.header
247
248loop.header:
249  %iv = phi i32 [ 1, %entry ], [ %iv.next, %loop.latch ]
250  %sum = phi i32 [ 0, %entry ], [ %sum.next, %loop.latch ]
251  %c.1 = icmp eq i32 %iv, %x
252  br i1 %c.1, label %then, label %else
253
254then:
255  %i = load i32, ptr %inv
256  %c.2 = icmp eq i32 %i, 20
257  br i1 %c.2, label %unreachable.exit, label %loop.latch
258
259else:
260  br label %loop.latch
261
262loop.latch:
263  %p = phi i32 [ %i, %then ], [ 0, %else ]
264  %gep = getelementptr i32, ptr %ptr, i32 %iv
265  %lv = load i32, ptr %gep
266  %add.1 = add i32 %lv, %p
267  %sum.next = add i32 %sum, %add.1
268  %iv.next = add nuw nsw i32  %iv, 1
269  %c.3 = icmp ult i32 %iv, 1000
270  br i1 %c.3, label %loop.header, label %exit
271
272exit:
273  ret i32 %sum.next
274
275unreachable.exit:
276  call void @foo()
277  unreachable
278}
279
280define i32 @do_not_peel_write1(ptr %ptr, i32 %N, i32 %x, ptr %inv, ptr %dst, i1 %c.1) {
281; CHECK-LABEL: @do_not_peel_write1(
282; CHECK-NEXT:  entry:
283; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
284; CHECK:       loop.header:
285; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
286; CHECK-NEXT:    [[SUM:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[SUM_NEXT:%.*]], [[LOOP_LATCH]] ]
287; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[UNREACHABLE_EXIT:%.*]]
288; CHECK:       then:
289; CHECK-NEXT:    [[I:%.*]] = load i32, ptr [[INV:%.*]], align 4
290; CHECK-NEXT:    [[C_2:%.*]] = icmp ult i32 [[I]], 2
291; CHECK-NEXT:    br i1 [[C_2]], label [[LOOP_LATCH]], label [[UNREACHABLE_EXIT]]
292; CHECK:       loop.latch:
293; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i32, ptr [[PTR:%.*]], i32 [[IV]]
294; CHECK-NEXT:    [[LV:%.*]] = load i32, ptr [[GEP]], align 4
295; CHECK-NEXT:    store i32 [[LV]], ptr [[DST:%.*]], align 4
296; CHECK-NEXT:    [[SUM_NEXT]] = add i32 [[SUM]], [[LV]]
297; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
298; CHECK-NEXT:    [[C_3:%.*]] = icmp ult i32 [[IV]], 1000
299; CHECK-NEXT:    br i1 [[C_3]], label [[LOOP_HEADER]], label [[EXIT:%.*]]
300; CHECK:       exit:
301; CHECK-NEXT:    [[SUM_NEXT_LCSSA:%.*]] = phi i32 [ [[SUM_NEXT]], [[LOOP_LATCH]] ]
302; CHECK-NEXT:    ret i32 [[SUM_NEXT_LCSSA]]
303; CHECK:       unreachable.exit:
304; CHECK-NEXT:    call void @foo()
305; CHECK-NEXT:    unreachable
306;
307entry:
308  br label %loop.header
309
310loop.header:
311  %iv = phi i32 [ 1, %entry ], [ %iv.next, %loop.latch ]
312  %sum = phi i32 [ 0, %entry ], [ %sum.next, %loop.latch ]
313  br i1 %c.1, label %then, label %unreachable.exit
314
315then:
316  %i = load i32, ptr %inv
317  %c.2 = icmp ult i32 %i, 2
318  br i1 %c.2, label %loop.latch, label %unreachable.exit
319
320loop.latch:
321  %gep = getelementptr i32, ptr %ptr, i32 %iv
322  %lv = load i32, ptr %gep
323  store i32 %lv, ptr %dst
324  %sum.next = add i32 %sum, %lv
325  %iv.next = add nuw nsw i32  %iv, 1
326  %c.3 = icmp ult i32 %iv, 1000
327  br i1 %c.3, label %loop.header, label %exit
328
329exit:
330  ret i32 %sum.next
331
332unreachable.exit:
333  call void @foo()
334  unreachable
335}
336
337define i32 @do_not_peel_write2(ptr %ptr, i32 %N, ptr %inv, ptr %dst) {
338; CHECK-LABEL: @do_not_peel_write2(
339; CHECK-NEXT:  entry:
340; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
341; CHECK:       loop.header:
342; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
343; CHECK-NEXT:    [[SUM:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[SUM_NEXT:%.*]], [[LOOP_LATCH]] ]
344; CHECK-NEXT:    [[I:%.*]] = load i32, ptr [[INV:%.*]], align 4
345; CHECK-NEXT:    [[C_1:%.*]] = icmp eq i32 [[I]], 20
346; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[ELSE:%.*]]
347; CHECK:       then:
348; CHECK-NEXT:    store i32 [[I]], ptr [[DST:%.*]], align 4
349; CHECK-NEXT:    br label [[LOOP_LATCH]]
350; CHECK:       else:
351; CHECK-NEXT:    br label [[UNREACHABLE_EXIT:%.*]]
352; CHECK:       loop.latch:
353; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i32, ptr [[PTR:%.*]], i32 [[IV]]
354; CHECK-NEXT:    [[LV:%.*]] = load i32, ptr [[GEP]], align 4
355; CHECK-NEXT:    [[ADD_1:%.*]] = add i32 [[LV]], [[I]]
356; CHECK-NEXT:    [[SUM_NEXT]] = add i32 [[SUM]], [[ADD_1]]
357; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
358; CHECK-NEXT:    [[C_3:%.*]] = icmp ult i32 [[IV]], 1000
359; CHECK-NEXT:    br i1 [[C_3]], label [[LOOP_HEADER]], label [[EXIT:%.*]]
360; CHECK:       exit:
361; CHECK-NEXT:    [[SUM_NEXT_LCSSA:%.*]] = phi i32 [ [[SUM_NEXT]], [[LOOP_LATCH]] ]
362; CHECK-NEXT:    ret i32 [[SUM_NEXT_LCSSA]]
363; CHECK:       unreachable.exit:
364; CHECK-NEXT:    call void @foo()
365; CHECK-NEXT:    unreachable
366;
367entry:
368  br label %loop.header
369
370loop.header:
371  %iv = phi i32 [ 1, %entry ], [ %iv.next, %loop.latch ]
372  %sum = phi i32 [ 0, %entry ], [ %sum.next, %loop.latch ]
373  %i = load i32, ptr %inv
374  %c.1 = icmp eq i32 %i, 20
375  br i1 %c.1, label %then, label %else
376
377then:
378  store i32 %i, ptr %dst
379  br label %loop.latch
380
381else:
382  br label %unreachable.exit
383
384loop.latch:
385  %gep = getelementptr i32, ptr %ptr, i32 %iv
386  %lv = load i32, ptr %gep
387  %add.1 = add i32 %lv, %i
388  %sum.next = add i32 %sum, %add.1
389  %iv.next = add nuw nsw i32  %iv, 1
390  %c.3 = icmp ult i32 %iv, 1000
391  br i1 %c.3, label %loop.header, label %exit
392
393exit:
394  ret i32 %sum.next
395
396unreachable.exit:
397  call void @foo()
398  unreachable
399}
400
401declare i32 @llvm.experimental.deoptimize.i32(...)
402
403define i32 @peel_with_deopt_exit(ptr %ptr, i32 %N, ptr %inv, i1 %c.1) {
404; CHECK-LABEL: @peel_with_deopt_exit(
405; CHECK-NEXT:  entry:
406; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
407; CHECK:       loop.header:
408; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
409; CHECK-NEXT:    [[SUM:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[SUM_NEXT:%.*]], [[LOOP_LATCH]] ]
410; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[DEOPT_EXIT:%.*]]
411; CHECK:       then:
412; CHECK-NEXT:    [[I:%.*]] = load i32, ptr [[INV:%.*]], align 4
413; CHECK-NEXT:    [[C_2:%.*]] = icmp ult i32 [[I]], 2
414; CHECK-NEXT:    br i1 [[C_2]], label [[LOOP_LATCH]], label [[DEOPT_EXIT]]
415; CHECK:       loop.latch:
416; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i32, ptr [[PTR:%.*]], i32 [[IV]]
417; CHECK-NEXT:    [[LV:%.*]] = load i32, ptr [[GEP]], align 4
418; CHECK-NEXT:    [[SUM_NEXT]] = add i32 [[SUM]], [[LV]]
419; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
420; CHECK-NEXT:    [[C_3:%.*]] = icmp ult i32 [[IV]], 1000
421; CHECK-NEXT:    br i1 [[C_3]], label [[LOOP_HEADER]], label [[EXIT:%.*]]
422; CHECK:       exit:
423; CHECK-NEXT:    [[SUM_NEXT_LCSSA:%.*]] = phi i32 [ [[SUM_NEXT]], [[LOOP_LATCH]] ]
424; CHECK-NEXT:    ret i32 [[SUM_NEXT_LCSSA]]
425; CHECK:       deopt.exit:
426; CHECK-NEXT:    [[SUM_LCSSA:%.*]] = phi i32 [ [[SUM]], [[THEN]] ], [ [[SUM]], [[LOOP_HEADER]] ]
427; CHECK-NEXT:    [[RVAL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 [[SUM_LCSSA]]) ]
428; CHECK-NEXT:    ret i32 [[RVAL]]
429;
430entry:
431  br label %loop.header
432
433loop.header:
434  %iv = phi i32 [ 1, %entry ], [ %iv.next, %loop.latch ]
435  %sum = phi i32 [ 0, %entry ], [ %sum.next, %loop.latch ]
436  br i1 %c.1, label %then, label %deopt.exit
437
438then:
439  %i = load i32, ptr %inv
440  %c.2 = icmp ult i32 %i, 2
441  br i1 %c.2, label %loop.latch, label %deopt.exit
442
443loop.latch:
444  %gep = getelementptr i32, ptr %ptr, i32 %iv
445  %lv = load i32, ptr %gep
446  %sum.next = add i32 %sum, %lv
447  %iv.next = add nuw nsw i32  %iv, 1
448  %c.3 = icmp ult i32 %iv, 1000
449  br i1 %c.3, label %loop.header, label %exit
450
451exit:
452  ret i32 %sum.next
453
454deopt.exit:
455  %rval = call i32(...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 %sum) ]
456  ret i32 %rval
457}
458
459define i32 @do_not_peel_when_header_exiting(ptr %ptr, i32 %N, ptr %inv) {
460; CHECK-LABEL: @do_not_peel_when_header_exiting(
461; CHECK-NEXT:  entry:
462; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
463; CHECK:       loop.header:
464; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
465; CHECK-NEXT:    [[SUM:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[SUM_NEXT:%.*]], [[LOOP_LATCH]] ]
466; CHECK-NEXT:    [[C_1:%.*]] = icmp ult i32 [[IV]], 1000
467; CHECK-NEXT:    br i1 [[C_1]], label [[THEN:%.*]], label [[EXIT:%.*]]
468; CHECK:       then:
469; CHECK-NEXT:    [[I:%.*]] = load i32, ptr [[INV:%.*]], align 4
470; CHECK-NEXT:    [[C_2:%.*]] = icmp ult i32 [[I]], 2
471; CHECK-NEXT:    br i1 [[C_2]], label [[LOOP_LATCH]], label [[UNREACHABLE_EXIT:%.*]]
472; CHECK:       loop.latch:
473; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i32, ptr [[PTR:%.*]], i32 [[IV]]
474; CHECK-NEXT:    [[LV:%.*]] = load i32, ptr [[GEP]], align 4
475; CHECK-NEXT:    [[SUM_NEXT]] = add i32 [[SUM]], [[LV]]
476; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
477; CHECK-NEXT:    br label [[LOOP_HEADER]]
478; CHECK:       exit:
479; CHECK-NEXT:    [[SUM_LCSSA:%.*]] = phi i32 [ [[SUM]], [[LOOP_HEADER]] ]
480; CHECK-NEXT:    ret i32 [[SUM_LCSSA]]
481; CHECK:       unreachable.exit:
482; CHECK-NEXT:    call void @foo()
483; CHECK-NEXT:    unreachable
484;
485entry:
486  br label %loop.header
487
488loop.header:
489  %iv = phi i32 [ 1, %entry ], [ %iv.next, %loop.latch ]
490  %sum = phi i32 [ 0, %entry ], [ %sum.next, %loop.latch ]
491  %c.1 = icmp ult i32 %iv, 1000
492  br i1 %c.1, label %then, label %exit
493
494then:
495  %i = load i32, ptr %inv
496  %c.2 = icmp ult i32 %i, 2
497  br i1 %c.2, label %loop.latch, label %unreachable.exit
498
499loop.latch:
500  %gep = getelementptr i32, ptr %ptr, i32 %iv
501  %lv = load i32, ptr %gep
502  %sum.next = add i32 %sum, %lv
503  %iv.next = add nuw nsw i32  %iv, 1
504  br label %loop.header
505
506exit:
507  ret i32 %sum
508
509unreachable.exit:
510  call void @foo()
511  unreachable
512}
513
514define i32 @do_not_peel_readonly_to_make_loads_derefenceable_but_does_not_control_exit(ptr %ptr, i32 %N, ptr %inv, i1 %c.1, i32 %N.2) {
515; CHECK-LABEL: @do_not_peel_readonly_to_make_loads_derefenceable_but_does_not_control_exit(
516; CHECK-NEXT:  entry:
517; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
518; CHECK:       loop.header:
519; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
520; CHECK-NEXT:    [[SUM:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[SUM_NEXT:%.*]], [[LOOP_LATCH]] ]
521; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[UNREACHABLE_EXIT:%.*]]
522; CHECK:       then:
523; CHECK-NEXT:    [[I:%.*]] = load i32, ptr [[INV:%.*]], align 4
524; CHECK-NEXT:    [[C_2:%.*]] = icmp ult i32 [[IV]], [[N_2:%.*]]
525; CHECK-NEXT:    br i1 [[C_2]], label [[LOOP_LATCH]], label [[UNREACHABLE_EXIT]]
526; CHECK:       loop.latch:
527; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i32, ptr [[PTR:%.*]], i32 [[IV]]
528; CHECK-NEXT:    [[LV:%.*]] = load i32, ptr [[GEP]], align 4
529; CHECK-NEXT:    [[SUM_NEXT]] = add i32 [[SUM]], [[LV]]
530; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
531; CHECK-NEXT:    [[C_3:%.*]] = icmp ult i32 [[IV]], 1000
532; CHECK-NEXT:    br i1 [[C_3]], label [[LOOP_HEADER]], label [[EXIT:%.*]]
533; CHECK:       exit:
534; CHECK-NEXT:    [[SUM_NEXT_LCSSA:%.*]] = phi i32 [ [[SUM_NEXT]], [[LOOP_LATCH]] ]
535; CHECK-NEXT:    ret i32 [[SUM_NEXT_LCSSA]]
536; CHECK:       unreachable.exit:
537; CHECK-NEXT:    call void @foo()
538; CHECK-NEXT:    unreachable
539;
540entry:
541  br label %loop.header
542
543loop.header:
544  %iv = phi i32 [ 1, %entry ], [ %iv.next, %loop.latch ]
545  %sum = phi i32 [ 0, %entry ], [ %sum.next, %loop.latch ]
546  br i1 %c.1, label %then, label %unreachable.exit
547
548then:
549  %i = load i32, ptr %inv
550  %c.2 = icmp ult i32 %iv, %N.2
551  br i1 %c.2, label %loop.latch, label %unreachable.exit
552
553loop.latch:
554  %gep = getelementptr i32, ptr %ptr, i32 %iv
555  %lv = load i32, ptr %gep
556  %sum.next = add i32 %sum, %lv
557  %iv.next = add nuw nsw i32  %iv, 1
558  %c.3 = icmp ult i32 %iv, 1000
559  br i1 %c.3, label %loop.header, label %exit
560
561exit:
562  ret i32 %sum.next
563
564unreachable.exit:
565  call void @foo()
566  unreachable
567}
568
569@glob = global i32 10
570
571define i32 @do_not_peel_readonly_but_already_deref_glob(ptr %ptr, i32 %N, i1 %c.1) {
572; CHECK-LABEL: @do_not_peel_readonly_but_already_deref_glob(
573; CHECK-NEXT:  entry:
574; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
575; CHECK:       loop.header:
576; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP_LATCH:%.*]] ]
577; CHECK-NEXT:    [[SUM:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[SUM_NEXT:%.*]], [[LOOP_LATCH]] ]
578; CHECK-NEXT:    br i1 [[C_1:%.*]], label [[THEN:%.*]], label [[UNREACHABLE_EXIT:%.*]]
579; CHECK:       then:
580; CHECK-NEXT:    [[I:%.*]] = load i32, ptr @glob, align 4
581; CHECK-NEXT:    [[C_2:%.*]] = icmp ult i32 [[I]], 2
582; CHECK-NEXT:    br i1 [[C_2]], label [[LOOP_LATCH]], label [[UNREACHABLE_EXIT]]
583; CHECK:       loop.latch:
584; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i32, ptr [[PTR:%.*]], i32 [[IV]]
585; CHECK-NEXT:    [[LV:%.*]] = load i32, ptr [[GEP]], align 4
586; CHECK-NEXT:    [[SUM_NEXT]] = add i32 [[SUM]], [[LV]]
587; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
588; CHECK-NEXT:    [[C_3:%.*]] = icmp ult i32 [[IV]], 1000
589; CHECK-NEXT:    br i1 [[C_3]], label [[LOOP_HEADER]], label [[EXIT:%.*]]
590; CHECK:       exit:
591; CHECK-NEXT:    [[SUM_NEXT_LCSSA:%.*]] = phi i32 [ [[SUM_NEXT]], [[LOOP_LATCH]] ]
592; CHECK-NEXT:    ret i32 [[SUM_NEXT_LCSSA]]
593; CHECK:       unreachable.exit:
594; CHECK-NEXT:    call void @foo()
595; CHECK-NEXT:    unreachable
596;
597entry:
598  br label %loop.header
599
600loop.header:
601  %iv = phi i32 [ 1, %entry ], [ %iv.next, %loop.latch ]
602  %sum = phi i32 [ 0, %entry ], [ %sum.next, %loop.latch ]
603  br i1 %c.1, label %then, label %unreachable.exit
604
605then:
606  %i = load i32, ptr @glob
607  %c.2 = icmp ult i32 %i, 2
608  br i1 %c.2, label %loop.latch, label %unreachable.exit
609
610loop.latch:
611  %gep = getelementptr i32, ptr %ptr, i32 %iv
612  %lv = load i32, ptr %gep
613  %sum.next = add i32 %sum, %lv
614  %iv.next = add nuw nsw i32  %iv, 1
615  %c.3 = icmp ult i32 %iv, 1000
616  br i1 %c.3, label %loop.header, label %exit
617
618exit:
619  ret i32 %sum.next
620
621unreachable.exit:
622  call void @foo()
623  unreachable
624}
625