1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
3 ; RUN: opt -S -passes=licm -ipt-expensive-asserts=true < %s | FileCheck %s
5 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
7 declare void @f() nounwind
8 declare void @llvm.experimental.guard(i1,...)
10 ; constant fold on first ieration
11 define i32 @test1(ptr noalias nocapture readonly %a) nounwind uwtable {
12 ; CHECK-LABEL: define i32 @test1(
13 ; CHECK-SAME: ptr noalias nocapture readonly [[A:%.*]]) #[[ATTR1:[0-9]+]] {
15 ; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 4
16 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
18 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[CONTINUE:%.*]] ]
19 ; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[CONTINUE]] ]
20 ; CHECK-NEXT: [[R_CHK:%.*]] = icmp ult i32 [[IV]], 2000
21 ; CHECK-NEXT: br i1 [[R_CHK]], label [[CONTINUE]], label [[FAIL:%.*]]
23 ; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[ACC]]
24 ; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[IV]], 1
25 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 1000
26 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]]
27 ; CHECK: for.cond.cleanup:
28 ; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[CONTINUE]] ]
29 ; CHECK-NEXT: ret i32 [[ADD_LCSSA]]
31 ; CHECK-NEXT: call void @f()
32 ; CHECK-NEXT: ret i32 -1
38 %iv = phi i32 [ 0, %entry ], [ %inc, %continue ]
39 %acc = phi i32 [ 0, %entry ], [ %add, %continue ]
40 %r.chk = icmp ult i32 %iv, 2000
41 br i1 %r.chk, label %continue, label %fail
43 %i1 = load i32, ptr %a, align 4
44 %add = add nsw i32 %i1, %acc
45 %inc = add nuw nsw i32 %iv, 1
46 %exitcond = icmp eq i32 %inc, 1000
47 br i1 %exitcond, label %for.cond.cleanup, label %for.body
57 ; Same as test1, but with a floating point IR and fcmp
58 define i32 @test_fcmp(ptr noalias nocapture readonly %a) nounwind uwtable {
59 ; CHECK-LABEL: define i32 @test_fcmp(
60 ; CHECK-SAME: ptr noalias nocapture readonly [[A:%.*]]) #[[ATTR1]] {
62 ; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 4
63 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
65 ; CHECK-NEXT: [[IV:%.*]] = phi float [ 0.000000e+00, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[CONTINUE:%.*]] ]
66 ; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[CONTINUE]] ]
67 ; CHECK-NEXT: [[R_CHK:%.*]] = fcmp olt float [[IV]], 2.000000e+03
68 ; CHECK-NEXT: br i1 [[R_CHK]], label [[CONTINUE]], label [[FAIL:%.*]]
70 ; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[ACC]]
71 ; CHECK-NEXT: [[INC]] = fadd float [[IV]], 1.000000e+00
72 ; CHECK-NEXT: [[EXITCOND:%.*]] = fcmp ogt float [[INC]], 1.000000e+03
73 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]]
74 ; CHECK: for.cond.cleanup:
75 ; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[CONTINUE]] ]
76 ; CHECK-NEXT: ret i32 [[ADD_LCSSA]]
78 ; CHECK-NEXT: call void @f()
79 ; CHECK-NEXT: ret i32 -1
85 %iv = phi float [ 0.0, %entry ], [ %inc, %continue ]
86 %acc = phi i32 [ 0, %entry ], [ %add, %continue ]
87 %r.chk = fcmp olt float %iv, 2000.0
88 br i1 %r.chk, label %continue, label %fail
90 %i1 = load i32, ptr %a, align 4
91 %add = add nsw i32 %i1, %acc
92 %inc = fadd float %iv, 1.0
93 %exitcond = fcmp ogt float %inc, 1000.0
94 br i1 %exitcond, label %for.cond.cleanup, label %for.body
104 ; Count down from a.length w/entry guard
105 ; TODO: currently unable to prove the following:
106 ; ule i32 (add nsw i32 %len, -1), %len where len is [0, 512]
107 define i32 @test2(ptr noalias nocapture readonly %a) nounwind uwtable {
108 ; CHECK-LABEL: define i32 @test2(
109 ; CHECK-SAME: ptr noalias nocapture readonly [[A:%.*]]) #[[ATTR1]] {
111 ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[A]], align 4, !range [[RNG0:![0-9]+]]
112 ; CHECK-NEXT: [[IS_NON_POS:%.*]] = icmp eq i32 [[LEN]], 0
113 ; CHECK-NEXT: br i1 [[IS_NON_POS]], label [[FAIL:%.*]], label [[PREHEADER:%.*]]
115 ; CHECK-NEXT: [[LENMINUSONE:%.*]] = add nsw i32 [[LEN]], -1
116 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
118 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[LENMINUSONE]], [[PREHEADER]] ], [ [[DEC:%.*]], [[CONTINUE:%.*]] ]
119 ; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[ADD:%.*]], [[CONTINUE]] ]
120 ; CHECK-NEXT: [[R_CHK:%.*]] = icmp ule i32 [[IV]], [[LEN]]
121 ; CHECK-NEXT: br i1 [[R_CHK]], label [[CONTINUE]], label [[FAIL_LOOPEXIT:%.*]]
123 ; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 4
124 ; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[ACC]]
125 ; CHECK-NEXT: [[DEC]] = add nsw i32 [[IV]], -1
126 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[DEC]], 0
127 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]]
128 ; CHECK: for.cond.cleanup:
129 ; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[CONTINUE]] ]
130 ; CHECK-NEXT: ret i32 [[ADD_LCSSA]]
131 ; CHECK: fail.loopexit:
132 ; CHECK-NEXT: br label [[FAIL]]
134 ; CHECK-NEXT: call void @f()
135 ; CHECK-NEXT: ret i32 -1
138 %len = load i32, ptr %a, align 4, !range !{i32 0, i32 512}
139 %is.non.pos = icmp eq i32 %len, 0
140 br i1 %is.non.pos, label %fail, label %preheader
142 %lenminusone = add nsw i32 %len, -1
145 %iv = phi i32 [ %lenminusone, %preheader ], [ %dec, %continue ]
146 %acc = phi i32 [ 0, %preheader ], [ %add, %continue ]
147 %r.chk = icmp ule i32 %iv, %len
148 br i1 %r.chk, label %continue, label %fail
150 %i1 = load i32, ptr %a, align 4
151 %add = add nsw i32 %i1, %acc
152 %dec = add nsw i32 %iv, -1
153 %exitcond = icmp eq i32 %dec, 0
154 br i1 %exitcond, label %for.cond.cleanup, label %for.body
164 ; trivially true for zero
165 define i32 @test3(ptr noalias nocapture readonly %a) nounwind uwtable {
166 ; CHECK-LABEL: define i32 @test3(
167 ; CHECK-SAME: ptr noalias nocapture readonly [[A:%.*]]) #[[ATTR1]] {
169 ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[A]], align 4, !range [[RNG0]]
170 ; CHECK-NEXT: [[IS_ZERO:%.*]] = icmp eq i32 [[LEN]], 0
171 ; CHECK-NEXT: br i1 [[IS_ZERO]], label [[FAIL:%.*]], label [[PREHEADER:%.*]]
173 ; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 4
174 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
176 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[INC:%.*]], [[CONTINUE:%.*]] ]
177 ; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[ADD:%.*]], [[CONTINUE]] ]
178 ; CHECK-NEXT: [[R_CHK:%.*]] = icmp ule i32 [[IV]], [[LEN]]
179 ; CHECK-NEXT: br i1 [[R_CHK]], label [[CONTINUE]], label [[FAIL_LOOPEXIT:%.*]]
181 ; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[ACC]]
182 ; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[IV]], 1
183 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 1000
184 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]]
185 ; CHECK: for.cond.cleanup:
186 ; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[CONTINUE]] ]
187 ; CHECK-NEXT: ret i32 [[ADD_LCSSA]]
188 ; CHECK: fail.loopexit:
189 ; CHECK-NEXT: br label [[FAIL]]
191 ; CHECK-NEXT: call void @f()
192 ; CHECK-NEXT: ret i32 -1
195 %len = load i32, ptr %a, align 4, !range !{i32 0, i32 512}
196 %is.zero = icmp eq i32 %len, 0
197 br i1 %is.zero, label %fail, label %preheader
201 %iv = phi i32 [ 0, %preheader ], [ %inc, %continue ]
202 %acc = phi i32 [ 0, %preheader ], [ %add, %continue ]
203 %r.chk = icmp ule i32 %iv, %len
204 br i1 %r.chk, label %continue, label %fail
206 %i1 = load i32, ptr %a, align 4
207 %add = add nsw i32 %i1, %acc
208 %inc = add nuw nsw i32 %iv, 1
209 %exitcond = icmp eq i32 %inc, 1000
210 br i1 %exitcond, label %for.cond.cleanup, label %for.body
220 ; Same as previous case, with commuted icmp.
221 define i32 @test3_commuted(ptr noalias nocapture readonly %a) nounwind uwtable {
222 ; CHECK-LABEL: define i32 @test3_commuted(
223 ; CHECK-SAME: ptr noalias nocapture readonly [[A:%.*]]) #[[ATTR1]] {
225 ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[A]], align 4, !range [[RNG0]]
226 ; CHECK-NEXT: [[IS_ZERO:%.*]] = icmp eq i32 [[LEN]], 0
227 ; CHECK-NEXT: br i1 [[IS_ZERO]], label [[FAIL:%.*]], label [[PREHEADER:%.*]]
229 ; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 4
230 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
232 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[INC:%.*]], [[CONTINUE:%.*]] ]
233 ; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[ADD:%.*]], [[CONTINUE]] ]
234 ; CHECK-NEXT: [[R_CHK:%.*]] = icmp uge i32 [[LEN]], [[IV]]
235 ; CHECK-NEXT: br i1 [[R_CHK]], label [[CONTINUE]], label [[FAIL_LOOPEXIT:%.*]]
237 ; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[ACC]]
238 ; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[IV]], 1
239 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 1000
240 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]]
241 ; CHECK: for.cond.cleanup:
242 ; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[CONTINUE]] ]
243 ; CHECK-NEXT: ret i32 [[ADD_LCSSA]]
244 ; CHECK: fail.loopexit:
245 ; CHECK-NEXT: br label [[FAIL]]
247 ; CHECK-NEXT: call void @f()
248 ; CHECK-NEXT: ret i32 -1
251 %len = load i32, ptr %a, align 4, !range !{i32 0, i32 512}
252 %is.zero = icmp eq i32 %len, 0
253 br i1 %is.zero, label %fail, label %preheader
257 %iv = phi i32 [ 0, %preheader ], [ %inc, %continue ]
258 %acc = phi i32 [ 0, %preheader ], [ %add, %continue ]
259 %r.chk = icmp uge i32 %len, %iv
260 br i1 %r.chk, label %continue, label %fail
262 %i1 = load i32, ptr %a, align 4
263 %add = add nsw i32 %i1, %acc
264 %inc = add nuw nsw i32 %iv, 1
265 %exitcond = icmp eq i32 %inc, 1000
266 br i1 %exitcond, label %for.cond.cleanup, label %for.body
276 ; requires fact length is non-zero
277 define i32 @test4(ptr noalias nocapture readonly %a) nounwind uwtable {
278 ; CHECK-LABEL: define i32 @test4(
279 ; CHECK-SAME: ptr noalias nocapture readonly [[A:%.*]]) #[[ATTR1]] {
281 ; CHECK-NEXT: [[LEN:%.*]] = load i32, ptr [[A]], align 4, !range [[RNG0]]
282 ; CHECK-NEXT: [[IS_ZERO:%.*]] = icmp eq i32 [[LEN]], 0
283 ; CHECK-NEXT: br i1 [[IS_ZERO]], label [[FAIL:%.*]], label [[PREHEADER:%.*]]
285 ; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 4
286 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
288 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[INC:%.*]], [[CONTINUE:%.*]] ]
289 ; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[PREHEADER]] ], [ [[ADD:%.*]], [[CONTINUE]] ]
290 ; CHECK-NEXT: [[R_CHK:%.*]] = icmp ult i32 [[IV]], [[LEN]]
291 ; CHECK-NEXT: br i1 [[R_CHK]], label [[CONTINUE]], label [[FAIL_LOOPEXIT:%.*]]
293 ; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[ACC]]
294 ; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[IV]], 1
295 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 1000
296 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]]
297 ; CHECK: for.cond.cleanup:
298 ; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[CONTINUE]] ]
299 ; CHECK-NEXT: ret i32 [[ADD_LCSSA]]
300 ; CHECK: fail.loopexit:
301 ; CHECK-NEXT: br label [[FAIL]]
303 ; CHECK-NEXT: call void @f()
304 ; CHECK-NEXT: ret i32 -1
307 %len = load i32, ptr %a, align 4, !range !{i32 0, i32 512}
308 %is.zero = icmp eq i32 %len, 0
309 br i1 %is.zero, label %fail, label %preheader
313 %iv = phi i32 [ 0, %preheader ], [ %inc, %continue ]
314 %acc = phi i32 [ 0, %preheader ], [ %add, %continue ]
315 %r.chk = icmp ult i32 %iv, %len
316 br i1 %r.chk, label %continue, label %fail
318 %i1 = load i32, ptr %a, align 4
319 %add = add nsw i32 %i1, %acc
320 %inc = add nuw nsw i32 %iv, 1
321 %exitcond = icmp eq i32 %inc, 1000
322 br i1 %exitcond, label %for.cond.cleanup, label %for.body
332 ; variation on test1 with branch swapped
333 define i32 @test-brswap(ptr noalias nocapture readonly %a) nounwind uwtable {
334 ; CHECK-LABEL: define i32 @test-brswap(
335 ; CHECK-SAME: ptr noalias nocapture readonly [[A:%.*]]) #[[ATTR1]] {
337 ; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 4
338 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
340 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[CONTINUE:%.*]] ]
341 ; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[CONTINUE]] ]
342 ; CHECK-NEXT: [[R_CHK:%.*]] = icmp ugt i32 [[IV]], 2000
343 ; CHECK-NEXT: br i1 [[R_CHK]], label [[FAIL:%.*]], label [[CONTINUE]]
345 ; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[ACC]]
346 ; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[IV]], 1
347 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 1000
348 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]]
349 ; CHECK: for.cond.cleanup:
350 ; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[CONTINUE]] ]
351 ; CHECK-NEXT: ret i32 [[ADD_LCSSA]]
353 ; CHECK-NEXT: call void @f()
354 ; CHECK-NEXT: ret i32 -1
360 %iv = phi i32 [ 0, %entry ], [ %inc, %continue ]
361 %acc = phi i32 [ 0, %entry ], [ %add, %continue ]
362 %r.chk = icmp ugt i32 %iv, 2000
363 br i1 %r.chk, label %fail, label %continue
365 %i1 = load i32, ptr %a, align 4
366 %add = add nsw i32 %i1, %acc
367 %inc = add nuw nsw i32 %iv, 1
368 %exitcond = icmp eq i32 %inc, 1000
369 br i1 %exitcond, label %for.cond.cleanup, label %for.body
379 define i32 @test-nonphi(ptr noalias nocapture readonly %a) nounwind uwtable {
380 ; CHECK-LABEL: define i32 @test-nonphi(
381 ; CHECK-SAME: ptr noalias nocapture readonly [[A:%.*]]) #[[ATTR1]] {
383 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
385 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[CONTINUE:%.*]] ]
386 ; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[CONTINUE]] ]
387 ; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[IV]], 72
388 ; CHECK-NEXT: [[R_CHK:%.*]] = icmp ugt i32 [[XOR]], 2000
389 ; CHECK-NEXT: br i1 [[R_CHK]], label [[FAIL:%.*]], label [[CONTINUE]]
391 ; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 4
392 ; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[ACC]]
393 ; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[IV]], 1
394 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 1000
395 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]]
396 ; CHECK: for.cond.cleanup:
397 ; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[CONTINUE]] ]
398 ; CHECK-NEXT: ret i32 [[ADD_LCSSA]]
400 ; CHECK-NEXT: call void @f()
401 ; CHECK-NEXT: ret i32 -1
407 %iv = phi i32 [ 0, %entry ], [ %inc, %continue ]
408 %acc = phi i32 [ 0, %entry ], [ %add, %continue ]
409 %xor = xor i32 %iv, 72
410 %r.chk = icmp ugt i32 %xor, 2000
411 br i1 %r.chk, label %fail, label %continue
413 %i1 = load i32, ptr %a, align 4
414 %add = add nsw i32 %i1, %acc
415 %inc = add nuw nsw i32 %iv, 1
416 %exitcond = icmp eq i32 %inc, 1000
417 br i1 %exitcond, label %for.cond.cleanup, label %for.body
427 define i32 @test-wrongphi(ptr noalias nocapture readonly %a) nounwind uwtable {
428 ; CHECK-LABEL: define i32 @test-wrongphi(
429 ; CHECK-SAME: ptr noalias nocapture readonly [[A:%.*]]) #[[ATTR1]] {
431 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
433 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[CONTINUE:%.*]] ]
434 ; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[CONTINUE]] ]
435 ; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[IV]], 500
436 ; CHECK-NEXT: br i1 [[COND]], label [[DUMMY_BLOCK1:%.*]], label [[DUMMY_BLOCK2:%.*]]
437 ; CHECK: dummy_block1:
438 ; CHECK-NEXT: br label [[DUMMY_BLOCK2]]
439 ; CHECK: dummy_block2:
440 ; CHECK-NEXT: [[WRONGPHI:%.*]] = phi i32 [ 11, [[FOR_BODY]] ], [ 12, [[DUMMY_BLOCK1]] ]
441 ; CHECK-NEXT: [[R_CHK:%.*]] = icmp ugt i32 [[WRONGPHI]], 2000
442 ; CHECK-NEXT: br i1 [[R_CHK]], label [[FAIL:%.*]], label [[CONTINUE]]
444 ; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 4
445 ; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[ACC]]
446 ; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[IV]], 1
447 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 1000
448 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]]
449 ; CHECK: for.cond.cleanup:
450 ; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[CONTINUE]] ]
451 ; CHECK-NEXT: ret i32 [[ADD_LCSSA]]
453 ; CHECK-NEXT: call void @f()
454 ; CHECK-NEXT: ret i32 -1
460 %iv = phi i32 [ 0, %entry ], [ %inc, %continue ]
461 %acc = phi i32 [ 0, %entry ], [ %add, %continue ]
462 %cond = icmp ult i32 %iv, 500
463 br i1 %cond, label %dummy_block1, label %dummy_block2
466 br label %dummy_block2
469 %wrongphi = phi i32 [11, %for.body], [12, %dummy_block1]
470 %r.chk = icmp ugt i32 %wrongphi, 2000
471 br i1 %r.chk, label %fail, label %continue
473 %i1 = load i32, ptr %a, align 4
474 %add = add nsw i32 %i1, %acc
475 %inc = add nuw nsw i32 %iv, 1
476 %exitcond = icmp eq i32 %inc, 1000
477 br i1 %exitcond, label %for.cond.cleanup, label %for.body
487 ; This works because loop-simplify is run implicitly, but test for it anyways
488 define i32 @test-multiple-latch(ptr noalias nocapture readonly %a) nounwind uwtable {
489 ; CHECK-LABEL: define i32 @test-multiple-latch(
490 ; CHECK-SAME: ptr noalias nocapture readonly [[A:%.*]]) #[[ATTR1]] {
492 ; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[A]], align 4
493 ; CHECK-NEXT: br label [[FOR_BODY:%.*]]
495 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY_BACKEDGE:%.*]] ]
496 ; CHECK-NEXT: [[ACC:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY_BACKEDGE]] ]
497 ; CHECK-NEXT: [[R_CHK:%.*]] = icmp ult i32 [[IV]], 2000
498 ; CHECK-NEXT: br i1 [[R_CHK]], label [[CONTINUE1:%.*]], label [[FAIL:%.*]]
500 ; CHECK-NEXT: [[ADD]] = add nsw i32 [[I1]], [[ACC]]
501 ; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[IV]], 1
502 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[ADD]], 0
503 ; CHECK-NEXT: br i1 [[CMP]], label [[CONTINUE2:%.*]], label [[FOR_BODY_BACKEDGE]]
504 ; CHECK: for.body.backedge:
505 ; CHECK-NEXT: br label [[FOR_BODY]]
507 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 1000
508 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY_BACKEDGE]]
509 ; CHECK: for.cond.cleanup:
510 ; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[CONTINUE2]] ]
511 ; CHECK-NEXT: ret i32 [[ADD_LCSSA]]
513 ; CHECK-NEXT: call void @f()
514 ; CHECK-NEXT: ret i32 -1
520 %iv = phi i32 [ 0, %entry ], [ %inc, %continue1 ], [ %inc, %continue2 ]
521 %acc = phi i32 [ 0, %entry ], [ %add, %continue1 ], [ %add, %continue2 ]
522 %r.chk = icmp ult i32 %iv, 2000
523 br i1 %r.chk, label %continue1, label %fail
525 %i1 = load i32, ptr %a, align 4
526 %add = add nsw i32 %i1, %acc
527 %inc = add nuw nsw i32 %iv, 1
528 %cmp = icmp eq i32 %add, 0
529 br i1 %cmp, label %continue2, label %for.body
531 %exitcond = icmp eq i32 %inc, 1000
532 br i1 %exitcond, label %for.cond.cleanup, label %for.body
542 define void @test-hoisting-in-presence-of-guards(i1 %c, ptr %p) {
543 ; CHECK-LABEL: define void @test-hoisting-in-presence-of-guards(
544 ; CHECK-SAME: i1 [[C:%.*]], ptr [[P:%.*]]) {
546 ; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[P]], align 4
547 ; CHECK-NEXT: [[INVARIANT_COND:%.*]] = icmp ne i32 [[A]], 100
548 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[INVARIANT_COND]]) [ "deopt"() ]
549 ; CHECK-NEXT: br label [[LOOP:%.*]]
551 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
552 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
553 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 1000
554 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
556 ; CHECK-NEXT: ret void
563 %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
564 %iv.next = add i32 %iv, 1
565 %a = load i32, ptr %p
566 %invariant_cond = icmp ne i32 %a, 100
567 call void (i1, ...) @llvm.experimental.guard(i1 %invariant_cond) [ "deopt"() ]
568 %loop_cond = icmp slt i32 %iv.next, 1000
569 br i1 %loop_cond, label %loop, label %exit
576 declare void @may_throw() inaccessiblememonly
578 ; Test that we can sink a mustexecute load from loop header even in presence of
579 ; throwing instructions after it.
580 define void @test_hoist_from_header_01(ptr %p, i32 %n) {
581 ; CHECK-LABEL: define void @test_hoist_from_header_01(
582 ; CHECK-SAME: ptr [[P:%.*]], i32 [[N:%.*]]) {
584 ; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[P]], align 4
585 ; CHECK-NEXT: br label [[LOOP:%.*]]
587 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
588 ; CHECK-NEXT: call void @may_throw()
589 ; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[IV]], [[N]]
590 ; CHECK-NEXT: br i1 [[COND]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
592 ; CHECK-NEXT: [[A:%.*]] = add i32 [[IV]], [[IV]]
593 ; CHECK-NEXT: br label [[BACKEDGE]]
595 ; CHECK-NEXT: [[B:%.*]] = mul i32 [[IV]], [[IV]]
596 ; CHECK-NEXT: br label [[BACKEDGE]]
598 ; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ [[A]], [[IF_TRUE]] ], [ [[B]], [[IF_FALSE]] ]
599 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[MERGE]]
600 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LOAD]]
601 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
603 ; CHECK-NEXT: ret void
610 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
611 %dummy = phi i32 [ 0, %entry ], [ %merge, %backedge ]
612 %load = load i32, ptr %p
613 call void @may_throw()
614 %cond = icmp slt i32 %iv, %n
615 br i1 %cond, label %if.true, label %if.false
618 %a = add i32 %iv, %iv
622 %b = mul i32 %iv, %iv
626 %merge = phi i32 [ %a, %if.true ], [ %b, %if.false ]
627 %iv.next = add i32 %iv, %merge
628 %loop.cond = icmp ult i32 %iv.next, %load
629 br i1 %loop.cond, label %loop, label %exit
635 define void @test_hoist_from_header_02(ptr %p, i32 %n) {
636 ; CHECK-LABEL: define void @test_hoist_from_header_02(
637 ; CHECK-SAME: ptr [[P:%.*]], i32 [[N:%.*]]) {
639 ; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[P]], align 4
640 ; CHECK-NEXT: br label [[LOOP:%.*]]
642 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
643 ; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[IV]], [[N]]
644 ; CHECK-NEXT: br i1 [[COND]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
646 ; CHECK-NEXT: call void @may_throw()
647 ; CHECK-NEXT: [[A:%.*]] = add i32 [[IV]], [[IV]]
648 ; CHECK-NEXT: br label [[BACKEDGE]]
650 ; CHECK-NEXT: [[B:%.*]] = mul i32 [[IV]], [[IV]]
651 ; CHECK-NEXT: br label [[BACKEDGE]]
653 ; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ [[A]], [[IF_TRUE]] ], [ [[B]], [[IF_FALSE]] ]
654 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[MERGE]]
655 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LOAD]]
656 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
658 ; CHECK-NEXT: ret void
665 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
666 %dummy = phi i32 [ 0, %entry ], [ %merge, %backedge ]
667 %load = load i32, ptr %p
668 %cond = icmp slt i32 %iv, %n
669 br i1 %cond, label %if.true, label %if.false
672 call void @may_throw()
673 %a = add i32 %iv, %iv
677 %b = mul i32 %iv, %iv
681 %merge = phi i32 [ %a, %if.true ], [ %b, %if.false ]
682 %iv.next = add i32 %iv, %merge
683 %loop.cond = icmp ult i32 %iv.next, %load
684 br i1 %loop.cond, label %loop, label %exit
690 define void @test_hoist_from_header_03(ptr %p, i32 %n) {
691 ; CHECK-LABEL: define void @test_hoist_from_header_03(
692 ; CHECK-SAME: ptr [[P:%.*]], i32 [[N:%.*]]) {
694 ; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[P]], align 4
695 ; CHECK-NEXT: br label [[LOOP:%.*]]
697 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
698 ; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[IV]], [[N]]
699 ; CHECK-NEXT: br i1 [[COND]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
701 ; CHECK-NEXT: [[A:%.*]] = add i32 [[IV]], [[IV]]
702 ; CHECK-NEXT: br label [[BACKEDGE]]
704 ; CHECK-NEXT: [[B:%.*]] = mul i32 [[IV]], [[IV]]
705 ; CHECK-NEXT: br label [[BACKEDGE]]
707 ; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ [[A]], [[IF_TRUE]] ], [ [[B]], [[IF_FALSE]] ]
708 ; CHECK-NEXT: call void @may_throw()
709 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[MERGE]]
710 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LOAD]]
711 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
713 ; CHECK-NEXT: ret void
720 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
721 %dummy = phi i32 [ 0, %entry ], [ %merge, %backedge ]
722 %load = load i32, ptr %p
723 %cond = icmp slt i32 %iv, %n
724 br i1 %cond, label %if.true, label %if.false
727 %a = add i32 %iv, %iv
731 %b = mul i32 %iv, %iv
735 %merge = phi i32 [ %a, %if.true ], [ %b, %if.false ]
736 call void @may_throw()
737 %iv.next = add i32 %iv, %merge
738 %loop.cond = icmp ult i32 %iv.next, %load
739 br i1 %loop.cond, label %loop, label %exit
745 ; Check that a throwing instruction prohibits hoisting across it.
746 define void @test_hoist_from_header_04(ptr %p, i32 %n) {
747 ; CHECK-LABEL: define void @test_hoist_from_header_04(
748 ; CHECK-SAME: ptr [[P:%.*]], i32 [[N:%.*]]) {
750 ; CHECK-NEXT: br label [[LOOP:%.*]]
752 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
753 ; CHECK-NEXT: call void @may_throw()
754 ; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[P]], align 4
755 ; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[IV]], [[N]]
756 ; CHECK-NEXT: br i1 [[COND]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
758 ; CHECK-NEXT: [[A:%.*]] = add i32 [[IV]], [[IV]]
759 ; CHECK-NEXT: br label [[BACKEDGE]]
761 ; CHECK-NEXT: [[B:%.*]] = mul i32 [[IV]], [[IV]]
762 ; CHECK-NEXT: br label [[BACKEDGE]]
764 ; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ [[A]], [[IF_TRUE]] ], [ [[B]], [[IF_FALSE]] ]
765 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[MERGE]]
766 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LOAD]]
767 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
769 ; CHECK-NEXT: ret void
776 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
777 %dummy = phi i32 [ 0, %entry ], [ %merge, %backedge ]
778 call void @may_throw()
779 %load = load i32, ptr %p
780 %cond = icmp slt i32 %iv, %n
781 br i1 %cond, label %if.true, label %if.false
784 %a = add i32 %iv, %iv
788 %b = mul i32 %iv, %iv
792 %merge = phi i32 [ %a, %if.true ], [ %b, %if.false ]
793 %iv.next = add i32 %iv, %merge
794 %loop.cond = icmp ult i32 %iv.next, %load
795 br i1 %loop.cond, label %loop, label %exit
801 ; Check that we can hoist a mustexecute load from backedge even if something
803 define void @test_hoist_from_backedge_01(ptr %p, i32 %n) {
804 ; CHECK-LABEL: define void @test_hoist_from_backedge_01(
805 ; CHECK-SAME: ptr [[P:%.*]], i32 [[N:%.*]]) {
807 ; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[P]], align 4
808 ; CHECK-NEXT: br label [[LOOP:%.*]]
810 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
811 ; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[IV]], [[N]]
812 ; CHECK-NEXT: br i1 [[COND]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
814 ; CHECK-NEXT: [[A:%.*]] = add i32 [[IV]], [[IV]]
815 ; CHECK-NEXT: br label [[BACKEDGE]]
817 ; CHECK-NEXT: [[B:%.*]] = mul i32 [[IV]], [[IV]]
818 ; CHECK-NEXT: br label [[BACKEDGE]]
820 ; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ [[A]], [[IF_TRUE]] ], [ [[B]], [[IF_FALSE]] ]
821 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[MERGE]]
822 ; CHECK-NEXT: call void @may_throw()
823 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LOAD]]
824 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
826 ; CHECK-NEXT: ret void
833 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
834 %dummy = phi i32 [ 0, %entry ], [ %merge, %backedge ]
835 %cond = icmp slt i32 %iv, %n
836 br i1 %cond, label %if.true, label %if.false
839 %a = add i32 %iv, %iv
843 %b = mul i32 %iv, %iv
847 %merge = phi i32 [ %a, %if.true ], [ %b, %if.false ]
848 %iv.next = add i32 %iv, %merge
849 %load = load i32, ptr %p
850 call void @may_throw()
851 %loop.cond = icmp ult i32 %iv.next, %load
852 br i1 %loop.cond, label %loop, label %exit
858 ; Check that we don't hoist the load if something before it can throw.
859 define void @test_hoist_from_backedge_02(ptr %p, i32 %n) {
860 ; CHECK-LABEL: define void @test_hoist_from_backedge_02(
861 ; CHECK-SAME: ptr [[P:%.*]], i32 [[N:%.*]]) {
863 ; CHECK-NEXT: br label [[LOOP:%.*]]
865 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
866 ; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[IV]], [[N]]
867 ; CHECK-NEXT: br i1 [[COND]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
869 ; CHECK-NEXT: [[A:%.*]] = add i32 [[IV]], [[IV]]
870 ; CHECK-NEXT: br label [[BACKEDGE]]
872 ; CHECK-NEXT: [[B:%.*]] = mul i32 [[IV]], [[IV]]
873 ; CHECK-NEXT: br label [[BACKEDGE]]
875 ; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ [[A]], [[IF_TRUE]] ], [ [[B]], [[IF_FALSE]] ]
876 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[MERGE]]
877 ; CHECK-NEXT: call void @may_throw()
878 ; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[P]], align 4
879 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LOAD]]
880 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
882 ; CHECK-NEXT: ret void
889 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
890 %dummy = phi i32 [ 0, %entry ], [ %merge, %backedge ]
891 %cond = icmp slt i32 %iv, %n
892 br i1 %cond, label %if.true, label %if.false
895 %a = add i32 %iv, %iv
899 %b = mul i32 %iv, %iv
903 %merge = phi i32 [ %a, %if.true ], [ %b, %if.false ]
904 %iv.next = add i32 %iv, %merge
905 call void @may_throw()
906 %load = load i32, ptr %p
907 %loop.cond = icmp ult i32 %iv.next, %load
908 br i1 %loop.cond, label %loop, label %exit
914 define void @test_hoist_from_backedge_03(ptr %p, i32 %n) {
915 ; CHECK-LABEL: define void @test_hoist_from_backedge_03(
916 ; CHECK-SAME: ptr [[P:%.*]], i32 [[N:%.*]]) {
918 ; CHECK-NEXT: br label [[LOOP:%.*]]
920 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
921 ; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[IV]], [[N]]
922 ; CHECK-NEXT: br i1 [[COND]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
924 ; CHECK-NEXT: [[A:%.*]] = add i32 [[IV]], [[IV]]
925 ; CHECK-NEXT: br label [[BACKEDGE]]
927 ; CHECK-NEXT: [[B:%.*]] = mul i32 [[IV]], [[IV]]
928 ; CHECK-NEXT: call void @may_throw()
929 ; CHECK-NEXT: br label [[BACKEDGE]]
931 ; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ [[A]], [[IF_TRUE]] ], [ [[B]], [[IF_FALSE]] ]
932 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[MERGE]]
933 ; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[P]], align 4
934 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LOAD]]
935 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
937 ; CHECK-NEXT: ret void
944 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
945 %dummy = phi i32 [ 0, %entry ], [ %merge, %backedge ]
946 %cond = icmp slt i32 %iv, %n
947 br i1 %cond, label %if.true, label %if.false
950 %a = add i32 %iv, %iv
954 %b = mul i32 %iv, %iv
955 call void @may_throw()
959 %merge = phi i32 [ %a, %if.true ], [ %b, %if.false ]
960 %iv.next = add i32 %iv, %merge
961 %load = load i32, ptr %p
962 %loop.cond = icmp ult i32 %iv.next, %load
963 br i1 %loop.cond, label %loop, label %exit
969 define void @test_hoist_from_backedge_04(ptr %p, i32 %n) {
970 ; CHECK-LABEL: define void @test_hoist_from_backedge_04(
971 ; CHECK-SAME: ptr [[P:%.*]], i32 [[N:%.*]]) {
973 ; CHECK-NEXT: br label [[LOOP:%.*]]
975 ; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
976 ; CHECK-NEXT: call void @may_throw()
977 ; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[IV]], [[N]]
978 ; CHECK-NEXT: br i1 [[COND]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
980 ; CHECK-NEXT: [[A:%.*]] = add i32 [[IV]], [[IV]]
981 ; CHECK-NEXT: br label [[BACKEDGE]]
983 ; CHECK-NEXT: [[B:%.*]] = mul i32 [[IV]], [[IV]]
984 ; CHECK-NEXT: br label [[BACKEDGE]]
986 ; CHECK-NEXT: [[MERGE:%.*]] = phi i32 [ [[A]], [[IF_TRUE]] ], [ [[B]], [[IF_FALSE]] ]
987 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], [[MERGE]]
988 ; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[P]], align 4
989 ; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[IV_NEXT]], [[LOAD]]
990 ; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
992 ; CHECK-NEXT: ret void
999 %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
1000 %dummy = phi i32 [ 0, %entry ], [ %merge, %backedge ]
1001 call void @may_throw()
1002 %cond = icmp slt i32 %iv, %n
1003 br i1 %cond, label %if.true, label %if.false
1006 %a = add i32 %iv, %iv
1010 %b = mul i32 %iv, %iv
1014 %merge = phi i32 [ %a, %if.true ], [ %b, %if.false ]
1015 %iv.next = add i32 %iv, %merge
1016 %load = load i32, ptr %p
1017 %loop.cond = icmp ult i32 %iv.next, %load
1018 br i1 %loop.cond, label %loop, label %exit
1024 ; CHECK: [[RNG0]] = !{i32 0, i32 512}