1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -guard-widening < %s        | FileCheck %s
3; RUN: opt -S -passes=guard-widening < %s | FileCheck %s
4
5declare void @llvm.experimental.guard(i1,...)
6
7; Basic test case: we wide the first check to check both the
8; conditions.
9define void @f_0(i1 %cond_0, i1 %cond_1) {
10; CHECK-LABEL: @f_0(
11; CHECK-NEXT:  entry:
12; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]]
13; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
14; CHECK-NEXT:    ret void
15;
16entry:
17
18  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
19  call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
20  ret void
21}
22
23; Same as @f_0, but with using a more general notion of postdominance.
24define void @f_1(i1 %cond_0, i1 %cond_1) {
25; CHECK-LABEL: @f_1(
26; CHECK-NEXT:  entry:
27; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]]
28; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
29; CHECK-NEXT:    br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]]
30; CHECK:       left:
31; CHECK-NEXT:    br label [[MERGE:%.*]]
32; CHECK:       right:
33; CHECK-NEXT:    br label [[MERGE]]
34; CHECK:       merge:
35; CHECK-NEXT:    ret void
36;
37entry:
38
39  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
40  br i1 undef, label %left, label %right
41
42left:
43  br label %merge
44
45right:
46  br label %merge
47
48merge:
49  call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
50  ret void
51}
52
53; Like @f_1, but we have some code we need to hoist before we can
54; widen a dominanting check.
55define void @f_2(i32 %a, i32 %b) {
56; CHECK-LABEL: @f_2(
57; CHECK-NEXT:  entry:
58; CHECK-NEXT:    [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 10
59; CHECK-NEXT:    [[COND_1:%.*]] = icmp ult i32 [[B:%.*]], 10
60; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0]], [[COND_1]]
61; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
62; CHECK-NEXT:    br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]]
63; CHECK:       left:
64; CHECK-NEXT:    br label [[MERGE:%.*]]
65; CHECK:       right:
66; CHECK-NEXT:    br label [[MERGE]]
67; CHECK:       merge:
68; CHECK-NEXT:    ret void
69;
70entry:
71
72  %cond_0 = icmp ult i32 %a, 10
73  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
74  br i1 undef, label %left, label %right
75
76left:
77  br label %merge
78
79right:
80  br label %merge
81
82merge:
83  %cond_1 = icmp ult i32 %b, 10
84  call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
85  ret void
86}
87
88; Negative test: don't hoist stuff out of control flow
89; indiscriminately, since that can make us do more work than needed.
90define void @f_3(i32 %a, i32 %b) {
91; CHECK-LABEL: @f_3(
92; CHECK-NEXT:  entry:
93; CHECK-NEXT:    [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 10
94; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[COND_0]]) [ "deopt"() ]
95; CHECK-NEXT:    br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]]
96; CHECK:       left:
97; CHECK-NEXT:    [[COND_1:%.*]] = icmp ult i32 [[B:%.*]], 10
98; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[COND_1]]) [ "deopt"() ]
99; CHECK-NEXT:    ret void
100; CHECK:       right:
101; CHECK-NEXT:    ret void
102;
103entry:
104
105  %cond_0 = icmp ult i32 %a, 10
106  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
107  br i1 undef, label %left, label %right
108
109left:
110
111  %cond_1 = icmp ult i32 %b, 10
112  call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
113  ret void
114
115right:
116  ret void
117}
118
119; But hoisting out of control flow is fine if it makes a loop computed
120; condition loop invariant.  This behavior may require some tuning in
121; the future.
122define void @f_4(i32 %a, i32 %b) {
123; CHECK-LABEL: @f_4(
124; CHECK-NEXT:  entry:
125; CHECK-NEXT:    [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 10
126; CHECK-NEXT:    [[COND_1:%.*]] = icmp ult i32 [[B:%.*]], 10
127; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0]], [[COND_1]]
128; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
129; CHECK-NEXT:    br i1 undef, label [[LOOP:%.*]], label [[LEAVE:%.*]]
130; CHECK:       loop:
131; CHECK-NEXT:    br i1 undef, label [[LOOP]], label [[LEAVE]]
132; CHECK:       leave:
133; CHECK-NEXT:    ret void
134;
135entry:
136
137  %cond_0 = icmp ult i32 %a, 10
138  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
139  br i1 undef, label %loop, label %leave
140
141loop:
142  %cond_1 = icmp ult i32 %b, 10
143  call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
144  br i1 undef, label %loop, label %leave
145
146leave:
147  ret void
148}
149
150; Hoisting out of control flow is also fine if we can widen the
151; dominating check without doing any extra work.
152define void @f_5(i32 %a) {
153; CHECK-LABEL: @f_5(
154; CHECK-NEXT:  entry:
155; CHECK-NEXT:    [[COND_0:%.*]] = icmp ugt i32 [[A:%.*]], 7
156; CHECK-NEXT:    [[WIDE_CHK:%.*]] = icmp uge i32 [[A]], 11
157; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
158; CHECK-NEXT:    br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]]
159; CHECK:       left:
160; CHECK-NEXT:    [[COND_1:%.*]] = icmp ugt i32 [[A]], 10
161; CHECK-NEXT:    ret void
162; CHECK:       right:
163; CHECK-NEXT:    ret void
164;
165entry:
166
167  %cond_0 = icmp ugt i32 %a, 7
168  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
169  br i1 undef, label %left, label %right
170
171left:
172  %cond_1 = icmp ugt i32 %a, 10
173  call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
174  ret void
175
176right:
177  ret void
178}
179
180; Negative test: the load from %a can be safely speculated to before
181; the first guard, but there is no guarantee that it will produce the
182; same value.
183define void @f_6(i1* dereferenceable(32) %a, i1* %b, i1 %unknown) {
184; CHECK-LABEL: @f_6(
185; CHECK-NEXT:  entry:
186; CHECK-NEXT:    [[COND_0:%.*]] = load i1, i1* [[A:%.*]], align 1
187; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[COND_0]]) [ "deopt"() ]
188; CHECK-NEXT:    store i1 [[UNKNOWN:%.*]], i1* [[B:%.*]], align 1
189; CHECK-NEXT:    [[COND_1:%.*]] = load i1, i1* [[A]], align 1
190; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[COND_1]]) [ "deopt"() ]
191; CHECK-NEXT:    ret void
192;
193entry:
194  %cond_0 = load i1, i1* %a
195  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
196  store i1 %unknown, i1* %b
197  %cond_1 = load i1, i1* %a
198  call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
199  ret void
200}
201
202; All else equal, we try to widen the earliest guard we can.  This
203; heuristic can use some tuning.
204define void @f_7(i32 %a, i1* %cond_buf) {
205; CHECK-LABEL: @f_7(
206; CHECK-NEXT:  entry:
207; CHECK-NEXT:    [[COND_1:%.*]] = load volatile i1, i1* [[COND_BUF:%.*]], align 1
208; CHECK-NEXT:    [[COND_3:%.*]] = icmp ult i32 [[A:%.*]], 7
209; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_3]]
210; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
211; CHECK-NEXT:    [[COND_2:%.*]] = load volatile i1, i1* [[COND_BUF]], align 1
212; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[COND_2]]) [ "deopt"() ]
213; CHECK-NEXT:    br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]]
214; CHECK:       left:
215; CHECK-NEXT:    br label [[LEFT]]
216; CHECK:       right:
217; CHECK-NEXT:    ret void
218;
219entry:
220
221  %cond_1 = load volatile i1, i1* %cond_buf
222  call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
223  %cond_2 = load volatile i1, i1* %cond_buf
224  call void(i1, ...) @llvm.experimental.guard(i1 %cond_2) [ "deopt"() ]
225  br i1 undef, label %left, label %right
226
227left:
228  %cond_3 = icmp ult i32 %a, 7
229  call void(i1, ...) @llvm.experimental.guard(i1 %cond_3) [ "deopt"() ]
230  br label %left
231
232right:
233  ret void
234}
235
236; In this case the earliest dominating guard is in a loop, and we
237; don't want to put extra work in there.  This heuristic can use some
238; tuning.
239define void @f_8(i32 %a, i1 %cond_1, i1 %cond_2) {
240; CHECK-LABEL: @f_8(
241; CHECK-NEXT:  entry:
242; CHECK-NEXT:    br label [[LOOP:%.*]]
243; CHECK:       loop:
244; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[COND_1:%.*]]) [ "deopt"() ]
245; CHECK-NEXT:    br i1 undef, label [[LOOP]], label [[LEAVE:%.*]]
246; CHECK:       leave:
247; CHECK-NEXT:    [[COND_3:%.*]] = icmp ult i32 [[A:%.*]], 7
248; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_2:%.*]], [[COND_3]]
249; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
250; CHECK-NEXT:    br i1 undef, label [[LOOP2:%.*]], label [[LEAVE2:%.*]]
251; CHECK:       loop2:
252; CHECK-NEXT:    br label [[LOOP2]]
253; CHECK:       leave2:
254; CHECK-NEXT:    ret void
255;
256entry:
257  br label %loop
258
259loop:
260  call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
261  br i1 undef, label %loop, label %leave
262
263leave:
264
265  call void(i1, ...) @llvm.experimental.guard(i1 %cond_2) [ "deopt"() ]
266  br i1 undef, label %loop2, label %leave2
267
268loop2:
269  %cond_3 = icmp ult i32 %a, 7
270  call void(i1, ...) @llvm.experimental.guard(i1 %cond_3) [ "deopt"() ]
271  br label %loop2
272
273leave2:
274  ret void
275}
276
277; In cases like these where there isn't any "obviously profitable"
278; widening sites, we refuse to do anything.
279define void @f_9(i32 %a, i1 %cond_0, i1 %cond_1) {
280; CHECK-LABEL: @f_9(
281; CHECK-NEXT:  entry:
282; CHECK-NEXT:    br label [[FIRST_LOOP:%.*]]
283; CHECK:       first_loop:
284; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[COND_0:%.*]]) [ "deopt"() ]
285; CHECK-NEXT:    br i1 undef, label [[FIRST_LOOP]], label [[SECOND_LOOP:%.*]]
286; CHECK:       second_loop:
287; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[COND_1:%.*]]) [ "deopt"() ]
288; CHECK-NEXT:    br label [[SECOND_LOOP]]
289;
290entry:
291  br label %first_loop
292
293first_loop:
294
295  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
296  br i1 undef, label %first_loop, label %second_loop
297
298second_loop:
299
300  call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
301  br label %second_loop
302}
303
304; Same situation as in @f_9: no "obviously profitable" widening sites,
305; so we refuse to do anything.
306define void @f_10(i32 %a, i1 %cond_0, i1 %cond_1) {
307; CHECK-LABEL: @f_10(
308; CHECK-NEXT:  entry:
309; CHECK-NEXT:    br label [[LOOP:%.*]]
310; CHECK:       loop:
311; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[COND_0:%.*]]) [ "deopt"() ]
312; CHECK-NEXT:    br i1 undef, label [[LOOP]], label [[NO_LOOP:%.*]]
313; CHECK:       no_loop:
314; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[COND_1:%.*]]) [ "deopt"() ]
315; CHECK-NEXT:    ret void
316;
317entry:
318  br label %loop
319
320loop:
321
322  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
323  br i1 undef, label %loop, label %no_loop
324
325no_loop:
326  call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
327  ret void
328}
329
330; With guards in loops, we're okay hoisting out the guard into the
331; containing loop.
332define void @f_11(i32 %a, i1 %cond_0, i1 %cond_1) {
333; CHECK-LABEL: @f_11(
334; CHECK-NEXT:  entry:
335; CHECK-NEXT:    br label [[INNER:%.*]]
336; CHECK:       inner:
337; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]]
338; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
339; CHECK-NEXT:    br i1 undef, label [[INNER]], label [[OUTER:%.*]]
340; CHECK:       outer:
341; CHECK-NEXT:    br label [[INNER]]
342;
343entry:
344  br label %inner
345
346inner:
347
348  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
349  br i1 undef, label %inner, label %outer
350
351outer:
352  call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
353  br label %inner
354}
355
356; Checks that we are adequately guarded against exponential-time
357; behavior when hoisting code.
358define void @f_12(i32 %a0) {
359; CHECK-LABEL: @f_12(
360; CHECK-NEXT:  entry:
361; CHECK-NEXT:    [[A1:%.*]] = mul i32 [[A0:%.*]], [[A0]]
362; CHECK-NEXT:    [[A2:%.*]] = mul i32 [[A1]], [[A1]]
363; CHECK-NEXT:    [[A3:%.*]] = mul i32 [[A2]], [[A2]]
364; CHECK-NEXT:    [[A4:%.*]] = mul i32 [[A3]], [[A3]]
365; CHECK-NEXT:    [[A5:%.*]] = mul i32 [[A4]], [[A4]]
366; CHECK-NEXT:    [[A6:%.*]] = mul i32 [[A5]], [[A5]]
367; CHECK-NEXT:    [[A7:%.*]] = mul i32 [[A6]], [[A6]]
368; CHECK-NEXT:    [[A8:%.*]] = mul i32 [[A7]], [[A7]]
369; CHECK-NEXT:    [[A9:%.*]] = mul i32 [[A8]], [[A8]]
370; CHECK-NEXT:    [[A10:%.*]] = mul i32 [[A9]], [[A9]]
371; CHECK-NEXT:    [[A11:%.*]] = mul i32 [[A10]], [[A10]]
372; CHECK-NEXT:    [[A12:%.*]] = mul i32 [[A11]], [[A11]]
373; CHECK-NEXT:    [[A13:%.*]] = mul i32 [[A12]], [[A12]]
374; CHECK-NEXT:    [[A14:%.*]] = mul i32 [[A13]], [[A13]]
375; CHECK-NEXT:    [[A15:%.*]] = mul i32 [[A14]], [[A14]]
376; CHECK-NEXT:    [[A16:%.*]] = mul i32 [[A15]], [[A15]]
377; CHECK-NEXT:    [[A17:%.*]] = mul i32 [[A16]], [[A16]]
378; CHECK-NEXT:    [[A18:%.*]] = mul i32 [[A17]], [[A17]]
379; CHECK-NEXT:    [[A19:%.*]] = mul i32 [[A18]], [[A18]]
380; CHECK-NEXT:    [[A20:%.*]] = mul i32 [[A19]], [[A19]]
381; CHECK-NEXT:    [[A21:%.*]] = mul i32 [[A20]], [[A20]]
382; CHECK-NEXT:    [[A22:%.*]] = mul i32 [[A21]], [[A21]]
383; CHECK-NEXT:    [[A23:%.*]] = mul i32 [[A22]], [[A22]]
384; CHECK-NEXT:    [[A24:%.*]] = mul i32 [[A23]], [[A23]]
385; CHECK-NEXT:    [[A25:%.*]] = mul i32 [[A24]], [[A24]]
386; CHECK-NEXT:    [[A26:%.*]] = mul i32 [[A25]], [[A25]]
387; CHECK-NEXT:    [[A27:%.*]] = mul i32 [[A26]], [[A26]]
388; CHECK-NEXT:    [[A28:%.*]] = mul i32 [[A27]], [[A27]]
389; CHECK-NEXT:    [[A29:%.*]] = mul i32 [[A28]], [[A28]]
390; CHECK-NEXT:    [[A30:%.*]] = mul i32 [[A29]], [[A29]]
391; CHECK-NEXT:    [[COND:%.*]] = trunc i32 [[A30]] to i1
392; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 true, [[COND]]
393; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
394; CHECK-NEXT:    ret void
395;
396
397; Eliding the earlier 29 multiplications for brevity
398
399entry:
400  call void(i1, ...) @llvm.experimental.guard(i1 true) [ "deopt"() ]
401  %a1 = mul i32 %a0, %a0
402  %a2 = mul i32 %a1, %a1
403  %a3 = mul i32 %a2, %a2
404  %a4 = mul i32 %a3, %a3
405  %a5 = mul i32 %a4, %a4
406  %a6 = mul i32 %a5, %a5
407  %a7 = mul i32 %a6, %a6
408  %a8 = mul i32 %a7, %a7
409  %a9 = mul i32 %a8, %a8
410  %a10 = mul i32 %a9, %a9
411  %a11 = mul i32 %a10, %a10
412  %a12 = mul i32 %a11, %a11
413  %a13 = mul i32 %a12, %a12
414  %a14 = mul i32 %a13, %a13
415  %a15 = mul i32 %a14, %a14
416  %a16 = mul i32 %a15, %a15
417  %a17 = mul i32 %a16, %a16
418  %a18 = mul i32 %a17, %a17
419  %a19 = mul i32 %a18, %a18
420  %a20 = mul i32 %a19, %a19
421  %a21 = mul i32 %a20, %a20
422  %a22 = mul i32 %a21, %a21
423  %a23 = mul i32 %a22, %a22
424  %a24 = mul i32 %a23, %a23
425  %a25 = mul i32 %a24, %a24
426  %a26 = mul i32 %a25, %a25
427  %a27 = mul i32 %a26, %a26
428  %a28 = mul i32 %a27, %a27
429  %a29 = mul i32 %a28, %a28
430  %a30 = mul i32 %a29, %a29
431  %cond = trunc i32 %a30 to i1
432  call void(i1, ...) @llvm.experimental.guard(i1 %cond) [ "deopt"() ]
433  ret void
434}
435
436define void @f_13(i32 %a) {
437; CHECK-LABEL: @f_13(
438; CHECK-NEXT:  entry:
439; CHECK-NEXT:    [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 14
440; CHECK-NEXT:    [[WIDE_CHK:%.*]] = icmp ult i32 [[A]], 10
441; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[WIDE_CHK]]) [ "deopt"() ]
442; CHECK-NEXT:    br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]]
443; CHECK:       left:
444; CHECK-NEXT:    [[COND_1:%.*]] = icmp slt i32 [[A]], 10
445; CHECK-NEXT:    ret void
446; CHECK:       right:
447; CHECK-NEXT:    ret void
448;
449entry:
450
451  %cond_0 = icmp ult i32 %a, 14
452  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
453  br i1 undef, label %left, label %right
454
455left:
456  %cond_1 = icmp slt i32 %a, 10
457  call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
458  ret void
459
460right:
461  ret void
462}
463
464define void @f_14(i32 %a) {
465; CHECK-LABEL: @f_14(
466; CHECK-NEXT:  entry:
467; CHECK-NEXT:    [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 14
468; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[COND_0]]) [ "deopt"() ]
469; CHECK-NEXT:    br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]]
470; CHECK:       left:
471; CHECK-NEXT:    [[COND_1:%.*]] = icmp sgt i32 [[A]], 10
472; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[COND_1]]) [ "deopt"() ]
473; CHECK-NEXT:    ret void
474; CHECK:       right:
475; CHECK-NEXT:    ret void
476;
477entry:
478
479  %cond_0 = icmp ult i32 %a, 14
480  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
481  br i1 undef, label %left, label %right
482
483left:
484
485  %cond_1 = icmp sgt i32 %a, 10
486  call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
487  ret void
488
489right:
490  ret void
491}
492
493; Make sure we do not widen guard by trivial true conditions into something.
494define void @f_15(i1 %cond_0, i1 %cond_1) {
495; CHECK-LABEL: @f_15(
496; CHECK-NEXT:  entry:
497; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[COND_0:%.*]]) [ "deopt"() ]
498; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 true) [ "deopt"() ]
499; CHECK-NEXT:    ret void
500;
501entry:
502
503  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
504  call void(i1, ...) @llvm.experimental.guard(i1 true) [ "deopt"() ]
505  ret void
506}
507
508; Make sure we do not widen guard by trivial false conditions into something.
509define void @f_16(i1 %cond_0, i1 %cond_1) {
510; CHECK-LABEL: @f_16(
511; CHECK-NEXT:  entry:
512; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 [[COND_0:%.*]]) [ "deopt"() ]
513; CHECK-NEXT:    call void (i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ]
514; CHECK-NEXT:    ret void
515;
516entry:
517
518  call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
519  call void(i1, ...) @llvm.experimental.guard(i1 false) [ "deopt"() ]
520  ret void
521}
522