1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -passes=loop-bound-split -S < %s | FileCheck %s
4 ; The transformation is failed with this test because we can not guarantee the
5 ; split condition is always true in pre-loop after transformation.
6 define void @variable_split_loop_bound_and_exit_cond_inc_with_sgt(i64 %a, ptr noalias %src, ptr noalias %dst, i64 %n) {
7 ; CHECK-LABEL: @variable_split_loop_bound_and_exit_cond_inc_with_sgt(
9 ; CHECK-NEXT: br label [[LOOP:%.*]]
11 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ]
12 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], [[A:%.*]]
13 ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
15 ; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[SRC:%.*]], i64 [[IV]]
16 ; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[SRC_ARRAYIDX]], align 4
17 ; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]]
18 ; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4
19 ; CHECK-NEXT: br label [[FOR_INC]]
21 ; CHECK-NEXT: br label [[FOR_INC]]
23 ; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 1
24 ; CHECK-NEXT: [[COND:%.*]] = icmp sgt i64 [[INC]], [[N:%.*]]
25 ; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]]
27 ; CHECK-NEXT: ret void
33 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ]
34 %cmp = icmp ult i64 %iv, %a
35 br i1 %cmp, label %if.then, label %if.else
38 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv
39 %val = load i64, ptr %src.arrayidx
40 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv
41 store i64 %val, ptr %dst.arrayidx
48 %inc = add nuw nsw i64 %iv, 1
49 %cond = icmp sgt i64 %inc, %n
50 br i1 %cond, label %exit, label %loop
56 ; The transformation works with this test because we can guarantee the split
57 ; condition is always true in pre-loop after transformation.
58 define void @umax_variable_split_loop_bound_and_exit_cond_inc_with_sgt(i64 %a, ptr noalias %src, ptr noalias %dst, i64 %n) {
59 ; CHECK-LABEL: @umax_variable_split_loop_bound_and_exit_cond_inc_with_sgt(
60 ; CHECK-NEXT: loop.ph:
61 ; CHECK-NEXT: [[B:%.*]] = call i64 @llvm.umax.i64(i64 [[A:%.*]], i64 1)
62 ; CHECK-NEXT: br label [[LOOP_PH_SPLIT:%.*]]
63 ; CHECK: loop.ph.split:
64 ; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N:%.*]], i64 0)
65 ; CHECK-NEXT: [[NEW_BOUND:%.*]] = call i64 @llvm.smin.i64(i64 [[SMAX]], i64 [[B]])
66 ; CHECK-NEXT: br label [[LOOP:%.*]]
68 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH_SPLIT]] ]
69 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], [[B]]
70 ; CHECK-NEXT: br i1 true, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
72 ; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[SRC:%.*]], i64 [[IV]]
73 ; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[SRC_ARRAYIDX]], align 4
74 ; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]]
75 ; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4
76 ; CHECK-NEXT: br label [[FOR_INC]]
78 ; CHECK-NEXT: br label [[FOR_INC]]
80 ; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 1
81 ; CHECK-NEXT: [[COND:%.*]] = icmp sgt i64 [[INC]], [[NEW_BOUND]]
82 ; CHECK-NEXT: br i1 [[COND]], label [[LOOP_PH_SPLIT_SPLIT:%.*]], label [[LOOP]]
83 ; CHECK: loop.ph.split.split:
84 ; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i64 [ [[INC]], [[FOR_INC]] ]
85 ; CHECK-NEXT: [[TMP0:%.*]] = icmp ne i64 [[IV_LCSSA]], [[N]]
86 ; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_SPLIT_PREHEADER:%.*]], label [[EXIT:%.*]]
87 ; CHECK: loop.split.preheader:
88 ; CHECK-NEXT: br label [[LOOP_SPLIT:%.*]]
90 ; CHECK-NEXT: [[IV_SPLIT:%.*]] = phi i64 [ [[INC_SPLIT:%.*]], [[FOR_INC_SPLIT:%.*]] ], [ [[IV_LCSSA]], [[LOOP_SPLIT_PREHEADER]] ]
91 ; CHECK-NEXT: [[CMP_SPLIT:%.*]] = icmp ult i64 [[IV_SPLIT]], [[B]]
92 ; CHECK-NEXT: br i1 false, label [[IF_THEN_SPLIT:%.*]], label [[IF_ELSE_SPLIT:%.*]]
93 ; CHECK: if.else.split:
94 ; CHECK-NEXT: br label [[FOR_INC_SPLIT]]
95 ; CHECK: if.then.split:
96 ; CHECK-NEXT: [[SRC_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, ptr [[SRC]], i64 [[IV_SPLIT]]
97 ; CHECK-NEXT: [[VAL_SPLIT:%.*]] = load i64, ptr [[SRC_ARRAYIDX_SPLIT]], align 4
98 ; CHECK-NEXT: [[DST_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, ptr [[DST]], i64 [[IV_SPLIT]]
99 ; CHECK-NEXT: store i64 [[VAL_SPLIT]], ptr [[DST_ARRAYIDX_SPLIT]], align 4
100 ; CHECK-NEXT: br label [[FOR_INC_SPLIT]]
101 ; CHECK: for.inc.split:
102 ; CHECK-NEXT: [[INC_SPLIT]] = add nuw nsw i64 [[IV_SPLIT]], 1
103 ; CHECK-NEXT: [[COND_SPLIT:%.*]] = icmp sgt i64 [[INC_SPLIT]], [[N]]
104 ; CHECK-NEXT: br i1 [[COND_SPLIT]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP_SPLIT]]
105 ; CHECK: exit.loopexit:
106 ; CHECK-NEXT: br label [[EXIT]]
108 ; CHECK-NEXT: ret void
111 %b = call i64 @llvm.umax.i64(i64 %a, i64 1)
115 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ]
116 %cmp = icmp ult i64 %iv, %b
117 br i1 %cmp, label %if.then, label %if.else
120 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv
121 %val = load i64, ptr %src.arrayidx
122 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv
123 store i64 %val, ptr %dst.arrayidx
130 %inc = add nuw nsw i64 %iv, 1
131 %cond = icmp sgt i64 %inc, %n
132 br i1 %cond, label %exit, label %loop
138 ; The transformation works with this test because we can guarantee the split
139 ; condition is always true in pre-loop after transformation.
140 define void @constant_split_loop_bound_and_exit_cond_inc_with_sgt(ptr noalias %src, ptr noalias %dst, i64 %n) {
141 ; CHECK-LABEL: @constant_split_loop_bound_and_exit_cond_inc_with_sgt(
142 ; CHECK-NEXT: loop.ph:
143 ; CHECK-NEXT: br label [[LOOP_PH_SPLIT:%.*]]
144 ; CHECK: loop.ph.split:
145 ; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N:%.*]], i64 0)
146 ; CHECK-NEXT: [[NEW_BOUND:%.*]] = call i64 @llvm.smin.i64(i64 [[SMAX]], i64 10)
147 ; CHECK-NEXT: br label [[LOOP:%.*]]
149 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH_SPLIT]] ]
150 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], 10
151 ; CHECK-NEXT: br i1 true, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
153 ; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[SRC:%.*]], i64 [[IV]]
154 ; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[SRC_ARRAYIDX]], align 4
155 ; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]]
156 ; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4
157 ; CHECK-NEXT: br label [[FOR_INC]]
159 ; CHECK-NEXT: br label [[FOR_INC]]
161 ; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 1
162 ; CHECK-NEXT: [[COND:%.*]] = icmp sgt i64 [[INC]], [[NEW_BOUND]]
163 ; CHECK-NEXT: br i1 [[COND]], label [[LOOP_PH_SPLIT_SPLIT:%.*]], label [[LOOP]]
164 ; CHECK: loop.ph.split.split:
165 ; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i64 [ [[INC]], [[FOR_INC]] ]
166 ; CHECK-NEXT: [[TMP0:%.*]] = icmp ne i64 [[IV_LCSSA]], [[N]]
167 ; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_SPLIT_PREHEADER:%.*]], label [[EXIT:%.*]]
168 ; CHECK: loop.split.preheader:
169 ; CHECK-NEXT: br label [[LOOP_SPLIT:%.*]]
171 ; CHECK-NEXT: [[IV_SPLIT:%.*]] = phi i64 [ [[INC_SPLIT:%.*]], [[FOR_INC_SPLIT:%.*]] ], [ [[IV_LCSSA]], [[LOOP_SPLIT_PREHEADER]] ]
172 ; CHECK-NEXT: [[CMP_SPLIT:%.*]] = icmp ult i64 [[IV_SPLIT]], 10
173 ; CHECK-NEXT: br i1 false, label [[IF_THEN_SPLIT:%.*]], label [[IF_ELSE_SPLIT:%.*]]
174 ; CHECK: if.else.split:
175 ; CHECK-NEXT: br label [[FOR_INC_SPLIT]]
176 ; CHECK: if.then.split:
177 ; CHECK-NEXT: [[SRC_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, ptr [[SRC]], i64 [[IV_SPLIT]]
178 ; CHECK-NEXT: [[VAL_SPLIT:%.*]] = load i64, ptr [[SRC_ARRAYIDX_SPLIT]], align 4
179 ; CHECK-NEXT: [[DST_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, ptr [[DST]], i64 [[IV_SPLIT]]
180 ; CHECK-NEXT: store i64 [[VAL_SPLIT]], ptr [[DST_ARRAYIDX_SPLIT]], align 4
181 ; CHECK-NEXT: br label [[FOR_INC_SPLIT]]
182 ; CHECK: for.inc.split:
183 ; CHECK-NEXT: [[INC_SPLIT]] = add nuw nsw i64 [[IV_SPLIT]], 1
184 ; CHECK-NEXT: [[COND_SPLIT:%.*]] = icmp sgt i64 [[INC_SPLIT]], [[N]]
185 ; CHECK-NEXT: br i1 [[COND_SPLIT]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP_SPLIT]]
186 ; CHECK: exit.loopexit:
187 ; CHECK-NEXT: br label [[EXIT]]
189 ; CHECK-NEXT: ret void
195 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ]
196 %cmp = icmp ult i64 %iv, 10
197 br i1 %cmp, label %if.then, label %if.else
200 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv
201 %val = load i64, ptr %src.arrayidx
202 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv
203 store i64 %val, ptr %dst.arrayidx
210 %inc = add nuw nsw i64 %iv, 1
211 %cond = icmp sgt i64 %inc, %n
212 br i1 %cond, label %exit, label %loop
218 define void @variable_split_loop_bound_and_exit_cond_inc_with_eq(i64 %a, ptr noalias %src, ptr noalias %dst, i64 %n) {
219 ; CHECK-LABEL: @variable_split_loop_bound_and_exit_cond_inc_with_eq(
220 ; CHECK-NEXT: loop.ph:
221 ; CHECK-NEXT: br label [[LOOP:%.*]]
223 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ]
224 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], [[A:%.*]]
225 ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
227 ; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[SRC:%.*]], i64 [[IV]]
228 ; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[SRC_ARRAYIDX]], align 4
229 ; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]]
230 ; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4
231 ; CHECK-NEXT: br label [[FOR_INC]]
233 ; CHECK-NEXT: br label [[FOR_INC]]
235 ; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 1
236 ; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[INC]], [[N:%.*]]
237 ; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]]
239 ; CHECK-NEXT: ret void
245 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ]
246 %cmp = icmp ult i64 %iv, %a
247 br i1 %cmp, label %if.then, label %if.else
250 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv
251 %val = load i64, ptr %src.arrayidx
252 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv
253 store i64 %val, ptr %dst.arrayidx
260 %inc = add nuw nsw i64 %iv, 1
261 %cond = icmp eq i64 %inc, %n
262 br i1 %cond, label %exit, label %loop
268 define void @constant_split_loop_bound_and_exit_cond_inc_with_eq(ptr noalias %src, ptr noalias %dst, i64 %n) {
269 ; CHECK-LABEL: @constant_split_loop_bound_and_exit_cond_inc_with_eq(
270 ; CHECK-NEXT: loop.ph:
271 ; CHECK-NEXT: br label [[LOOP_PH_SPLIT:%.*]]
272 ; CHECK: loop.ph.split:
273 ; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[N:%.*]], -1
274 ; CHECK-NEXT: [[NEW_BOUND:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP0]], i64 10)
275 ; CHECK-NEXT: br label [[LOOP:%.*]]
277 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH_SPLIT]] ]
278 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], 10
279 ; CHECK-NEXT: br i1 true, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
281 ; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[SRC:%.*]], i64 [[IV]]
282 ; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[SRC_ARRAYIDX]], align 4
283 ; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]]
284 ; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4
285 ; CHECK-NEXT: br label [[FOR_INC]]
287 ; CHECK-NEXT: br label [[FOR_INC]]
289 ; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 1
290 ; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[INC]], [[NEW_BOUND]]
291 ; CHECK-NEXT: br i1 [[COND]], label [[LOOP_PH_SPLIT_SPLIT:%.*]], label [[LOOP]]
292 ; CHECK: loop.ph.split.split:
293 ; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i64 [ [[INC]], [[FOR_INC]] ]
294 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i64 [[IV_LCSSA]], [[N]]
295 ; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_SPLIT_PREHEADER:%.*]], label [[EXIT:%.*]]
296 ; CHECK: loop.split.preheader:
297 ; CHECK-NEXT: br label [[LOOP_SPLIT:%.*]]
299 ; CHECK-NEXT: [[IV_SPLIT:%.*]] = phi i64 [ [[INC_SPLIT:%.*]], [[FOR_INC_SPLIT:%.*]] ], [ [[IV_LCSSA]], [[LOOP_SPLIT_PREHEADER]] ]
300 ; CHECK-NEXT: [[CMP_SPLIT:%.*]] = icmp ult i64 [[IV_SPLIT]], 10
301 ; CHECK-NEXT: br i1 false, label [[IF_THEN_SPLIT:%.*]], label [[IF_ELSE_SPLIT:%.*]]
302 ; CHECK: if.else.split:
303 ; CHECK-NEXT: br label [[FOR_INC_SPLIT]]
304 ; CHECK: if.then.split:
305 ; CHECK-NEXT: [[SRC_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, ptr [[SRC]], i64 [[IV_SPLIT]]
306 ; CHECK-NEXT: [[VAL_SPLIT:%.*]] = load i64, ptr [[SRC_ARRAYIDX_SPLIT]], align 4
307 ; CHECK-NEXT: [[DST_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, ptr [[DST]], i64 [[IV_SPLIT]]
308 ; CHECK-NEXT: store i64 [[VAL_SPLIT]], ptr [[DST_ARRAYIDX_SPLIT]], align 4
309 ; CHECK-NEXT: br label [[FOR_INC_SPLIT]]
310 ; CHECK: for.inc.split:
311 ; CHECK-NEXT: [[INC_SPLIT]] = add nuw nsw i64 [[IV_SPLIT]], 1
312 ; CHECK-NEXT: [[COND_SPLIT:%.*]] = icmp eq i64 [[INC_SPLIT]], [[N]]
313 ; CHECK-NEXT: br i1 [[COND_SPLIT]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP_SPLIT]]
314 ; CHECK: exit.loopexit:
315 ; CHECK-NEXT: br label [[EXIT]]
317 ; CHECK-NEXT: ret void
323 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ]
324 %cmp = icmp ult i64 %iv, 10
325 br i1 %cmp, label %if.then, label %if.else
328 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv
329 %val = load i64, ptr %src.arrayidx
330 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv
331 store i64 %val, ptr %dst.arrayidx
338 %inc = add nuw nsw i64 %iv, 1
339 %cond = icmp eq i64 %inc, %n
340 br i1 %cond, label %exit, label %loop
346 define void @variable_split_loop_bound_and_exit_cond_inc_with_sge(i64 %a, ptr noalias %src, ptr noalias %dst, i64 %n) {
347 ; CHECK-LABEL: @variable_split_loop_bound_and_exit_cond_inc_with_sge(
348 ; CHECK-NEXT: loop.ph:
349 ; CHECK-NEXT: br label [[LOOP:%.*]]
351 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ]
352 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], [[A:%.*]]
353 ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
355 ; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[SRC:%.*]], i64 [[IV]]
356 ; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[SRC_ARRAYIDX]], align 4
357 ; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]]
358 ; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4
359 ; CHECK-NEXT: br label [[FOR_INC]]
361 ; CHECK-NEXT: br label [[FOR_INC]]
363 ; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 1
364 ; CHECK-NEXT: [[COND:%.*]] = icmp sge i64 [[INC]], [[N:%.*]]
365 ; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]]
367 ; CHECK-NEXT: ret void
373 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ]
374 %cmp = icmp ult i64 %iv, %a
375 br i1 %cmp, label %if.then, label %if.else
378 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv
379 %val = load i64, ptr %src.arrayidx
380 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv
381 store i64 %val, ptr %dst.arrayidx
388 %inc = add nuw nsw i64 %iv, 1
389 %cond = icmp sge i64 %inc, %n
390 br i1 %cond, label %exit, label %loop
396 define void @constant_split_loop_bound_and_exit_cond_inc_with_sge(ptr noalias %src, ptr noalias %dst, i64 %n) {
397 ; CHECK-LABEL: @constant_split_loop_bound_and_exit_cond_inc_with_sge(
398 ; CHECK-NEXT: loop.ph:
399 ; CHECK-NEXT: br label [[LOOP_PH_SPLIT:%.*]]
400 ; CHECK: loop.ph.split:
401 ; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N:%.*]], i64 1)
402 ; CHECK-NEXT: [[TMP0:%.*]] = add nsw i64 [[SMAX]], -1
403 ; CHECK-NEXT: [[NEW_BOUND:%.*]] = call i64 @llvm.smin.i64(i64 [[TMP0]], i64 10)
404 ; CHECK-NEXT: br label [[LOOP:%.*]]
406 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH_SPLIT]] ]
407 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], 10
408 ; CHECK-NEXT: br i1 true, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
410 ; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[SRC:%.*]], i64 [[IV]]
411 ; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[SRC_ARRAYIDX]], align 4
412 ; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]]
413 ; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4
414 ; CHECK-NEXT: br label [[FOR_INC]]
416 ; CHECK-NEXT: br label [[FOR_INC]]
418 ; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 1
419 ; CHECK-NEXT: [[COND:%.*]] = icmp sge i64 [[INC]], [[NEW_BOUND]]
420 ; CHECK-NEXT: br i1 [[COND]], label [[LOOP_PH_SPLIT_SPLIT:%.*]], label [[LOOP]]
421 ; CHECK: loop.ph.split.split:
422 ; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i64 [ [[INC]], [[FOR_INC]] ]
423 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i64 [[IV_LCSSA]], [[N]]
424 ; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_SPLIT_PREHEADER:%.*]], label [[EXIT:%.*]]
425 ; CHECK: loop.split.preheader:
426 ; CHECK-NEXT: br label [[LOOP_SPLIT:%.*]]
428 ; CHECK-NEXT: [[IV_SPLIT:%.*]] = phi i64 [ [[INC_SPLIT:%.*]], [[FOR_INC_SPLIT:%.*]] ], [ [[IV_LCSSA]], [[LOOP_SPLIT_PREHEADER]] ]
429 ; CHECK-NEXT: [[CMP_SPLIT:%.*]] = icmp ult i64 [[IV_SPLIT]], 10
430 ; CHECK-NEXT: br i1 false, label [[IF_THEN_SPLIT:%.*]], label [[IF_ELSE_SPLIT:%.*]]
431 ; CHECK: if.else.split:
432 ; CHECK-NEXT: br label [[FOR_INC_SPLIT]]
433 ; CHECK: if.then.split:
434 ; CHECK-NEXT: [[SRC_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, ptr [[SRC]], i64 [[IV_SPLIT]]
435 ; CHECK-NEXT: [[VAL_SPLIT:%.*]] = load i64, ptr [[SRC_ARRAYIDX_SPLIT]], align 4
436 ; CHECK-NEXT: [[DST_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, ptr [[DST]], i64 [[IV_SPLIT]]
437 ; CHECK-NEXT: store i64 [[VAL_SPLIT]], ptr [[DST_ARRAYIDX_SPLIT]], align 4
438 ; CHECK-NEXT: br label [[FOR_INC_SPLIT]]
439 ; CHECK: for.inc.split:
440 ; CHECK-NEXT: [[INC_SPLIT]] = add nuw nsw i64 [[IV_SPLIT]], 1
441 ; CHECK-NEXT: [[COND_SPLIT:%.*]] = icmp sge i64 [[INC_SPLIT]], [[N]]
442 ; CHECK-NEXT: br i1 [[COND_SPLIT]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP_SPLIT]]
443 ; CHECK: exit.loopexit:
444 ; CHECK-NEXT: br label [[EXIT]]
446 ; CHECK-NEXT: ret void
452 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ]
453 %cmp = icmp ult i64 %iv, 10
454 br i1 %cmp, label %if.then, label %if.else
457 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv
458 %val = load i64, ptr %src.arrayidx
459 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv
460 store i64 %val, ptr %dst.arrayidx
467 %inc = add nuw nsw i64 %iv, 1
468 %cond = icmp sge i64 %inc, %n
469 br i1 %cond, label %exit, label %loop
475 define void @variable_split_loop_bound_and_exit_cond_inc_with_step_is_not_one(i64 %a, ptr noalias %src, ptr noalias %dst, i64 %n) {
476 ; CHECK-LABEL: @variable_split_loop_bound_and_exit_cond_inc_with_step_is_not_one(
477 ; CHECK-NEXT: loop.ph:
478 ; CHECK-NEXT: br label [[LOOP:%.*]]
480 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ]
481 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], [[A:%.*]]
482 ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
484 ; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[SRC:%.*]], i64 [[IV]]
485 ; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[SRC_ARRAYIDX]], align 4
486 ; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]]
487 ; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4
488 ; CHECK-NEXT: br label [[FOR_INC]]
490 ; CHECK-NEXT: br label [[FOR_INC]]
492 ; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 2
493 ; CHECK-NEXT: [[COND:%.*]] = icmp sgt i64 [[INC]], [[N:%.*]]
494 ; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]]
496 ; CHECK-NEXT: ret void
502 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ]
503 %cmp = icmp ult i64 %iv, %a
504 br i1 %cmp, label %if.then, label %if.else
507 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv
508 %val = load i64, ptr %src.arrayidx
509 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv
510 store i64 %val, ptr %dst.arrayidx
517 %inc = add nuw nsw i64 %iv, 2
518 %cond = icmp sgt i64 %inc, %n
519 br i1 %cond, label %exit, label %loop
525 define void @constant_split_loop_bound_and_exit_cond_inc_with_step_is_not_one(ptr noalias %src, ptr noalias %dst, i64 %n) {
526 ; CHECK-LABEL: @constant_split_loop_bound_and_exit_cond_inc_with_step_is_not_one(
527 ; CHECK-NEXT: loop.ph:
528 ; CHECK-NEXT: br label [[LOOP_PH_SPLIT:%.*]]
529 ; CHECK: loop.ph.split:
530 ; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N:%.*]], i64 1)
531 ; CHECK-NEXT: [[TMP0:%.*]] = lshr i64 [[SMAX]], 1
532 ; CHECK-NEXT: [[NEW_BOUND:%.*]] = call i64 @llvm.smin.i64(i64 [[TMP0]], i64 10)
533 ; CHECK-NEXT: br label [[LOOP:%.*]]
535 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH_SPLIT]] ]
536 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], 10
537 ; CHECK-NEXT: br i1 true, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
539 ; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[SRC:%.*]], i64 [[IV]]
540 ; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[SRC_ARRAYIDX]], align 4
541 ; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]]
542 ; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4
543 ; CHECK-NEXT: br label [[FOR_INC]]
545 ; CHECK-NEXT: br label [[FOR_INC]]
547 ; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 2
548 ; CHECK-NEXT: [[COND:%.*]] = icmp sgt i64 [[INC]], [[NEW_BOUND]]
549 ; CHECK-NEXT: br i1 [[COND]], label [[LOOP_PH_SPLIT_SPLIT:%.*]], label [[LOOP]]
550 ; CHECK: loop.ph.split.split:
551 ; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i64 [ [[INC]], [[FOR_INC]] ]
552 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i64 [[IV_LCSSA]], [[N]]
553 ; CHECK-NEXT: br i1 [[TMP1]], label [[LOOP_SPLIT_PREHEADER:%.*]], label [[EXIT:%.*]]
554 ; CHECK: loop.split.preheader:
555 ; CHECK-NEXT: br label [[LOOP_SPLIT:%.*]]
557 ; CHECK-NEXT: [[IV_SPLIT:%.*]] = phi i64 [ [[INC_SPLIT:%.*]], [[FOR_INC_SPLIT:%.*]] ], [ [[IV_LCSSA]], [[LOOP_SPLIT_PREHEADER]] ]
558 ; CHECK-NEXT: [[CMP_SPLIT:%.*]] = icmp ult i64 [[IV_SPLIT]], 10
559 ; CHECK-NEXT: br i1 false, label [[IF_THEN_SPLIT:%.*]], label [[IF_ELSE_SPLIT:%.*]]
560 ; CHECK: if.else.split:
561 ; CHECK-NEXT: br label [[FOR_INC_SPLIT]]
562 ; CHECK: if.then.split:
563 ; CHECK-NEXT: [[SRC_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, ptr [[SRC]], i64 [[IV_SPLIT]]
564 ; CHECK-NEXT: [[VAL_SPLIT:%.*]] = load i64, ptr [[SRC_ARRAYIDX_SPLIT]], align 4
565 ; CHECK-NEXT: [[DST_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, ptr [[DST]], i64 [[IV_SPLIT]]
566 ; CHECK-NEXT: store i64 [[VAL_SPLIT]], ptr [[DST_ARRAYIDX_SPLIT]], align 4
567 ; CHECK-NEXT: br label [[FOR_INC_SPLIT]]
568 ; CHECK: for.inc.split:
569 ; CHECK-NEXT: [[INC_SPLIT]] = add nuw nsw i64 [[IV_SPLIT]], 2
570 ; CHECK-NEXT: [[COND_SPLIT:%.*]] = icmp sgt i64 [[INC_SPLIT]], [[N]]
571 ; CHECK-NEXT: br i1 [[COND_SPLIT]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP_SPLIT]]
572 ; CHECK: exit.loopexit:
573 ; CHECK-NEXT: br label [[EXIT]]
575 ; CHECK-NEXT: ret void
581 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ]
582 %cmp = icmp ult i64 %iv, 10
583 br i1 %cmp, label %if.then, label %if.else
586 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv
587 %val = load i64, ptr %src.arrayidx
588 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv
589 store i64 %val, ptr %dst.arrayidx
596 %inc = add nuw nsw i64 %iv, 2
597 %cond = icmp sgt i64 %inc, %n
598 br i1 %cond, label %exit, label %loop
604 define void @variable_split_loop_bound_and_exit_cond_inc_with_ne(i64 %a, ptr noalias %src, ptr noalias %dst, i64 %n) {
605 ; CHECK-LABEL: @variable_split_loop_bound_and_exit_cond_inc_with_ne(
606 ; CHECK-NEXT: loop.ph:
607 ; CHECK-NEXT: br label [[LOOP:%.*]]
609 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ]
610 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], [[A:%.*]]
611 ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[FOR_INC]]
613 ; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[SRC:%.*]], i64 [[IV]]
614 ; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[SRC_ARRAYIDX]], align 4
615 ; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]]
616 ; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4
617 ; CHECK-NEXT: br label [[FOR_INC]]
619 ; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 1
620 ; CHECK-NEXT: [[COND:%.*]] = icmp ne i64 [[INC]], [[N:%.*]]
621 ; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]]
623 ; CHECK-NEXT: ret void
629 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ]
630 %cmp = icmp ult i64 %iv, %a
631 br i1 %cmp, label %if.then, label %for.inc
634 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv
635 %val = load i64, ptr %src.arrayidx
636 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv
637 store i64 %val, ptr %dst.arrayidx
641 %inc = add nuw nsw i64 %iv, 1
642 %cond = icmp ne i64 %inc, %n
643 br i1 %cond, label %exit, label %loop
649 define void @constant_split_loop_bound_and_exit_cond_inc_with_ne(ptr noalias %src, ptr noalias %dst, i64 %n) {
650 ; CHECK-LABEL: @constant_split_loop_bound_and_exit_cond_inc_with_ne(
651 ; CHECK-NEXT: loop.ph:
652 ; CHECK-NEXT: br label [[LOOP:%.*]]
654 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ]
655 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], 10
656 ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[FOR_INC]]
658 ; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[SRC:%.*]], i64 [[IV]]
659 ; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[SRC_ARRAYIDX]], align 4
660 ; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]]
661 ; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4
662 ; CHECK-NEXT: br label [[FOR_INC]]
664 ; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 1
665 ; CHECK-NEXT: [[COND:%.*]] = icmp ne i64 [[INC]], [[N:%.*]]
666 ; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]]
668 ; CHECK-NEXT: ret void
674 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ]
675 %cmp = icmp ult i64 %iv, 10
676 br i1 %cmp, label %if.then, label %for.inc
679 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv
680 %val = load i64, ptr %src.arrayidx
681 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv
682 store i64 %val, ptr %dst.arrayidx
686 %inc = add nuw nsw i64 %iv, 1
687 %cond = icmp ne i64 %inc, %n
688 br i1 %cond, label %exit, label %loop
694 define void @varialbe_split_loop_bound_and_exit_cond_dec_with_slt(i64 %a, ptr noalias %src, ptr noalias %dst, i64 %n) {
695 ; CHECK-LABEL: @varialbe_split_loop_bound_and_exit_cond_dec_with_slt(
696 ; CHECK-NEXT: loop.ph:
697 ; CHECK-NEXT: br label [[LOOP:%.*]]
699 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[DEC:%.*]], [[FOR_DEC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ]
700 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], [[A:%.*]]
701 ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[FOR_DEC]]
703 ; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[SRC:%.*]], i64 [[IV]]
704 ; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[SRC_ARRAYIDX]], align 4
705 ; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]]
706 ; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4
707 ; CHECK-NEXT: br label [[FOR_DEC]]
709 ; CHECK-NEXT: [[DEC]] = sub nuw nsw i64 [[IV]], 1
710 ; CHECK-NEXT: [[COND:%.*]] = icmp slt i64 [[DEC]], [[N:%.*]]
711 ; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]]
713 ; CHECK-NEXT: ret void
719 %iv = phi i64 [ %dec, %for.dec ], [ 0, %loop.ph ]
720 %cmp = icmp ult i64 %iv, %a
721 br i1 %cmp, label %if.then, label %for.dec
724 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv
725 %val = load i64, ptr %src.arrayidx
726 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv
727 store i64 %val, ptr %dst.arrayidx
731 %dec = sub nuw nsw i64 %iv, 1
732 %cond = icmp slt i64 %dec, %n
733 br i1 %cond, label %exit, label %loop
739 define void @constant_split_loop_bound_and_exit_cond_dec_with_slt(ptr noalias %src, ptr noalias %dst, i64 %n) {
740 ; CHECK-LABEL: @constant_split_loop_bound_and_exit_cond_dec_with_slt(
741 ; CHECK-NEXT: loop.ph:
742 ; CHECK-NEXT: br label [[LOOP:%.*]]
744 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[DEC:%.*]], [[FOR_DEC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ]
745 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], 10
746 ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[FOR_DEC]]
748 ; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[SRC:%.*]], i64 [[IV]]
749 ; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[SRC_ARRAYIDX]], align 4
750 ; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]]
751 ; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4
752 ; CHECK-NEXT: br label [[FOR_DEC]]
754 ; CHECK-NEXT: [[DEC]] = sub nuw nsw i64 [[IV]], 1
755 ; CHECK-NEXT: [[COND:%.*]] = icmp slt i64 [[DEC]], [[N:%.*]]
756 ; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]]
758 ; CHECK-NEXT: ret void
764 %iv = phi i64 [ %dec, %for.dec ], [ 0, %loop.ph ]
765 %cmp = icmp ult i64 %iv, 10
766 br i1 %cmp, label %if.then, label %for.dec
769 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv
770 %val = load i64, ptr %src.arrayidx
771 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv
772 store i64 %val, ptr %dst.arrayidx
776 %dec = sub nuw nsw i64 %iv, 1
777 %cond = icmp slt i64 %dec, %n
778 br i1 %cond, label %exit, label %loop
784 define void @variable_split_loop_bound_and_exit_cond_dec_with_sle(i64 %a, ptr noalias %src, ptr noalias %dst, i64 %n) {
785 ; CHECK-LABEL: @variable_split_loop_bound_and_exit_cond_dec_with_sle(
786 ; CHECK-NEXT: loop.ph:
787 ; CHECK-NEXT: br label [[LOOP:%.*]]
789 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[DEC:%.*]], [[FOR_DEC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ]
790 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], [[A:%.*]]
791 ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[FOR_DEC]]
793 ; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[SRC:%.*]], i64 [[IV]]
794 ; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[SRC_ARRAYIDX]], align 4
795 ; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]]
796 ; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4
797 ; CHECK-NEXT: br label [[FOR_DEC]]
799 ; CHECK-NEXT: [[DEC]] = sub nuw nsw i64 [[IV]], 1
800 ; CHECK-NEXT: [[COND:%.*]] = icmp sle i64 [[DEC]], [[N:%.*]]
801 ; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]]
803 ; CHECK-NEXT: ret void
809 %iv = phi i64 [ %dec, %for.dec ], [ 0, %loop.ph ]
810 %cmp = icmp ult i64 %iv, %a
811 br i1 %cmp, label %if.then, label %for.dec
814 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv
815 %val = load i64, ptr %src.arrayidx
816 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv
817 store i64 %val, ptr %dst.arrayidx
821 %dec = sub nuw nsw i64 %iv, 1
822 %cond = icmp sle i64 %dec, %n
823 br i1 %cond, label %exit, label %loop
829 define void @constant_split_loop_bound_and_exit_cond_dec_with_sle(ptr noalias %src, ptr noalias %dst, i64 %n) {
830 ; CHECK-LABEL: @constant_split_loop_bound_and_exit_cond_dec_with_sle(
831 ; CHECK-NEXT: loop.ph:
832 ; CHECK-NEXT: br label [[LOOP:%.*]]
834 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[DEC:%.*]], [[FOR_DEC:%.*]] ], [ 0, [[LOOP_PH:%.*]] ]
835 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], 10
836 ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[FOR_DEC]]
838 ; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[SRC:%.*]], i64 [[IV]]
839 ; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[SRC_ARRAYIDX]], align 4
840 ; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]]
841 ; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4
842 ; CHECK-NEXT: br label [[FOR_DEC]]
844 ; CHECK-NEXT: [[DEC]] = sub nuw nsw i64 [[IV]], 1
845 ; CHECK-NEXT: [[COND:%.*]] = icmp sle i64 [[DEC]], [[N:%.*]]
846 ; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP]]
848 ; CHECK-NEXT: ret void
854 %iv = phi i64 [ %dec, %for.dec ], [ 0, %loop.ph ]
855 %cmp = icmp ult i64 %iv, 10
856 br i1 %cmp, label %if.then, label %for.dec
859 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv
860 %val = load i64, ptr %src.arrayidx
861 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv
862 store i64 %val, ptr %dst.arrayidx
866 %dec = sub nuw nsw i64 %iv, 1
867 %cond = icmp sle i64 %dec, %n
868 br i1 %cond, label %exit, label %loop
874 ; LoopBoundSplit pass should ignore phi which is not scevable phi.
875 define void @constant_split_loop_bound_and_exit_cond_inc_with_sgt_and_is_not_scevable_phi(ptr noalias %src, ptr noalias %dst, i64 %n) {
876 ; CHECK-LABEL: @constant_split_loop_bound_and_exit_cond_inc_with_sgt_and_is_not_scevable_phi(
877 ; CHECK-NEXT: loop.ph:
878 ; CHECK-NEXT: br label [[LOOP_PH_SPLIT:%.*]]
879 ; CHECK: loop.ph.split:
880 ; CHECK-NEXT: [[SMAX:%.*]] = call i64 @llvm.smax.i64(i64 [[N:%.*]], i64 0)
881 ; CHECK-NEXT: [[NEW_BOUND:%.*]] = call i64 @llvm.smin.i64(i64 [[SMAX]], i64 10)
882 ; CHECK-NEXT: br label [[LOOP:%.*]]
884 ; CHECK-NEXT: [[IS_NOT_SCEVABLE_PHI:%.*]] = phi double [ 1.000000e+00, [[FOR_INC:%.*]] ], [ 2.000000e+00, [[LOOP_PH_SPLIT]] ]
885 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[INC:%.*]], [[FOR_INC]] ], [ 0, [[LOOP_PH_SPLIT]] ]
886 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[IV]], 10
887 ; CHECK-NEXT: br i1 true, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
889 ; CHECK-NEXT: [[SRC_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[SRC:%.*]], i64 [[IV]]
890 ; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[SRC_ARRAYIDX]], align 4
891 ; CHECK-NEXT: [[DST_ARRAYIDX:%.*]] = getelementptr inbounds i64, ptr [[DST:%.*]], i64 [[IV]]
892 ; CHECK-NEXT: store i64 [[VAL]], ptr [[DST_ARRAYIDX]], align 4
893 ; CHECK-NEXT: br label [[FOR_INC]]
895 ; CHECK-NEXT: br label [[FOR_INC]]
897 ; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[IV]], 1
898 ; CHECK-NEXT: [[COND:%.*]] = icmp sgt i64 [[INC]], [[NEW_BOUND]]
899 ; CHECK-NEXT: br i1 [[COND]], label [[LOOP_PH_SPLIT_SPLIT:%.*]], label [[LOOP]]
900 ; CHECK: loop.ph.split.split:
901 ; CHECK-NEXT: [[IS_NOT_SCEVABLE_PHI_LCSSA:%.*]] = phi double [ 1.000000e+00, [[FOR_INC]] ]
902 ; CHECK-NEXT: [[IV_LCSSA:%.*]] = phi i64 [ [[INC]], [[FOR_INC]] ]
903 ; CHECK-NEXT: [[TMP0:%.*]] = icmp ne i64 [[IV_LCSSA]], [[N]]
904 ; CHECK-NEXT: br i1 [[TMP0]], label [[LOOP_SPLIT_PREHEADER:%.*]], label [[EXIT:%.*]]
905 ; CHECK: loop.split.preheader:
906 ; CHECK-NEXT: br label [[LOOP_SPLIT:%.*]]
908 ; CHECK-NEXT: [[IS_NOT_SCEVABLE_PHI_SPLIT:%.*]] = phi double [ 1.000000e+00, [[FOR_INC_SPLIT:%.*]] ], [ [[IS_NOT_SCEVABLE_PHI_LCSSA]], [[LOOP_SPLIT_PREHEADER]] ]
909 ; CHECK-NEXT: [[IV_SPLIT:%.*]] = phi i64 [ [[INC_SPLIT:%.*]], [[FOR_INC_SPLIT]] ], [ [[IV_LCSSA]], [[LOOP_SPLIT_PREHEADER]] ]
910 ; CHECK-NEXT: [[CMP_SPLIT:%.*]] = icmp ult i64 [[IV_SPLIT]], 10
911 ; CHECK-NEXT: br i1 false, label [[IF_THEN_SPLIT:%.*]], label [[IF_ELSE_SPLIT:%.*]]
912 ; CHECK: if.else.split:
913 ; CHECK-NEXT: br label [[FOR_INC_SPLIT]]
914 ; CHECK: if.then.split:
915 ; CHECK-NEXT: [[SRC_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, ptr [[SRC]], i64 [[IV_SPLIT]]
916 ; CHECK-NEXT: [[VAL_SPLIT:%.*]] = load i64, ptr [[SRC_ARRAYIDX_SPLIT]], align 4
917 ; CHECK-NEXT: [[DST_ARRAYIDX_SPLIT:%.*]] = getelementptr inbounds i64, ptr [[DST]], i64 [[IV_SPLIT]]
918 ; CHECK-NEXT: store i64 [[VAL_SPLIT]], ptr [[DST_ARRAYIDX_SPLIT]], align 4
919 ; CHECK-NEXT: br label [[FOR_INC_SPLIT]]
920 ; CHECK: for.inc.split:
921 ; CHECK-NEXT: [[INC_SPLIT]] = add nuw nsw i64 [[IV_SPLIT]], 1
922 ; CHECK-NEXT: [[COND_SPLIT:%.*]] = icmp sgt i64 [[INC_SPLIT]], [[N]]
923 ; CHECK-NEXT: br i1 [[COND_SPLIT]], label [[EXIT_LOOPEXIT:%.*]], label [[LOOP_SPLIT]]
924 ; CHECK: exit.loopexit:
925 ; CHECK-NEXT: br label [[EXIT]]
927 ; CHECK-NEXT: ret void
933 %is_not_scevable_phi = phi double [ 1.0, %for.inc ], [ 2.0, %loop.ph ]
934 %iv = phi i64 [ %inc, %for.inc ], [ 0, %loop.ph ]
935 %cmp = icmp ult i64 %iv, 10
936 br i1 %cmp, label %if.then, label %if.else
939 %src.arrayidx = getelementptr inbounds i64, ptr %src, i64 %iv
940 %val = load i64, ptr %src.arrayidx
941 %dst.arrayidx = getelementptr inbounds i64, ptr %dst, i64 %iv
942 store i64 %val, ptr %dst.arrayidx
949 %inc = add nuw nsw i64 %iv, 1
950 %cond = icmp sgt i64 %inc, %n
951 br i1 %cond, label %exit, label %loop
957 declare i64 @llvm.umax.i64(i64, i64)