Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / LoopBoundSplit / loop-bound-split.ll
blob433b0f051598e8bd62326454f782e60f31596961
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(
8 ; CHECK-NEXT:  loop.ph:
9 ; CHECK-NEXT:    br label [[LOOP:%.*]]
10 ; CHECK:       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:%.*]]
14 ; CHECK:       if.then:
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]]
20 ; CHECK:       if.else:
21 ; CHECK-NEXT:    br label [[FOR_INC]]
22 ; CHECK:       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]]
26 ; CHECK:       exit:
27 ; CHECK-NEXT:    ret void
29 loop.ph:
30   br label %loop
32 loop:
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
37 if.then:
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
42   br label %for.inc
44 if.else:
45   br label %for.inc
47 for.inc:
48   %inc = add nuw nsw i64 %iv, 1
49   %cond = icmp sgt i64 %inc, %n
50   br i1 %cond, label %exit, label %loop
52 exit:
53   ret void
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:%.*]]
67 ; CHECK:       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:%.*]]
71 ; CHECK:       if.then:
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]]
77 ; CHECK:       if.else:
78 ; CHECK-NEXT:    br label [[FOR_INC]]
79 ; CHECK:       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:%.*]]
89 ; CHECK:       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]]
107 ; CHECK:       exit:
108 ; CHECK-NEXT:    ret void
110 loop.ph:
111   %b = call i64 @llvm.umax.i64(i64 %a, i64 1)
112   br label %loop
114 loop:
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
119 if.then:
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
124   br label %for.inc
126 if.else:
127   br label %for.inc
129 for.inc:
130   %inc = add nuw nsw i64 %iv, 1
131   %cond = icmp sgt i64 %inc, %n
132   br i1 %cond, label %exit, label %loop
134 exit:
135   ret void
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:%.*]]
148 ; CHECK:       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:%.*]]
152 ; CHECK:       if.then:
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]]
158 ; CHECK:       if.else:
159 ; CHECK-NEXT:    br label [[FOR_INC]]
160 ; CHECK:       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:%.*]]
170 ; CHECK:       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]]
188 ; CHECK:       exit:
189 ; CHECK-NEXT:    ret void
191 loop.ph:
192   br label %loop
194 loop:
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
199 if.then:
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
204   br label %for.inc
206 if.else:
207   br label %for.inc
209 for.inc:
210   %inc = add nuw nsw i64 %iv, 1
211   %cond = icmp sgt i64 %inc, %n
212   br i1 %cond, label %exit, label %loop
214 exit:
215   ret void
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:%.*]]
222 ; CHECK:       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:%.*]]
226 ; CHECK:       if.then:
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]]
232 ; CHECK:       if.else:
233 ; CHECK-NEXT:    br label [[FOR_INC]]
234 ; CHECK:       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]]
238 ; CHECK:       exit:
239 ; CHECK-NEXT:    ret void
241 loop.ph:
242   br label %loop
244 loop:
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
249 if.then:
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
254   br label %for.inc
256 if.else:
257   br label %for.inc
259 for.inc:
260   %inc = add nuw nsw i64 %iv, 1
261   %cond = icmp eq i64 %inc, %n
262   br i1 %cond, label %exit, label %loop
264 exit:
265   ret void
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:%.*]]
276 ; CHECK:       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:%.*]]
280 ; CHECK:       if.then:
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]]
286 ; CHECK:       if.else:
287 ; CHECK-NEXT:    br label [[FOR_INC]]
288 ; CHECK:       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:%.*]]
298 ; CHECK:       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]]
316 ; CHECK:       exit:
317 ; CHECK-NEXT:    ret void
319 loop.ph:
320   br label %loop
322 loop:
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
327 if.then:
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
332   br label %for.inc
334 if.else:
335   br label %for.inc
337 for.inc:
338   %inc = add nuw nsw i64 %iv, 1
339   %cond = icmp eq i64 %inc, %n
340   br i1 %cond, label %exit, label %loop
342 exit:
343   ret void
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:%.*]]
350 ; CHECK:       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:%.*]]
354 ; CHECK:       if.then:
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]]
360 ; CHECK:       if.else:
361 ; CHECK-NEXT:    br label [[FOR_INC]]
362 ; CHECK:       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]]
366 ; CHECK:       exit:
367 ; CHECK-NEXT:    ret void
369 loop.ph:
370   br label %loop
372 loop:
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
377 if.then:
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
382   br label %for.inc
384 if.else:
385   br label %for.inc
387 for.inc:
388   %inc = add nuw nsw i64 %iv, 1
389   %cond = icmp sge i64 %inc, %n
390   br i1 %cond, label %exit, label %loop
392 exit:
393   ret void
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:%.*]]
405 ; CHECK:       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:%.*]]
409 ; CHECK:       if.then:
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]]
415 ; CHECK:       if.else:
416 ; CHECK-NEXT:    br label [[FOR_INC]]
417 ; CHECK:       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:%.*]]
427 ; CHECK:       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]]
445 ; CHECK:       exit:
446 ; CHECK-NEXT:    ret void
448 loop.ph:
449   br label %loop
451 loop:
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
456 if.then:
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
461   br label %for.inc
463 if.else:
464   br label %for.inc
466 for.inc:
467   %inc = add nuw nsw i64 %iv, 1
468   %cond = icmp sge i64 %inc, %n
469   br i1 %cond, label %exit, label %loop
471 exit:
472   ret void
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:%.*]]
479 ; CHECK:       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:%.*]]
483 ; CHECK:       if.then:
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]]
489 ; CHECK:       if.else:
490 ; CHECK-NEXT:    br label [[FOR_INC]]
491 ; CHECK:       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]]
495 ; CHECK:       exit:
496 ; CHECK-NEXT:    ret void
498 loop.ph:
499   br label %loop
501 loop:
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
506 if.then:
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
511   br label %for.inc
513 if.else:
514   br label %for.inc
516 for.inc:
517   %inc = add nuw nsw i64 %iv, 2
518   %cond = icmp sgt i64 %inc, %n
519   br i1 %cond, label %exit, label %loop
521 exit:
522   ret void
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:%.*]]
534 ; CHECK:       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:%.*]]
538 ; CHECK:       if.then:
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]]
544 ; CHECK:       if.else:
545 ; CHECK-NEXT:    br label [[FOR_INC]]
546 ; CHECK:       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:%.*]]
556 ; CHECK:       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]]
574 ; CHECK:       exit:
575 ; CHECK-NEXT:    ret void
577 loop.ph:
578   br label %loop
580 loop:
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
585 if.then:
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
590   br label %for.inc
592 if.else:
593   br label %for.inc
595 for.inc:
596   %inc = add nuw nsw i64 %iv, 2
597   %cond = icmp sgt i64 %inc, %n
598   br i1 %cond, label %exit, label %loop
600 exit:
601   ret void
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:%.*]]
608 ; CHECK:       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]]
612 ; CHECK:       if.then:
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]]
618 ; CHECK:       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]]
622 ; CHECK:       exit:
623 ; CHECK-NEXT:    ret void
625 loop.ph:
626   br label %loop
628 loop:
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
633 if.then:
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
638   br label %for.inc
640 for.inc:
641   %inc = add nuw nsw i64 %iv, 1
642   %cond = icmp ne i64 %inc, %n
643   br i1 %cond, label %exit, label %loop
645 exit:
646   ret void
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:%.*]]
653 ; CHECK:       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]]
657 ; CHECK:       if.then:
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]]
663 ; CHECK:       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]]
667 ; CHECK:       exit:
668 ; CHECK-NEXT:    ret void
670 loop.ph:
671   br label %loop
673 loop:
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
678 if.then:
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
683   br label %for.inc
685 for.inc:
686   %inc = add nuw nsw i64 %iv, 1
687   %cond = icmp ne i64 %inc, %n
688   br i1 %cond, label %exit, label %loop
690 exit:
691   ret void
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:%.*]]
698 ; CHECK:       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]]
702 ; CHECK:       if.then:
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]]
708 ; CHECK:       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]]
712 ; CHECK:       exit:
713 ; CHECK-NEXT:    ret void
715 loop.ph:
716   br label %loop
718 loop:
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
723 if.then:
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
728   br label %for.dec
730 for.dec:
731   %dec = sub nuw nsw i64 %iv, 1
732   %cond = icmp slt i64 %dec, %n
733   br i1 %cond, label %exit, label %loop
735 exit:
736   ret void
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:%.*]]
743 ; CHECK:       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]]
747 ; CHECK:       if.then:
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]]
753 ; CHECK:       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]]
757 ; CHECK:       exit:
758 ; CHECK-NEXT:    ret void
760 loop.ph:
761   br label %loop
763 loop:
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
768 if.then:
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
773   br label %for.dec
775 for.dec:
776   %dec = sub nuw nsw i64 %iv, 1
777   %cond = icmp slt i64 %dec, %n
778   br i1 %cond, label %exit, label %loop
780 exit:
781   ret void
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:%.*]]
788 ; CHECK:       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]]
792 ; CHECK:       if.then:
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]]
798 ; CHECK:       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]]
802 ; CHECK:       exit:
803 ; CHECK-NEXT:    ret void
805 loop.ph:
806   br label %loop
808 loop:
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
813 if.then:
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
818   br label %for.dec
820 for.dec:
821   %dec = sub nuw nsw i64 %iv, 1
822   %cond = icmp sle i64 %dec, %n
823   br i1 %cond, label %exit, label %loop
825 exit:
826   ret void
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:%.*]]
833 ; CHECK:       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]]
837 ; CHECK:       if.then:
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]]
843 ; CHECK:       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]]
847 ; CHECK:       exit:
848 ; CHECK-NEXT:    ret void
850 loop.ph:
851   br label %loop
853 loop:
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
858 if.then:
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
863   br label %for.dec
865 for.dec:
866   %dec = sub nuw nsw i64 %iv, 1
867   %cond = icmp sle i64 %dec, %n
868   br i1 %cond, label %exit, label %loop
870 exit:
871   ret void
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:%.*]]
883 ; CHECK:       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:%.*]]
888 ; CHECK:       if.then:
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]]
894 ; CHECK:       if.else:
895 ; CHECK-NEXT:    br label [[FOR_INC]]
896 ; CHECK:       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:%.*]]
907 ; CHECK:       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]]
926 ; CHECK:       exit:
927 ; CHECK-NEXT:    ret void
929 loop.ph:
930   br label %loop
932 loop:
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
938 if.then:
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
943   br label %for.inc
945 if.else:
946   br label %for.inc
948 for.inc:
949   %inc = add nuw nsw i64 %iv, 1
950   %cond = icmp sgt i64 %inc, %n
951   br i1 %cond, label %exit, label %loop
953 exit:
954   ret void
957 declare i64 @llvm.umax.i64(i64, i64)