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