1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -passes=loop-bound-split -S < %s | FileCheck %s
4 define 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(
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:%.*]]
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:%.*]]
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]]
23 ; CHECK-NEXT: br label [[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:%.*]]
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]]
53 ; CHECK-NEXT: ret void
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
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
74 %inc = add nuw nsw i64 %iv, 1
75 %cond = icmp sgt i64 %inc, %n
76 br i1 %cond, label %exit, label %loop
82 define 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:%.*]]
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:%.*]]
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]]
101 ; CHECK-NEXT: br label [[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:%.*]]
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]]
131 ; CHECK-NEXT: ret void
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
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
152 %inc = add nuw nsw i64 %iv, 1
153 %cond = icmp eq i64 %inc, %n
154 br i1 %cond, label %exit, label %loop
160 define 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:%.*]]
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:%.*]]
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]]
180 ; CHECK-NEXT: br label [[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:%.*]]
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]]
210 ; CHECK-NEXT: ret void
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
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
231 %inc = add nuw nsw i64 %iv, 1
232 %cond = icmp sge i64 %inc, %n
233 br i1 %cond, label %exit, label %loop
239 define 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:%.*]]
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:%.*]]
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]]
259 ; CHECK-NEXT: br label [[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:%.*]]
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]]
289 ; CHECK-NEXT: ret void
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
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
310 %inc = add nuw nsw i64 %iv, 2
311 %cond = icmp sgt i64 %inc, %n
312 br i1 %cond, label %exit, label %loop
318 define 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:%.*]]
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]]
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]]
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]]
337 ; CHECK-NEXT: ret void
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
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
355 %inc = add nuw nsw i64 %iv, 1
356 %cond = icmp ne i64 %inc, %n
357 br i1 %cond, label %exit, label %loop
363 define 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:%.*]]
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]]
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]]
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]]
382 ; CHECK-NEXT: ret void
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
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
400 %dec = sub nuw nsw i64 %iv, 1
401 %cond = icmp slt i64 %dec, %n
402 br i1 %cond, label %exit, label %loop
408 define 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:%.*]]
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]]
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]]
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]]
427 ; CHECK-NEXT: ret void
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
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
445 %dec = sub nuw nsw i64 %iv, 1
446 %cond = icmp sle i64 %dec, %n
447 br i1 %cond, label %exit, label %loop
453 ; LoopBoundSplit pass should ignore phi which is not scevable phi.
454 define 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:%.*]]
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:%.*]]
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]]
474 ; CHECK-NEXT: br label [[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:%.*]]
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]]
505 ; CHECK-NEXT: ret void
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
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
527 %inc = add nuw nsw i64 %iv, 1
528 %cond = icmp sgt i64 %inc, %n
529 br i1 %cond, label %exit, label %loop