xref: /llvm-project/llvm/test/Transforms/LICM/hoist-mustexec.ll (revision 29441e4f5fa5f5c7709f7cf180815ba97f611297)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
2; REQUIRES: asserts
3; RUN: opt -S -passes=licm -ipt-expensive-asserts=true < %s | FileCheck %s
4
5target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
6
7declare void @f() nounwind
8declare void @llvm.experimental.guard(i1,...)
9
10; constant fold on first ieration
11define i32 @test1(ptr noalias nocapture readonly %a) nounwind uwtable {
12; CHECK-LABEL: define i32 @test1(
13; CHECK-SAME: ptr noalias readonly captures(none) [[A:%.*]]) #[[ATTR1:[0-9]+]] {
14; CHECK-NEXT:  entry:
15; CHECK-NEXT:    [[I1:%.*]] = load i32, ptr [[A]], align 4
16; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
17; CHECK:       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:%.*]]
22; CHECK:       continue:
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]]
30; CHECK:       fail:
31; CHECK-NEXT:    call void @f()
32; CHECK-NEXT:    ret i32 -1
33;
34entry:
35  br label %for.body
36
37for.body:
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
42continue:
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
48
49for.cond.cleanup:
50  ret i32 %add
51
52fail:
53  call void @f()
54  ret i32 -1
55}
56
57; Same as test1, but with a floating point IR and fcmp
58define i32 @test_fcmp(ptr noalias nocapture readonly %a) nounwind uwtable {
59; CHECK-LABEL: define i32 @test_fcmp(
60; CHECK-SAME: ptr noalias readonly captures(none) [[A:%.*]]) #[[ATTR1]] {
61; CHECK-NEXT:  entry:
62; CHECK-NEXT:    [[I1:%.*]] = load i32, ptr [[A]], align 4
63; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
64; CHECK:       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:%.*]]
69; CHECK:       continue:
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]]
77; CHECK:       fail:
78; CHECK-NEXT:    call void @f()
79; CHECK-NEXT:    ret i32 -1
80;
81entry:
82  br label %for.body
83
84for.body:
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
89continue:
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
95
96for.cond.cleanup:
97  ret i32 %add
98
99fail:
100  call void @f()
101  ret i32 -1
102}
103
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]
107define i32 @test2(ptr noalias nocapture readonly %a) nounwind uwtable {
108; CHECK-LABEL: define i32 @test2(
109; CHECK-SAME: ptr noalias readonly captures(none) [[A:%.*]]) #[[ATTR1]] {
110; CHECK-NEXT:  entry:
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:%.*]]
114; CHECK:       preheader:
115; CHECK-NEXT:    [[LENMINUSONE:%.*]] = add nsw i32 [[LEN]], -1
116; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
117; CHECK:       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:%.*]]
122; CHECK:       continue:
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]]
133; CHECK:       fail:
134; CHECK-NEXT:    call void @f()
135; CHECK-NEXT:    ret i32 -1
136;
137entry:
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
141preheader:
142  %lenminusone = add nsw i32 %len, -1
143  br label %for.body
144for.body:
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
149continue:
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
155
156for.cond.cleanup:
157  ret i32 %add
158
159fail:
160  call void @f()
161  ret i32 -1
162}
163
164; trivially true for zero
165define i32 @test3(ptr noalias nocapture readonly %a) nounwind uwtable {
166; CHECK-LABEL: define i32 @test3(
167; CHECK-SAME: ptr noalias readonly captures(none) [[A:%.*]]) #[[ATTR1]] {
168; CHECK-NEXT:  entry:
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:%.*]]
172; CHECK:       preheader:
173; CHECK-NEXT:    [[I1:%.*]] = load i32, ptr [[A]], align 4
174; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
175; CHECK:       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:%.*]]
180; CHECK:       continue:
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]]
190; CHECK:       fail:
191; CHECK-NEXT:    call void @f()
192; CHECK-NEXT:    ret i32 -1
193;
194entry:
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
198preheader:
199  br label %for.body
200for.body:
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
205continue:
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
211
212for.cond.cleanup:
213  ret i32 %add
214
215fail:
216  call void @f()
217  ret i32 -1
218}
219
220; Same as previous case, with commuted icmp.
221define i32 @test3_commuted(ptr noalias nocapture readonly %a) nounwind uwtable {
222; CHECK-LABEL: define i32 @test3_commuted(
223; CHECK-SAME: ptr noalias readonly captures(none) [[A:%.*]]) #[[ATTR1]] {
224; CHECK-NEXT:  entry:
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:%.*]]
228; CHECK:       preheader:
229; CHECK-NEXT:    [[I1:%.*]] = load i32, ptr [[A]], align 4
230; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
231; CHECK:       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:%.*]]
236; CHECK:       continue:
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]]
246; CHECK:       fail:
247; CHECK-NEXT:    call void @f()
248; CHECK-NEXT:    ret i32 -1
249;
250entry:
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
254preheader:
255  br label %for.body
256for.body:
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
261continue:
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
267
268for.cond.cleanup:
269  ret i32 %add
270
271fail:
272  call void @f()
273  ret i32 -1
274}
275
276; requires fact length is non-zero
277define i32 @test4(ptr noalias nocapture readonly %a) nounwind uwtable {
278; CHECK-LABEL: define i32 @test4(
279; CHECK-SAME: ptr noalias readonly captures(none) [[A:%.*]]) #[[ATTR1]] {
280; CHECK-NEXT:  entry:
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:%.*]]
284; CHECK:       preheader:
285; CHECK-NEXT:    [[I1:%.*]] = load i32, ptr [[A]], align 4
286; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
287; CHECK:       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:%.*]]
292; CHECK:       continue:
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]]
302; CHECK:       fail:
303; CHECK-NEXT:    call void @f()
304; CHECK-NEXT:    ret i32 -1
305;
306entry:
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
310preheader:
311  br label %for.body
312for.body:
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
317continue:
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
323
324for.cond.cleanup:
325  ret i32 %add
326
327fail:
328  call void @f()
329  ret i32 -1
330}
331
332; variation on test1 with branch swapped
333define i32 @test-brswap(ptr noalias nocapture readonly %a) nounwind uwtable {
334; CHECK-LABEL: define i32 @test-brswap(
335; CHECK-SAME: ptr noalias readonly captures(none) [[A:%.*]]) #[[ATTR1]] {
336; CHECK-NEXT:  entry:
337; CHECK-NEXT:    [[I1:%.*]] = load i32, ptr [[A]], align 4
338; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
339; CHECK:       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]]
344; CHECK:       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]]
352; CHECK:       fail:
353; CHECK-NEXT:    call void @f()
354; CHECK-NEXT:    ret i32 -1
355;
356entry:
357  br label %for.body
358
359for.body:
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
364continue:
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
370
371for.cond.cleanup:
372  ret i32 %add
373
374fail:
375  call void @f()
376  ret i32 -1
377}
378
379define i32 @test-nonphi(ptr noalias nocapture readonly %a) nounwind uwtable {
380; CHECK-LABEL: define i32 @test-nonphi(
381; CHECK-SAME: ptr noalias readonly captures(none) [[A:%.*]]) #[[ATTR1]] {
382; CHECK-NEXT:  entry:
383; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
384; CHECK:       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]]
390; CHECK:       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]]
399; CHECK:       fail:
400; CHECK-NEXT:    call void @f()
401; CHECK-NEXT:    ret i32 -1
402;
403entry:
404  br label %for.body
405
406for.body:
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
412continue:
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
418
419for.cond.cleanup:
420  ret i32 %add
421
422fail:
423  call void @f()
424  ret i32 -1
425}
426
427define i32 @test-wrongphi(ptr noalias nocapture readonly %a) nounwind uwtable {
428; CHECK-LABEL: define i32 @test-wrongphi(
429; CHECK-SAME: ptr noalias readonly captures(none) [[A:%.*]]) #[[ATTR1]] {
430; CHECK-NEXT:  entry:
431; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
432; CHECK:       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]]
443; CHECK:       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]]
452; CHECK:       fail:
453; CHECK-NEXT:    call void @f()
454; CHECK-NEXT:    ret i32 -1
455;
456entry:
457  br label %for.body
458
459for.body:
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
464
465dummy_block1:
466  br label %dummy_block2
467
468dummy_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
472continue:
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
478
479for.cond.cleanup:
480  ret i32 %add
481
482fail:
483  call void @f()
484  ret i32 -1
485}
486
487; This works because loop-simplify is run implicitly, but test for it anyways
488define i32 @test-multiple-latch(ptr noalias nocapture readonly %a) nounwind uwtable {
489; CHECK-LABEL: define i32 @test-multiple-latch(
490; CHECK-SAME: ptr noalias readonly captures(none) [[A:%.*]]) #[[ATTR1]] {
491; CHECK-NEXT:  entry:
492; CHECK-NEXT:    [[I1:%.*]] = load i32, ptr [[A]], align 4
493; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
494; CHECK:       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:%.*]]
499; CHECK:       continue1:
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]]
506; CHECK:       continue2:
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]]
512; CHECK:       fail:
513; CHECK-NEXT:    call void @f()
514; CHECK-NEXT:    ret i32 -1
515;
516entry:
517  br label %for.body
518
519for.body:
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
524continue1:
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
530continue2:
531  %exitcond = icmp eq i32 %inc, 1000
532  br i1 %exitcond, label %for.cond.cleanup, label %for.body
533
534for.cond.cleanup:
535  ret i32 %add
536
537fail:
538  call void @f()
539  ret i32 -1
540}
541
542define 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:%.*]]) {
545; CHECK-NEXT:  entry:
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:%.*]]
550; CHECK:       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:%.*]]
555; CHECK:       exit:
556; CHECK-NEXT:    ret void
557;
558
559entry:
560  br label %loop
561
562loop:
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
570
571exit:
572  ret void
573}
574
575
576declare void @may_throw() inaccessiblememonly
577
578; Test that we can sink a mustexecute load from loop header even in presence of
579; throwing instructions after it.
580define 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:%.*]]) {
583; CHECK-NEXT:  entry:
584; CHECK-NEXT:    [[LOAD:%.*]] = load i32, ptr [[P]], align 4
585; CHECK-NEXT:    br label [[LOOP:%.*]]
586; CHECK:       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:%.*]]
591; CHECK:       if.true:
592; CHECK-NEXT:    [[A:%.*]] = add i32 [[IV]], [[IV]]
593; CHECK-NEXT:    br label [[BACKEDGE]]
594; CHECK:       if.false:
595; CHECK-NEXT:    [[B:%.*]] = mul i32 [[IV]], [[IV]]
596; CHECK-NEXT:    br label [[BACKEDGE]]
597; CHECK:       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:%.*]]
602; CHECK:       exit:
603; CHECK-NEXT:    ret void
604;
605
606entry:
607  br label %loop
608
609loop:
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
616
617if.true:
618  %a = add i32 %iv, %iv
619  br label %backedge
620
621if.false:
622  %b = mul i32 %iv, %iv
623  br label %backedge
624
625backedge:
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
630
631exit:
632  ret void
633}
634
635define 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:%.*]]) {
638; CHECK-NEXT:  entry:
639; CHECK-NEXT:    [[LOAD:%.*]] = load i32, ptr [[P]], align 4
640; CHECK-NEXT:    br label [[LOOP:%.*]]
641; CHECK:       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:%.*]]
645; CHECK:       if.true:
646; CHECK-NEXT:    call void @may_throw()
647; CHECK-NEXT:    [[A:%.*]] = add i32 [[IV]], [[IV]]
648; CHECK-NEXT:    br label [[BACKEDGE]]
649; CHECK:       if.false:
650; CHECK-NEXT:    [[B:%.*]] = mul i32 [[IV]], [[IV]]
651; CHECK-NEXT:    br label [[BACKEDGE]]
652; CHECK:       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:%.*]]
657; CHECK:       exit:
658; CHECK-NEXT:    ret void
659;
660
661entry:
662  br label %loop
663
664loop:
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
670
671if.true:
672  call void @may_throw()
673  %a = add i32 %iv, %iv
674  br label %backedge
675
676if.false:
677  %b = mul i32 %iv, %iv
678  br label %backedge
679
680backedge:
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
685
686exit:
687  ret void
688}
689
690define 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:%.*]]) {
693; CHECK-NEXT:  entry:
694; CHECK-NEXT:    [[LOAD:%.*]] = load i32, ptr [[P]], align 4
695; CHECK-NEXT:    br label [[LOOP:%.*]]
696; CHECK:       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:%.*]]
700; CHECK:       if.true:
701; CHECK-NEXT:    [[A:%.*]] = add i32 [[IV]], [[IV]]
702; CHECK-NEXT:    br label [[BACKEDGE]]
703; CHECK:       if.false:
704; CHECK-NEXT:    [[B:%.*]] = mul i32 [[IV]], [[IV]]
705; CHECK-NEXT:    br label [[BACKEDGE]]
706; CHECK:       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:%.*]]
712; CHECK:       exit:
713; CHECK-NEXT:    ret void
714;
715
716entry:
717  br label %loop
718
719loop:
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
725
726if.true:
727  %a = add i32 %iv, %iv
728  br label %backedge
729
730if.false:
731  %b = mul i32 %iv, %iv
732  br label %backedge
733
734backedge:
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
740
741exit:
742  ret void
743}
744
745; Check that a throwing instruction prohibits hoisting across it.
746define 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:%.*]]) {
749; CHECK-NEXT:  entry:
750; CHECK-NEXT:    br label [[LOOP:%.*]]
751; CHECK:       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:%.*]]
757; CHECK:       if.true:
758; CHECK-NEXT:    [[A:%.*]] = add i32 [[IV]], [[IV]]
759; CHECK-NEXT:    br label [[BACKEDGE]]
760; CHECK:       if.false:
761; CHECK-NEXT:    [[B:%.*]] = mul i32 [[IV]], [[IV]]
762; CHECK-NEXT:    br label [[BACKEDGE]]
763; CHECK:       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:%.*]]
768; CHECK:       exit:
769; CHECK-NEXT:    ret void
770;
771
772entry:
773  br label %loop
774
775loop:
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
782
783if.true:
784  %a = add i32 %iv, %iv
785  br label %backedge
786
787if.false:
788  %b = mul i32 %iv, %iv
789  br label %backedge
790
791backedge:
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
796
797exit:
798  ret void
799}
800
801; Check that we can hoist a mustexecute load from backedge even if something
802; throws after it.
803define 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:%.*]]) {
806; CHECK-NEXT:  entry:
807; CHECK-NEXT:    [[LOAD:%.*]] = load i32, ptr [[P]], align 4
808; CHECK-NEXT:    br label [[LOOP:%.*]]
809; CHECK:       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:%.*]]
813; CHECK:       if.true:
814; CHECK-NEXT:    [[A:%.*]] = add i32 [[IV]], [[IV]]
815; CHECK-NEXT:    br label [[BACKEDGE]]
816; CHECK:       if.false:
817; CHECK-NEXT:    [[B:%.*]] = mul i32 [[IV]], [[IV]]
818; CHECK-NEXT:    br label [[BACKEDGE]]
819; CHECK:       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:%.*]]
825; CHECK:       exit:
826; CHECK-NEXT:    ret void
827;
828
829entry:
830  br label %loop
831
832loop:
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
837
838if.true:
839  %a = add i32 %iv, %iv
840  br label %backedge
841
842if.false:
843  %b = mul i32 %iv, %iv
844  br label %backedge
845
846backedge:
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
853
854exit:
855  ret void
856}
857
858; Check that we don't hoist the load if something before it can throw.
859define 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:%.*]]) {
862; CHECK-NEXT:  entry:
863; CHECK-NEXT:    br label [[LOOP:%.*]]
864; CHECK:       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:%.*]]
868; CHECK:       if.true:
869; CHECK-NEXT:    [[A:%.*]] = add i32 [[IV]], [[IV]]
870; CHECK-NEXT:    br label [[BACKEDGE]]
871; CHECK:       if.false:
872; CHECK-NEXT:    [[B:%.*]] = mul i32 [[IV]], [[IV]]
873; CHECK-NEXT:    br label [[BACKEDGE]]
874; CHECK:       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:%.*]]
881; CHECK:       exit:
882; CHECK-NEXT:    ret void
883;
884
885entry:
886  br label %loop
887
888loop:
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
893
894if.true:
895  %a = add i32 %iv, %iv
896  br label %backedge
897
898if.false:
899  %b = mul i32 %iv, %iv
900  br label %backedge
901
902backedge:
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
909
910exit:
911  ret void
912}
913
914define 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:%.*]]) {
917; CHECK-NEXT:  entry:
918; CHECK-NEXT:    br label [[LOOP:%.*]]
919; CHECK:       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:%.*]]
923; CHECK:       if.true:
924; CHECK-NEXT:    [[A:%.*]] = add i32 [[IV]], [[IV]]
925; CHECK-NEXT:    br label [[BACKEDGE]]
926; CHECK:       if.false:
927; CHECK-NEXT:    [[B:%.*]] = mul i32 [[IV]], [[IV]]
928; CHECK-NEXT:    call void @may_throw()
929; CHECK-NEXT:    br label [[BACKEDGE]]
930; CHECK:       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:%.*]]
936; CHECK:       exit:
937; CHECK-NEXT:    ret void
938;
939
940entry:
941  br label %loop
942
943loop:
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
948
949if.true:
950  %a = add i32 %iv, %iv
951  br label %backedge
952
953if.false:
954  %b = mul i32 %iv, %iv
955  call void @may_throw()
956  br label %backedge
957
958backedge:
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
964
965exit:
966  ret void
967}
968
969define 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:%.*]]) {
972; CHECK-NEXT:  entry:
973; CHECK-NEXT:    br label [[LOOP:%.*]]
974; CHECK:       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:%.*]]
979; CHECK:       if.true:
980; CHECK-NEXT:    [[A:%.*]] = add i32 [[IV]], [[IV]]
981; CHECK-NEXT:    br label [[BACKEDGE]]
982; CHECK:       if.false:
983; CHECK-NEXT:    [[B:%.*]] = mul i32 [[IV]], [[IV]]
984; CHECK-NEXT:    br label [[BACKEDGE]]
985; CHECK:       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:%.*]]
991; CHECK:       exit:
992; CHECK-NEXT:    ret void
993;
994
995entry:
996  br label %loop
997
998loop:
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
1004
1005if.true:
1006  %a = add i32 %iv, %iv
1007  br label %backedge
1008
1009if.false:
1010  %b = mul i32 %iv, %iv
1011  br label %backedge
1012
1013backedge:
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
1019
1020exit:
1021  ret void
1022}
1023;.
1024; CHECK: [[RNG0]] = !{i32 0, i32 512}
1025;.
1026