1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt  -passes=loop-bound-split -S < %s | FileCheck %s
3
4define void @split_loop_bound_inc_with_sgt(i64 %a, i64* noalias %src, i64* noalias %dst, i64 %n) {
5; CHECK-LABEL: @split_loop_bound_inc_with_sgt(
6; CHECK-NEXT:  loop.ph:
7; CHECK-NEXT:    br label [[LOOP_PH_SPLIT:%.*]]
8; CHECK:       loop.ph.split:
9; CHECK-NEXT:    [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N:%.*]], i64 0)
10; CHECK-NEXT:    [[NEW_BOUND:%.*]] = call i64 @llvm.smin.i64(i64 [[A:%.*]], i64 [[SMAX]])
11; CHECK-NEXT:    br label [[LOOP:%.*]]
12; CHECK:       loop:
13; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH_SPLIT]] ]
14; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[IV]], [[A]]
15; CHECK-NEXT:    br i1 true, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
16; CHECK:       if.then:
17; CHECK-NEXT:    [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[SRC:%.*]], i64 [[IV]]
18; CHECK-NEXT:    [[VAL:%.*]] = load i64, i64* [[SRC_ARRAYIDX]], align 4
19; CHECK-NEXT:    [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[DST:%.*]], i64 [[IV]]
20; CHECK-NEXT:    store i64 [[VAL]], i64* [[DST_ARRAYIDX]], align 4
21; CHECK-NEXT:    br label [[FOR_INC]]
22; CHECK:       if.else:
23; CHECK-NEXT:    br label [[FOR_INC]]
24; CHECK:       for.inc:
25; CHECK-NEXT:    [[INC]] = add nuw nsw i64 [[IV]], 1
26; CHECK-NEXT:    [[COND:%.*]] = icmp sgt i64 [[INC]], [[NEW_BOUND]]
27; CHECK-NEXT:    br i1 [[COND]], label [[LOOP_PH_SPLIT_SPLIT:%.*]], label [[LOOP]]
28; CHECK:       loop.ph.split.split:
29; CHECK-NEXT:    [[INC_LCSSA:%.*]] = phi i64 [ [[INC]], [[FOR_INC]] ]
30; CHECK-NEXT:    [[TMP0:%.*]] = icmp ne i64 [[INC_LCSSA]], [[N]]
31; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP_SPLIT_PREHEADER:%.*]], label [[EXIT:%.*]]
32; CHECK:       loop.split.preheader:
33; CHECK-NEXT:    br label [[LOOP_SPLIT:%.*]]
34; CHECK:       loop.split:
35; CHECK-NEXT:    [[IV_SPLIT:%.*]] = phi i64 [ [[INC_SPLIT:%.*]], [[FOR_INC_SPLIT:%.*]] ], [ [[NEW_BOUND]], [[LOOP_SPLIT_PREHEADER]] ]
36; CHECK-NEXT:    [[CMP_SPLIT:%.*]] = icmp slt i64 [[IV_SPLIT]], [[A]]
37; CHECK-NEXT:    br i1 false, label [[IF_THEN_SPLIT:%.*]], label [[IF_ELSE_SPLIT:%.*]]
38; CHECK:       if.else.split:
39; CHECK-NEXT:    br label [[FOR_INC_SPLIT]]
40; CHECK:       if.then.split:
41; CHECK-NEXT:    [[SRC_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, i64* [[SRC]], i64 [[IV_SPLIT]]
42; CHECK-NEXT:    [[VAL_SPLIT:%.*]] = load i64, i64* [[SRC_ARRAYIDX_SPLIT]], align 4
43; CHECK-NEXT:    [[DST_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, i64* [[DST]], i64 [[IV_SPLIT]]
44; CHECK-NEXT:    store i64 [[VAL_SPLIT]], i64* [[DST_ARRAYIDX_SPLIT]], align 4
45; CHECK-NEXT:    br label [[FOR_INC_SPLIT]]
46; CHECK:       for.inc.split:
47; CHECK-NEXT:    [[INC_SPLIT]] = add nuw nsw i64 [[IV_SPLIT]], 1
48; CHECK-NEXT:    [[COND_SPLIT:%.*]] = icmp sgt i64 [[INC_SPLIT]], [[N]]
49; CHECK-NEXT:    br i1 [[COND_SPLIT]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP_SPLIT]]
50; CHECK:       exit.loopexit:
51; CHECK-NEXT:    br label [[EXIT]]
52; CHECK:       exit:
53; CHECK-NEXT:    ret void
54;
55loop.ph:
56  br label %loop
57
58loop:
59  %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ]
60  %cmp = icmp slt i64 %iv, %a
61  br i1 %cmp, label %if.then, label %if.else
62
63if.then:
64  %src.arrayidx = getelementptr inbounds i64, i64* %src, i64 %iv
65  %val = load i64, i64* %src.arrayidx
66  %dst.arrayidx = getelementptr inbounds i64, i64* %dst, i64 %iv
67  store i64 %val, i64* %dst.arrayidx
68  br label %for.inc
69
70if.else:
71  br label %for.inc
72
73for.inc:
74  %inc = add nuw nsw i64 %iv, 1
75  %cond = icmp sgt i64 %inc, %n
76  br i1 %cond, label %exit, label %loop
77
78exit:
79  ret void
80}
81
82define void @split_loop_bound_inc_with_eq(i64 %a, i64* noalias %src, i64* noalias %dst, i64 %n) {
83; CHECK-LABEL: @split_loop_bound_inc_with_eq(
84; CHECK-NEXT:  loop.ph:
85; CHECK-NEXT:    br label [[LOOP_PH_SPLIT:%.*]]
86; CHECK:       loop.ph.split:
87; CHECK-NEXT:    [[TMP0:%.*]] = add i64 [[N:%.*]], -1
88; CHECK-NEXT:    [[NEW_BOUND:%.*]] = call i64 @llvm.umin.i64(i64 [[A:%.*]], i64 [[TMP0]])
89; CHECK-NEXT:    br label [[LOOP:%.*]]
90; CHECK:       loop:
91; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH_SPLIT]] ]
92; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[IV]], [[A]]
93; CHECK-NEXT:    br i1 true, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
94; CHECK:       if.then:
95; CHECK-NEXT:    [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[SRC:%.*]], i64 [[IV]]
96; CHECK-NEXT:    [[VAL:%.*]] = load i64, i64* [[SRC_ARRAYIDX]], align 4
97; CHECK-NEXT:    [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[DST:%.*]], i64 [[IV]]
98; CHECK-NEXT:    store i64 [[VAL]], i64* [[DST_ARRAYIDX]], align 4
99; CHECK-NEXT:    br label [[FOR_INC]]
100; CHECK:       if.else:
101; CHECK-NEXT:    br label [[FOR_INC]]
102; CHECK:       for.inc:
103; CHECK-NEXT:    [[INC]] = add nuw nsw i64 [[IV]], 1
104; CHECK-NEXT:    [[COND:%.*]] = icmp eq i64 [[INC]], [[NEW_BOUND]]
105; CHECK-NEXT:    br i1 [[COND]], label [[LOOP_PH_SPLIT_SPLIT:%.*]], label [[LOOP]]
106; CHECK:       loop.ph.split.split:
107; CHECK-NEXT:    [[INC_LCSSA:%.*]] = phi i64 [ [[INC]], [[FOR_INC]] ]
108; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i64 [[INC_LCSSA]], [[N]]
109; CHECK-NEXT:    br i1 [[TMP1]], label [[LOOP_SPLIT_PREHEADER:%.*]], label [[EXIT:%.*]]
110; CHECK:       loop.split.preheader:
111; CHECK-NEXT:    br label [[LOOP_SPLIT:%.*]]
112; CHECK:       loop.split:
113; CHECK-NEXT:    [[IV_SPLIT:%.*]] = phi i64 [ [[INC_SPLIT:%.*]], [[FOR_INC_SPLIT:%.*]] ], [ [[NEW_BOUND]], [[LOOP_SPLIT_PREHEADER]] ]
114; CHECK-NEXT:    [[CMP_SPLIT:%.*]] = icmp slt i64 [[IV_SPLIT]], [[A]]
115; CHECK-NEXT:    br i1 false, label [[IF_THEN_SPLIT:%.*]], label [[IF_ELSE_SPLIT:%.*]]
116; CHECK:       if.else.split:
117; CHECK-NEXT:    br label [[FOR_INC_SPLIT]]
118; CHECK:       if.then.split:
119; CHECK-NEXT:    [[SRC_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, i64* [[SRC]], i64 [[IV_SPLIT]]
120; CHECK-NEXT:    [[VAL_SPLIT:%.*]] = load i64, i64* [[SRC_ARRAYIDX_SPLIT]], align 4
121; CHECK-NEXT:    [[DST_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, i64* [[DST]], i64 [[IV_SPLIT]]
122; CHECK-NEXT:    store i64 [[VAL_SPLIT]], i64* [[DST_ARRAYIDX_SPLIT]], align 4
123; CHECK-NEXT:    br label [[FOR_INC_SPLIT]]
124; CHECK:       for.inc.split:
125; CHECK-NEXT:    [[INC_SPLIT]] = add nuw nsw i64 [[IV_SPLIT]], 1
126; CHECK-NEXT:    [[COND_SPLIT:%.*]] = icmp eq i64 [[INC_SPLIT]], [[N]]
127; CHECK-NEXT:    br i1 [[COND_SPLIT]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP_SPLIT]]
128; CHECK:       exit.loopexit:
129; CHECK-NEXT:    br label [[EXIT]]
130; CHECK:       exit:
131; CHECK-NEXT:    ret void
132;
133loop.ph:
134  br label %loop
135
136loop:
137  %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ]
138  %cmp = icmp slt i64 %iv, %a
139  br i1 %cmp, label %if.then, label %if.else
140
141if.then:
142  %src.arrayidx = getelementptr inbounds i64, i64* %src, i64 %iv
143  %val = load i64, i64* %src.arrayidx
144  %dst.arrayidx = getelementptr inbounds i64, i64* %dst, i64 %iv
145  store i64 %val, i64* %dst.arrayidx
146  br label %for.inc
147
148if.else:
149  br label %for.inc
150
151for.inc:
152  %inc = add nuw nsw i64 %iv, 1
153  %cond = icmp eq i64 %inc, %n
154  br i1 %cond, label %exit, label %loop
155
156exit:
157  ret void
158}
159
160define void @split_loop_bound_inc_with_sge(i64 %a, i64* noalias %src, i64* noalias %dst, i64 %n) {
161; CHECK-LABEL: @split_loop_bound_inc_with_sge(
162; CHECK-NEXT:  loop.ph:
163; CHECK-NEXT:    br label [[LOOP_PH_SPLIT:%.*]]
164; CHECK:       loop.ph.split:
165; CHECK-NEXT:    [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N:%.*]], i64 1)
166; CHECK-NEXT:    [[TMP0:%.*]] = add nsw i64 [[SMAX]], -1
167; CHECK-NEXT:    [[NEW_BOUND:%.*]] = call i64 @llvm.smin.i64(i64 [[A:%.*]], i64 [[TMP0]])
168; CHECK-NEXT:    br label [[LOOP:%.*]]
169; CHECK:       loop:
170; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH_SPLIT]] ]
171; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[IV]], [[A]]
172; CHECK-NEXT:    br i1 true, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
173; CHECK:       if.then:
174; CHECK-NEXT:    [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[SRC:%.*]], i64 [[IV]]
175; CHECK-NEXT:    [[VAL:%.*]] = load i64, i64* [[SRC_ARRAYIDX]], align 4
176; CHECK-NEXT:    [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[DST:%.*]], i64 [[IV]]
177; CHECK-NEXT:    store i64 [[VAL]], i64* [[DST_ARRAYIDX]], align 4
178; CHECK-NEXT:    br label [[FOR_INC]]
179; CHECK:       if.else:
180; CHECK-NEXT:    br label [[FOR_INC]]
181; CHECK:       for.inc:
182; CHECK-NEXT:    [[INC]] = add nuw nsw i64 [[IV]], 1
183; CHECK-NEXT:    [[COND:%.*]] = icmp sge i64 [[INC]], [[NEW_BOUND]]
184; CHECK-NEXT:    br i1 [[COND]], label [[LOOP_PH_SPLIT_SPLIT:%.*]], label [[LOOP]]
185; CHECK:       loop.ph.split.split:
186; CHECK-NEXT:    [[INC_LCSSA:%.*]] = phi i64 [ [[INC]], [[FOR_INC]] ]
187; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i64 [[INC_LCSSA]], [[N]]
188; CHECK-NEXT:    br i1 [[TMP1]], label [[LOOP_SPLIT_PREHEADER:%.*]], label [[EXIT:%.*]]
189; CHECK:       loop.split.preheader:
190; CHECK-NEXT:    br label [[LOOP_SPLIT:%.*]]
191; CHECK:       loop.split:
192; CHECK-NEXT:    [[IV_SPLIT:%.*]] = phi i64 [ [[INC_SPLIT:%.*]], [[FOR_INC_SPLIT:%.*]] ], [ [[NEW_BOUND]], [[LOOP_SPLIT_PREHEADER]] ]
193; CHECK-NEXT:    [[CMP_SPLIT:%.*]] = icmp slt i64 [[IV_SPLIT]], [[A]]
194; CHECK-NEXT:    br i1 false, label [[IF_THEN_SPLIT:%.*]], label [[IF_ELSE_SPLIT:%.*]]
195; CHECK:       if.else.split:
196; CHECK-NEXT:    br label [[FOR_INC_SPLIT]]
197; CHECK:       if.then.split:
198; CHECK-NEXT:    [[SRC_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, i64* [[SRC]], i64 [[IV_SPLIT]]
199; CHECK-NEXT:    [[VAL_SPLIT:%.*]] = load i64, i64* [[SRC_ARRAYIDX_SPLIT]], align 4
200; CHECK-NEXT:    [[DST_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, i64* [[DST]], i64 [[IV_SPLIT]]
201; CHECK-NEXT:    store i64 [[VAL_SPLIT]], i64* [[DST_ARRAYIDX_SPLIT]], align 4
202; CHECK-NEXT:    br label [[FOR_INC_SPLIT]]
203; CHECK:       for.inc.split:
204; CHECK-NEXT:    [[INC_SPLIT]] = add nuw nsw i64 [[IV_SPLIT]], 1
205; CHECK-NEXT:    [[COND_SPLIT:%.*]] = icmp sge i64 [[INC_SPLIT]], [[N]]
206; CHECK-NEXT:    br i1 [[COND_SPLIT]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP_SPLIT]]
207; CHECK:       exit.loopexit:
208; CHECK-NEXT:    br label [[EXIT]]
209; CHECK:       exit:
210; CHECK-NEXT:    ret void
211;
212loop.ph:
213  br label %loop
214
215loop:
216  %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ]
217  %cmp = icmp slt i64 %iv, %a
218  br i1 %cmp, label %if.then, label %if.else
219
220if.then:
221  %src.arrayidx = getelementptr inbounds i64, i64* %src, i64 %iv
222  %val = load i64, i64* %src.arrayidx
223  %dst.arrayidx = getelementptr inbounds i64, i64* %dst, i64 %iv
224  store i64 %val, i64* %dst.arrayidx
225  br label %for.inc
226
227if.else:
228  br label %for.inc
229
230for.inc:
231  %inc = add nuw nsw i64 %iv, 1
232  %cond = icmp sge i64 %inc, %n
233  br i1 %cond, label %exit, label %loop
234
235exit:
236  ret void
237}
238
239define void @split_loop_bound_inc_with_step_is_not_one(i64 %a, i64* noalias %src, i64* noalias %dst, i64 %n) {
240; CHECK-LABEL: @split_loop_bound_inc_with_step_is_not_one(
241; CHECK-NEXT:  loop.ph:
242; CHECK-NEXT:    br label [[LOOP_PH_SPLIT:%.*]]
243; CHECK:       loop.ph.split:
244; CHECK-NEXT:    [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N:%.*]], i64 1)
245; CHECK-NEXT:    [[TMP0:%.*]] = lshr i64 [[SMAX]], 1
246; CHECK-NEXT:    [[NEW_BOUND:%.*]] = call i64 @llvm.smin.i64(i64 [[A:%.*]], i64 [[TMP0]])
247; CHECK-NEXT:    br label [[LOOP:%.*]]
248; CHECK:       loop:
249; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH_SPLIT]] ]
250; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[IV]], [[A]]
251; CHECK-NEXT:    br i1 true, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
252; CHECK:       if.then:
253; CHECK-NEXT:    [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[SRC:%.*]], i64 [[IV]]
254; CHECK-NEXT:    [[VAL:%.*]] = load i64, i64* [[SRC_ARRAYIDX]], align 4
255; CHECK-NEXT:    [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[DST:%.*]], i64 [[IV]]
256; CHECK-NEXT:    store i64 [[VAL]], i64* [[DST_ARRAYIDX]], align 4
257; CHECK-NEXT:    br label [[FOR_INC]]
258; CHECK:       if.else:
259; CHECK-NEXT:    br label [[FOR_INC]]
260; CHECK:       for.inc:
261; CHECK-NEXT:    [[INC]] = add nuw nsw i64 [[IV]], 2
262; CHECK-NEXT:    [[COND:%.*]] = icmp sgt i64 [[INC]], [[NEW_BOUND]]
263; CHECK-NEXT:    br i1 [[COND]], label [[LOOP_PH_SPLIT_SPLIT:%.*]], label [[LOOP]]
264; CHECK:       loop.ph.split.split:
265; CHECK-NEXT:    [[INC_LCSSA:%.*]] = phi i64 [ [[INC]], [[FOR_INC]] ]
266; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i64 [[INC_LCSSA]], [[N]]
267; CHECK-NEXT:    br i1 [[TMP1]], label [[LOOP_SPLIT_PREHEADER:%.*]], label [[EXIT:%.*]]
268; CHECK:       loop.split.preheader:
269; CHECK-NEXT:    br label [[LOOP_SPLIT:%.*]]
270; CHECK:       loop.split:
271; CHECK-NEXT:    [[IV_SPLIT:%.*]] = phi i64 [ [[INC_SPLIT:%.*]], [[FOR_INC_SPLIT:%.*]] ], [ [[NEW_BOUND]], [[LOOP_SPLIT_PREHEADER]] ]
272; CHECK-NEXT:    [[CMP_SPLIT:%.*]] = icmp slt i64 [[IV_SPLIT]], [[A]]
273; CHECK-NEXT:    br i1 false, label [[IF_THEN_SPLIT:%.*]], label [[IF_ELSE_SPLIT:%.*]]
274; CHECK:       if.else.split:
275; CHECK-NEXT:    br label [[FOR_INC_SPLIT]]
276; CHECK:       if.then.split:
277; CHECK-NEXT:    [[SRC_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, i64* [[SRC]], i64 [[IV_SPLIT]]
278; CHECK-NEXT:    [[VAL_SPLIT:%.*]] = load i64, i64* [[SRC_ARRAYIDX_SPLIT]], align 4
279; CHECK-NEXT:    [[DST_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, i64* [[DST]], i64 [[IV_SPLIT]]
280; CHECK-NEXT:    store i64 [[VAL_SPLIT]], i64* [[DST_ARRAYIDX_SPLIT]], align 4
281; CHECK-NEXT:    br label [[FOR_INC_SPLIT]]
282; CHECK:       for.inc.split:
283; CHECK-NEXT:    [[INC_SPLIT]] = add nuw nsw i64 [[IV_SPLIT]], 2
284; CHECK-NEXT:    [[COND_SPLIT:%.*]] = icmp sgt i64 [[INC_SPLIT]], [[N]]
285; CHECK-NEXT:    br i1 [[COND_SPLIT]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP_SPLIT]]
286; CHECK:       exit.loopexit:
287; CHECK-NEXT:    br label [[EXIT]]
288; CHECK:       exit:
289; CHECK-NEXT:    ret void
290;
291loop.ph:
292  br label %loop
293
294loop:
295  %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ]
296  %cmp = icmp slt i64 %iv, %a
297  br i1 %cmp, label %if.then, label %if.else
298
299if.then:
300  %src.arrayidx = getelementptr inbounds i64, i64* %src, i64 %iv
301  %val = load i64, i64* %src.arrayidx
302  %dst.arrayidx = getelementptr inbounds i64, i64* %dst, i64 %iv
303  store i64 %val, i64* %dst.arrayidx
304  br label %for.inc
305
306if.else:
307  br label %for.inc
308
309for.inc:
310  %inc = add nuw nsw i64 %iv, 2
311  %cond = icmp sgt i64 %inc, %n
312  br i1 %cond, label %exit, label %loop
313
314exit:
315  ret void
316}
317
318define void @split_loop_bound_inc_with_ne(i64 %a, i64* noalias %src, i64* noalias %dst, i64 %n) {
319; CHECK-LABEL: @split_loop_bound_inc_with_ne(
320; CHECK-NEXT:  loop.ph:
321; CHECK-NEXT:    br label [[LOOP:%.*]]
322; CHECK:       loop:
323; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ]
324; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[IV]], [[A:%.*]]
325; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[FOR_INC]]
326; CHECK:       if.then:
327; CHECK-NEXT:    [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[SRC:%.*]], i64 [[IV]]
328; CHECK-NEXT:    [[VAL:%.*]] = load i64, i64* [[SRC_ARRAYIDX]], align 4
329; CHECK-NEXT:    [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[DST:%.*]], i64 [[IV]]
330; CHECK-NEXT:    store i64 [[VAL]], i64* [[DST_ARRAYIDX]], align 4
331; CHECK-NEXT:    br label [[FOR_INC]]
332; CHECK:       for.inc:
333; CHECK-NEXT:    [[INC]] = add nuw nsw i64 [[IV]], 1
334; CHECK-NEXT:    [[COND:%.*]] = icmp ne i64 [[INC]], [[N:%.*]]
335; CHECK-NEXT:    br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]]
336; CHECK:       exit:
337; CHECK-NEXT:    ret void
338;
339loop.ph:
340  br label %loop
341
342loop:
343  %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ]
344  %cmp = icmp slt i64 %iv, %a
345  br i1 %cmp, label %if.then, label %for.inc
346
347if.then:
348  %src.arrayidx = getelementptr inbounds i64, i64* %src, i64 %iv
349  %val = load i64, i64* %src.arrayidx
350  %dst.arrayidx = getelementptr inbounds i64, i64* %dst, i64 %iv
351  store i64 %val, i64* %dst.arrayidx
352  br label %for.inc
353
354for.inc:
355  %inc = add nuw nsw i64 %iv, 1
356  %cond = icmp ne i64 %inc, %n
357  br i1 %cond, label %exit, label %loop
358
359exit:
360  ret void
361}
362
363define void @split_loop_bound_dec_with_slt(i64 %a, i64* noalias %src, i64* noalias %dst, i64 %n) {
364; CHECK-LABEL: @split_loop_bound_dec_with_slt(
365; CHECK-NEXT:  loop.ph:
366; CHECK-NEXT:    br label [[LOOP:%.*]]
367; CHECK:       loop:
368; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[DEC:%.*]], [[FOR_DEC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ]
369; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[IV]], [[A:%.*]]
370; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[FOR_DEC]]
371; CHECK:       if.then:
372; CHECK-NEXT:    [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[SRC:%.*]], i64 [[IV]]
373; CHECK-NEXT:    [[VAL:%.*]] = load i64, i64* [[SRC_ARRAYIDX]], align 4
374; CHECK-NEXT:    [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[DST:%.*]], i64 [[IV]]
375; CHECK-NEXT:    store i64 [[VAL]], i64* [[DST_ARRAYIDX]], align 4
376; CHECK-NEXT:    br label [[FOR_DEC]]
377; CHECK:       for.dec:
378; CHECK-NEXT:    [[DEC]] = sub nuw nsw i64 [[IV]], 1
379; CHECK-NEXT:    [[COND:%.*]] = icmp slt i64 [[DEC]], [[N:%.*]]
380; CHECK-NEXT:    br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]]
381; CHECK:       exit:
382; CHECK-NEXT:    ret void
383;
384loop.ph:
385  br label %loop
386
387loop:
388  %iv = phi i64 [ %dec, %for.dec ], [ 0, %loop.ph ]
389  %cmp = icmp slt i64 %iv, %a
390  br i1 %cmp, label %if.then, label %for.dec
391
392if.then:
393  %src.arrayidx = getelementptr inbounds i64, i64* %src, i64 %iv
394  %val = load i64, i64* %src.arrayidx
395  %dst.arrayidx = getelementptr inbounds i64, i64* %dst, i64 %iv
396  store i64 %val, i64* %dst.arrayidx
397  br label %for.dec
398
399for.dec:
400  %dec = sub nuw nsw i64 %iv, 1
401  %cond = icmp slt i64 %dec, %n
402  br i1 %cond, label %exit, label %loop
403
404exit:
405  ret void
406}
407
408define void @split_loop_bound_dec_with_sle(i64 %a, i64* noalias %src, i64* noalias %dst, i64 %n) {
409; CHECK-LABEL: @split_loop_bound_dec_with_sle(
410; CHECK-NEXT:  loop.ph:
411; CHECK-NEXT:    br label [[LOOP:%.*]]
412; CHECK:       loop:
413; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[DEC:%.*]], [[FOR_DEC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ]
414; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[IV]], [[A:%.*]]
415; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[FOR_DEC]]
416; CHECK:       if.then:
417; CHECK-NEXT:    [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[SRC:%.*]], i64 [[IV]]
418; CHECK-NEXT:    [[VAL:%.*]] = load i64, i64* [[SRC_ARRAYIDX]], align 4
419; CHECK-NEXT:    [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[DST:%.*]], i64 [[IV]]
420; CHECK-NEXT:    store i64 [[VAL]], i64* [[DST_ARRAYIDX]], align 4
421; CHECK-NEXT:    br label [[FOR_DEC]]
422; CHECK:       for.dec:
423; CHECK-NEXT:    [[DEC]] = sub nuw nsw i64 [[IV]], 1
424; CHECK-NEXT:    [[COND:%.*]] = icmp sle i64 [[DEC]], [[N:%.*]]
425; CHECK-NEXT:    br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]]
426; CHECK:       exit:
427; CHECK-NEXT:    ret void
428;
429loop.ph:
430  br label %loop
431
432loop:
433  %iv = phi i64 [ %dec, %for.dec ], [ 0, %loop.ph ]
434  %cmp = icmp slt i64 %iv, %a
435  br i1 %cmp, label %if.then, label %for.dec
436
437if.then:
438  %src.arrayidx = getelementptr inbounds i64, i64* %src, i64 %iv
439  %val = load i64, i64* %src.arrayidx
440  %dst.arrayidx = getelementptr inbounds i64, i64* %dst, i64 %iv
441  store i64 %val, i64* %dst.arrayidx
442  br label %for.dec
443
444for.dec:
445  %dec = sub nuw nsw i64 %iv, 1
446  %cond = icmp sle i64 %dec, %n
447  br i1 %cond, label %exit, label %loop
448
449exit:
450  ret void
451}
452
453; LoopBoundSplit pass should ignore phi which is not scevable phi.
454define void @split_loop_bound_inc_with_sgt_and_is_not_scevable_phi(i64 %a, i64* noalias %src, i64* noalias %dst, i64 %n) {
455; CHECK-LABEL: @split_loop_bound_inc_with_sgt_and_is_not_scevable_phi(
456; CHECK-NEXT:  loop.ph:
457; CHECK-NEXT:    br label [[LOOP_PH_SPLIT:%.*]]
458; CHECK:       loop.ph.split:
459; CHECK-NEXT:    [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N:%.*]], i64 0)
460; CHECK-NEXT:    [[NEW_BOUND:%.*]] = call i64 @llvm.smin.i64(i64 [[A:%.*]], i64 [[SMAX]])
461; CHECK-NEXT:    br label [[LOOP:%.*]]
462; CHECK:       loop:
463; CHECK-NEXT:    [[IS_NOT_SCEVABLE_PHI:%.*]] = phi double [ 1.000000e+00, [[FOR_INC:%.*]] ], [ 2.000000e+00, [[LOOP_PH_SPLIT]] ]
464; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC]] ], [ 0, [[LOOP_PH_SPLIT]] ]
465; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i64 [[IV]], [[A]]
466; CHECK-NEXT:    br i1 true, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
467; CHECK:       if.then:
468; CHECK-NEXT:    [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[SRC:%.*]], i64 [[IV]]
469; CHECK-NEXT:    [[VAL:%.*]] = load i64, i64* [[SRC_ARRAYIDX]], align 4
470; CHECK-NEXT:    [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[DST:%.*]], i64 [[IV]]
471; CHECK-NEXT:    store i64 [[VAL]], i64* [[DST_ARRAYIDX]], align 4
472; CHECK-NEXT:    br label [[FOR_INC]]
473; CHECK:       if.else:
474; CHECK-NEXT:    br label [[FOR_INC]]
475; CHECK:       for.inc:
476; CHECK-NEXT:    [[INC]] = add nuw nsw i64 [[IV]], 1
477; CHECK-NEXT:    [[COND:%.*]] = icmp sgt i64 [[INC]], [[NEW_BOUND]]
478; CHECK-NEXT:    br i1 [[COND]], label [[LOOP_PH_SPLIT_SPLIT:%.*]], label [[LOOP]]
479; CHECK:       loop.ph.split.split:
480; CHECK-NEXT:    [[INC_LCSSA:%.*]] = phi i64 [ [[INC]], [[FOR_INC]] ]
481; CHECK-NEXT:    [[TMP0:%.*]] = icmp ne i64 [[INC_LCSSA]], [[N]]
482; CHECK-NEXT:    br i1 [[TMP0]], label [[LOOP_SPLIT_PREHEADER:%.*]], label [[EXIT:%.*]]
483; CHECK:       loop.split.preheader:
484; CHECK-NEXT:    br label [[LOOP_SPLIT:%.*]]
485; CHECK:       loop.split:
486; CHECK-NEXT:    [[IS_NOT_SCEVABLE_PHI_SPLIT:%.*]] = phi double [ 1.000000e+00, [[FOR_INC_SPLIT:%.*]] ], [ 2.000000e+00, [[LOOP_SPLIT_PREHEADER]] ]
487; CHECK-NEXT:    [[IV_SPLIT:%.*]] = phi i64 [ [[INC_SPLIT:%.*]], [[FOR_INC_SPLIT]] ], [ [[NEW_BOUND]], [[LOOP_SPLIT_PREHEADER]] ]
488; CHECK-NEXT:    [[CMP_SPLIT:%.*]] = icmp slt i64 [[IV_SPLIT]], [[A]]
489; CHECK-NEXT:    br i1 false, label [[IF_THEN_SPLIT:%.*]], label [[IF_ELSE_SPLIT:%.*]]
490; CHECK:       if.else.split:
491; CHECK-NEXT:    br label [[FOR_INC_SPLIT]]
492; CHECK:       if.then.split:
493; CHECK-NEXT:    [[SRC_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, i64* [[SRC]], i64 [[IV_SPLIT]]
494; CHECK-NEXT:    [[VAL_SPLIT:%.*]] = load i64, i64* [[SRC_ARRAYIDX_SPLIT]], align 4
495; CHECK-NEXT:    [[DST_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, i64* [[DST]], i64 [[IV_SPLIT]]
496; CHECK-NEXT:    store i64 [[VAL_SPLIT]], i64* [[DST_ARRAYIDX_SPLIT]], align 4
497; CHECK-NEXT:    br label [[FOR_INC_SPLIT]]
498; CHECK:       for.inc.split:
499; CHECK-NEXT:    [[INC_SPLIT]] = add nuw nsw i64 [[IV_SPLIT]], 1
500; CHECK-NEXT:    [[COND_SPLIT:%.*]] = icmp sgt i64 [[INC_SPLIT]], [[N]]
501; CHECK-NEXT:    br i1 [[COND_SPLIT]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP_SPLIT]]
502; CHECK:       exit.loopexit:
503; CHECK-NEXT:    br label [[EXIT]]
504; CHECK:       exit:
505; CHECK-NEXT:    ret void
506;
507loop.ph:
508  br label %loop
509
510loop:
511  %is_not_scevable_phi = phi double [ 1.0, %for.inc ], [ 2.0, %loop.ph ]
512  %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ]
513  %cmp = icmp slt i64 %iv, %a
514  br i1 %cmp, label %if.then, label %if.else
515
516if.then:
517  %src.arrayidx = getelementptr inbounds i64, i64* %src, i64 %iv
518  %val = load i64, i64* %src.arrayidx
519  %dst.arrayidx = getelementptr inbounds i64, i64* %dst, i64 %iv
520  store i64 %val, i64* %dst.arrayidx
521  br label %for.inc
522
523if.else:
524  br label %for.inc
525
526for.inc:
527  %inc = add nuw nsw i64 %iv, 1
528  %cond = icmp sgt i64 %inc, %n
529  br i1 %cond, label %exit, label %loop
530
531exit:
532  ret void
533}
534
535