1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -indvars -indvars-predicate-loops=1 -S | FileCheck %s
3
4declare void @prevent_merging()
5
6; Base case
7define i32 @test1(i32* %array, i32 %length, i32 %n) {
8; CHECK-LABEL: @test1(
9; CHECK-NEXT:  loop.preheader:
10; CHECK-NEXT:    [[TMP0:%.*]] = icmp ugt i32 [[N:%.*]], 1
11; CHECK-NEXT:    [[UMAX:%.*]] = select i1 [[TMP0]], i32 [[N]], i32 1
12; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[UMAX]], -1
13; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 [[LENGTH:%.*]], [[TMP1]]
14; CHECK-NEXT:    [[UMIN:%.*]] = select i1 [[TMP2]], i32 [[LENGTH]], i32 [[TMP1]]
15; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[LENGTH]], [[UMIN]]
16; CHECK-NEXT:    br label [[LOOP:%.*]]
17; CHECK:       loop:
18; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
19; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
20; CHECK-NEXT:    br i1 [[TMP3]], label [[GUARDED]], label [[DEOPT:%.*]], !prof !0
21; CHECK:       deopt:
22; CHECK-NEXT:    call void @prevent_merging()
23; CHECK-NEXT:    ret i32 -1
24; CHECK:       guarded:
25; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
26; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
27; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
28; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
29; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
30; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
31; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
32; CHECK:       exit:
33; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
34; CHECK-NEXT:    ret i32 [[RESULT]]
35;
36loop.preheader:                                   ; preds = %entry
37  br label %loop
38
39loop:                                             ; preds = %guarded, %loop.preheader
40  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
41  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
42  %within.bounds = icmp ult i32 %i, %length
43  br i1 %within.bounds, label %guarded, label %deopt, !prof !0
44
45deopt:                                            ; preds = %loop
46  call void @prevent_merging()
47  ret i32 -1
48
49guarded:                                          ; preds = %loop
50  %i.i64 = zext i32 %i to i64
51  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
52  %array.i = load i32, i32* %array.i.ptr, align 4
53  %loop.acc.next = add i32 %loop.acc, %array.i
54  %i.next = add nuw i32 %i, 1
55  %continue = icmp ult i32 %i.next, %n
56  br i1 %continue, label %loop, label %exit
57
58exit:                                             ; preds = %guarded, %entry
59  %result = phi i32 [ %loop.acc.next, %guarded ]
60  ret i32 %result
61}
62
63; Has side effect which must be reflected
64define i32 @neg_store(i32* %array, i32 %length, i32 %n) {
65; CHECK-LABEL: @neg_store(
66; CHECK-NEXT:  loop.preheader:
67; CHECK-NEXT:    br label [[LOOP:%.*]]
68; CHECK:       loop:
69; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
70; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
71; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]]
72; CHECK-NEXT:    br i1 [[WITHIN_BOUNDS]], label [[GUARDED]], label [[DEOPT:%.*]], !prof !0
73; CHECK:       deopt:
74; CHECK-NEXT:    call void @prevent_merging()
75; CHECK-NEXT:    ret i32 -1
76; CHECK:       guarded:
77; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
78; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
79; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
80; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
81; CHECK-NEXT:    store i32 0, i32* [[ARRAY_I_PTR]]
82; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
83; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N:%.*]]
84; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
85; CHECK:       exit:
86; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
87; CHECK-NEXT:    ret i32 [[RESULT]]
88;
89loop.preheader:                                   ; preds = %entry
90  br label %loop
91
92loop:                                             ; preds = %guarded, %loop.preheader
93  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
94  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
95  %within.bounds = icmp ult i32 %i, %length
96  br i1 %within.bounds, label %guarded, label %deopt, !prof !0
97
98deopt:                                            ; preds = %loop
99  call void @prevent_merging()
100  ret i32 -1
101
102guarded:                                          ; preds = %loop
103  %i.i64 = zext i32 %i to i64
104  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
105  %array.i = load i32, i32* %array.i.ptr, align 4
106  %loop.acc.next = add i32 %loop.acc, %array.i
107  store i32 0, i32* %array.i.ptr
108  %i.next = add nuw i32 %i, 1
109  %continue = icmp ult i32 %i.next, %n
110  br i1 %continue, label %loop, label %exit
111
112exit:                                             ; preds = %guarded, %entry
113  %result = phi i32 [ %loop.acc.next, %guarded ]
114  ret i32 %result
115}
116
117declare void @maythrow()
118
119; May exit through implicit exception edge
120define i32 @neg_implicit_exit(i32* %array, i32 %length, i32 %n) {
121; CHECK-LABEL: @neg_implicit_exit(
122; CHECK-NEXT:  loop.preheader:
123; CHECK-NEXT:    br label [[LOOP:%.*]]
124; CHECK:       loop:
125; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
126; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
127; CHECK-NEXT:    call void @maythrow()
128; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]]
129; CHECK-NEXT:    br i1 [[WITHIN_BOUNDS]], label [[GUARDED]], label [[DEOPT:%.*]], !prof !0
130; CHECK:       deopt:
131; CHECK-NEXT:    call void @prevent_merging()
132; CHECK-NEXT:    ret i32 -1
133; CHECK:       guarded:
134; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
135; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
136; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
137; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
138; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
139; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N:%.*]]
140; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
141; CHECK:       exit:
142; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
143; CHECK-NEXT:    ret i32 [[RESULT]]
144;
145loop.preheader:                                   ; preds = %entry
146  br label %loop
147
148loop:                                             ; preds = %guarded, %loop.preheader
149  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
150  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
151  call void @maythrow()
152  %within.bounds = icmp ult i32 %i, %length
153  br i1 %within.bounds, label %guarded, label %deopt, !prof !0
154
155deopt:                                            ; preds = %loop
156  call void @prevent_merging()
157  ret i32 -1
158
159guarded:                                          ; preds = %loop
160  %i.i64 = zext i32 %i to i64
161  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
162  %array.i = load i32, i32* %array.i.ptr, align 4
163  %loop.acc.next = add i32 %loop.acc, %array.i
164  %i.next = add nuw i32 %i, 1
165  %continue = icmp ult i32 %i.next, %n
166  br i1 %continue, label %loop, label %exit
167
168exit:                                             ; preds = %guarded, %entry
169  %result = phi i32 [ %loop.acc.next, %guarded ]
170  ret i32 %result
171}
172
173
174
175; Base case, but in LFTR form (just for sanity checking)
176define i32 @test2(i32* %array, i32 %length, i32 %n) {
177; CHECK-LABEL: @test2(
178; CHECK-NEXT:  loop.preheader:
179; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[N:%.*]], -1
180; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[LENGTH:%.*]], [[TMP0]]
181; CHECK-NEXT:    [[UMIN:%.*]] = select i1 [[TMP1]], i32 [[LENGTH]], i32 [[TMP0]]
182; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i32 [[LENGTH]], [[UMIN]]
183; CHECK-NEXT:    br label [[LOOP:%.*]]
184; CHECK:       loop:
185; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
186; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
187; CHECK-NEXT:    br i1 [[TMP2]], label [[GUARDED]], label [[DEOPT:%.*]], !prof !0
188; CHECK:       deopt:
189; CHECK-NEXT:    call void @prevent_merging()
190; CHECK-NEXT:    ret i32 -1
191; CHECK:       guarded:
192; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
193; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
194; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
195; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
196; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
197; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ne i32 [[I_NEXT]], [[N]]
198; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
199; CHECK:       exit:
200; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
201; CHECK-NEXT:    ret i32 [[RESULT]]
202;
203loop.preheader:                                   ; preds = %entry
204  br label %loop
205
206loop:                                             ; preds = %guarded, %loop.preheader
207  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
208  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
209  %within.bounds = icmp ne i32 %i, %length
210  br i1 %within.bounds, label %guarded, label %deopt, !prof !0
211
212deopt:                                            ; preds = %loop
213  call void @prevent_merging()
214  ret i32 -1
215
216guarded:                                          ; preds = %loop
217  %i.i64 = zext i32 %i to i64
218  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
219  %array.i = load i32, i32* %array.i.ptr, align 4
220  %loop.acc.next = add i32 %loop.acc, %array.i
221  %i.next = add nuw i32 %i, 1
222  %continue = icmp ne i32 %i.next, %n
223  br i1 %continue, label %loop, label %exit
224
225exit:                                             ; preds = %guarded, %entry
226  %result = phi i32 [ %loop.acc.next, %guarded ]
227  ret i32 %result
228}
229
230; br (and rcheck1, rcheck2)
231define i32 @two_range_checks(i32* %array.1, i32 %length.1, i32* %array.2, i32 %length.2, i32 %n) {
232; CHECK-LABEL: @two_range_checks(
233; CHECK-NEXT:  loop.preheader:
234; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 [[LENGTH_2:%.*]], [[LENGTH_1:%.*]]
235; CHECK-NEXT:    [[UMIN:%.*]] = select i1 [[TMP0]], i32 [[LENGTH_2]], i32 [[LENGTH_1]]
236; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[LENGTH_2]], [[LENGTH_1]]
237; CHECK-NEXT:    [[UMIN1:%.*]] = select i1 [[TMP1]], i32 [[LENGTH_2]], i32 [[LENGTH_1]]
238; CHECK-NEXT:    [[TMP2:%.*]] = icmp ugt i32 [[N:%.*]], 1
239; CHECK-NEXT:    [[UMAX:%.*]] = select i1 [[TMP2]], i32 [[N]], i32 1
240; CHECK-NEXT:    [[TMP3:%.*]] = add i32 [[UMAX]], -1
241; CHECK-NEXT:    [[TMP4:%.*]] = icmp ult i32 [[UMIN1]], [[TMP3]]
242; CHECK-NEXT:    [[UMIN2:%.*]] = select i1 [[TMP4]], i32 [[UMIN1]], i32 [[TMP3]]
243; CHECK-NEXT:    [[TMP5:%.*]] = icmp ne i32 [[UMIN]], [[UMIN2]]
244; CHECK-NEXT:    br label [[LOOP:%.*]]
245; CHECK:       loop:
246; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
247; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
248; CHECK-NEXT:    br i1 [[TMP5]], label [[GUARDED]], label [[DEOPT:%.*]], !prof !0
249; CHECK:       deopt:
250; CHECK-NEXT:    call void @prevent_merging()
251; CHECK-NEXT:    ret i32 -1
252; CHECK:       guarded:
253; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
254; CHECK-NEXT:    [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_1:%.*]], i64 [[I_I64]]
255; CHECK-NEXT:    [[ARRAY_1_I:%.*]] = load i32, i32* [[ARRAY_1_I_PTR]], align 4
256; CHECK-NEXT:    [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]]
257; CHECK-NEXT:    [[ARRAY_2_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_2:%.*]], i64 [[I_I64]]
258; CHECK-NEXT:    [[ARRAY_2_I:%.*]] = load i32, i32* [[ARRAY_2_I_PTR]], align 4
259; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_1]], [[ARRAY_2_I]]
260; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
261; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
262; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
263; CHECK:       exit:
264; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
265; CHECK-NEXT:    ret i32 [[RESULT]]
266;
267loop.preheader:                                   ; preds = %entry
268  br label %loop
269
270loop:                                             ; preds = %guarded, %loop.preheader
271  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
272  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
273  %within.bounds.1 = icmp ult i32 %i, %length.1
274  %within.bounds.2 = icmp ult i32 %i, %length.2
275  %within.bounds = and i1 %within.bounds.1, %within.bounds.2
276  br i1 %within.bounds, label %guarded, label %deopt, !prof !0
277
278deopt:                                            ; preds = %loop
279  call void @prevent_merging()
280  ret i32 -1
281
282guarded:                                          ; preds = %loop
283  %i.i64 = zext i32 %i to i64
284  %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64
285  %array.1.i = load i32, i32* %array.1.i.ptr, align 4
286  %loop.acc.1 = add i32 %loop.acc, %array.1.i
287  %array.2.i.ptr = getelementptr inbounds i32, i32* %array.2, i64 %i.i64
288  %array.2.i = load i32, i32* %array.2.i.ptr, align 4
289  %loop.acc.next = add i32 %loop.acc.1, %array.2.i
290  %i.next = add nuw i32 %i, 1
291  %continue = icmp ult i32 %i.next, %n
292  br i1 %continue, label %loop, label %exit
293
294exit:                                             ; preds = %guarded, %entry
295  %result = phi i32 [ %loop.acc.next, %guarded ]
296  ret i32 %result
297}
298
299define i32 @three_range_checks(i32* %array.1, i32 %length.1, i32* %array.2, i32 %length.2, i32* %array.3, i32 %length.3, i32 %n) {
300; CHECK-LABEL: @three_range_checks(
301; CHECK-NEXT:  loop.preheader:
302; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 [[LENGTH_3:%.*]], [[LENGTH_2:%.*]]
303; CHECK-NEXT:    [[UMIN:%.*]] = select i1 [[TMP0]], i32 [[LENGTH_3]], i32 [[LENGTH_2]]
304; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 [[UMIN]], [[LENGTH_1:%.*]]
305; CHECK-NEXT:    [[UMIN1:%.*]] = select i1 [[TMP1]], i32 [[UMIN]], i32 [[LENGTH_1]]
306; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 [[LENGTH_3]], [[LENGTH_2]]
307; CHECK-NEXT:    [[UMIN2:%.*]] = select i1 [[TMP2]], i32 [[LENGTH_3]], i32 [[LENGTH_2]]
308; CHECK-NEXT:    [[TMP3:%.*]] = icmp ult i32 [[UMIN2]], [[LENGTH_1]]
309; CHECK-NEXT:    [[UMIN3:%.*]] = select i1 [[TMP3]], i32 [[UMIN2]], i32 [[LENGTH_1]]
310; CHECK-NEXT:    [[TMP4:%.*]] = icmp ugt i32 [[N:%.*]], 1
311; CHECK-NEXT:    [[UMAX:%.*]] = select i1 [[TMP4]], i32 [[N]], i32 1
312; CHECK-NEXT:    [[TMP5:%.*]] = add i32 [[UMAX]], -1
313; CHECK-NEXT:    [[TMP6:%.*]] = icmp ult i32 [[UMIN3]], [[TMP5]]
314; CHECK-NEXT:    [[UMIN4:%.*]] = select i1 [[TMP6]], i32 [[UMIN3]], i32 [[TMP5]]
315; CHECK-NEXT:    [[TMP7:%.*]] = icmp ne i32 [[UMIN1]], [[UMIN4]]
316; CHECK-NEXT:    br label [[LOOP:%.*]]
317; CHECK:       loop:
318; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
319; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
320; CHECK-NEXT:    br i1 [[TMP7]], label [[GUARDED]], label [[DEOPT:%.*]], !prof !0
321; CHECK:       deopt:
322; CHECK-NEXT:    call void @prevent_merging()
323; CHECK-NEXT:    ret i32 -1
324; CHECK:       guarded:
325; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
326; CHECK-NEXT:    [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_1:%.*]], i64 [[I_I64]]
327; CHECK-NEXT:    [[ARRAY_1_I:%.*]] = load i32, i32* [[ARRAY_1_I_PTR]], align 4
328; CHECK-NEXT:    [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]]
329; CHECK-NEXT:    [[ARRAY_2_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_2:%.*]], i64 [[I_I64]]
330; CHECK-NEXT:    [[ARRAY_2_I:%.*]] = load i32, i32* [[ARRAY_2_I_PTR]], align 4
331; CHECK-NEXT:    [[LOOP_ACC_2:%.*]] = add i32 [[LOOP_ACC_1]], [[ARRAY_2_I]]
332; CHECK-NEXT:    [[ARRAY_3_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_3:%.*]], i64 [[I_I64]]
333; CHECK-NEXT:    [[ARRAY_3_I:%.*]] = load i32, i32* [[ARRAY_3_I_PTR]], align 4
334; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_2]], [[ARRAY_3_I]]
335; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
336; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
337; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
338; CHECK:       exit:
339; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
340; CHECK-NEXT:    ret i32 [[RESULT]]
341;
342loop.preheader:                                   ; preds = %entry
343  br label %loop
344
345loop:                                             ; preds = %guarded, %loop.preheader
346  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
347  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
348  %within.bounds.1 = icmp ult i32 %i, %length.1
349  %within.bounds.2 = icmp ult i32 %i, %length.2
350  %within.bounds.3 = icmp ult i32 %i, %length.3
351  %within.bounds.1.and.2 = and i1 %within.bounds.1, %within.bounds.2
352  %within.bounds = and i1 %within.bounds.1.and.2, %within.bounds.3
353  br i1 %within.bounds, label %guarded, label %deopt, !prof !0
354
355deopt:                                            ; preds = %loop
356  call void @prevent_merging()
357  ret i32 -1
358
359guarded:                                          ; preds = %loop
360  %i.i64 = zext i32 %i to i64
361  %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64
362  %array.1.i = load i32, i32* %array.1.i.ptr, align 4
363  %loop.acc.1 = add i32 %loop.acc, %array.1.i
364  %array.2.i.ptr = getelementptr inbounds i32, i32* %array.2, i64 %i.i64
365  %array.2.i = load i32, i32* %array.2.i.ptr, align 4
366  %loop.acc.2 = add i32 %loop.acc.1, %array.2.i
367  %array.3.i.ptr = getelementptr inbounds i32, i32* %array.3, i64 %i.i64
368  %array.3.i = load i32, i32* %array.3.i.ptr, align 4
369  %loop.acc.next = add i32 %loop.acc.2, %array.3.i
370  %i.next = add nuw i32 %i, 1
371  %continue = icmp ult i32 %i.next, %n
372  br i1 %continue, label %loop, label %exit
373
374exit:                                             ; preds = %guarded, %entry
375  %result = phi i32 [ %loop.acc.next, %guarded ]
376  ret i32 %result
377}
378
379; Analogous to the above, but with two distinct branches (on different conditions)
380define i32 @distinct_checks(i32* %array.1, i32 %length.1, i32* %array.2, i32 %length.2, i32* %array.3, i32 %length.3, i32 %n) {
381; CHECK-LABEL: @distinct_checks(
382; CHECK-NEXT:  loop.preheader:
383; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 [[LENGTH_2:%.*]], [[LENGTH_1:%.*]]
384; CHECK-NEXT:    [[UMIN:%.*]] = select i1 [[TMP0]], i32 [[LENGTH_2]], i32 [[LENGTH_1]]
385; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i32 [[N:%.*]], 1
386; CHECK-NEXT:    [[UMAX:%.*]] = select i1 [[TMP1]], i32 [[N]], i32 1
387; CHECK-NEXT:    [[TMP2:%.*]] = add i32 [[UMAX]], -1
388; CHECK-NEXT:    [[TMP3:%.*]] = icmp ult i32 [[UMIN]], [[TMP2]]
389; CHECK-NEXT:    [[UMIN1:%.*]] = select i1 [[TMP3]], i32 [[UMIN]], i32 [[TMP2]]
390; CHECK-NEXT:    [[TMP4:%.*]] = icmp ne i32 [[LENGTH_1]], [[UMIN1]]
391; CHECK-NEXT:    [[TMP5:%.*]] = icmp ne i32 [[LENGTH_2]], [[UMIN1]]
392; CHECK-NEXT:    br label [[LOOP:%.*]]
393; CHECK:       loop:
394; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED1:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
395; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED1]] ], [ 0, [[LOOP_PREHEADER]] ]
396; CHECK-NEXT:    br i1 [[TMP4]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
397; CHECK:       deopt:
398; CHECK-NEXT:    call void @prevent_merging()
399; CHECK-NEXT:    ret i32 -1
400; CHECK:       guarded:
401; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
402; CHECK-NEXT:    [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_1:%.*]], i64 [[I_I64]]
403; CHECK-NEXT:    [[ARRAY_1_I:%.*]] = load i32, i32* [[ARRAY_1_I_PTR]], align 4
404; CHECK-NEXT:    [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]]
405; CHECK-NEXT:    br i1 [[TMP5]], label [[GUARDED1]], label [[DEOPT2:%.*]], !prof !0
406; CHECK:       deopt2:
407; CHECK-NEXT:    call void @prevent_merging()
408; CHECK-NEXT:    ret i32 -1
409; CHECK:       guarded1:
410; CHECK-NEXT:    [[ARRAY_3_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_3:%.*]], i64 [[I_I64]]
411; CHECK-NEXT:    [[ARRAY_3_I:%.*]] = load i32, i32* [[ARRAY_3_I_PTR]], align 4
412; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_1]], [[ARRAY_3_I]]
413; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
414; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
415; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
416; CHECK:       exit:
417; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED1]] ]
418; CHECK-NEXT:    ret i32 [[RESULT]]
419;
420loop.preheader:                                   ; preds = %entry
421  br label %loop
422
423loop:                                             ; preds = %guarded4, %loop.preheader
424  %loop.acc = phi i32 [ %loop.acc.next, %guarded1 ], [ 0, %loop.preheader ]
425  %i = phi i32 [ %i.next, %guarded1 ], [ 0, %loop.preheader ]
426  %within.bounds.1 = icmp ult i32 %i, %length.1
427  br i1 %within.bounds.1, label %guarded, label %deopt, !prof !0
428
429deopt:                                            ; preds = %loop
430  call void @prevent_merging()
431  ret i32 -1
432
433guarded:                                          ; preds = %loop
434  %i.i64 = zext i32 %i to i64
435  %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64
436  %array.1.i = load i32, i32* %array.1.i.ptr, align 4
437  %loop.acc.1 = add i32 %loop.acc, %array.1.i
438  %within.bounds.2 = icmp ult i32 %i, %length.2
439  br i1 %within.bounds.2, label %guarded1, label %deopt2, !prof !0
440
441deopt2:                                           ; preds = %guarded
442  call void @prevent_merging()
443  ret i32 -1
444
445guarded1:                                         ; preds = %guarded1
446  %array.3.i.ptr = getelementptr inbounds i32, i32* %array.3, i64 %i.i64
447  %array.3.i = load i32, i32* %array.3.i.ptr, align 4
448  %loop.acc.next = add i32 %loop.acc.1, %array.3.i
449  %i.next = add nuw i32 %i, 1
450  %continue = icmp ult i32 %i.next, %n
451  br i1 %continue, label %loop, label %exit
452
453exit:
454  %result = phi i32 [ %loop.acc.next, %guarded1 ]
455  ret i32 %result
456}
457
458define i32 @duplicate_checks(i32* %array.1, i32* %array.2, i32* %array.3, i32 %length, i32 %n) {
459; CHECK-LABEL: @duplicate_checks(
460; CHECK-NEXT:  loop.preheader:
461; CHECK-NEXT:    [[TMP0:%.*]] = icmp ugt i32 [[N:%.*]], 1
462; CHECK-NEXT:    [[UMAX:%.*]] = select i1 [[TMP0]], i32 [[N]], i32 1
463; CHECK-NEXT:    [[TMP1:%.*]] = add i32 [[UMAX]], -1
464; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 [[LENGTH:%.*]], [[TMP1]]
465; CHECK-NEXT:    [[UMIN:%.*]] = select i1 [[TMP2]], i32 [[LENGTH]], i32 [[TMP1]]
466; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[LENGTH]], [[UMIN]]
467; CHECK-NEXT:    br label [[LOOP:%.*]]
468; CHECK:       loop:
469; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED1:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
470; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED1]] ], [ 0, [[LOOP_PREHEADER]] ]
471; CHECK-NEXT:    br i1 [[TMP3]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
472; CHECK:       deopt:
473; CHECK-NEXT:    call void @prevent_merging()
474; CHECK-NEXT:    ret i32 -1
475; CHECK:       guarded:
476; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
477; CHECK-NEXT:    [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_1:%.*]], i64 [[I_I64]]
478; CHECK-NEXT:    [[ARRAY_1_I:%.*]] = load i32, i32* [[ARRAY_1_I_PTR]], align 4
479; CHECK-NEXT:    [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]]
480; CHECK-NEXT:    br i1 true, label [[GUARDED1]], label [[DEOPT2:%.*]], !prof !0
481; CHECK:       deopt2:
482; CHECK-NEXT:    call void @prevent_merging()
483; CHECK-NEXT:    ret i32 -1
484; CHECK:       guarded1:
485; CHECK-NEXT:    [[ARRAY_3_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_3:%.*]], i64 [[I_I64]]
486; CHECK-NEXT:    [[ARRAY_3_I:%.*]] = load i32, i32* [[ARRAY_3_I_PTR]], align 4
487; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_1]], [[ARRAY_3_I]]
488; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
489; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
490; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
491; CHECK:       exit:
492; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED1]] ]
493; CHECK-NEXT:    ret i32 [[RESULT]]
494;
495loop.preheader:                                   ; preds = %entry
496  br label %loop
497
498loop:                                             ; preds = %guarded4, %loop.preheader
499  %loop.acc = phi i32 [ %loop.acc.next, %guarded1 ], [ 0, %loop.preheader ]
500  %i = phi i32 [ %i.next, %guarded1 ], [ 0, %loop.preheader ]
501  %within.bounds.1 = icmp ult i32 %i, %length
502  br i1 %within.bounds.1, label %guarded, label %deopt, !prof !0
503
504deopt:                                            ; preds = %loop
505  call void @prevent_merging()
506  ret i32 -1
507
508guarded:                                          ; preds = %loop
509  %i.i64 = zext i32 %i to i64
510  %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64
511  %array.1.i = load i32, i32* %array.1.i.ptr, align 4
512  %loop.acc.1 = add i32 %loop.acc, %array.1.i
513  %within.bounds.2 = icmp ult i32 %i, %length
514  br i1 %within.bounds.2, label %guarded1, label %deopt2, !prof !0
515
516deopt2:                                           ; preds = %guarded
517  call void @prevent_merging()
518  ret i32 -1
519
520guarded1:                                         ; preds = %guarded1
521  %array.3.i.ptr = getelementptr inbounds i32, i32* %array.3, i64 %i.i64
522  %array.3.i = load i32, i32* %array.3.i.ptr, align 4
523  %loop.acc.next = add i32 %loop.acc.1, %array.3.i
524  %i.next = add nuw i32 %i, 1
525  %continue = icmp ult i32 %i.next, %n
526  br i1 %continue, label %loop, label %exit
527
528exit:
529  %result = phi i32 [ %loop.acc.next, %guarded1 ]
530  ret i32 %result
531}
532
533
534define i32 @provably_taken(i32* %array, i32* %length.ptr) {
535; CHECK-LABEL: @provably_taken(
536; CHECK-NEXT:  loop.preheader:
537; CHECK-NEXT:    br label [[LOOP:%.*]]
538; CHECK:       loop:
539; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
540; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
541; CHECK-NEXT:    br i1 false, label [[GUARDED]], label [[DEOPT:%.*]], !prof !0
542; CHECK:       deopt:
543; CHECK-NEXT:    call void @prevent_merging()
544; CHECK-NEXT:    ret i32 -1
545; CHECK:       guarded:
546; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
547; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
548; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
549; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
550; CHECK-NEXT:    [[I_NEXT]] = add nuw nsw i32 [[I]], 1
551; CHECK-NEXT:    br i1 true, label [[LOOP]], label [[EXIT:%.*]]
552; CHECK:       exit:
553; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
554; CHECK-NEXT:    ret i32 [[RESULT]]
555;
556loop.preheader:
557  %length = load i32, i32* %length.ptr, !range !2
558  br label %loop
559
560loop:                                             ; preds = %guarded, %loop.preheader
561  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
562  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
563  %within.bounds = icmp ult i32 %i, %length
564  br i1 %within.bounds, label %guarded, label %deopt, !prof !0
565
566deopt:                                            ; preds = %loop
567  call void @prevent_merging()
568  ret i32 -1
569
570guarded:                                          ; preds = %loop
571  %i.i64 = zext i32 %i to i64
572  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
573  %array.i = load i32, i32* %array.i.ptr, align 4
574  %loop.acc.next = add i32 %loop.acc, %array.i
575  %i.next = add nuw i32 %i, 1
576  %continue = icmp slt i32 %i.next, 200
577  br i1 %continue, label %loop, label %exit
578
579exit:                                             ; preds = %guarded
580  %result = phi i32 [ %loop.acc.next, %guarded ]
581  ret i32 %result
582}
583
584; Non-latch exits can still be predicated
585define i32 @unconditional_latch(i32* %a, i32 %length) {
586; CHECK-LABEL: @unconditional_latch(
587; CHECK-NEXT:  loop.preheader:
588; CHECK-NEXT:    br label [[LOOP:%.*]]
589; CHECK:       loop:
590; CHECK-NEXT:    br i1 false, label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
591; CHECK:       deopt:
592; CHECK-NEXT:    call void @prevent_merging()
593; CHECK-NEXT:    ret i32 -1
594; CHECK:       guarded:
595; CHECK-NEXT:    br label [[LOOP]]
596;
597loop.preheader:
598  br label %loop
599
600loop:                                             ; preds = %guarded, %loop.preheader
601  %i = phi i32 [ %i.next, %guarded ], [ 400, %loop.preheader ]
602  %within.bounds = icmp ult i32 %i, %length
603  br i1 %within.bounds, label %guarded, label %deopt, !prof !0
604
605deopt:                                            ; preds = %loop
606  call void @prevent_merging()
607  ret i32 -1
608
609guarded:                                          ; preds = %loop
610  %i.next = add i32 %i, 1
611  br label %loop
612}
613
614; Side effect in loop must run proper number of times
615define i32 @unconditional_latch_with_side_effect(i32* %a, i32 %length) {
616; CHECK-LABEL: @unconditional_latch_with_side_effect(
617; CHECK-NEXT:  loop.preheader:
618; CHECK-NEXT:    br label [[LOOP:%.*]]
619; CHECK:       loop:
620; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED:%.*]] ], [ 400, [[LOOP_PREHEADER:%.*]] ]
621; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]]
622; CHECK-NEXT:    br i1 [[WITHIN_BOUNDS]], label [[GUARDED]], label [[DEOPT:%.*]], !prof !0
623; CHECK:       deopt:
624; CHECK-NEXT:    call void @prevent_merging()
625; CHECK-NEXT:    ret i32 -1
626; CHECK:       guarded:
627; CHECK-NEXT:    store volatile i32 0, i32* [[A:%.*]]
628; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
629; CHECK-NEXT:    br label [[LOOP]]
630;
631loop.preheader:
632  br label %loop
633
634loop:                                             ; preds = %guarded, %loop.preheader
635  %i = phi i32 [ %i.next, %guarded ], [ 400, %loop.preheader ]
636  %within.bounds = icmp ult i32 %i, %length
637  br i1 %within.bounds, label %guarded, label %deopt, !prof !0
638
639deopt:                                            ; preds = %loop
640  call void @prevent_merging()
641  ret i32 -1
642
643guarded:                                          ; preds = %loop
644  store volatile i32 0, i32* %a
645  %i.next = add i32 %i, 1
646  br label %loop
647}
648
649; Demonstrate that this approach works with IVs of different steps, and types
650; This version uses a manually lftred exit condition to work around an issue described
651; in detail on next test.
652define i32 @different_ivs(i32* %array, i32 %length, i32 %n) {
653; CHECK-LABEL: @different_ivs(
654; CHECK-NEXT:  loop.preheader:
655; CHECK-NEXT:    [[N64:%.*]] = zext i32 [[N:%.*]] to i64
656; CHECK-NEXT:    [[TMP0:%.*]] = icmp ugt i64 [[N64]], 1
657; CHECK-NEXT:    [[UMAX:%.*]] = select i1 [[TMP0]], i64 [[N64]], i64 1
658; CHECK-NEXT:    [[TMP1:%.*]] = add nsw i64 [[UMAX]], -1
659; CHECK-NEXT:    [[TMP2:%.*]] = zext i32 [[LENGTH:%.*]] to i64
660; CHECK-NEXT:    [[TMP3:%.*]] = icmp ult i64 [[TMP1]], [[TMP2]]
661; CHECK-NEXT:    [[UMIN:%.*]] = select i1 [[TMP3]], i64 [[TMP1]], i64 [[TMP2]]
662; CHECK-NEXT:    [[TMP4:%.*]] = zext i32 [[LENGTH]] to i64
663; CHECK-NEXT:    [[TMP5:%.*]] = icmp ne i64 [[TMP4]], [[UMIN]]
664; CHECK-NEXT:    br label [[LOOP:%.*]]
665; CHECK:       loop:
666; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
667; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
668; CHECK-NEXT:    br i1 [[TMP5]], label [[GUARDED]], label [[DEOPT:%.*]], !prof !0
669; CHECK:       deopt:
670; CHECK-NEXT:    call void @prevent_merging()
671; CHECK-NEXT:    ret i32 -1
672; CHECK:       guarded:
673; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I]]
674; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
675; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
676; CHECK-NEXT:    [[I_NEXT]] = add nuw nsw i64 [[I]], 1
677; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i64 [[I_NEXT]], [[N64]]
678; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
679; CHECK:       exit:
680; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
681; CHECK-NEXT:    ret i32 [[RESULT]]
682;
683loop.preheader:
684  %j.start = sub nuw nsw i32 %length, 1
685  %n64 = zext i32 %n to i64
686  br label %loop
687
688loop:
689  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
690  %i = phi i64 [ %i.next, %guarded ], [ 0, %loop.preheader ]
691  %j = phi i32 [ %j.next, %guarded ], [ %j.start, %loop.preheader ]
692  %within.bounds = icmp ne i32 %j, -1
693  br i1 %within.bounds, label %guarded, label %deopt, !prof !0
694
695deopt:
696  call void @prevent_merging()
697  ret i32 -1
698
699guarded:
700  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i
701  %array.i = load i32, i32* %array.i.ptr, align 4
702  %loop.acc.next = add i32 %loop.acc, %array.i
703  %i.next = add nuw i64 %i, 1
704  %j.next = sub nuw i32 %j, 1
705  %continue = icmp ult i64 %i.next, %n64
706  br i1 %continue, label %loop, label %exit
707
708exit:
709  %result = phi i32 [ %loop.acc.next, %guarded ]
710  ret i32 %result
711}
712
713; TODO: We're failing to compute an exit count for the bounds check.
714; From some quick analysis, it looks like we don't handle -1 step
715; in howManyLessThans.  Should be a simple fix.
716define i32 @different_ivs2(i32* %array, i32 %length, i32 %n) {
717; CHECK-LABEL: @different_ivs2(
718; CHECK-NEXT:  entry:
719; CHECK-NEXT:    [[POS_LENGTH:%.*]] = icmp sgt i32 [[LENGTH:%.*]], 0
720; CHECK-NEXT:    br i1 [[POS_LENGTH]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
721; CHECK:       loop.preheader:
722; CHECK-NEXT:    [[J_START:%.*]] = sub nuw nsw i32 [[LENGTH]], 1
723; CHECK-NEXT:    [[N64:%.*]] = zext i32 [[N:%.*]] to i64
724; CHECK-NEXT:    br label [[LOOP:%.*]]
725; CHECK:       loop:
726; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
727; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
728; CHECK-NEXT:    [[J:%.*]] = phi i32 [ [[J_NEXT:%.*]], [[GUARDED]] ], [ [[J_START]], [[LOOP_PREHEADER]] ]
729; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[J]], [[LENGTH]]
730; CHECK-NEXT:    br i1 [[WITHIN_BOUNDS]], label [[GUARDED]], label [[DEOPT:%.*]], !prof !0
731; CHECK:       deopt:
732; CHECK-NEXT:    call void @prevent_merging()
733; CHECK-NEXT:    ret i32 -1
734; CHECK:       guarded:
735; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I]]
736; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
737; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
738; CHECK-NEXT:    [[I_NEXT]] = add nuw nsw i64 [[I]], 1
739; CHECK-NEXT:    [[J_NEXT]] = sub nuw i32 [[J]], 1
740; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i64 [[I_NEXT]], [[N64]]
741; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
742; CHECK:       exit.loopexit:
743; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
744; CHECK-NEXT:    br label [[EXIT]]
745; CHECK:       exit:
746; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
747; CHECK-NEXT:    ret i32 [[RESULT]]
748;
749entry:
750  %pos_length = icmp sgt i32 %length, 0
751  br i1 %pos_length, label %loop.preheader, label %exit
752
753loop.preheader:
754  %j.start = sub nuw nsw i32 %length, 1
755  %n64 = zext i32 %n to i64
756  br label %loop
757
758loop:
759  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
760  %i = phi i64 [ %i.next, %guarded ], [ 0, %loop.preheader ]
761  %j = phi i32 [ %j.next, %guarded ], [ %j.start, %loop.preheader ]
762  %within.bounds = icmp ult i32 %j, %length
763  br i1 %within.bounds, label %guarded, label %deopt, !prof !0
764
765deopt:
766  call void @prevent_merging()
767  ret i32 -1
768
769guarded:
770  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i
771  %array.i = load i32, i32* %array.i.ptr, align 4
772  %loop.acc.next = add i32 %loop.acc, %array.i
773  %i.next = add nuw i64 %i, 1
774  %j.next = sub nuw i32 %j, 1
775  %continue = icmp ult i64 %i.next, %n64
776  br i1 %continue, label %loop, label %exit
777
778exit:
779  %result = phi i32 [ %loop.acc.next, %guarded ], [0, %entry]
780  ret i32 %result
781}
782
783; If we have a dominating exit (exit1) which can't be itself rewritten, we
784; can't rewrite a later exit (exit2).  Doing so would cause the loop to exit
785; from the exit2 when it should have exited from exit1.
786define i32 @neg_dominating_exit(i32* %array, i32 %length, i32 %length2, i32 %n) {
787; CHECK-LABEL: @neg_dominating_exit(
788; CHECK-NEXT:  loop.preheader:
789; CHECK-NEXT:    br label [[LOOP:%.*]]
790; CHECK:       loop:
791; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED2:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
792; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED2]] ], [ 0, [[LOOP_PREHEADER]] ]
793; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]]
794; CHECK-NEXT:    br i1 [[WITHIN_BOUNDS]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
795; CHECK:       deopt:
796; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC]], [[LOOP]] ]
797; CHECK-NEXT:    call void @prevent_merging()
798; CHECK-NEXT:    ret i32 [[RESULT]]
799; CHECK:       guarded:
800; CHECK-NEXT:    [[WITHIN_BOUNDS2:%.*]] = icmp ult i32 [[I]], [[LENGTH2:%.*]]
801; CHECK-NEXT:    br i1 [[WITHIN_BOUNDS2]], label [[GUARDED2]], label [[DEOPT2:%.*]], !prof !0
802; CHECK:       deopt2:
803; CHECK-NEXT:    call void @prevent_merging()
804; CHECK-NEXT:    ret i32 -1
805; CHECK:       guarded2:
806; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
807; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
808; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
809; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
810; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
811; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N:%.*]]
812; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
813; CHECK:       exit:
814; CHECK-NEXT:    [[RESULT2:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED2]] ]
815; CHECK-NEXT:    ret i32 [[RESULT2]]
816;
817loop.preheader:                                   ; preds = %entry
818  br label %loop
819
820loop:                                             ; preds = %guarded, %loop.preheader
821  %loop.acc = phi i32 [ %loop.acc.next, %guarded2 ], [ 0, %loop.preheader ]
822  %i = phi i32 [ %i.next, %guarded2 ], [ 0, %loop.preheader ]
823  %within.bounds = icmp ult i32 %i, %length
824  br i1 %within.bounds, label %guarded, label %deopt, !prof !0
825
826deopt:                                            ; preds = %loop
827  %result = phi i32 [ %loop.acc, %loop ]
828  call void @prevent_merging()
829  ret i32 %result
830
831guarded:                                          ; preds = %loop
832  %within.bounds2 = icmp ult i32 %i, %length2
833  br i1 %within.bounds2, label %guarded2, label %deopt2, !prof !0
834
835deopt2:                                            ; preds = %loop
836  call void @prevent_merging()
837  ret i32 -1
838
839guarded2:                                          ; preds = %loop
840  %i.i64 = zext i32 %i to i64
841  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
842  %array.i = load i32, i32* %array.i.ptr, align 4
843  %loop.acc.next = add i32 %loop.acc, %array.i
844  %i.next = add nuw i32 %i, 1
845  %continue = icmp ult i32 %i.next, %n
846  br i1 %continue, label %loop, label %exit
847
848exit:                                             ; preds = %guarded, %entry
849  %result2 = phi i32 [ %loop.acc.next, %guarded2 ]
850  ret i32 %result2
851}
852
853
854declare i32 @llvm.experimental.deoptimize.i32(...)
855
856!0 = !{!"branch_weights", i32 1048576, i32 1}
857!1 = !{i32 1, i32 -2147483648}
858!2 = !{i32 0, i32 50}
859