xref: /llvm-project/llvm/test/Transforms/LoopPredication/basic_widenable_branch_guards.ll (revision e9dfe083f0fc37ee03506f3b8b8d68750927f613)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -passes=loop-predication -loop-predication-predicate-widenable-branches-to-deopt=true < %s 2>&1 | FileCheck %s
3; RUN: opt -S -passes='require<scalar-evolution>,loop-mssa(loop-predication)'  -verify-memoryssa -loop-predication-predicate-widenable-branches-to-deopt=true < %s 2>&1 | FileCheck %s
4; RUN: opt -S -passes='require<scalar-evolution>,require<branch-prob>,loop-mssa(loop-predication)' -verify-memoryssa -loop-predication-predicate-widenable-branches-to-deopt=true < %s 2>&1 | FileCheck %s
5
6declare void @llvm.experimental.guard(i1, ...)
7
8define i32 @unsigned_loop_0_to_n_ult_check(ptr %array, i32 %length, i32 %n) {
9; CHECK-LABEL: @unsigned_loop_0_to_n_ult_check(
10; CHECK-NEXT:  entry:
11; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
12; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
13; CHECK:       loop.preheader:
14; CHECK-NEXT:    [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH:%.*]]
15; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
16; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
17; CHECK-NEXT:    [[TMP3:%.*]] = freeze i1 [[TMP2]]
18; CHECK-NEXT:    br label [[LOOP:%.*]]
19; CHECK:       loop:
20; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
21; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
22; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]]
23; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
24; CHECK-NEXT:    [[TMP4:%.*]] = and i1 [[TMP3]], [[WIDENABLE_COND]]
25; CHECK-NEXT:    br i1 [[TMP4]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0:![0-9]+]]
26; CHECK:       deopt:
27; CHECK-NEXT:    [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
28; CHECK-NEXT:    ret i32 [[DEOPTCALL]]
29; CHECK:       guarded:
30; CHECK-NEXT:    call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
31; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
32; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
33; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
34; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
35; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
36; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
37; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]], !prof [[PROF1:![0-9]+]]
38; CHECK:       exit.loopexit:
39; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
40; CHECK-NEXT:    br label [[EXIT]]
41; CHECK:       exit:
42; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
43; CHECK-NEXT:    ret i32 [[RESULT]]
44;
45entry:
46  %tmp5 = icmp eq i32 %n, 0
47  br i1 %tmp5, label %exit, label %loop.preheader
48
49loop.preheader:                                   ; preds = %entry
50  br label %loop
51
52loop:                                             ; preds = %guarded, %loop.preheader
53  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
54  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
55  %within.bounds = icmp ult i32 %i, %length
56  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
57  %exiplicit_guard_cond = and i1 %within.bounds, %widenable_cond
58  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
59
60deopt:                                            ; preds = %loop
61  %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
62  ret i32 %deoptcall
63
64guarded:                                          ; preds = %loop
65  %i.i64 = zext i32 %i to i64
66  %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
67  %array.i = load i32, ptr %array.i.ptr, align 4
68  %loop.acc.next = add i32 %loop.acc, %array.i
69  %i.next = add nuw i32 %i, 1
70  %continue = icmp ult i32 %i.next, %n
71  br i1 %continue, label %loop, label %exit, !prof !2
72
73exit:                                             ; preds = %guarded, %entry
74  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %guarded ]
75  ret i32 %result
76}
77
78define i32 @unsigned_loop_0_to_n_ule_latch_ult_check(ptr %array, i32 %length, i32 %n) {
79; CHECK-LABEL: @unsigned_loop_0_to_n_ule_latch_ult_check(
80; CHECK-NEXT:  entry:
81; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
82; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
83; CHECK:       loop.preheader:
84; CHECK-NEXT:    [[TMP0:%.*]] = icmp ult i32 [[N]], [[LENGTH:%.*]]
85; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
86; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
87; CHECK-NEXT:    [[TMP3:%.*]] = freeze i1 [[TMP2]]
88; CHECK-NEXT:    br label [[LOOP:%.*]]
89; CHECK:       loop:
90; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
91; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
92; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]]
93; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
94; CHECK-NEXT:    [[TMP4:%.*]] = and i1 [[TMP3]], [[WIDENABLE_COND]]
95; CHECK-NEXT:    br i1 [[TMP4]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
96; CHECK:       deopt:
97; CHECK-NEXT:    [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
98; CHECK-NEXT:    ret i32 [[DEOPTCALL]]
99; CHECK:       guarded:
100; CHECK-NEXT:    call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
101; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
102; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
103; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
104; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
105; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
106; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ule i32 [[I_NEXT]], [[N]]
107; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]], !prof [[PROF1]]
108; CHECK:       exit.loopexit:
109; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
110; CHECK-NEXT:    br label [[EXIT]]
111; CHECK:       exit:
112; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
113; CHECK-NEXT:    ret i32 [[RESULT]]
114;
115entry:
116  %tmp5 = icmp eq i32 %n, 0
117  br i1 %tmp5, label %exit, label %loop.preheader
118
119loop.preheader:                                   ; preds = %entry
120  br label %loop
121
122loop:                                             ; preds = %guarded, %loop.preheader
123  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
124  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
125  %within.bounds = icmp ult i32 %i, %length
126  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
127  %exiplicit_guard_cond = and i1 %within.bounds, %widenable_cond
128  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
129
130deopt:                                            ; preds = %loop
131  %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
132  ret i32 %deoptcall
133
134guarded:                                          ; preds = %loop
135  %i.i64 = zext i32 %i to i64
136  %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
137  %array.i = load i32, ptr %array.i.ptr, align 4
138  %loop.acc.next = add i32 %loop.acc, %array.i
139  %i.next = add nuw i32 %i, 1
140  %continue = icmp ule i32 %i.next, %n
141  br i1 %continue, label %loop, label %exit, !prof !2
142
143exit:                                             ; preds = %guarded, %entry
144  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %guarded ]
145  ret i32 %result
146}
147
148define i32 @unsigned_loop_0_to_n_ugt_check(ptr %array, i32 %length, i32 %n) {
149; CHECK-LABEL: @unsigned_loop_0_to_n_ugt_check(
150; CHECK-NEXT:  entry:
151; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
152; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
153; CHECK:       loop.preheader:
154; CHECK-NEXT:    [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH:%.*]]
155; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
156; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
157; CHECK-NEXT:    [[TMP3:%.*]] = freeze i1 [[TMP2]]
158; CHECK-NEXT:    br label [[LOOP:%.*]]
159; CHECK:       loop:
160; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
161; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
162; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ugt i32 [[LENGTH]], [[I]]
163; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
164; CHECK-NEXT:    [[TMP4:%.*]] = and i1 [[TMP3]], [[WIDENABLE_COND]]
165; CHECK-NEXT:    br i1 [[TMP4]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
166; CHECK:       deopt:
167; CHECK-NEXT:    [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
168; CHECK-NEXT:    ret i32 [[DEOPTCALL]]
169; CHECK:       guarded:
170; CHECK-NEXT:    call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
171; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
172; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
173; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
174; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
175; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
176; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
177; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]], !prof [[PROF1]]
178; CHECK:       exit.loopexit:
179; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
180; CHECK-NEXT:    br label [[EXIT]]
181; CHECK:       exit:
182; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
183; CHECK-NEXT:    ret i32 [[RESULT]]
184;
185entry:
186  %tmp5 = icmp eq i32 %n, 0
187  br i1 %tmp5, label %exit, label %loop.preheader
188
189loop.preheader:                                   ; preds = %entry
190  br label %loop
191
192loop:                                             ; preds = %guarded, %loop.preheader
193  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
194  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
195  %within.bounds = icmp ugt i32 %length, %i
196  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
197  %exiplicit_guard_cond = and i1 %within.bounds, %widenable_cond
198  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
199
200deopt:                                            ; preds = %loop
201  %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
202  ret i32 %deoptcall
203
204guarded:                                          ; preds = %loop
205  %i.i64 = zext i32 %i to i64
206  %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
207  %array.i = load i32, ptr %array.i.ptr, align 4
208  %loop.acc.next = add i32 %loop.acc, %array.i
209  %i.next = add nuw i32 %i, 1
210  %continue = icmp ult i32 %i.next, %n
211  br i1 %continue, label %loop, label %exit, !prof !2
212
213exit:                                             ; preds = %guarded, %entry
214  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %guarded ]
215  ret i32 %result
216}
217
218define i32 @signed_loop_0_to_n_ult_check(ptr %array, i32 %length, i32 %n) {
219; CHECK-LABEL: @signed_loop_0_to_n_ult_check(
220; CHECK-NEXT:  entry:
221; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
222; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
223; CHECK:       loop.preheader:
224; CHECK-NEXT:    [[TMP0:%.*]] = icmp sle i32 [[N]], [[LENGTH:%.*]]
225; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
226; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
227; CHECK-NEXT:    [[TMP3:%.*]] = freeze i1 [[TMP2]]
228; CHECK-NEXT:    br label [[LOOP:%.*]]
229; CHECK:       loop:
230; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
231; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
232; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]]
233; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
234; CHECK-NEXT:    [[TMP4:%.*]] = and i1 [[TMP3]], [[WIDENABLE_COND]]
235; CHECK-NEXT:    br i1 [[TMP4]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
236; CHECK:       deopt:
237; CHECK-NEXT:    [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
238; CHECK-NEXT:    ret i32 [[DEOPTCALL]]
239; CHECK:       guarded:
240; CHECK-NEXT:    call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
241; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
242; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
243; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
244; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
245; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
246; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
247; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]], !prof [[PROF1]]
248; CHECK:       exit.loopexit:
249; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
250; CHECK-NEXT:    br label [[EXIT]]
251; CHECK:       exit:
252; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
253; CHECK-NEXT:    ret i32 [[RESULT]]
254;
255
256entry:
257  %tmp5 = icmp sle i32 %n, 0
258  br i1 %tmp5, label %exit, label %loop.preheader
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 = icmp ult i32 %i, %length
267  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
268  %exiplicit_guard_cond = and i1 %within.bounds, %widenable_cond
269  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
270
271deopt:                                            ; preds = %loop
272  %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
273  ret i32 %deoptcall
274
275guarded:                                          ; preds = %loop
276  %i.i64 = zext i32 %i to i64
277  %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
278  %array.i = load i32, ptr %array.i.ptr, align 4
279  %loop.acc.next = add i32 %loop.acc, %array.i
280  %i.next = add nuw i32 %i, 1
281  %continue = icmp slt i32 %i.next, %n
282  br i1 %continue, label %loop, label %exit, !prof !2
283
284exit:                                             ; preds = %guarded, %entry
285  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %guarded ]
286  ret i32 %result
287}
288
289define i32 @signed_loop_0_to_n_ult_check_length_range_known(ptr %array, ptr %length.ptr, i32 %n) {
290; CHECK-LABEL: @signed_loop_0_to_n_ult_check_length_range_known(
291; CHECK-NEXT:  entry:
292; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
293; CHECK-NEXT:    [[LENGTH:%.*]] = load i32, ptr [[LENGTH_PTR:%.*]], align 4, !range [[RNG2:![0-9]+]]
294; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
295; CHECK:       loop.preheader:
296; CHECK-NEXT:    [[TMP0:%.*]] = icmp sle i32 [[N]], [[LENGTH]]
297; CHECK-NEXT:    [[TMP1:%.*]] = and i1 true, [[TMP0]]
298; CHECK-NEXT:    [[TMP2:%.*]] = freeze i1 [[TMP1]]
299; CHECK-NEXT:    br label [[LOOP:%.*]]
300; CHECK:       loop:
301; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
302; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
303; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]]
304; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
305; CHECK-NEXT:    [[TMP3:%.*]] = and i1 [[TMP2]], [[WIDENABLE_COND]]
306; CHECK-NEXT:    br i1 [[TMP3]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
307; CHECK:       deopt:
308; CHECK-NEXT:    [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
309; CHECK-NEXT:    ret i32 [[DEOPTCALL]]
310; CHECK:       guarded:
311; CHECK-NEXT:    call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
312; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
313; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
314; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
315; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
316; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
317; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
318; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]], !prof [[PROF1]]
319; CHECK:       exit.loopexit:
320; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
321; CHECK-NEXT:    br label [[EXIT]]
322; CHECK:       exit:
323; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
324; CHECK-NEXT:    ret i32 [[RESULT]]
325;
326entry:
327  %tmp5 = icmp sle i32 %n, 0
328  %length = load i32, ptr %length.ptr, !range !1
329  br i1 %tmp5, label %exit, label %loop.preheader
330
331loop.preheader:                                   ; preds = %entry
332  br label %loop
333
334loop:                                             ; preds = %guarded, %loop.preheader
335  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
336  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
337  %within.bounds = icmp ult i32 %i, %length
338  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
339  %exiplicit_guard_cond = and i1 %within.bounds, %widenable_cond
340  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
341
342deopt:                                            ; preds = %loop
343  %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
344  ret i32 %deoptcall
345
346guarded:                                          ; preds = %loop
347  %i.i64 = zext i32 %i to i64
348  %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
349  %array.i = load i32, ptr %array.i.ptr, align 4
350  %loop.acc.next = add i32 %loop.acc, %array.i
351  %i.next = add nuw i32 %i, 1
352  %continue = icmp slt i32 %i.next, %n
353  br i1 %continue, label %loop, label %exit, !prof !2
354
355exit:                                             ; preds = %guarded, %entry
356  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %guarded ]
357  ret i32 %result
358}
359
360define i32 @signed_loop_0_to_n_inverse_latch_predicate(ptr %array, i32 %length, i32 %n) {
361; CHECK-LABEL: @signed_loop_0_to_n_inverse_latch_predicate(
362; CHECK-NEXT:  entry:
363; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
364; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
365; CHECK:       loop.preheader:
366; CHECK-NEXT:    [[TMP0:%.*]] = icmp slt i32 [[N]], [[LENGTH:%.*]]
367; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
368; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
369; CHECK-NEXT:    [[TMP3:%.*]] = freeze i1 [[TMP2]]
370; CHECK-NEXT:    br label [[LOOP:%.*]]
371; CHECK:       loop:
372; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
373; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
374; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]]
375; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
376; CHECK-NEXT:    [[TMP4:%.*]] = and i1 [[TMP3]], [[WIDENABLE_COND]]
377; CHECK-NEXT:    br i1 [[TMP4]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
378; CHECK:       deopt:
379; CHECK-NEXT:    [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
380; CHECK-NEXT:    ret i32 [[DEOPTCALL]]
381; CHECK:       guarded:
382; CHECK-NEXT:    call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
383; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
384; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
385; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
386; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
387; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
388; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp sgt i32 [[I_NEXT]], [[N]]
389; CHECK-NEXT:    br i1 [[CONTINUE]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP]], !prof [[PROF1]]
390; CHECK:       exit.loopexit:
391; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
392; CHECK-NEXT:    br label [[EXIT]]
393; CHECK:       exit:
394; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
395; CHECK-NEXT:    ret i32 [[RESULT]]
396;
397entry:
398  %tmp5 = icmp sle i32 %n, 0
399  br i1 %tmp5, label %exit, label %loop.preheader
400
401loop.preheader:                                   ; preds = %entry
402  br label %loop
403
404loop:                                             ; preds = %guarded, %loop.preheader
405  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
406  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
407  %within.bounds = icmp ult i32 %i, %length
408  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
409  %exiplicit_guard_cond = and i1 %within.bounds, %widenable_cond
410  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
411
412deopt:                                            ; preds = %loop
413  %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
414  ret i32 %deoptcall
415
416guarded:                                          ; preds = %loop
417  %i.i64 = zext i32 %i to i64
418  %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
419  %array.i = load i32, ptr %array.i.ptr, align 4
420  %loop.acc.next = add i32 %loop.acc, %array.i
421  %i.next = add nuw i32 %i, 1
422  %continue = icmp sgt i32 %i.next, %n
423  br i1 %continue, label %exit, label %loop, !prof !2
424
425exit:                                             ; preds = %guarded, %entry
426  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %guarded ]
427  ret i32 %result
428}
429
430define i32 @signed_loop_0_to_n_sle_latch_ult_check(ptr %array, i32 %length, i32 %n) {
431; CHECK-LABEL: @signed_loop_0_to_n_sle_latch_ult_check(
432; CHECK-NEXT:  entry:
433; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
434; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
435; CHECK:       loop.preheader:
436; CHECK-NEXT:    [[TMP0:%.*]] = icmp slt i32 [[N]], [[LENGTH:%.*]]
437; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
438; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
439; CHECK-NEXT:    [[TMP3:%.*]] = freeze i1 [[TMP2]]
440; CHECK-NEXT:    br label [[LOOP:%.*]]
441; CHECK:       loop:
442; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
443; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
444; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]]
445; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
446; CHECK-NEXT:    [[TMP4:%.*]] = and i1 [[TMP3]], [[WIDENABLE_COND]]
447; CHECK-NEXT:    br i1 [[TMP4]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
448; CHECK:       deopt:
449; CHECK-NEXT:    [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
450; CHECK-NEXT:    ret i32 [[DEOPTCALL]]
451; CHECK:       guarded:
452; CHECK-NEXT:    call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
453; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
454; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
455; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
456; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
457; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
458; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp sle i32 [[I_NEXT]], [[N]]
459; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]], !prof [[PROF1]]
460; CHECK:       exit.loopexit:
461; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
462; CHECK-NEXT:    br label [[EXIT]]
463; CHECK:       exit:
464; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
465; CHECK-NEXT:    ret i32 [[RESULT]]
466;
467entry:
468  %tmp5 = icmp sle i32 %n, 0
469  br i1 %tmp5, label %exit, label %loop.preheader
470
471loop.preheader:                                   ; preds = %entry
472  br label %loop
473
474loop:                                             ; preds = %guarded, %loop.preheader
475  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
476  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
477  %within.bounds = icmp ult i32 %i, %length
478  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
479  %exiplicit_guard_cond = and i1 %within.bounds, %widenable_cond
480  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
481
482deopt:                                            ; preds = %loop
483  %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
484  ret i32 %deoptcall
485
486guarded:                                          ; preds = %loop
487  %i.i64 = zext i32 %i to i64
488  %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
489  %array.i = load i32, ptr %array.i.ptr, align 4
490  %loop.acc.next = add i32 %loop.acc, %array.i
491  %i.next = add nuw i32 %i, 1
492  %continue = icmp sle i32 %i.next, %n
493  br i1 %continue, label %loop, label %exit, !prof !2
494
495exit:                                             ; preds = %guarded, %entry
496  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %guarded ]
497  ret i32 %result
498}
499
500define i32 @signed_loop_0_to_n_preincrement_latch_check(ptr %array, i32 %length, i32 %n) {
501; CHECK-LABEL: @signed_loop_0_to_n_preincrement_latch_check(
502; CHECK-NEXT:  entry:
503; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
504; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
505; CHECK:       loop.preheader:
506; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], -1
507; CHECK-NEXT:    [[TMP1:%.*]] = icmp sle i32 [[N]], [[TMP0]]
508; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 0, [[LENGTH]]
509; CHECK-NEXT:    [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]]
510; CHECK-NEXT:    [[TMP4:%.*]] = freeze i1 [[TMP3]]
511; CHECK-NEXT:    br label [[LOOP:%.*]]
512; CHECK:       loop:
513; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
514; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
515; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]]
516; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
517; CHECK-NEXT:    [[TMP5:%.*]] = and i1 [[TMP4]], [[WIDENABLE_COND]]
518; CHECK-NEXT:    br i1 [[TMP5]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
519; CHECK:       deopt:
520; CHECK-NEXT:    [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
521; CHECK-NEXT:    ret i32 [[DEOPTCALL]]
522; CHECK:       guarded:
523; CHECK-NEXT:    call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
524; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
525; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
526; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
527; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
528; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
529; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp slt i32 [[I]], [[N]]
530; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]], !prof [[PROF1]]
531; CHECK:       exit.loopexit:
532; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
533; CHECK-NEXT:    br label [[EXIT]]
534; CHECK:       exit:
535; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
536; CHECK-NEXT:    ret i32 [[RESULT]]
537;
538entry:
539  %tmp5 = icmp sle i32 %n, 0
540  br i1 %tmp5, label %exit, label %loop.preheader
541
542loop.preheader:                                   ; preds = %entry
543  br label %loop
544
545loop:                                             ; preds = %guarded, %loop.preheader
546  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
547  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
548  %within.bounds = icmp ult i32 %i, %length
549  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
550  %exiplicit_guard_cond = and i1 %within.bounds, %widenable_cond
551  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
552
553deopt:                                            ; preds = %loop
554  %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
555  ret i32 %deoptcall
556
557guarded:                                          ; preds = %loop
558  %i.i64 = zext i32 %i to i64
559  %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
560  %array.i = load i32, ptr %array.i.ptr, align 4
561  %loop.acc.next = add i32 %loop.acc, %array.i
562  %i.next = add i32 %i, 1
563  %continue = icmp slt i32 %i, %n
564  br i1 %continue, label %loop, label %exit, !prof !2
565
566exit:                                             ; preds = %guarded, %entry
567  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %guarded ]
568  ret i32 %result
569}
570
571define i32 @signed_loop_0_to_n_preincrement_latch_check_postincrement_guard_check(ptr %array, i32 %length, i32 %n) {
572; CHECK-LABEL: @signed_loop_0_to_n_preincrement_latch_check_postincrement_guard_check(
573; CHECK-NEXT:  entry:
574; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
575; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
576; CHECK:       loop.preheader:
577; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], -2
578; CHECK-NEXT:    [[TMP1:%.*]] = icmp sle i32 [[N]], [[TMP0]]
579; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 1, [[LENGTH]]
580; CHECK-NEXT:    [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]]
581; CHECK-NEXT:    [[TMP4:%.*]] = freeze i1 [[TMP3]]
582; CHECK-NEXT:    br label [[LOOP:%.*]]
583; CHECK:       loop:
584; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
585; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
586; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
587; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_NEXT]], [[LENGTH]]
588; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
589; CHECK-NEXT:    [[TMP5:%.*]] = and i1 [[TMP4]], [[WIDENABLE_COND]]
590; CHECK-NEXT:    br i1 [[TMP5]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
591; CHECK:       deopt:
592; CHECK-NEXT:    [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
593; CHECK-NEXT:    ret i32 [[DEOPTCALL]]
594; CHECK:       guarded:
595; CHECK-NEXT:    call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
596; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
597; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
598; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
599; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
600; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp slt i32 [[I]], [[N]]
601; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]], !prof [[PROF1]]
602; CHECK:       exit.loopexit:
603; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
604; CHECK-NEXT:    br label [[EXIT]]
605; CHECK:       exit:
606; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
607; CHECK-NEXT:    ret i32 [[RESULT]]
608;
609entry:
610  %tmp5 = icmp sle i32 %n, 0
611  br i1 %tmp5, label %exit, label %loop.preheader
612
613loop.preheader:                                   ; preds = %entry
614  br label %loop
615
616loop:                                             ; preds = %guarded, %loop.preheader
617  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
618  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
619  %i.next = add i32 %i, 1
620  %within.bounds = icmp ult i32 %i.next, %length
621  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
622  %exiplicit_guard_cond = and i1 %within.bounds, %widenable_cond
623  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
624
625deopt:                                            ; preds = %loop
626  %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
627  ret i32 %deoptcall
628
629guarded:                                          ; preds = %loop
630  %i.i64 = zext i32 %i to i64
631  %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
632  %array.i = load i32, ptr %array.i.ptr, align 4
633  %loop.acc.next = add i32 %loop.acc, %array.i
634  %continue = icmp slt i32 %i, %n
635  br i1 %continue, label %loop, label %exit, !prof !2
636
637exit:                                             ; preds = %guarded, %entry
638  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %guarded ]
639  ret i32 %result
640}
641
642define i32 @signed_loop_0_to_n_sle_latch_offset_ult_check(ptr %array, i32 %length, i32 %n) {
643; CHECK-LABEL: @signed_loop_0_to_n_sle_latch_offset_ult_check(
644; CHECK-NEXT:  entry:
645; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
646; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
647; CHECK:       loop.preheader:
648; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], -1
649; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[N]], [[TMP0]]
650; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 1, [[LENGTH]]
651; CHECK-NEXT:    [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]]
652; CHECK-NEXT:    [[TMP4:%.*]] = freeze i1 [[TMP3]]
653; CHECK-NEXT:    br label [[LOOP:%.*]]
654; CHECK:       loop:
655; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
656; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
657; CHECK-NEXT:    [[I_OFFSET:%.*]] = add i32 [[I]], 1
658; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_OFFSET]], [[LENGTH]]
659; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
660; CHECK-NEXT:    [[TMP5:%.*]] = and i1 [[TMP4]], [[WIDENABLE_COND]]
661; CHECK-NEXT:    br i1 [[TMP5]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
662; CHECK:       deopt:
663; CHECK-NEXT:    [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
664; CHECK-NEXT:    ret i32 [[DEOPTCALL]]
665; CHECK:       guarded:
666; CHECK-NEXT:    call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
667; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
668; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
669; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
670; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
671; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
672; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp sle i32 [[I_NEXT]], [[N]]
673; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]], !prof [[PROF1]]
674; CHECK:       exit.loopexit:
675; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
676; CHECK-NEXT:    br label [[EXIT]]
677; CHECK:       exit:
678; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
679; CHECK-NEXT:    ret i32 [[RESULT]]
680;
681entry:
682  %tmp5 = icmp sle i32 %n, 0
683  br i1 %tmp5, label %exit, label %loop.preheader
684
685loop.preheader:                                   ; preds = %entry
686  br label %loop
687
688loop:                                             ; preds = %guarded, %loop.preheader
689  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
690  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
691  %i.offset = add i32 %i, 1
692  %within.bounds = icmp ult i32 %i.offset, %length
693  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
694  %exiplicit_guard_cond = and i1 %within.bounds, %widenable_cond
695  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
696
697deopt:                                            ; preds = %loop
698  %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
699  ret i32 %deoptcall
700
701guarded:                                          ; preds = %loop
702  %i.i64 = zext i32 %i to i64
703  %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
704  %array.i = load i32, ptr %array.i.ptr, align 4
705  %loop.acc.next = add i32 %loop.acc, %array.i
706  %i.next = add i32 %i, 1
707  %continue = icmp sle i32 %i.next, %n
708  br i1 %continue, label %loop, label %exit, !prof !2
709
710exit:                                             ; preds = %guarded, %entry
711  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %guarded ]
712  ret i32 %result
713}
714
715define i32 @signed_loop_0_to_n_offset_sle_latch_offset_ult_check(ptr %array, i32 %length, i32 %n) {
716; CHECK-LABEL: @signed_loop_0_to_n_offset_sle_latch_offset_ult_check(
717; CHECK-NEXT:  entry:
718; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
719; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
720; CHECK:       loop.preheader:
721; CHECK-NEXT:    [[TMP0:%.*]] = icmp slt i32 [[N]], [[LENGTH:%.*]]
722; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 1, [[LENGTH]]
723; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
724; CHECK-NEXT:    [[TMP3:%.*]] = freeze i1 [[TMP2]]
725; CHECK-NEXT:    br label [[LOOP:%.*]]
726; CHECK:       loop:
727; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
728; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
729; CHECK-NEXT:    [[I_OFFSET:%.*]] = add i32 [[I]], 1
730; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I_OFFSET]], [[LENGTH]]
731; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
732; CHECK-NEXT:    [[TMP4:%.*]] = and i1 [[TMP3]], [[WIDENABLE_COND]]
733; CHECK-NEXT:    br i1 [[TMP4]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
734; CHECK:       deopt:
735; CHECK-NEXT:    [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
736; CHECK-NEXT:    ret i32 [[DEOPTCALL]]
737; CHECK:       guarded:
738; CHECK-NEXT:    call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
739; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
740; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
741; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
742; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
743; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
744; CHECK-NEXT:    [[I_NEXT_OFFSET:%.*]] = add i32 [[I_NEXT]], 1
745; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp sle i32 [[I_NEXT_OFFSET]], [[N]]
746; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]], !prof [[PROF1]]
747; CHECK:       exit.loopexit:
748; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
749; CHECK-NEXT:    br label [[EXIT]]
750; CHECK:       exit:
751; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
752; CHECK-NEXT:    ret i32 [[RESULT]]
753;
754entry:
755  %tmp5 = icmp sle i32 %n, 0
756  br i1 %tmp5, label %exit, label %loop.preheader
757
758loop.preheader:                                   ; preds = %entry
759  br label %loop
760
761loop:                                             ; preds = %guarded, %loop.preheader
762  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
763  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
764  %i.offset = add i32 %i, 1
765  %within.bounds = icmp ult i32 %i.offset, %length
766  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
767  %exiplicit_guard_cond = and i1 %within.bounds, %widenable_cond
768  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
769
770deopt:                                            ; preds = %loop
771  %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
772  ret i32 %deoptcall
773
774guarded:                                          ; preds = %loop
775  %i.i64 = zext i32 %i to i64
776  %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
777  %array.i = load i32, ptr %array.i.ptr, align 4
778  %loop.acc.next = add i32 %loop.acc, %array.i
779  %i.next = add i32 %i, 1
780  %i.next.offset = add i32 %i.next, 1
781  %continue = icmp sle i32 %i.next.offset, %n
782  br i1 %continue, label %loop, label %exit, !prof !2
783
784exit:                                             ; preds = %guarded, %entry
785  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %guarded ]
786  ret i32 %result
787}
788
789define i32 @unsupported_latch_pred_loop_0_to_n(ptr %array, i32 %length, i32 %n) {
790; CHECK-LABEL: @unsupported_latch_pred_loop_0_to_n(
791; CHECK-NEXT:  entry:
792; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
793; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
794; CHECK:       loop.preheader:
795; CHECK-NEXT:    br label [[LOOP:%.*]]
796; CHECK:       loop:
797; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
798; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
799; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]]
800; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
801; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WITHIN_BOUNDS]], [[WIDENABLE_COND]]
802; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
803; CHECK:       deopt:
804; CHECK-NEXT:    [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
805; CHECK-NEXT:    ret i32 [[DEOPTCALL]]
806; CHECK:       guarded:
807; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
808; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
809; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
810; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
811; CHECK-NEXT:    [[I_NEXT]] = add nsw i32 [[I]], 1
812; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ne i32 [[I_NEXT]], [[N]]
813; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]], !prof [[PROF1]]
814; CHECK:       exit.loopexit:
815; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
816; CHECK-NEXT:    br label [[EXIT]]
817; CHECK:       exit:
818; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
819; CHECK-NEXT:    ret i32 [[RESULT]]
820;
821entry:
822  %tmp5 = icmp sle i32 %n, 0
823  br i1 %tmp5, label %exit, label %loop.preheader
824
825loop.preheader:                                   ; preds = %entry
826  br label %loop
827
828loop:                                             ; preds = %guarded, %loop.preheader
829  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
830  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
831  %within.bounds = icmp ult i32 %i, %length
832  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
833  %exiplicit_guard_cond = and i1 %within.bounds, %widenable_cond
834  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
835
836deopt:                                            ; preds = %loop
837  %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
838  ret i32 %deoptcall
839
840guarded:                                          ; preds = %loop
841  %i.i64 = zext i32 %i to i64
842  %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
843  %array.i = load i32, ptr %array.i.ptr, align 4
844  %loop.acc.next = add i32 %loop.acc, %array.i
845  %i.next = add nsw i32 %i, 1
846  %continue = icmp ne i32 %i.next, %n
847  br i1 %continue, label %loop, label %exit, !prof !2
848
849exit:                                             ; preds = %guarded, %entry
850  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %guarded ]
851  ret i32 %result
852}
853
854define i32 @signed_loop_0_to_n_unsupported_iv_step(ptr %array, i32 %length, i32 %n) {
855; CHECK-LABEL: @signed_loop_0_to_n_unsupported_iv_step(
856; CHECK-NEXT:  entry:
857; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
858; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
859; CHECK:       loop.preheader:
860; CHECK-NEXT:    br label [[LOOP:%.*]]
861; CHECK:       loop:
862; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
863; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
864; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]]
865; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
866; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WITHIN_BOUNDS]], [[WIDENABLE_COND]]
867; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
868; CHECK:       deopt:
869; CHECK-NEXT:    [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
870; CHECK-NEXT:    ret i32 [[DEOPTCALL]]
871; CHECK:       guarded:
872; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
873; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
874; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
875; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
876; CHECK-NEXT:    [[I_NEXT]] = add nsw i32 [[I]], 2
877; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
878; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]], !prof [[PROF1]]
879; CHECK:       exit.loopexit:
880; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
881; CHECK-NEXT:    br label [[EXIT]]
882; CHECK:       exit:
883; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
884; CHECK-NEXT:    ret i32 [[RESULT]]
885;
886entry:
887  %tmp5 = icmp sle i32 %n, 0
888  br i1 %tmp5, label %exit, label %loop.preheader
889
890loop.preheader:                                   ; preds = %entry
891  br label %loop
892
893loop:                                             ; preds = %guarded, %loop.preheader
894  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
895  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
896  %within.bounds = icmp ult i32 %i, %length
897  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
898  %exiplicit_guard_cond = and i1 %within.bounds, %widenable_cond
899  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
900
901deopt:                                            ; preds = %loop
902  %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
903  ret i32 %deoptcall
904
905guarded:                                          ; preds = %loop
906  %i.i64 = zext i32 %i to i64
907  %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
908  %array.i = load i32, ptr %array.i.ptr, align 4
909  %loop.acc.next = add i32 %loop.acc, %array.i
910  %i.next = add nsw i32 %i, 2
911  %continue = icmp slt i32 %i.next, %n
912  br i1 %continue, label %loop, label %exit, !prof !2
913
914exit:                                             ; preds = %guarded, %entry
915  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %guarded ]
916  ret i32 %result
917}
918
919define i32 @signed_loop_0_to_n_equal_iv_range_check(ptr %array, i32 %length, i32 %n) {
920; CHECK-LABEL: @signed_loop_0_to_n_equal_iv_range_check(
921; CHECK-NEXT:  entry:
922; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
923; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
924; CHECK:       loop.preheader:
925; CHECK-NEXT:    [[TMP0:%.*]] = icmp sle i32 [[N]], [[LENGTH:%.*]]
926; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
927; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
928; CHECK-NEXT:    [[TMP3:%.*]] = freeze i1 [[TMP2]]
929; CHECK-NEXT:    br label [[LOOP:%.*]]
930; CHECK:       loop:
931; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
932; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
933; CHECK-NEXT:    [[J:%.*]] = phi i32 [ [[J_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
934; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[J]], [[LENGTH]]
935; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
936; CHECK-NEXT:    [[TMP4:%.*]] = and i1 [[TMP3]], [[WIDENABLE_COND]]
937; CHECK-NEXT:    br i1 [[TMP4]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
938; CHECK:       deopt:
939; CHECK-NEXT:    [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
940; CHECK-NEXT:    ret i32 [[DEOPTCALL]]
941; CHECK:       guarded:
942; CHECK-NEXT:    call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
943; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
944; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
945; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
946; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
947; CHECK-NEXT:    [[J_NEXT]] = add nsw i32 [[J]], 1
948; CHECK-NEXT:    [[I_NEXT]] = add nsw i32 [[I]], 1
949; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
950; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]], !prof [[PROF1]]
951; CHECK:       exit.loopexit:
952; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
953; CHECK-NEXT:    br label [[EXIT]]
954; CHECK:       exit:
955; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
956; CHECK-NEXT:    ret i32 [[RESULT]]
957;
958entry:
959  %tmp5 = icmp sle i32 %n, 0
960  br i1 %tmp5, label %exit, label %loop.preheader
961
962loop.preheader:                                   ; preds = %entry
963  br label %loop
964
965loop:                                             ; preds = %guarded, %loop.preheader
966  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
967  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
968  %j = phi i32 [ %j.next, %guarded ], [ 0, %loop.preheader ]
969  %within.bounds = icmp ult i32 %j, %length
970  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
971  %exiplicit_guard_cond = and i1 %within.bounds, %widenable_cond
972  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
973
974deopt:                                            ; preds = %loop
975  %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
976  ret i32 %deoptcall
977
978guarded:                                          ; preds = %loop
979  %i.i64 = zext i32 %i to i64
980  %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
981  %array.i = load i32, ptr %array.i.ptr, align 4
982  %loop.acc.next = add i32 %loop.acc, %array.i
983  %j.next = add nsw i32 %j, 1
984  %i.next = add nsw i32 %i, 1
985  %continue = icmp slt i32 %i.next, %n
986  br i1 %continue, label %loop, label %exit, !prof !2
987
988exit:                                             ; preds = %guarded, %entry
989  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %guarded ]
990  ret i32 %result
991}
992
993define i32 @signed_loop_start_to_n_offset_iv_range_check(ptr %array, i32 %start.i, i32 %start.j, i32 %length, i32 %n) {
994; CHECK-LABEL: @signed_loop_start_to_n_offset_iv_range_check(
995; CHECK-NEXT:  entry:
996; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
997; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
998; CHECK:       loop.preheader:
999; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[LENGTH:%.*]], [[START_I:%.*]]
1000; CHECK-NEXT:    [[TMP1:%.*]] = sub i32 [[TMP0]], [[START_J:%.*]]
1001; CHECK-NEXT:    [[TMP2:%.*]] = icmp sle i32 [[N]], [[TMP1]]
1002; CHECK-NEXT:    [[TMP3:%.*]] = icmp ult i32 [[START_J]], [[LENGTH]]
1003; CHECK-NEXT:    [[TMP4:%.*]] = and i1 [[TMP3]], [[TMP2]]
1004; CHECK-NEXT:    [[TMP5:%.*]] = freeze i1 [[TMP4]]
1005; CHECK-NEXT:    br label [[LOOP:%.*]]
1006; CHECK:       loop:
1007; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
1008; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ [[START_I]], [[LOOP_PREHEADER]] ]
1009; CHECK-NEXT:    [[J:%.*]] = phi i32 [ [[J_NEXT:%.*]], [[GUARDED]] ], [ [[START_J]], [[LOOP_PREHEADER]] ]
1010; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[J]], [[LENGTH]]
1011; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
1012; CHECK-NEXT:    [[TMP6:%.*]] = and i1 [[TMP5]], [[WIDENABLE_COND]]
1013; CHECK-NEXT:    br i1 [[TMP6]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
1014; CHECK:       deopt:
1015; CHECK-NEXT:    [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
1016; CHECK-NEXT:    ret i32 [[DEOPTCALL]]
1017; CHECK:       guarded:
1018; CHECK-NEXT:    call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
1019; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
1020; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
1021; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
1022; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
1023; CHECK-NEXT:    [[J_NEXT]] = add i32 [[J]], 1
1024; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
1025; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
1026; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]], !prof [[PROF1]]
1027; CHECK:       exit.loopexit:
1028; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
1029; CHECK-NEXT:    br label [[EXIT]]
1030; CHECK:       exit:
1031; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1032; CHECK-NEXT:    ret i32 [[RESULT]]
1033;
1034entry:
1035  %tmp5 = icmp sle i32 %n, 0
1036  br i1 %tmp5, label %exit, label %loop.preheader
1037
1038loop.preheader:                                   ; preds = %entry
1039  br label %loop
1040
1041loop:                                             ; preds = %guarded, %loop.preheader
1042  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
1043  %i = phi i32 [ %i.next, %guarded ], [ %start.i, %loop.preheader ]
1044  %j = phi i32 [ %j.next, %guarded ], [ %start.j, %loop.preheader ]
1045  %within.bounds = icmp ult i32 %j, %length
1046  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
1047  %exiplicit_guard_cond = and i1 %within.bounds, %widenable_cond
1048  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
1049
1050deopt:                                            ; preds = %loop
1051  %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
1052  ret i32 %deoptcall
1053
1054guarded:                                          ; preds = %loop
1055  %i.i64 = zext i32 %i to i64
1056  %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
1057  %array.i = load i32, ptr %array.i.ptr, align 4
1058  %loop.acc.next = add i32 %loop.acc, %array.i
1059  %j.next = add i32 %j, 1
1060  %i.next = add i32 %i, 1
1061  %continue = icmp slt i32 %i.next, %n
1062  br i1 %continue, label %loop, label %exit, !prof !2
1063
1064exit:                                             ; preds = %guarded, %entry
1065  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %guarded ]
1066  ret i32 %result
1067}
1068
1069define i32 @signed_loop_0_to_n_different_iv_types(ptr %array, i16 %length, i32 %n) {
1070; CHECK-LABEL: @signed_loop_0_to_n_different_iv_types(
1071; CHECK-NEXT:  entry:
1072; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
1073; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1074; CHECK:       loop.preheader:
1075; CHECK-NEXT:    br label [[LOOP:%.*]]
1076; CHECK:       loop:
1077; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
1078; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
1079; CHECK-NEXT:    [[J:%.*]] = phi i16 [ [[J_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
1080; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i16 [[J]], [[LENGTH:%.*]]
1081; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
1082; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WITHIN_BOUNDS]], [[WIDENABLE_COND]]
1083; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
1084; CHECK:       deopt:
1085; CHECK-NEXT:    [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
1086; CHECK-NEXT:    ret i32 [[DEOPTCALL]]
1087; CHECK:       guarded:
1088; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
1089; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
1090; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
1091; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
1092; CHECK-NEXT:    [[J_NEXT]] = add i16 [[J]], 1
1093; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
1094; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
1095; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]], !prof [[PROF1]]
1096; CHECK:       exit.loopexit:
1097; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
1098; CHECK-NEXT:    br label [[EXIT]]
1099; CHECK:       exit:
1100; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1101; CHECK-NEXT:    ret i32 [[RESULT]]
1102;
1103entry:
1104  %tmp5 = icmp sle i32 %n, 0
1105  br i1 %tmp5, label %exit, label %loop.preheader
1106
1107loop.preheader:                                   ; preds = %entry
1108  br label %loop
1109
1110loop:                                             ; preds = %guarded, %loop.preheader
1111  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
1112  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
1113  %j = phi i16 [ %j.next, %guarded ], [ 0, %loop.preheader ]
1114  %within.bounds = icmp ult i16 %j, %length
1115  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
1116  %exiplicit_guard_cond = and i1 %within.bounds, %widenable_cond
1117  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
1118
1119deopt:                                            ; preds = %loop
1120  %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
1121  ret i32 %deoptcall
1122
1123guarded:                                          ; preds = %loop
1124  %i.i64 = zext i32 %i to i64
1125  %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
1126  %array.i = load i32, ptr %array.i.ptr, align 4
1127  %loop.acc.next = add i32 %loop.acc, %array.i
1128  %j.next = add i16 %j, 1
1129  %i.next = add i32 %i, 1
1130  %continue = icmp slt i32 %i.next, %n
1131  br i1 %continue, label %loop, label %exit, !prof !2
1132
1133exit:                                             ; preds = %guarded, %entry
1134  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %guarded ]
1135  ret i32 %result
1136}
1137
1138define i32 @signed_loop_0_to_n_different_iv_strides(ptr %array, i32 %length, i32 %n) {
1139; CHECK-LABEL: @signed_loop_0_to_n_different_iv_strides(
1140; CHECK-NEXT:  entry:
1141; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
1142; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1143; CHECK:       loop.preheader:
1144; CHECK-NEXT:    br label [[LOOP:%.*]]
1145; CHECK:       loop:
1146; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
1147; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
1148; CHECK-NEXT:    [[J:%.*]] = phi i32 [ [[J_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
1149; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[J]], [[LENGTH:%.*]]
1150; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
1151; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WITHIN_BOUNDS]], [[WIDENABLE_COND]]
1152; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
1153; CHECK:       deopt:
1154; CHECK-NEXT:    [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
1155; CHECK-NEXT:    ret i32 [[DEOPTCALL]]
1156; CHECK:       guarded:
1157; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
1158; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
1159; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
1160; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
1161; CHECK-NEXT:    [[J_NEXT]] = add nsw i32 [[J]], 2
1162; CHECK-NEXT:    [[I_NEXT]] = add nsw i32 [[I]], 1
1163; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
1164; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]], !prof [[PROF1]]
1165; CHECK:       exit.loopexit:
1166; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
1167; CHECK-NEXT:    br label [[EXIT]]
1168; CHECK:       exit:
1169; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1170; CHECK-NEXT:    ret i32 [[RESULT]]
1171;
1172entry:
1173  %tmp5 = icmp sle i32 %n, 0
1174  br i1 %tmp5, label %exit, label %loop.preheader
1175
1176loop.preheader:                                   ; preds = %entry
1177  br label %loop
1178
1179loop:                                             ; preds = %guarded, %loop.preheader
1180  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
1181  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
1182  %j = phi i32 [ %j.next, %guarded ], [ 0, %loop.preheader ]
1183  %within.bounds = icmp ult i32 %j, %length
1184  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
1185  %exiplicit_guard_cond = and i1 %within.bounds, %widenable_cond
1186  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
1187
1188deopt:                                            ; preds = %loop
1189  %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
1190  ret i32 %deoptcall
1191
1192guarded:                                          ; preds = %loop
1193  %i.i64 = zext i32 %i to i64
1194  %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
1195  %array.i = load i32, ptr %array.i.ptr, align 4
1196  %loop.acc.next = add i32 %loop.acc, %array.i
1197  %j.next = add nsw i32 %j, 2
1198  %i.next = add nsw i32 %i, 1
1199  %continue = icmp slt i32 %i.next, %n
1200  br i1 %continue, label %loop, label %exit, !prof !2
1201
1202exit:                                             ; preds = %guarded, %entry
1203  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %guarded ]
1204  ret i32 %result
1205}
1206
1207define i32 @two_range_checks(ptr %array.1, i32 %length.1, ptr %array.2, i32 %length.2, i32 %n) {
1208; CHECK-LABEL: @two_range_checks(
1209; CHECK-NEXT:  entry:
1210; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
1211; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1212; CHECK:       loop.preheader:
1213; CHECK-NEXT:    [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH_2:%.*]]
1214; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH_2]]
1215; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
1216; CHECK-NEXT:    [[TMP3:%.*]] = freeze i1 [[TMP2]]
1217; CHECK-NEXT:    [[TMP4:%.*]] = icmp ule i32 [[N]], [[LENGTH_1:%.*]]
1218; CHECK-NEXT:    [[TMP5:%.*]] = icmp ult i32 0, [[LENGTH_1]]
1219; CHECK-NEXT:    [[TMP6:%.*]] = and i1 [[TMP5]], [[TMP4]]
1220; CHECK-NEXT:    [[TMP7:%.*]] = freeze i1 [[TMP6]]
1221; CHECK-NEXT:    br label [[LOOP:%.*]]
1222; CHECK:       loop:
1223; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
1224; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
1225; CHECK-NEXT:    [[WITHIN_BOUNDS_1:%.*]] = icmp ult i32 [[I]], [[LENGTH_1]]
1226; CHECK-NEXT:    [[WITHIN_BOUNDS_2:%.*]] = icmp ult i32 [[I]], [[LENGTH_2]]
1227; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
1228; CHECK-NEXT:    [[TMP8:%.*]] = and i1 [[TMP3]], [[TMP7]]
1229; CHECK-NEXT:    [[TMP9:%.*]] = and i1 [[TMP8]], [[WIDENABLE_COND]]
1230; CHECK-NEXT:    br i1 [[TMP9]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
1231; CHECK:       deopt:
1232; CHECK-NEXT:    [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
1233; CHECK-NEXT:    ret i32 [[DEOPTCALL]]
1234; CHECK:       guarded:
1235; CHECK-NEXT:    [[TMP10:%.*]] = and i1 [[WITHIN_BOUNDS_2]], [[WITHIN_BOUNDS_1]]
1236; CHECK-NEXT:    call void @llvm.assume(i1 [[TMP10]])
1237; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
1238; CHECK-NEXT:    [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY_1:%.*]], i64 [[I_I64]]
1239; CHECK-NEXT:    [[ARRAY_1_I:%.*]] = load i32, ptr [[ARRAY_1_I_PTR]], align 4
1240; CHECK-NEXT:    [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]]
1241; CHECK-NEXT:    [[ARRAY_2_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY_2:%.*]], i64 [[I_I64]]
1242; CHECK-NEXT:    [[ARRAY_2_I:%.*]] = load i32, ptr [[ARRAY_2_I_PTR]], align 4
1243; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_1]], [[ARRAY_2_I]]
1244; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
1245; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
1246; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]], !prof [[PROF1]]
1247; CHECK:       exit.loopexit:
1248; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
1249; CHECK-NEXT:    br label [[EXIT]]
1250; CHECK:       exit:
1251; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1252; CHECK-NEXT:    ret i32 [[RESULT]]
1253;
1254entry:
1255  %tmp5 = icmp eq i32 %n, 0
1256  br i1 %tmp5, label %exit, label %loop.preheader
1257
1258loop.preheader:                                   ; preds = %entry
1259  br label %loop
1260
1261loop:                                             ; preds = %guarded, %loop.preheader
1262  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
1263  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
1264  %within.bounds.1 = icmp ult i32 %i, %length.1
1265  %within.bounds.2 = icmp ult i32 %i, %length.2
1266  %within.bounds = and i1 %within.bounds.1, %within.bounds.2
1267  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
1268  %exiplicit_guard_cond = and i1 %within.bounds, %widenable_cond
1269  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
1270
1271deopt:                                            ; preds = %loop
1272  %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
1273  ret i32 %deoptcall
1274
1275guarded:                                          ; preds = %loop
1276  %i.i64 = zext i32 %i to i64
1277  %array.1.i.ptr = getelementptr inbounds i32, ptr %array.1, i64 %i.i64
1278  %array.1.i = load i32, ptr %array.1.i.ptr, align 4
1279  %loop.acc.1 = add i32 %loop.acc, %array.1.i
1280  %array.2.i.ptr = getelementptr inbounds i32, ptr %array.2, i64 %i.i64
1281  %array.2.i = load i32, ptr %array.2.i.ptr, align 4
1282  %loop.acc.next = add i32 %loop.acc.1, %array.2.i
1283  %i.next = add nuw i32 %i, 1
1284  %continue = icmp ult i32 %i.next, %n
1285  br i1 %continue, label %loop, label %exit, !prof !2
1286
1287exit:                                             ; preds = %guarded, %entry
1288  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %guarded ]
1289  ret i32 %result
1290}
1291
1292define i32 @three_range_checks(ptr %array.1, i32 %length.1, ptr %array.2, i32 %length.2, ptr %array.3, i32 %length.3, i32 %n) {
1293; CHECK-LABEL: @three_range_checks(
1294; CHECK-NEXT:  entry:
1295; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
1296; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1297; CHECK:       loop.preheader:
1298; CHECK-NEXT:    [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH_3:%.*]]
1299; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH_3]]
1300; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
1301; CHECK-NEXT:    [[TMP3:%.*]] = freeze i1 [[TMP2]]
1302; CHECK-NEXT:    [[TMP4:%.*]] = icmp ule i32 [[N]], [[LENGTH_2:%.*]]
1303; CHECK-NEXT:    [[TMP5:%.*]] = icmp ult i32 0, [[LENGTH_2]]
1304; CHECK-NEXT:    [[TMP6:%.*]] = and i1 [[TMP5]], [[TMP4]]
1305; CHECK-NEXT:    [[TMP7:%.*]] = freeze i1 [[TMP6]]
1306; CHECK-NEXT:    [[TMP8:%.*]] = icmp ule i32 [[N]], [[LENGTH_1:%.*]]
1307; CHECK-NEXT:    [[TMP9:%.*]] = icmp ult i32 0, [[LENGTH_1]]
1308; CHECK-NEXT:    [[TMP10:%.*]] = and i1 [[TMP9]], [[TMP8]]
1309; CHECK-NEXT:    [[TMP11:%.*]] = freeze i1 [[TMP10]]
1310; CHECK-NEXT:    br label [[LOOP:%.*]]
1311; CHECK:       loop:
1312; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
1313; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
1314; CHECK-NEXT:    [[WITHIN_BOUNDS_1:%.*]] = icmp ult i32 [[I]], [[LENGTH_1]]
1315; CHECK-NEXT:    [[WITHIN_BOUNDS_2:%.*]] = icmp ult i32 [[I]], [[LENGTH_2]]
1316; CHECK-NEXT:    [[WITHIN_BOUNDS_3:%.*]] = icmp ult i32 [[I]], [[LENGTH_3]]
1317; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
1318; CHECK-NEXT:    [[TMP12:%.*]] = and i1 [[TMP3]], [[TMP7]]
1319; CHECK-NEXT:    [[TMP13:%.*]] = and i1 [[TMP12]], [[TMP11]]
1320; CHECK-NEXT:    [[TMP14:%.*]] = and i1 [[TMP13]], [[WIDENABLE_COND]]
1321; CHECK-NEXT:    br i1 [[TMP14]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
1322; CHECK:       deopt:
1323; CHECK-NEXT:    [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
1324; CHECK-NEXT:    ret i32 [[DEOPTCALL]]
1325; CHECK:       guarded:
1326; CHECK-NEXT:    [[TMP15:%.*]] = and i1 [[WITHIN_BOUNDS_3]], [[WITHIN_BOUNDS_2]]
1327; CHECK-NEXT:    [[TMP16:%.*]] = and i1 [[TMP15]], [[WITHIN_BOUNDS_1]]
1328; CHECK-NEXT:    call void @llvm.assume(i1 [[TMP16]])
1329; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
1330; CHECK-NEXT:    [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY_1:%.*]], i64 [[I_I64]]
1331; CHECK-NEXT:    [[ARRAY_1_I:%.*]] = load i32, ptr [[ARRAY_1_I_PTR]], align 4
1332; CHECK-NEXT:    [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]]
1333; CHECK-NEXT:    [[ARRAY_2_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY_2:%.*]], i64 [[I_I64]]
1334; CHECK-NEXT:    [[ARRAY_2_I:%.*]] = load i32, ptr [[ARRAY_2_I_PTR]], align 4
1335; CHECK-NEXT:    [[LOOP_ACC_2:%.*]] = add i32 [[LOOP_ACC_1]], [[ARRAY_2_I]]
1336; CHECK-NEXT:    [[ARRAY_3_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY_3:%.*]], i64 [[I_I64]]
1337; CHECK-NEXT:    [[ARRAY_3_I:%.*]] = load i32, ptr [[ARRAY_3_I_PTR]], align 4
1338; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_2]], [[ARRAY_3_I]]
1339; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
1340; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
1341; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]], !prof [[PROF1]]
1342; CHECK:       exit.loopexit:
1343; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
1344; CHECK-NEXT:    br label [[EXIT]]
1345; CHECK:       exit:
1346; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1347; CHECK-NEXT:    ret i32 [[RESULT]]
1348;
1349entry:
1350  %tmp5 = icmp eq i32 %n, 0
1351  br i1 %tmp5, label %exit, label %loop.preheader
1352
1353loop.preheader:                                   ; preds = %entry
1354  br label %loop
1355
1356loop:                                             ; preds = %guarded, %loop.preheader
1357  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
1358  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
1359  %within.bounds.1 = icmp ult i32 %i, %length.1
1360  %within.bounds.2 = icmp ult i32 %i, %length.2
1361  %within.bounds.3 = icmp ult i32 %i, %length.3
1362  %within.bounds.1.and.2 = and i1 %within.bounds.1, %within.bounds.2
1363  %within.bounds = and i1 %within.bounds.1.and.2, %within.bounds.3
1364  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
1365  %exiplicit_guard_cond = and i1 %within.bounds, %widenable_cond
1366  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
1367
1368deopt:                                            ; preds = %loop
1369  %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
1370  ret i32 %deoptcall
1371
1372guarded:                                          ; preds = %loop
1373  %i.i64 = zext i32 %i to i64
1374  %array.1.i.ptr = getelementptr inbounds i32, ptr %array.1, i64 %i.i64
1375  %array.1.i = load i32, ptr %array.1.i.ptr, align 4
1376  %loop.acc.1 = add i32 %loop.acc, %array.1.i
1377  %array.2.i.ptr = getelementptr inbounds i32, ptr %array.2, i64 %i.i64
1378  %array.2.i = load i32, ptr %array.2.i.ptr, align 4
1379  %loop.acc.2 = add i32 %loop.acc.1, %array.2.i
1380  %array.3.i.ptr = getelementptr inbounds i32, ptr %array.3, i64 %i.i64
1381  %array.3.i = load i32, ptr %array.3.i.ptr, align 4
1382  %loop.acc.next = add i32 %loop.acc.2, %array.3.i
1383  %i.next = add nuw i32 %i, 1
1384  %continue = icmp ult i32 %i.next, %n
1385  br i1 %continue, label %loop, label %exit, !prof !2
1386
1387exit:                                             ; preds = %guarded, %entry
1388  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %guarded ]
1389  ret i32 %result
1390}
1391
1392define i32 @three_guards(ptr %array.1, i32 %length.1, ptr %array.2, i32 %length.2, ptr %array.3, i32 %length.3, i32 %n) {
1393; CHECK-LABEL: @three_guards(
1394; CHECK-NEXT:  entry:
1395; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
1396; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1397; CHECK:       loop.preheader:
1398; CHECK-NEXT:    [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH_1:%.*]]
1399; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH_1]]
1400; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
1401; CHECK-NEXT:    [[TMP3:%.*]] = freeze i1 [[TMP2]]
1402; CHECK-NEXT:    [[TMP4:%.*]] = icmp ule i32 [[N]], [[LENGTH_2:%.*]]
1403; CHECK-NEXT:    [[TMP5:%.*]] = icmp ult i32 0, [[LENGTH_2]]
1404; CHECK-NEXT:    [[TMP6:%.*]] = and i1 [[TMP5]], [[TMP4]]
1405; CHECK-NEXT:    [[TMP7:%.*]] = freeze i1 [[TMP6]]
1406; CHECK-NEXT:    [[TMP8:%.*]] = icmp ule i32 [[N]], [[LENGTH_3:%.*]]
1407; CHECK-NEXT:    [[TMP9:%.*]] = icmp ult i32 0, [[LENGTH_3]]
1408; CHECK-NEXT:    [[TMP10:%.*]] = and i1 [[TMP9]], [[TMP8]]
1409; CHECK-NEXT:    [[TMP11:%.*]] = freeze i1 [[TMP10]]
1410; CHECK-NEXT:    br label [[LOOP:%.*]]
1411; CHECK:       loop:
1412; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED6:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
1413; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED6]] ], [ 0, [[LOOP_PREHEADER]] ]
1414; CHECK-NEXT:    [[WITHIN_BOUNDS_1:%.*]] = icmp ult i32 [[I]], [[LENGTH_1]]
1415; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
1416; CHECK-NEXT:    [[TMP12:%.*]] = and i1 [[TMP3]], [[WIDENABLE_COND]]
1417; CHECK-NEXT:    br i1 [[TMP12]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
1418; CHECK:       deopt:
1419; CHECK-NEXT:    [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
1420; CHECK-NEXT:    ret i32 [[DEOPTCALL]]
1421; CHECK:       guarded:
1422; CHECK-NEXT:    call void @llvm.assume(i1 [[WITHIN_BOUNDS_1]])
1423; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
1424; CHECK-NEXT:    [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY_1:%.*]], i64 [[I_I64]]
1425; CHECK-NEXT:    [[ARRAY_1_I:%.*]] = load i32, ptr [[ARRAY_1_I_PTR]], align 4
1426; CHECK-NEXT:    [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]]
1427; CHECK-NEXT:    [[WITHIN_BOUNDS_2:%.*]] = icmp ult i32 [[I]], [[LENGTH_2]]
1428; CHECK-NEXT:    [[WIDENABLE_COND4:%.*]] = call i1 @llvm.experimental.widenable.condition()
1429; CHECK-NEXT:    [[TMP13:%.*]] = and i1 [[TMP7]], [[WIDENABLE_COND4]]
1430; CHECK-NEXT:    br i1 [[TMP13]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]]
1431; CHECK:       deopt2:
1432; CHECK-NEXT:    [[DEOPTCALL3:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
1433; CHECK-NEXT:    ret i32 [[DEOPTCALL3]]
1434; CHECK:       guarded1:
1435; CHECK-NEXT:    call void @llvm.assume(i1 [[WITHIN_BOUNDS_2]])
1436; CHECK-NEXT:    [[ARRAY_2_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY_2:%.*]], i64 [[I_I64]]
1437; CHECK-NEXT:    [[ARRAY_2_I:%.*]] = load i32, ptr [[ARRAY_2_I_PTR]], align 4
1438; CHECK-NEXT:    [[LOOP_ACC_2:%.*]] = add i32 [[LOOP_ACC_1]], [[ARRAY_2_I]]
1439; CHECK-NEXT:    [[WITHIN_BOUNDS_3:%.*]] = icmp ult i32 [[I]], [[LENGTH_3]]
1440; CHECK-NEXT:    [[WIDENABLE_COND9:%.*]] = call i1 @llvm.experimental.widenable.condition()
1441; CHECK-NEXT:    [[TMP14:%.*]] = and i1 [[TMP11]], [[WIDENABLE_COND9]]
1442; CHECK-NEXT:    br i1 [[TMP14]], label [[GUARDED6]], label [[DEOPT7:%.*]], !prof [[PROF0]]
1443; CHECK:       deopt7:
1444; CHECK-NEXT:    [[DEOPTCALL8:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
1445; CHECK-NEXT:    ret i32 [[DEOPTCALL8]]
1446; CHECK:       guarded6:
1447; CHECK-NEXT:    call void @llvm.assume(i1 [[WITHIN_BOUNDS_3]])
1448; CHECK-NEXT:    [[ARRAY_3_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY_3:%.*]], i64 [[I_I64]]
1449; CHECK-NEXT:    [[ARRAY_3_I:%.*]] = load i32, ptr [[ARRAY_3_I_PTR]], align 4
1450; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_2]], [[ARRAY_3_I]]
1451; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
1452; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
1453; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]], !prof [[PROF1]]
1454; CHECK:       exit.loopexit:
1455; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED6]] ]
1456; CHECK-NEXT:    br label [[EXIT]]
1457; CHECK:       exit:
1458; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1459; CHECK-NEXT:    ret i32 [[RESULT]]
1460;
1461entry:
1462  %tmp5 = icmp eq i32 %n, 0
1463  br i1 %tmp5, label %exit, label %loop.preheader
1464
1465loop.preheader:                                   ; preds = %entry
1466  br label %loop
1467
1468loop:                                             ; preds = %guarded6, %loop.preheader
1469  %loop.acc = phi i32 [ %loop.acc.next, %guarded6 ], [ 0, %loop.preheader ]
1470  %i = phi i32 [ %i.next, %guarded6 ], [ 0, %loop.preheader ]
1471  %within.bounds.1 = icmp ult i32 %i, %length.1
1472  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
1473  %exiplicit_guard_cond = and i1 %within.bounds.1, %widenable_cond
1474  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
1475
1476deopt:                                            ; preds = %loop
1477  %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
1478  ret i32 %deoptcall
1479
1480guarded:                                          ; preds = %loop
1481  %i.i64 = zext i32 %i to i64
1482  %array.1.i.ptr = getelementptr inbounds i32, ptr %array.1, i64 %i.i64
1483  %array.1.i = load i32, ptr %array.1.i.ptr, align 4
1484  %loop.acc.1 = add i32 %loop.acc, %array.1.i
1485  %within.bounds.2 = icmp ult i32 %i, %length.2
1486  %widenable_cond4 = call i1 @llvm.experimental.widenable.condition()
1487  %exiplicit_guard_cond5 = and i1 %within.bounds.2, %widenable_cond4
1488  br i1 %exiplicit_guard_cond5, label %guarded1, label %deopt2, !prof !0
1489
1490deopt2:                                           ; preds = %guarded
1491  %deoptcall3 = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
1492  ret i32 %deoptcall3
1493
1494guarded1:                                         ; preds = %guarded
1495  %array.2.i.ptr = getelementptr inbounds i32, ptr %array.2, i64 %i.i64
1496  %array.2.i = load i32, ptr %array.2.i.ptr, align 4
1497  %loop.acc.2 = add i32 %loop.acc.1, %array.2.i
1498  %within.bounds.3 = icmp ult i32 %i, %length.3
1499  %widenable_cond9 = call i1 @llvm.experimental.widenable.condition()
1500  %exiplicit_guard_cond10 = and i1 %within.bounds.3, %widenable_cond9
1501  br i1 %exiplicit_guard_cond10, label %guarded6, label %deopt7, !prof !0
1502
1503deopt7:                                           ; preds = %guarded1
1504  %deoptcall8 = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
1505  ret i32 %deoptcall8
1506
1507guarded6:                                         ; preds = %guarded1
1508  %array.3.i.ptr = getelementptr inbounds i32, ptr %array.3, i64 %i.i64
1509  %array.3.i = load i32, ptr %array.3.i.ptr, align 4
1510  %loop.acc.next = add i32 %loop.acc.2, %array.3.i
1511  %i.next = add nuw i32 %i, 1
1512  %continue = icmp ult i32 %i.next, %n
1513  br i1 %continue, label %loop, label %exit, !prof !2
1514
1515exit:                                             ; preds = %guarded6, %entry
1516  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %guarded6 ]
1517  ret i32 %result
1518}
1519
1520define i32 @unsigned_loop_0_to_n_unrelated_condition(ptr %array, i32 %length, i32 %n, i32 %x) {
1521; CHECK-LABEL: @unsigned_loop_0_to_n_unrelated_condition(
1522; CHECK-NEXT:  entry:
1523; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
1524; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1525; CHECK:       loop.preheader:
1526; CHECK-NEXT:    [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH:%.*]]
1527; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
1528; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
1529; CHECK-NEXT:    [[TMP3:%.*]] = freeze i1 [[TMP2]]
1530; CHECK-NEXT:    br label [[LOOP:%.*]]
1531; CHECK:       loop:
1532; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
1533; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
1534; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]]
1535; CHECK-NEXT:    [[UNRELATED_COND:%.*]] = icmp ult i32 [[X:%.*]], [[LENGTH]]
1536; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
1537; CHECK-NEXT:    [[TMP4:%.*]] = and i1 [[UNRELATED_COND]], [[TMP3]]
1538; CHECK-NEXT:    [[TMP5:%.*]] = and i1 [[TMP4]], [[WIDENABLE_COND]]
1539; CHECK-NEXT:    br i1 [[TMP5]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
1540; CHECK:       deopt:
1541; CHECK-NEXT:    [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
1542; CHECK-NEXT:    ret i32 [[DEOPTCALL]]
1543; CHECK:       guarded:
1544; CHECK-NEXT:    call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
1545; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
1546; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
1547; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
1548; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
1549; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
1550; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
1551; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]], !prof [[PROF1]]
1552; CHECK:       exit.loopexit:
1553; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
1554; CHECK-NEXT:    br label [[EXIT]]
1555; CHECK:       exit:
1556; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1557; CHECK-NEXT:    ret i32 [[RESULT]]
1558;
1559entry:
1560  %tmp5 = icmp eq i32 %n, 0
1561  br i1 %tmp5, label %exit, label %loop.preheader
1562
1563loop.preheader:                                   ; preds = %entry
1564  br label %loop
1565
1566loop:                                             ; preds = %guarded, %loop.preheader
1567  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
1568  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
1569  %within.bounds = icmp ult i32 %i, %length
1570  %unrelated.cond = icmp ult i32 %x, %length
1571  %guard.cond = and i1 %within.bounds, %unrelated.cond
1572  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
1573  %exiplicit_guard_cond = and i1 %guard.cond, %widenable_cond
1574  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
1575
1576deopt:                                            ; preds = %loop
1577  %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
1578  ret i32 %deoptcall
1579
1580guarded:                                          ; preds = %loop
1581  %i.i64 = zext i32 %i to i64
1582  %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
1583  %array.i = load i32, ptr %array.i.ptr, align 4
1584  %loop.acc.next = add i32 %loop.acc, %array.i
1585  %i.next = add nuw i32 %i, 1
1586  %continue = icmp ult i32 %i.next, %n
1587  br i1 %continue, label %loop, label %exit, !prof !2
1588
1589exit:                                             ; preds = %guarded, %entry
1590  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %guarded ]
1591  ret i32 %result
1592}
1593
1594define i32 @test_no_widened_conditions(ptr %array, i32 %length, i32 %n, i32 %x1, i32 %x2, i32 %x3) {
1595; CHECK-LABEL: @test_no_widened_conditions(
1596; CHECK-NEXT:  entry:
1597; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
1598; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1599; CHECK:       loop.preheader:
1600; CHECK-NEXT:    br label [[LOOP:%.*]]
1601; CHECK:       loop:
1602; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
1603; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
1604; CHECK-NEXT:    [[UNRELATED_COND_1:%.*]] = icmp eq i32 [[X1:%.*]], [[I]]
1605; CHECK-NEXT:    [[UNRELATED_COND_2:%.*]] = icmp eq i32 [[X2:%.*]], [[I]]
1606; CHECK-NEXT:    [[UNRELATED_COND_3:%.*]] = icmp eq i32 [[X3:%.*]], [[I]]
1607; CHECK-NEXT:    [[UNRELATED_COND_AND_1:%.*]] = and i1 [[UNRELATED_COND_1]], [[UNRELATED_COND_2]]
1608; CHECK-NEXT:    [[GUARD_COND:%.*]] = and i1 [[UNRELATED_COND_AND_1]], [[UNRELATED_COND_3]]
1609; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
1610; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[GUARD_COND]], [[WIDENABLE_COND]]
1611; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
1612; CHECK:       deopt:
1613; CHECK-NEXT:    [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
1614; CHECK-NEXT:    ret i32 [[DEOPTCALL]]
1615; CHECK:       guarded:
1616; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
1617; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
1618; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
1619; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
1620; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
1621; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
1622; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]], !prof [[PROF1]]
1623; CHECK:       exit.loopexit:
1624; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
1625; CHECK-NEXT:    br label [[EXIT]]
1626; CHECK:       exit:
1627; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1628; CHECK-NEXT:    ret i32 [[RESULT]]
1629;
1630entry:
1631  %tmp5 = icmp eq i32 %n, 0
1632  br i1 %tmp5, label %exit, label %loop.preheader
1633
1634loop.preheader:                                   ; preds = %entry
1635  br label %loop
1636
1637loop:                                             ; preds = %guarded, %loop.preheader
1638  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
1639  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
1640  %unrelated.cond.1 = icmp eq i32 %x1, %i
1641  %unrelated.cond.2 = icmp eq i32 %x2, %i
1642  %unrelated.cond.3 = icmp eq i32 %x3, %i
1643  %unrelated.cond.and.1 = and i1 %unrelated.cond.1, %unrelated.cond.2
1644  %guard.cond = and i1 %unrelated.cond.and.1, %unrelated.cond.3
1645  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
1646  %exiplicit_guard_cond = and i1 %guard.cond, %widenable_cond
1647  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
1648
1649deopt:                                            ; preds = %loop
1650  %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
1651  ret i32 %deoptcall
1652
1653guarded:                                          ; preds = %loop
1654  %i.i64 = zext i32 %i to i64
1655  %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
1656  %array.i = load i32, ptr %array.i.ptr, align 4
1657  %loop.acc.next = add i32 %loop.acc, %array.i
1658  %i.next = add nuw i32 %i, 1
1659  %continue = icmp ult i32 %i.next, %n
1660  br i1 %continue, label %loop, label %exit, !prof !2
1661
1662exit:                                             ; preds = %guarded, %entry
1663  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %guarded ]
1664  ret i32 %result
1665}
1666
1667define i32 @signed_loop_start_to_n_loop_variant_bound(ptr %array, i32 %x, i32 %start, i32 %n) {
1668; CHECK-LABEL: @signed_loop_start_to_n_loop_variant_bound(
1669; CHECK-NEXT:  entry:
1670; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
1671; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1672; CHECK:       loop.preheader:
1673; CHECK-NEXT:    br label [[LOOP:%.*]]
1674; CHECK:       loop:
1675; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
1676; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ [[START:%.*]], [[LOOP_PREHEADER]] ]
1677; CHECK-NEXT:    [[BOUND:%.*]] = add i32 [[I]], [[X:%.*]]
1678; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[BOUND]]
1679; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
1680; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WITHIN_BOUNDS]], [[WIDENABLE_COND]]
1681; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
1682; CHECK:       deopt:
1683; CHECK-NEXT:    [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
1684; CHECK-NEXT:    ret i32 [[DEOPTCALL]]
1685; CHECK:       guarded:
1686; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
1687; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
1688; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
1689; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
1690; CHECK-NEXT:    [[I_NEXT]] = add nsw i32 [[I]], 1
1691; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
1692; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]], !prof [[PROF1]]
1693; CHECK:       exit.loopexit:
1694; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
1695; CHECK-NEXT:    br label [[EXIT]]
1696; CHECK:       exit:
1697; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1698; CHECK-NEXT:    ret i32 [[RESULT]]
1699;
1700entry:
1701  %tmp5 = icmp sle i32 %n, 0
1702  br i1 %tmp5, label %exit, label %loop.preheader
1703
1704loop.preheader:                                   ; preds = %entry
1705  br label %loop
1706
1707loop:                                             ; preds = %guarded, %loop.preheader
1708  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
1709  %i = phi i32 [ %i.next, %guarded ], [ %start, %loop.preheader ]
1710  %bound = add i32 %i, %x
1711  %within.bounds = icmp ult i32 %i, %bound
1712  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
1713  %exiplicit_guard_cond = and i1 %within.bounds, %widenable_cond
1714  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
1715
1716deopt:                                            ; preds = %loop
1717  %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
1718  ret i32 %deoptcall
1719
1720guarded:                                          ; preds = %loop
1721  %i.i64 = zext i32 %i to i64
1722  %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
1723  %array.i = load i32, ptr %array.i.ptr, align 4
1724  %loop.acc.next = add i32 %loop.acc, %array.i
1725  %i.next = add nsw i32 %i, 1
1726  %continue = icmp slt i32 %i.next, %n
1727  br i1 %continue, label %loop, label %exit, !prof !2
1728
1729exit:                                             ; preds = %guarded, %entry
1730  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %guarded ]
1731  ret i32 %result
1732}
1733
1734define i32 @signed_loop_start_to_n_non_monotonic_predicate(ptr %array, i32 %x, i32 %start, i32 %n) {
1735; CHECK-LABEL: @signed_loop_start_to_n_non_monotonic_predicate(
1736; CHECK-NEXT:  entry:
1737; CHECK-NEXT:    [[TMP5:%.*]] = icmp sle i32 [[N:%.*]], 0
1738; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1739; CHECK:       loop.preheader:
1740; CHECK-NEXT:    br label [[LOOP:%.*]]
1741; CHECK:       loop:
1742; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
1743; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ [[START:%.*]], [[LOOP_PREHEADER]] ]
1744; CHECK-NEXT:    [[GUARD_COND:%.*]] = icmp eq i32 [[I]], [[X:%.*]]
1745; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
1746; CHECK-NEXT:    [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[GUARD_COND]], [[WIDENABLE_COND]]
1747; CHECK-NEXT:    br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
1748; CHECK:       deopt:
1749; CHECK-NEXT:    [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
1750; CHECK-NEXT:    ret i32 [[DEOPTCALL]]
1751; CHECK:       guarded:
1752; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
1753; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
1754; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
1755; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
1756; CHECK-NEXT:    [[I_NEXT]] = add nsw i32 [[I]], 1
1757; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp slt i32 [[I_NEXT]], [[N]]
1758; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]], !prof [[PROF1]]
1759; CHECK:       exit.loopexit:
1760; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
1761; CHECK-NEXT:    br label [[EXIT]]
1762; CHECK:       exit:
1763; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1764; CHECK-NEXT:    ret i32 [[RESULT]]
1765;
1766entry:
1767  %tmp5 = icmp sle i32 %n, 0
1768  br i1 %tmp5, label %exit, label %loop.preheader
1769
1770loop.preheader:                                   ; preds = %entry
1771  br label %loop
1772
1773loop:                                             ; preds = %guarded, %loop.preheader
1774  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
1775  %i = phi i32 [ %i.next, %guarded ], [ %start, %loop.preheader ]
1776  %guard.cond = icmp eq i32 %i, %x
1777  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
1778  %exiplicit_guard_cond = and i1 %guard.cond, %widenable_cond
1779  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
1780
1781deopt:                                            ; preds = %loop
1782  %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
1783  ret i32 %deoptcall
1784
1785guarded:                                          ; preds = %loop
1786  %i.i64 = zext i32 %i to i64
1787  %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
1788  %array.i = load i32, ptr %array.i.ptr, align 4
1789  %loop.acc.next = add i32 %loop.acc, %array.i
1790  %i.next = add nsw i32 %i, 1
1791  %continue = icmp slt i32 %i.next, %n
1792  br i1 %continue, label %loop, label %exit, !prof !2
1793
1794exit:                                             ; preds = %guarded, %entry
1795  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %guarded ]
1796  ret i32 %result
1797}
1798
1799define i32 @unsigned_loop_0_to_n_hoist_length(ptr %array, i16 %length.i16, i32 %n) {
1800; CHECK-LABEL: @unsigned_loop_0_to_n_hoist_length(
1801; CHECK-NEXT:  entry:
1802; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
1803; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1804; CHECK:       loop.preheader:
1805; CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[LENGTH_I16:%.*]] to i32
1806; CHECK-NEXT:    [[TMP1:%.*]] = icmp ule i32 [[N]], [[TMP0]]
1807; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 0, [[TMP0]]
1808; CHECK-NEXT:    [[TMP3:%.*]] = and i1 [[TMP2]], [[TMP1]]
1809; CHECK-NEXT:    [[TMP4:%.*]] = freeze i1 [[TMP3]]
1810; CHECK-NEXT:    br label [[LOOP:%.*]]
1811; CHECK:       loop:
1812; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
1813; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
1814; CHECK-NEXT:    [[LENGTH:%.*]] = zext i16 [[LENGTH_I16]] to i32
1815; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]]
1816; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
1817; CHECK-NEXT:    [[TMP5:%.*]] = and i1 [[TMP4]], [[WIDENABLE_COND]]
1818; CHECK-NEXT:    br i1 [[TMP5]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
1819; CHECK:       deopt:
1820; CHECK-NEXT:    [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
1821; CHECK-NEXT:    ret i32 [[DEOPTCALL]]
1822; CHECK:       guarded:
1823; CHECK-NEXT:    call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
1824; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
1825; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
1826; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
1827; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
1828; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
1829; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
1830; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]], !prof [[PROF1]]
1831; CHECK:       exit.loopexit:
1832; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
1833; CHECK-NEXT:    br label [[EXIT]]
1834; CHECK:       exit:
1835; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1836; CHECK-NEXT:    ret i32 [[RESULT]]
1837;
1838entry:
1839  %tmp5 = icmp eq i32 %n, 0
1840  br i1 %tmp5, label %exit, label %loop.preheader
1841
1842loop.preheader:                                   ; preds = %entry
1843  br label %loop
1844
1845loop:                                             ; preds = %guarded, %loop.preheader
1846  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
1847  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
1848  %length = zext i16 %length.i16 to i32
1849  %within.bounds = icmp ult i32 %i, %length
1850  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
1851  %exiplicit_guard_cond = and i1 %within.bounds, %widenable_cond
1852  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
1853
1854deopt:                                            ; preds = %loop
1855  %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
1856  ret i32 %deoptcall
1857
1858guarded:                                          ; preds = %loop
1859  %i.i64 = zext i32 %i to i64
1860  %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
1861  %array.i = load i32, ptr %array.i.ptr, align 4
1862  %loop.acc.next = add i32 %loop.acc, %array.i
1863  %i.next = add nuw i32 %i, 1
1864  %continue = icmp ult i32 %i.next, %n
1865  br i1 %continue, label %loop, label %exit, !prof !2
1866
1867exit:                                             ; preds = %guarded, %entry
1868  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %guarded ]
1869  ret i32 %result
1870}
1871
1872define i32 @unsigned_loop_0_to_n_cant_hoist_length(ptr %array, i32 %length, i32 %divider, i32 %n) {
1873; CHECK-LABEL: @unsigned_loop_0_to_n_cant_hoist_length(
1874; CHECK-NEXT:  entry:
1875; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
1876; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1877; CHECK:       loop.preheader:
1878; CHECK-NEXT:    br label [[LOOP:%.*]]
1879; CHECK:       loop:
1880; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
1881; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
1882; CHECK-NEXT:    [[LENGTH_UDIV:%.*]] = udiv i32 [[LENGTH:%.*]], [[DIVIDER:%.*]]
1883; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH_UDIV]]
1884; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
1885; CHECK-NEXT:    [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH_UDIV]]
1886; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH_UDIV]]
1887; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
1888; CHECK-NEXT:    [[TMP3:%.*]] = freeze i1 [[TMP2]]
1889; CHECK-NEXT:    [[TMP4:%.*]] = and i1 [[TMP3]], [[WIDENABLE_COND]]
1890; CHECK-NEXT:    br i1 [[TMP4]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
1891; CHECK:       deopt:
1892; CHECK-NEXT:    [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
1893; CHECK-NEXT:    ret i32 [[DEOPTCALL]]
1894; CHECK:       guarded:
1895; CHECK-NEXT:    call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
1896; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
1897; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
1898; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
1899; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
1900; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
1901; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
1902; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]], !prof [[PROF1]]
1903; CHECK:       exit.loopexit:
1904; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
1905; CHECK-NEXT:    br label [[EXIT]]
1906; CHECK:       exit:
1907; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
1908; CHECK-NEXT:    ret i32 [[RESULT]]
1909;
1910entry:
1911  %tmp5 = icmp eq i32 %n, 0
1912  br i1 %tmp5, label %exit, label %loop.preheader
1913
1914loop.preheader:                                   ; preds = %entry
1915  br label %loop
1916
1917loop:                                             ; preds = %guarded, %loop.preheader
1918  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
1919  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
1920  %length.udiv = udiv i32 %length, %divider
1921  %within.bounds = icmp ult i32 %i, %length.udiv
1922  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
1923  %exiplicit_guard_cond = and i1 %within.bounds, %widenable_cond
1924  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
1925
1926deopt:                                            ; preds = %loop
1927  %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
1928  ret i32 %deoptcall
1929
1930guarded:                                          ; preds = %loop
1931  %i.i64 = zext i32 %i to i64
1932  %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
1933  %array.i = load i32, ptr %array.i.ptr, align 4
1934  %loop.acc.next = add i32 %loop.acc, %array.i
1935  %i.next = add nuw i32 %i, 1
1936  %continue = icmp ult i32 %i.next, %n
1937  br i1 %continue, label %loop, label %exit, !prof !2
1938
1939exit:                                             ; preds = %guarded, %entry
1940  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %guarded ]
1941  ret i32 %result
1942}
1943
1944; Make sure that if we're going to consider a branch widenable, that the
1945; call to widenable condition is actually present.
1946define i32 @negative_WC_required(ptr %array, i32 %length, i32 %n, i1 %unrelated) {
1947; CHECK-LABEL: @negative_WC_required(
1948; CHECK-NEXT:  entry:
1949; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
1950; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
1951; CHECK:       loop.preheader:
1952; CHECK-NEXT:    br label [[LOOP:%.*]]
1953; CHECK:       loop:
1954; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
1955; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]]
1956; CHECK-NEXT:    [[NOT_WIDENABLE:%.*]] = and i1 [[WITHIN_BOUNDS]], [[UNRELATED:%.*]]
1957; CHECK-NEXT:    br i1 [[NOT_WIDENABLE]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
1958; CHECK:       deopt:
1959; CHECK-NEXT:    [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
1960; CHECK-NEXT:    ret i32 [[DEOPTCALL]]
1961; CHECK:       guarded:
1962; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
1963; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
1964; CHECK-NEXT:    store i32 0, ptr [[ARRAY_I_PTR]], align 4
1965; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
1966; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
1967; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]], !prof [[PROF1]]
1968; CHECK:       exit.loopexit:
1969; CHECK-NEXT:    br label [[EXIT]]
1970; CHECK:       exit:
1971; CHECK-NEXT:    ret i32 0
1972;
1973entry:
1974  %tmp5 = icmp eq i32 %n, 0
1975  br i1 %tmp5, label %exit, label %loop.preheader
1976
1977loop.preheader:                                   ; preds = %entry
1978  br label %loop
1979
1980loop:
1981  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
1982  %within.bounds = icmp ult i32 %i, %length
1983  %not_widenable = and i1 %within.bounds, %unrelated
1984  br i1 %not_widenable, label %guarded, label %deopt, !prof !0
1985
1986deopt:
1987  %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
1988  ret i32 %deoptcall
1989
1990guarded:                                          ; preds = %loop
1991  %i.i64 = zext i32 %i to i64
1992  %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
1993  store i32 0, ptr %array.i.ptr, align 4
1994  %i.next = add nuw i32 %i, 1
1995  %continue = icmp ult i32 %i.next, %n
1996  br i1 %continue, label %loop, label %exit, !prof !2
1997
1998exit:                                             ; preds = %guarded, %entry
1999  ret i32 0
2000}
2001
2002define i32 @swapped_wb(ptr %array, i32 %length, i32 %n) {
2003; CHECK-LABEL: @swapped_wb(
2004; CHECK-NEXT:  entry:
2005; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
2006; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
2007; CHECK:       loop.preheader:
2008; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
2009; CHECK-NEXT:    [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH:%.*]]
2010; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
2011; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
2012; CHECK-NEXT:    [[TMP3:%.*]] = freeze i1 [[TMP2]]
2013; CHECK-NEXT:    [[TMP4:%.*]] = and i1 [[TMP3]], [[WIDENABLE_COND]]
2014; CHECK-NEXT:    br label [[LOOP:%.*]]
2015; CHECK:       loop:
2016; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
2017; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
2018; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]]
2019; CHECK-NEXT:    br i1 [[TMP4]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
2020; CHECK:       deopt:
2021; CHECK-NEXT:    [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
2022; CHECK-NEXT:    ret i32 [[DEOPTCALL]]
2023; CHECK:       guarded:
2024; CHECK-NEXT:    call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
2025; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
2026; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
2027; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
2028; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
2029; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
2030; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
2031; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]], !prof [[PROF1]]
2032; CHECK:       exit.loopexit:
2033; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
2034; CHECK-NEXT:    br label [[EXIT]]
2035; CHECK:       exit:
2036; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
2037; CHECK-NEXT:    ret i32 [[RESULT]]
2038;
2039entry:
2040  %tmp5 = icmp eq i32 %n, 0
2041  br i1 %tmp5, label %exit, label %loop.preheader
2042
2043loop.preheader:                                   ; preds = %entry
2044  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
2045  br label %loop
2046
2047loop:                                             ; preds = %guarded, %loop.preheader
2048  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
2049  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
2050  %within.bounds = icmp ult i32 %i, %length
2051  %exiplicit_guard_cond = and i1 %widenable_cond, %within.bounds
2052  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
2053
2054deopt:                                            ; preds = %loop
2055  %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
2056  ret i32 %deoptcall
2057
2058guarded:                                          ; preds = %loop
2059  %i.i64 = zext i32 %i to i64
2060  %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
2061  %array.i = load i32, ptr %array.i.ptr, align 4
2062  %loop.acc.next = add i32 %loop.acc, %array.i
2063  %i.next = add nuw i32 %i, 1
2064  %continue = icmp ult i32 %i.next, %n
2065  br i1 %continue, label %loop, label %exit, !prof !2
2066
2067exit:                                             ; preds = %guarded, %entry
2068  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %guarded ]
2069  ret i32 %result
2070}
2071
2072define i32 @unsigned_loop_0_to_n_ult_check_deep_deopt(ptr %array, i32 %length, i32 %n) {
2073; CHECK-LABEL: @unsigned_loop_0_to_n_ult_check_deep_deopt(
2074; CHECK-NEXT:  entry:
2075; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0
2076; CHECK-NEXT:    br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]]
2077; CHECK:       loop.preheader:
2078; CHECK-NEXT:    [[TMP0:%.*]] = icmp ule i32 [[N]], [[LENGTH:%.*]]
2079; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i32 0, [[LENGTH]]
2080; CHECK-NEXT:    [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]]
2081; CHECK-NEXT:    [[TMP3:%.*]] = freeze i1 [[TMP2]]
2082; CHECK-NEXT:    br label [[LOOP:%.*]]
2083; CHECK:       loop:
2084; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
2085; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
2086; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH]]
2087; CHECK-NEXT:    [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
2088; CHECK-NEXT:    [[TMP4:%.*]] = and i1 [[TMP3]], [[WIDENABLE_COND]]
2089; CHECK-NEXT:    br i1 [[TMP4]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
2090; CHECK:       deopt:
2091; CHECK-NEXT:    br label [[REAL_DEOPT:%.*]]
2092; CHECK:       real_deopt:
2093; CHECK-NEXT:    [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
2094; CHECK-NEXT:    ret i32 [[DEOPTCALL]]
2095; CHECK:       guarded:
2096; CHECK-NEXT:    call void @llvm.assume(i1 [[WITHIN_BOUNDS]])
2097; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
2098; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARRAY:%.*]], i64 [[I_I64]]
2099; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, ptr [[ARRAY_I_PTR]], align 4
2100; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
2101; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
2102; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
2103; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]], !prof [[PROF1]]
2104; CHECK:       exit.loopexit:
2105; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
2106; CHECK-NEXT:    br label [[EXIT]]
2107; CHECK:       exit:
2108; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
2109; CHECK-NEXT:    ret i32 [[RESULT]]
2110;
2111entry:
2112  %tmp5 = icmp eq i32 %n, 0
2113  br i1 %tmp5, label %exit, label %loop.preheader
2114
2115loop.preheader:                                   ; preds = %entry
2116  br label %loop
2117
2118loop:                                             ; preds = %guarded, %loop.preheader
2119  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
2120  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
2121  %within.bounds = icmp ult i32 %i, %length
2122  %widenable_cond = call i1 @llvm.experimental.widenable.condition()
2123  %exiplicit_guard_cond = and i1 %within.bounds, %widenable_cond
2124  br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
2125
2126deopt:                                            ; preds = %loop
2127  br label %real_deopt
2128
2129real_deopt:                                       ; preds = %deopt
2130  %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
2131  ret i32 %deoptcall
2132
2133guarded:                                          ; preds = %loop
2134  %i.i64 = zext i32 %i to i64
2135  %array.i.ptr = getelementptr inbounds i32, ptr %array, i64 %i.i64
2136  %array.i = load i32, ptr %array.i.ptr, align 4
2137  %loop.acc.next = add i32 %loop.acc, %array.i
2138  %i.next = add nuw i32 %i, 1
2139  %continue = icmp ult i32 %i.next, %n
2140  br i1 %continue, label %loop, label %exit, !prof !2
2141
2142exit:                                             ; preds = %guarded, %entry
2143  %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %guarded ]
2144  ret i32 %result
2145}
2146
2147; TODO: Support widenable branch in the form of br((wc and cond0) and cond1)
2148; At present LoopPredication assumes the form of br(wc && (...)) only.
2149define i32 @wc_deep_in_expression_tree(i1 %cond0, i1 %cond1, i32 %limit) {
2150; CHECK-LABEL: @wc_deep_in_expression_tree(
2151; CHECK-NEXT:  entry:
2152; CHECK-NEXT:    [[WC:%.*]] = call i1 @llvm.experimental.widenable.condition()
2153; CHECK-NEXT:    [[AND0:%.*]] = and i1 [[WC]], [[COND0:%.*]]
2154; CHECK-NEXT:    [[AND1:%.*]] = and i1 [[AND0]], [[COND1:%.*]]
2155; CHECK-NEXT:    br i1 [[AND1]], label [[LOOP_PREHEADER:%.*]], label [[DEOPT:%.*]]
2156; CHECK:       loop.preheader:
2157; CHECK-NEXT:    br label [[LOOP:%.*]]
2158; CHECK:       loop:
2159; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
2160; CHECK-NEXT:    [[GUARD_COND:%.*]] = icmp sgt i32 [[IV]], 100
2161; CHECK-NEXT:    br i1 [[GUARD_COND]], label [[DEOPT_LOOPEXIT:%.*]], label [[GUARDED]]
2162; CHECK:       guarded:
2163; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
2164; CHECK-NEXT:    [[EXIT_COND:%.*]] = icmp ult i32 [[IV]], [[LIMIT:%.*]]
2165; CHECK-NEXT:    br i1 [[EXIT_COND]], label [[LOOP]], label [[EXIT:%.*]]
2166; CHECK:       deopt.loopexit:
2167; CHECK-NEXT:    br label [[DEOPT]]
2168; CHECK:       deopt:
2169; CHECK-NEXT:    [[DEOPTCALL:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
2170; CHECK-NEXT:    ret i32 [[DEOPTCALL]]
2171; CHECK:       exit:
2172; CHECK-NEXT:    ret i32 0
2173;
2174entry:
2175  %wc = call i1 @llvm.experimental.widenable.condition()
2176  %and0 = and i1 %wc, %cond0
2177  %and1 = and i1 %and0, %cond1
2178  br i1 %and1, label %loop, label %deopt
2179
2180loop:
2181  %iv = phi i32 [ %iv.next, %guarded ], [ 0, %entry ]
2182  %guard.cond = icmp sgt i32 %iv, 100
2183  br i1 %guard.cond, label %deopt, label %guarded
2184
2185guarded:
2186  %iv.next = add i32 %iv, 1
2187  %exit.cond = icmp ult i32 %iv, %limit
2188  br i1 %exit.cond, label %loop, label %exit
2189
2190deopt:
2191  %deoptcall = call i32 (...) @llvm.experimental.deoptimize.i32(i32 9) [ "deopt"() ]
2192  ret i32 %deoptcall
2193exit:
2194  ret i32 0
2195}
2196
2197declare i32 @llvm.experimental.deoptimize.i32(...)
2198
2199; Function Attrs: inaccessiblememonly nounwind
2200declare i1 @llvm.experimental.widenable.condition() #0
2201
2202attributes #0 = { inaccessiblememonly nounwind }
2203
2204!0 = !{!"branch_weights", i32 1048576, i32 1}
2205!1 = !{i32 1, i32 -2147483648}
2206!2 = !{!"branch_weights", i32 1024, i32 1}
2207