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