[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / IndVarSimplify / loop-predication.ll
blobeb5620572bc49a4261471a606465dad385331094
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -indvars -indvars-predicate-loops=1 -S | FileCheck %s
4 declare void @prevent_merging()
6 ; Base case
7 define 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]]
34 loop.preheader:                                   ; preds = %entry
35   br label %loop
37 loop:                                             ; 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
43 deopt:                                            ; preds = %loop
44   call void @prevent_merging()
45   ret i32 -1
47 guarded:                                          ; 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
56 exit:                                             ; preds = %guarded, %entry
57   %result = phi i32 [ %loop.acc.next, %guarded ]
58   ret i32 %result
61 ; Has side effect which must be reflected
62 define 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]]
87 loop.preheader:                                   ; preds = %entry
88   br label %loop
90 loop:                                             ; 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
96 deopt:                                            ; preds = %loop
97   call void @prevent_merging()
98   ret i32 -1
100 guarded:                                          ; 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
110 exit:                                             ; preds = %guarded, %entry
111   %result = phi i32 [ %loop.acc.next, %guarded ]
112   ret i32 %result
115 declare void @maythrow()
117 ; May exit through implicit exception edge
118 define 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]]
143 loop.preheader:                                   ; preds = %entry
144   br label %loop
146 loop:                                             ; 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
153 deopt:                                            ; preds = %loop
154   call void @prevent_merging()
155   ret i32 -1
157 guarded:                                          ; 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
166 exit:                                             ; preds = %guarded, %entry
167   %result = phi i32 [ %loop.acc.next, %guarded ]
168   ret i32 %result
173 ; Base case, but in LFTR form (just for sanity checking)
174 define 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]]
200 loop.preheader:                                   ; preds = %entry
201   br label %loop
203 loop:                                             ; 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
209 deopt:                                            ; preds = %loop
210   call void @prevent_merging()
211   ret i32 -1
213 guarded:                                          ; 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
222 exit:                                             ; preds = %guarded, %entry
223   %result = phi i32 [ %loop.acc.next, %guarded ]
224   ret i32 %result
227 ; br (and rcheck1, rcheck2)
228 define 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]]
260 loop.preheader:                                   ; preds = %entry
261   br label %loop
263 loop:                                             ; 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
271 deopt:                                            ; preds = %loop
272   call void @prevent_merging()
273   ret i32 -1
275 guarded:                                          ; 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
287 exit:                                             ; preds = %guarded, %entry
288   %result = phi i32 [ %loop.acc.next, %guarded ]
289   ret i32 %result
292 define 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]]
329 loop.preheader:                                   ; preds = %entry
330   br label %loop
332 loop:                                             ; 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
342 deopt:                                            ; preds = %loop
343   call void @prevent_merging()
344   ret i32 -1
346 guarded:                                          ; 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
361 exit:                                             ; preds = %guarded, %entry
362   %result = phi i32 [ %loop.acc.next, %guarded ]
363   ret i32 %result
366 ; Analogous to the above, but with two distinct branches (on different conditions)
367 define 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]]
404 loop.preheader:                                   ; preds = %entry
405   br label %loop
407 loop:                                             ; 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
413 deopt:                                            ; preds = %loop
414   call void @prevent_merging()
415   ret i32 -1
417 guarded:                                          ; 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
425 deopt2:                                           ; preds = %guarded
426   call void @prevent_merging()
427   ret i32 -1
429 guarded1:                                         ; 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
437 exit:
438   %result = phi i32 [ %loop.acc.next, %guarded1 ]
439   ret i32 %result
442 define 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]]
477 loop.preheader:                                   ; preds = %entry
478   br label %loop
480 loop:                                             ; 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
486 deopt:                                            ; preds = %loop
487   call void @prevent_merging()
488   ret i32 -1
490 guarded:                                          ; 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
498 deopt2:                                           ; preds = %guarded
499   call void @prevent_merging()
500   ret i32 -1
502 guarded1:                                         ; 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
510 exit:
511   %result = phi i32 [ %loop.acc.next, %guarded1 ]
512   ret i32 %result
516 define 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]]
538 loop.preheader:
539   %length = load i32, i32* %length.ptr, !range !2
540   br label %loop
542 loop:                                             ; 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
548 deopt:                                            ; preds = %loop
549   call void @prevent_merging()
550   ret i32 -1
552 guarded:                                          ; 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
561 exit:                                             ; preds = %guarded
562   %result = phi i32 [ %loop.acc.next, %guarded ]
563   ret i32 %result
566 ; Non-latch exits can still be predicated
567 define 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]]
579 loop.preheader:
580   br label %loop
582 loop:                                             ; 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
587 deopt:                                            ; preds = %loop
588   call void @prevent_merging()
589   ret i32 -1
591 guarded:                                          ; preds = %loop
592   %i.next = add i32 %i, 1
593   br label %loop
596 ; Side effect in loop must run proper number of times
597 define 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]]
613 loop.preheader:
614   br label %loop
616 loop:                                             ; 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
621 deopt:                                            ; preds = %loop
622   call void @prevent_merging()
623   ret i32 -1
625 guarded:                                          ; preds = %loop
626   store volatile i32 0, i32* %a
627   %i.next = add i32 %i, 1
628   br label %loop
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.
634 define 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]]
663 loop.preheader:
664   %j.start = sub nuw nsw i32 %length, 1
665   %n64 = zext i32 %n to i64
666   br label %loop
668 loop:
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
675 deopt:
676   call void @prevent_merging()
677   ret i32 -1
679 guarded:
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
688 exit:
689   %result = phi i32 [ %loop.acc.next, %guarded ]
690   ret i32 %result
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.
696 define 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]]
729 entry:
730   %pos_length = icmp sgt i32 %length, 0
731   br i1 %pos_length, label %loop.preheader, label %exit
733 loop.preheader:
734   %j.start = sub nuw nsw i32 %length, 1
735   %n64 = zext i32 %n to i64
736   br label %loop
738 loop:
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
745 deopt:
746   call void @prevent_merging()
747   ret i32 -1
749 guarded:
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
758 exit:
759   %result = phi i32 [ %loop.acc.next, %guarded ], [0, %entry]
760   ret i32 %result
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.
766 define 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]]
797 loop.preheader:                                   ; preds = %entry
798   br label %loop
800 loop:                                             ; 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
806 deopt:                                            ; preds = %loop
807   %result = phi i32 [ %loop.acc, %loop ]
808   call void @prevent_merging()
809   ret i32 %result
811 guarded:                                          ; preds = %loop
812   %within.bounds2 = icmp ult i32 %i, %length2
813   br i1 %within.bounds2, label %guarded2, label %deopt2, !prof !0
815 deopt2:                                            ; preds = %loop
816   call void @prevent_merging()
817   ret i32 -1
819 guarded2:                                          ; 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
828 exit:                                             ; preds = %guarded, %entry
829   %result2 = phi i32 [ %loop.acc.next, %guarded2 ]
830   ret i32 %result2
834 declare i32 @llvm.experimental.deoptimize.i32(...)
836 !0 = !{!"branch_weights", i32 1048576, i32 1}
837 !1 = !{i32 1, i32 -2147483648}
838 !2 = !{i32 0, i32 50}