1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; REQUIRES: asserts
3; RUN: opt -licm -basic-aa -ipt-expensive-asserts=true < %s -S | FileCheck %s
4; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' -ipt-expensive-asserts=true < %s -S | FileCheck %s
5
6; Hoist guard and load.
7define void @test1(i1 %cond, i32* %ptr) {
8; CHECK-LABEL: @test1(
9; CHECK-NEXT:  entry:
10; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[COND:%.*]]) [ "deopt"(i32 0) ]
11; CHECK-NEXT:    [[VAL:%.*]] = load i32, i32* [[PTR:%.*]]
12; CHECK-NEXT:    br label [[LOOP:%.*]]
13; CHECK:       loop:
14; CHECK-NEXT:    [[X:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[X_INC:%.*]], [[LOOP]] ]
15; CHECK-NEXT:    [[X_INC]] = add i32 [[X]], [[VAL]]
16; CHECK-NEXT:    br label [[LOOP]]
17;
18
19entry:
20  br label %loop
21
22loop:
23  %x = phi i32 [ 0, %entry ], [ %x.inc, %loop ]
24  call void (i1, ...) @llvm.experimental.guard(i1 %cond) ["deopt" (i32 0)]
25  %val = load i32, i32* %ptr
26  %x.inc = add i32 %x, %val
27  br label %loop
28}
29
30; Can't hoist over a side effect
31define void @test2(i1 %cond, i32* %ptr) {
32; CHECK-LABEL: @test2(
33; CHECK-NEXT:  entry:
34; CHECK-NEXT:    br label [[LOOP:%.*]]
35; CHECK:       loop:
36; CHECK-NEXT:    [[X:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[X_INC:%.*]], [[LOOP]] ]
37; CHECK-NEXT:    store i32 0, i32* [[PTR:%.*]]
38; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[COND:%.*]]) [ "deopt"(i32 0) ]
39; CHECK-NEXT:    [[VAL:%.*]] = load i32, i32* [[PTR]]
40; CHECK-NEXT:    [[X_INC]] = add i32 [[X]], [[VAL]]
41; CHECK-NEXT:    br label [[LOOP]]
42;
43
44entry:
45  br label %loop
46
47loop:
48  %x = phi i32 [ 0, %entry ], [ %x.inc, %loop ]
49  store i32 0, i32* %ptr
50  call void (i1, ...) @llvm.experimental.guard(i1 %cond) ["deopt" (i32 0)]
51  %val = load i32, i32* %ptr
52  %x.inc = add i32 %x, %val
53  br label %loop
54}
55
56; Can't hoist over a side effect
57define void @test2b(i1 %cond, i32* %ptr) {
58; CHECK-LABEL: @test2b(
59; CHECK-NEXT:  entry:
60; CHECK-NEXT:    [[P2:%.*]] = getelementptr i32, i32* [[PTR:%.*]], i32 1
61; CHECK-NEXT:    br label [[LOOP:%.*]]
62; CHECK:       loop:
63; CHECK-NEXT:    [[X:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[X_INC:%.*]], [[LOOP]] ]
64; CHECK-NEXT:    store i32 [[X]], i32* [[P2]]
65; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[COND:%.*]]) [ "deopt"(i32 0) ]
66; CHECK-NEXT:    [[VAL:%.*]] = load i32, i32* [[PTR]]
67; CHECK-NEXT:    [[X_INC]] = add i32 [[X]], [[VAL]]
68; CHECK-NEXT:    br label [[LOOP]]
69;
70
71entry:
72  br label %loop
73
74loop:
75  %x = phi i32 [ 0, %entry ], [ %x.inc, %loop ]
76  %p2 = getelementptr i32, i32* %ptr, i32 1
77  store i32 %x, i32* %p2
78  call void (i1, ...) @llvm.experimental.guard(i1 %cond) ["deopt" (i32 0)]
79  %val = load i32, i32* %ptr
80  %x.inc = add i32 %x, %val
81  br label %loop
82}
83
84; But can hoist if the side effect is hoisted with MSSA
85define void @test2b_prime(i1 %cond, i32* noalias %ptr) {
86; CHECK-LABEL: @test2b_prime(
87; CHECK-NEXT:  entry:
88; CHECK-NEXT:    [[P2:%.*]] = getelementptr i32, i32* [[PTR:%.*]], i32 1
89; CHECK-NEXT:    store i32 0, i32* [[P2]]
90; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[COND:%.*]]) [ "deopt"(i32 0) ]
91; CHECK-NEXT:    [[VAL:%.*]] = load i32, i32* [[PTR]]
92; CHECK-NEXT:    br label [[LOOP:%.*]]
93; CHECK:       loop:
94; CHECK-NEXT:    [[X:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[X_INC:%.*]], [[LOOP]] ]
95; CHECK-NEXT:    [[X_INC]] = add i32 [[X]], [[VAL]]
96; CHECK-NEXT:    br label [[LOOP]]
97
98entry:
99  br label %loop
100
101loop:
102  %x = phi i32 [ 0, %entry ], [ %x.inc, %loop ]
103  %p2 = getelementptr i32, i32* %ptr, i32 1
104  store i32 0, i32* %p2
105  call void (i1, ...) @llvm.experimental.guard(i1 %cond) ["deopt" (i32 0)]
106  %val = load i32, i32* %ptr
107  %x.inc = add i32 %x, %val
108  br label %loop
109}
110
111; Hoist guard. Cannot hoist load because of aliasing.
112define void @test3(i1 %cond, i32* %ptr) {
113; CHECK-LABEL: @test3(
114; CHECK-NEXT:  entry:
115; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[COND:%.*]]) [ "deopt"(i32 0) ]
116; CHECK-NEXT:    br label [[LOOP:%.*]]
117; CHECK:       loop:
118; CHECK-NEXT:    [[X:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[X_INC:%.*]], [[LOOP]] ]
119; CHECK-NEXT:    [[VAL:%.*]] = load i32, i32* [[PTR:%.*]], align 4
120; CHECK-NEXT:    store i32 0, i32* [[PTR]]
121; CHECK-NEXT:    [[X_INC]] = add i32 [[X]], [[VAL]]
122; CHECK-NEXT:    br label [[LOOP]]
123;
124
125entry:
126  br label %loop
127
128loop:
129  %x = phi i32 [ 0, %entry ], [ %x.inc, %loop ]
130  call void (i1, ...) @llvm.experimental.guard(i1 %cond) ["deopt" (i32 0)]
131  %val = load i32, i32* %ptr
132  store i32 0, i32* %ptr
133  %x.inc = add i32 %x, %val
134  br label %loop
135}
136
137; Hoist load and guard.
138define void @test4(i1 %c, i32* %p) {
139; CHECK-LABEL: @test4(
140; CHECK-NEXT:  entry:
141; CHECK-NEXT:    [[A:%.*]] = load i32, i32* [[P:%.*]]
142; CHECK-NEXT:    [[INVARIANT_COND:%.*]] = icmp ne i32 [[A]], 100
143; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[INVARIANT_COND]]) [ "deopt"() ]
144; CHECK-NEXT:    br label [[LOOP:%.*]]
145; CHECK:       loop:
146; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
147; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
148; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
149; CHECK:       if.true:
150; CHECK-NEXT:    br label [[BACKEDGE]]
151; CHECK:       if.false:
152; CHECK-NEXT:    br label [[BACKEDGE]]
153; CHECK:       backedge:
154; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 1000
155; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
156; CHECK:       exit:
157; CHECK-NEXT:    ret void
158;
159
160entry:
161  br label %loop
162
163loop:
164  %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
165  %iv.next = add i32 %iv, 1
166  br i1 %c, label %if.true, label %if.false
167
168if.true:
169  br label %backedge
170
171if.false:
172  br label %backedge
173
174backedge:
175  %a = load i32, i32* %p
176  %invariant_cond = icmp ne i32 %a, 100
177  call void (i1, ...) @llvm.experimental.guard(i1 %invariant_cond) [ "deopt"() ]
178  %loop_cond = icmp slt i32 %iv.next, 1000
179  br i1 %loop_cond, label %loop, label %exit
180
181exit:
182  ret void
183}
184
185; Do not hoist across a conditionally executed side effect.
186define void @test4a(i1 %c, i32* %p, i32* %q) {
187; CHECK-LABEL: @test4a(
188; CHECK-NEXT:  entry:
189; CHECK-NEXT:    br label [[LOOP:%.*]]
190; CHECK:       loop:
191; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
192; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
193; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
194; CHECK:       if.true:
195; CHECK-NEXT:    store i32 123, i32* [[Q:%.*]]
196; CHECK-NEXT:    br label [[BACKEDGE]]
197; CHECK:       if.false:
198; CHECK-NEXT:    br label [[BACKEDGE]]
199; CHECK:       backedge:
200; CHECK-NEXT:    [[A:%.*]] = load i32, i32* [[P:%.*]]
201; CHECK-NEXT:    [[INVARIANT_COND:%.*]] = icmp ne i32 [[A]], 100
202; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[INVARIANT_COND]]) [ "deopt"() ]
203; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 1000
204; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
205; CHECK:       exit:
206; CHECK-NEXT:    ret void
207;
208
209entry:
210  br label %loop
211
212loop:
213  %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
214  %iv.next = add i32 %iv, 1
215  br i1 %c, label %if.true, label %if.false
216
217if.true:
218  store i32 123, i32* %q
219  br label %backedge
220
221if.false:
222  br label %backedge
223
224backedge:
225  %a = load i32, i32* %p
226  %invariant_cond = icmp ne i32 %a, 100
227  call void (i1, ...) @llvm.experimental.guard(i1 %invariant_cond) [ "deopt"() ]
228  %loop_cond = icmp slt i32 %iv.next, 1000
229  br i1 %loop_cond, label %loop, label %exit
230
231exit:
232  ret void
233}
234
235; Do not hoist a conditionally executed guard.
236define void @test4b(i1 %c, i32* %p, i32* %q) {
237; CHECK-LABEL: @test4b(
238; CHECK-NEXT:  entry:
239; CHECK-NEXT:    br label [[LOOP:%.*]]
240; CHECK:       loop:
241; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
242; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
243; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
244; CHECK:       if.true:
245; CHECK-NEXT:    [[A:%.*]] = load i32, i32* [[P:%.*]]
246; CHECK-NEXT:    [[INVARIANT_COND:%.*]] = icmp ne i32 [[A]], 100
247; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[INVARIANT_COND]]) [ "deopt"() ]
248; CHECK-NEXT:    br label [[BACKEDGE]]
249; CHECK:       if.false:
250; CHECK-NEXT:    br label [[BACKEDGE]]
251; CHECK:       backedge:
252; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 1000
253; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
254; CHECK:       exit:
255; CHECK-NEXT:    ret void
256;
257
258entry:
259  br label %loop
260
261loop:
262  %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
263  %iv.next = add i32 %iv, 1
264  br i1 %c, label %if.true, label %if.false
265
266if.true:
267  %a = load i32, i32* %p
268  %invariant_cond = icmp ne i32 %a, 100
269  call void (i1, ...) @llvm.experimental.guard(i1 %invariant_cond) [ "deopt"() ]
270  br label %backedge
271
272if.false:
273  br label %backedge
274
275backedge:
276  %loop_cond = icmp slt i32 %iv.next, 1000
277  br i1 %loop_cond, label %loop, label %exit
278
279exit:
280  ret void
281}
282
283; Hoist store, load and guard.
284define void @test4c(i1 %c, i32* %p, i8* noalias %s) {
285; CHECK-LABEL: @test4c(
286; CHECK-NEXT:  entry:
287; CHECK-NEXT:    store i8 0, i8* [[S:%.*]]
288; CHECK-NEXT:    [[A:%.*]] = load i32, i32* [[P:%.*]]
289; CHECK-NEXT:    [[INVARIANT_COND:%.*]] = icmp ne i32 [[A]], 100
290; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[INVARIANT_COND]]) [ "deopt"() ]
291; CHECK-NEXT:    br label [[LOOP:%.*]]
292; CHECK:       loop:
293; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
294; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
295; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
296; CHECK:       if.true:
297; CHECK-NEXT:    br label [[BACKEDGE]]
298; CHECK:       if.false:
299; CHECK-NEXT:    br label [[BACKEDGE]]
300; CHECK:       backedge:
301; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 1000
302; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
303; CHECK:       exit:
304; CHECK-NEXT:    ret void
305;
306
307entry:
308  br label %loop
309
310loop:
311  %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
312  %iv.next = add i32 %iv, 1
313  store i8 0, i8* %s
314  br i1 %c, label %if.true, label %if.false
315
316if.true:
317  br label %backedge
318
319if.false:
320  br label %backedge
321
322backedge:
323  %a = load i32, i32* %p
324  %invariant_cond = icmp ne i32 %a, 100
325  call void (i1, ...) @llvm.experimental.guard(i1 %invariant_cond) [ "deopt"() ]
326  %loop_cond = icmp slt i32 %iv.next, 1000
327  br i1 %loop_cond, label %loop, label %exit
328
329exit:
330  ret void
331}
332
333; Check that we don't hoist across a store in a conditionally executed block.
334define void @test4d(i1 %c, i32* %p, i8* noalias %s) {
335; CHECK-LABEL: @test4d(
336; CHECK-NEXT:  entry:
337; CHECK-NEXT:    [[A:%.*]] = load i32, i32* [[P:%.*]]
338; CHECK-NEXT:    [[INVARIANT_COND:%.*]] = icmp ne i32 [[A]], 100
339; CHECK-NEXT:    br label [[LOOP:%.*]]
340; CHECK:       loop:
341; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
342; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
343; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
344; CHECK:       if.true:
345; CHECK-NEXT:    store i8 0, i8* [[S:%.*]]
346; CHECK-NEXT:    br label [[BACKEDGE]]
347; CHECK:       if.false:
348; CHECK-NEXT:    br label [[BACKEDGE]]
349; CHECK:       backedge:
350; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[INVARIANT_COND]]) [ "deopt"() ]
351; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 1000
352; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
353; CHECK:       exit:
354; CHECK-NEXT:    ret void
355;
356
357entry:
358  br label %loop
359
360loop:
361  %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
362  %iv.next = add i32 %iv, 1
363  br i1 %c, label %if.true, label %if.false
364
365if.true:
366  store i8 0, i8* %s
367  br label %backedge
368
369if.false:
370  br label %backedge
371
372backedge:
373  %a = load i32, i32* %p
374  %invariant_cond = icmp ne i32 %a, 100
375  call void (i1, ...) @llvm.experimental.guard(i1 %invariant_cond) [ "deopt"() ]
376  %loop_cond = icmp slt i32 %iv.next, 1000
377  br i1 %loop_cond, label %loop, label %exit
378
379exit:
380  ret void
381}
382
383; Check that we don't hoist across a store before the guard in the backedge.
384define void @test4e(i1 %c, i32* %p, i8* noalias %s) {
385; CHECK-LABEL: @test4e(
386; CHECK-NEXT:  entry:
387; CHECK-NEXT:    [[A:%.*]] = load i32, i32* [[P:%.*]]
388; CHECK-NEXT:    [[INVARIANT_COND:%.*]] = icmp ne i32 [[A]], 100
389; CHECK-NEXT:    store i8 0, i8* [[S:%.*]]
390; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[INVARIANT_COND]]) [ "deopt"() ]
391; CHECK-NEXT:    br label [[LOOP:%.*]]
392; CHECK:       loop:
393; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
394; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
395; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
396; CHECK:       if.true:
397; CHECK-NEXT:    br label [[BACKEDGE]]
398; CHECK:       if.false:
399; CHECK-NEXT:    br label [[BACKEDGE]]
400; CHECK:       backedge:
401; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 1000
402; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
403; CHECK:       exit:
404; CHECK-NEXT:    ret void
405;
406
407entry:
408  br label %loop
409
410loop:
411  %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
412  %iv.next = add i32 %iv, 1
413  br i1 %c, label %if.true, label %if.false
414
415if.true:
416  br label %backedge
417
418if.false:
419  br label %backedge
420
421backedge:
422  %a = load i32, i32* %p
423  %invariant_cond = icmp ne i32 %a, 100
424  store i8 0, i8* %s
425  call void (i1, ...) @llvm.experimental.guard(i1 %invariant_cond) [ "deopt"() ]
426  %loop_cond = icmp slt i32 %iv.next, 1000
427  br i1 %loop_cond, label %loop, label %exit
428
429exit:
430  ret void
431}
432
433; Check that we can hoist the guard in spite of store which happens after.
434define void @test4f(i1 %c, i32* %p, i8* noalias %s) {
435; CHECK-LABEL: @test4f(
436; CHECK-NEXT:  entry:
437; CHECK-NEXT:    [[A:%.*]] = load i32, i32* [[P:%.*]]
438; CHECK-NEXT:    [[INVARIANT_COND:%.*]] = icmp ne i32 [[A]], 100
439; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[INVARIANT_COND]]) [ "deopt"() ]
440; CHECK-NEXT:    store i8 0, i8* [[S:%.*]]
441; CHECK-NEXT:    br label [[LOOP:%.*]]
442; CHECK:       loop:
443; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
444; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
445; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
446; CHECK:       if.true:
447; CHECK-NEXT:    br label [[BACKEDGE]]
448; CHECK:       if.false:
449; CHECK-NEXT:    br label [[BACKEDGE]]
450; CHECK:       backedge:
451; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 1000
452; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
453; CHECK:       exit:
454; CHECK-NEXT:    ret void
455;
456
457entry:
458  br label %loop
459
460loop:
461  %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
462  %iv.next = add i32 %iv, 1
463  br i1 %c, label %if.true, label %if.false
464
465if.true:
466  br label %backedge
467
468if.false:
469  br label %backedge
470
471backedge:
472  %a = load i32, i32* %p
473  %invariant_cond = icmp ne i32 %a, 100
474  call void (i1, ...) @llvm.experimental.guard(i1 %invariant_cond) [ "deopt"() ]
475  store i8 0, i8* %s
476  %loop_cond = icmp slt i32 %iv.next, 1000
477  br i1 %loop_cond, label %loop, label %exit
478
479exit:
480  ret void
481}
482
483; Do not hoist an invariant guard across a variant guard.
484define void @test5(i1 %c, i32* %p, i32* %q) {
485; CHECK-LABEL: @test5(
486; CHECK-NEXT:  entry:
487; CHECK-NEXT:    [[A:%.*]] = load i32, i32* [[P:%.*]]
488; CHECK-NEXT:    [[INVARIANT_COND:%.*]] = icmp ne i32 [[A]], 100
489; CHECK-NEXT:    br label [[LOOP:%.*]]
490; CHECK:       loop:
491; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
492; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
493; CHECK-NEXT:    [[VARIANT_COND:%.*]] = icmp ne i32 [[A]], [[IV]]
494; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[VARIANT_COND]]) [ "deopt"() ]
495; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[INVARIANT_COND]]) [ "deopt"() ]
496; CHECK-NEXT:    br label [[BACKEDGE]]
497; CHECK:       backedge:
498; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 1000
499; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
500; CHECK:       exit:
501; CHECK-NEXT:    ret void
502;
503
504entry:
505  br label %loop
506
507loop:
508  %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
509  %iv.next = add i32 %iv, 1
510  %a = load i32, i32* %p
511  %invariant_cond = icmp ne i32 %a, 100
512  %variant_cond = icmp ne i32 %a, %iv
513  call void (i1, ...) @llvm.experimental.guard(i1 %variant_cond) [ "deopt"() ]
514  call void (i1, ...) @llvm.experimental.guard(i1 %invariant_cond) [ "deopt"() ]
515  br label %backedge
516
517backedge:
518  %loop_cond = icmp slt i32 %iv.next, 1000
519  br i1 %loop_cond, label %loop, label %exit
520
521exit:
522  ret void
523}
524
525; Hoist an invariant guard, leave the following variant guard in the loop.
526define void @test5a(i1 %c, i32* %p, i32* %q) {
527; CHECK-LABEL: @test5a(
528; CHECK-NEXT:  entry:
529; CHECK-NEXT:    [[A:%.*]] = load i32, i32* [[P:%.*]]
530; CHECK-NEXT:    [[INVARIANT_COND:%.*]] = icmp ne i32 [[A]], 100
531; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[INVARIANT_COND]]) [ "deopt"() ]
532; CHECK-NEXT:    br label [[LOOP:%.*]]
533; CHECK:       loop:
534; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
535; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
536; CHECK-NEXT:    [[VARIANT_COND:%.*]] = icmp ne i32 [[A]], [[IV]]
537; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[VARIANT_COND]]) [ "deopt"() ]
538; CHECK-NEXT:    br label [[BACKEDGE]]
539; CHECK:       backedge:
540; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp slt i32 [[IV_NEXT]], 1000
541; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[EXIT:%.*]]
542; CHECK:       exit:
543; CHECK-NEXT:    ret void
544;
545
546entry:
547  br label %loop
548
549loop:
550  %iv = phi i32 [ 0, %entry ], [ %iv.next, %backedge ]
551  %iv.next = add i32 %iv, 1
552  %a = load i32, i32* %p
553  %invariant_cond = icmp ne i32 %a, 100
554  %variant_cond = icmp ne i32 %a, %iv
555  call void (i1, ...) @llvm.experimental.guard(i1 %invariant_cond) [ "deopt"() ]
556  call void (i1, ...) @llvm.experimental.guard(i1 %variant_cond) [ "deopt"() ]
557  br label %backedge
558
559backedge:
560  %loop_cond = icmp slt i32 %iv.next, 1000
561  br i1 %loop_cond, label %loop, label %exit
562
563exit:
564  ret void
565}
566
567declare void @llvm.experimental.guard(i1, ...)
568