1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -guard-widening-widen-branch-guards=true -guard-widening < %s | FileCheck %s
3 ; RUN: opt -S -guard-widening-widen-branch-guards=true -passes=guard-widening < %s | FileCheck %s
5 ; Basic test case: we wide the first check to check both the
7 define void @f_0(i1 %cond_0, i1 %cond_1) {
10 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
11 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0:%.*]], [[WIDENABLE_COND]]
12 ; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0]], [[COND_1:%.*]]
13 ; CHECK-NEXT: [[GUARD_CHK:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
14 ; CHECK-NEXT: br i1 [[GUARD_CHK]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
16 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
17 ; CHECK-NEXT: ret void
19 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
20 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]]
21 ; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
23 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
24 ; CHECK-NEXT: ret void
26 ; CHECK-NEXT: ret void
29 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
30 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
31 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
33 deopt: ; preds = %entry
34 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
37 guarded: ; preds = %entry
38 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
39 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3
40 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
42 deopt2: ; preds = %guarded
43 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
46 guarded1: ; preds = %guarded
50 ; Same as @f_0, but with using a more general notion of postdominance.
51 define void @f_1(i1 %cond_0, i1 %cond_1) {
54 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
55 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0:%.*]], [[WIDENABLE_COND]]
56 ; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0]], [[COND_1:%.*]]
57 ; CHECK-NEXT: [[GUARD_CHK:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
58 ; CHECK-NEXT: br i1 [[GUARD_CHK]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
60 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
61 ; CHECK-NEXT: ret void
63 ; CHECK-NEXT: br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]]
65 ; CHECK-NEXT: br label [[MERGE:%.*]]
67 ; CHECK-NEXT: br label [[MERGE]]
69 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
70 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]]
71 ; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
73 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
74 ; CHECK-NEXT: ret void
76 ; CHECK-NEXT: ret void
79 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
80 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
81 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
83 deopt: ; preds = %entry
84 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
87 guarded: ; preds = %entry
88 br i1 undef, label %left, label %right
90 left: ; preds = %guarded
93 right: ; preds = %guarded
96 merge: ; preds = %right, %left
97 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
98 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3
99 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
101 deopt2: ; preds = %merge
102 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
105 guarded1: ; preds = %merge
109 ; Like @f_1, but we have some code we need to hoist before we can
110 ; widen a dominanting check.
111 define void @f_2(i32 %a, i32 %b) {
114 ; CHECK-NEXT: [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 10
115 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
116 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0]], [[WIDENABLE_COND]]
117 ; CHECK-NEXT: [[COND_1:%.*]] = icmp ult i32 [[B:%.*]], 10
118 ; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0]], [[COND_1]]
119 ; CHECK-NEXT: [[GUARD_CHK:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
120 ; CHECK-NEXT: br i1 [[GUARD_CHK]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
122 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
123 ; CHECK-NEXT: ret void
125 ; CHECK-NEXT: br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]]
127 ; CHECK-NEXT: br label [[MERGE:%.*]]
129 ; CHECK-NEXT: br label [[MERGE]]
131 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
132 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]]
133 ; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
135 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
136 ; CHECK-NEXT: ret void
138 ; CHECK-NEXT: ret void
141 %cond_0 = icmp ult i32 %a, 10
142 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
143 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
144 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
146 deopt: ; preds = %entry
147 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
150 guarded: ; preds = %entry
151 br i1 undef, label %left, label %right
153 left: ; preds = %guarded
156 right: ; preds = %guarded
159 merge: ; preds = %right, %left
160 %cond_1 = icmp ult i32 %b, 10
161 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
162 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3
163 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
165 deopt2: ; preds = %merge
166 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
169 guarded1: ; preds = %merge
173 ; Negative test: don't hoist stuff out of control flow
174 ; indiscriminately, since that can make us do more work than needed.
175 define void @f_3(i32 %a, i32 %b) {
178 ; CHECK-NEXT: [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 10
179 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
180 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0]], [[WIDENABLE_COND]]
181 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
183 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
184 ; CHECK-NEXT: ret void
186 ; CHECK-NEXT: br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]]
188 ; CHECK-NEXT: [[COND_1:%.*]] = icmp ult i32 [[B:%.*]], 10
189 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
190 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]]
191 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
193 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
194 ; CHECK-NEXT: ret void
196 ; CHECK-NEXT: ret void
198 ; CHECK-NEXT: ret void
201 %cond_0 = icmp ult i32 %a, 10
202 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
203 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
204 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
206 deopt: ; preds = %entry
207 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
210 guarded: ; preds = %entry
211 br i1 undef, label %left, label %right
213 left: ; preds = %guarded
214 %cond_1 = icmp ult i32 %b, 10
215 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
216 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3
217 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
219 deopt2: ; preds = %left
220 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
223 guarded1: ; preds = %left
226 right: ; preds = %guarded
230 ; But hoisting out of control flow is fine if it makes a loop computed
231 ; condition loop invariant. This behavior may require some tuning in
233 define void @f_4(i32 %a, i32 %b) {
236 ; CHECK-NEXT: [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 10
237 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
238 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0]], [[WIDENABLE_COND]]
239 ; CHECK-NEXT: [[COND_1:%.*]] = icmp ult i32 [[B:%.*]], 10
240 ; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0]], [[COND_1]]
241 ; CHECK-NEXT: [[GUARD_CHK:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
242 ; CHECK-NEXT: br i1 [[GUARD_CHK]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
244 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
245 ; CHECK-NEXT: ret void
247 ; CHECK-NEXT: br i1 undef, label [[LOOP:%.*]], label [[LEAVE:%.*]]
249 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
250 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]]
251 ; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
253 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
254 ; CHECK-NEXT: ret void
256 ; CHECK-NEXT: br i1 undef, label [[LOOP]], label [[LEAVE]]
258 ; CHECK-NEXT: ret void
261 %cond_0 = icmp ult i32 %a, 10
262 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
263 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
264 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
266 deopt: ; preds = %entry
267 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
270 guarded: ; preds = %entry
271 br i1 undef, label %loop, label %leave
273 loop: ; preds = %guarded1, %guarded
274 %cond_1 = icmp ult i32 %b, 10
275 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
276 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3
277 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
279 deopt2: ; preds = %loop
280 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
283 guarded1: ; preds = %loop
284 br i1 undef, label %loop, label %leave
286 leave: ; preds = %guarded1, %guarded
290 ; Hoisting out of control flow is also fine if we can widen the
291 ; dominating check without doing any extra work.
292 define void @f_5(i32 %a) {
295 ; CHECK-NEXT: [[COND_0:%.*]] = icmp ugt i32 [[A:%.*]], 7
296 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
297 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0]], [[WIDENABLE_COND]]
298 ; CHECK-NEXT: [[WIDE_CHK:%.*]] = icmp uge i32 [[A]], 11
299 ; CHECK-NEXT: [[GUARD_CHK:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
300 ; CHECK-NEXT: br i1 [[GUARD_CHK]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
302 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
303 ; CHECK-NEXT: ret void
305 ; CHECK-NEXT: br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]]
307 ; CHECK-NEXT: [[COND_1:%.*]] = icmp ugt i32 [[A]], 10
308 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
309 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]]
310 ; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
312 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
313 ; CHECK-NEXT: ret void
315 ; CHECK-NEXT: ret void
317 ; CHECK-NEXT: ret void
320 %cond_0 = icmp ugt i32 %a, 7
321 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
322 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
323 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
325 deopt: ; preds = %entry
326 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
329 guarded: ; preds = %entry
330 br i1 undef, label %left, label %right
332 left: ; preds = %guarded
333 %cond_1 = icmp ugt i32 %a, 10
334 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
335 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3
336 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
338 deopt2: ; preds = %left
339 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
342 guarded1: ; preds = %left
345 right: ; preds = %guarded
349 ; Negative test: the load from %a can be safely speculated to before
350 ; the first guard, but there is no guarantee that it will produce the
352 define void @f_6(i1* dereferenceable(32) %a, i1* %b, i1 %unknown) {
355 ; CHECK-NEXT: [[COND_0:%.*]] = load i1, i1* [[A:%.*]]
356 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
357 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0]], [[WIDENABLE_COND]]
358 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
360 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
361 ; CHECK-NEXT: ret void
363 ; CHECK-NEXT: store i1 [[UNKNOWN:%.*]], i1* [[B:%.*]]
364 ; CHECK-NEXT: [[COND_1:%.*]] = load i1, i1* [[A]]
365 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
366 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]]
367 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
369 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
370 ; CHECK-NEXT: ret void
372 ; CHECK-NEXT: ret void
375 %cond_0 = load i1, i1* %a
376 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
377 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
378 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
380 deopt: ; preds = %entry
381 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
384 guarded: ; preds = %entry
385 store i1 %unknown, i1* %b
386 %cond_1 = load i1, i1* %a
387 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
388 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3
389 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
391 deopt2: ; preds = %guarded
392 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
395 guarded1: ; preds = %guarded
399 ; All else equal, we try to widen the earliest guard we can. This
400 ; heuristic can use some tuning.
401 define void @f_7(i32 %a, i1* %cond_buf) {
404 ; CHECK-NEXT: [[COND_1:%.*]] = load volatile i1, i1* [[COND_BUF:%.*]]
405 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
406 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND]]
407 ; CHECK-NEXT: [[COND_3:%.*]] = icmp ult i32 [[A:%.*]], 7
408 ; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_3]]
409 ; CHECK-NEXT: [[GUARD_CHK:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
410 ; CHECK-NEXT: br i1 [[GUARD_CHK]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
412 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
413 ; CHECK-NEXT: ret void
415 ; CHECK-NEXT: [[COND_2:%.*]] = load volatile i1, i1* [[COND_BUF]]
416 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
417 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_2]], [[WIDENABLE_COND3]]
418 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
420 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
421 ; CHECK-NEXT: ret void
423 ; CHECK-NEXT: br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]]
425 ; CHECK-NEXT: [[WIDENABLE_COND7:%.*]] = call i1 @llvm.experimental.widenable.condition()
426 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND8:%.*]] = and i1 [[COND_3]], [[WIDENABLE_COND7]]
427 ; CHECK-NEXT: br i1 true, label [[GUARDED5:%.*]], label [[DEOPT6:%.*]], !prof !0
429 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
430 ; CHECK-NEXT: ret void
432 ; CHECK-NEXT: br label [[LEFT]]
434 ; CHECK-NEXT: ret void
437 %cond_1 = load volatile i1, i1* %cond_buf
438 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
439 %exiplicit_guard_cond = and i1 %cond_1, %widenable_cond
440 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
442 deopt: ; preds = %entry
443 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
446 guarded: ; preds = %entry
447 %cond_2 = load volatile i1, i1* %cond_buf
448 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
449 %exiplicit_guard_cond4 = and i1 %cond_2, %widenable_cond3
450 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
452 deopt2: ; preds = %guarded
453 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
456 guarded1: ; preds = %guarded
457 br i1 undef, label %left, label %right
459 left: ; preds = %guarded5, %guarded1
460 %cond_3 = icmp ult i32 %a, 7
461 %widenable_cond7 = call i1 @llvm.experimental.widenable.condition()
462 %exiplicit_guard_cond8 = and i1 %cond_3, %widenable_cond7
463 br i1 %exiplicit_guard_cond8, label %guarded5, label %deopt6, !prof !0
465 deopt6: ; preds = %left
466 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
469 guarded5: ; preds = %left
472 right: ; preds = %guarded1
476 ; In this case the earliest dominating guard is in a loop, and we
477 ; don't want to put extra work in there. This heuristic can use some
479 define void @f_8(i32 %a, i1 %cond_1, i1 %cond_2) {
482 ; CHECK-NEXT: br label [[LOOP:%.*]]
484 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
485 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_1:%.*]], [[WIDENABLE_COND]]
486 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
488 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
489 ; CHECK-NEXT: ret void
491 ; CHECK-NEXT: br i1 undef, label [[LOOP]], label [[LEAVE:%.*]]
493 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
494 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_2:%.*]], [[WIDENABLE_COND3]]
495 ; CHECK-NEXT: [[COND_3:%.*]] = icmp ult i32 [[A:%.*]], 7
496 ; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_2]], [[COND_3]]
497 ; CHECK-NEXT: [[GUARD_CHK:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND3]]
498 ; CHECK-NEXT: br i1 [[GUARD_CHK]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
500 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
501 ; CHECK-NEXT: ret void
503 ; CHECK-NEXT: br i1 undef, label [[LOOP2:%.*]], label [[LEAVE2:%.*]]
505 ; CHECK-NEXT: [[WIDENABLE_COND7:%.*]] = call i1 @llvm.experimental.widenable.condition()
506 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND8:%.*]] = and i1 [[COND_3]], [[WIDENABLE_COND7]]
507 ; CHECK-NEXT: br i1 true, label [[GUARDED5:%.*]], label [[DEOPT6:%.*]], !prof !0
509 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
510 ; CHECK-NEXT: ret void
512 ; CHECK-NEXT: br label [[LOOP2]]
514 ; CHECK-NEXT: ret void
519 loop: ; preds = %guarded, %entry
520 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
521 %exiplicit_guard_cond = and i1 %cond_1, %widenable_cond
522 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
524 deopt: ; preds = %loop
525 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
528 guarded: ; preds = %loop
529 br i1 undef, label %loop, label %leave
531 leave: ; preds = %guarded
532 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
533 %exiplicit_guard_cond4 = and i1 %cond_2, %widenable_cond3
534 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
536 deopt2: ; preds = %leave
537 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
540 guarded1: ; preds = %leave
541 br i1 undef, label %loop2, label %leave2
543 loop2: ; preds = %guarded5, %guarded1
544 %cond_3 = icmp ult i32 %a, 7
545 %widenable_cond7 = call i1 @llvm.experimental.widenable.condition()
546 %exiplicit_guard_cond8 = and i1 %cond_3, %widenable_cond7
547 br i1 %exiplicit_guard_cond8, label %guarded5, label %deopt6, !prof !0
549 deopt6: ; preds = %loop2
550 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
553 guarded5: ; preds = %loop2
556 leave2: ; preds = %guarded1
560 ; In cases like these where there isn't any "obviously profitable"
561 ; widening sites, we refuse to do anything.
562 define void @f_9(i32 %a, i1 %cond_0, i1 %cond_1) {
565 ; CHECK-NEXT: br label [[FIRST_LOOP:%.*]]
567 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
568 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0:%.*]], [[WIDENABLE_COND]]
569 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
571 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
572 ; CHECK-NEXT: ret void
574 ; CHECK-NEXT: br i1 undef, label [[FIRST_LOOP]], label [[SECOND_LOOP:%.*]]
575 ; CHECK: second_loop:
576 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
577 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1:%.*]], [[WIDENABLE_COND3]]
578 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
580 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
581 ; CHECK-NEXT: ret void
583 ; CHECK-NEXT: br label [[SECOND_LOOP]]
588 first_loop: ; preds = %guarded, %entry
589 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
590 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
591 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
593 deopt: ; preds = %first_loop
594 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
597 guarded: ; preds = %first_loop
598 br i1 undef, label %first_loop, label %second_loop
600 second_loop: ; preds = %guarded1, %guarded
601 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
602 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3
603 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
605 deopt2: ; preds = %second_loop
606 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
609 guarded1: ; preds = %second_loop
610 br label %second_loop
613 ; Same situation as in @f_9: no "obviously profitable" widening sites,
614 ; so we refuse to do anything.
615 define void @f_10(i32 %a, i1 %cond_0, i1 %cond_1) {
616 ; CHECK-LABEL: @f_10(
618 ; CHECK-NEXT: br label [[LOOP:%.*]]
620 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
621 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0:%.*]], [[WIDENABLE_COND]]
622 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
624 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
625 ; CHECK-NEXT: ret void
627 ; CHECK-NEXT: br i1 undef, label [[LOOP]], label [[NO_LOOP:%.*]]
629 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
630 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1:%.*]], [[WIDENABLE_COND3]]
631 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
633 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
634 ; CHECK-NEXT: ret void
636 ; CHECK-NEXT: ret void
641 loop: ; preds = %guarded, %entry
642 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
643 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
644 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
646 deopt: ; preds = %loop
647 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
650 guarded: ; preds = %loop
651 br i1 undef, label %loop, label %no_loop
653 no_loop: ; preds = %guarded
654 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
655 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3
656 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
658 deopt2: ; preds = %no_loop
659 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
662 guarded1: ; preds = %no_loop
666 ; With guards in loops, we're okay hoisting out the guard into the
668 define void @f_11(i32 %a, i1 %cond_0, i1 %cond_1) {
669 ; CHECK-LABEL: @f_11(
671 ; CHECK-NEXT: br label [[OUTER_HEADER:%.*]]
672 ; CHECK: outer_header:
673 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
674 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0:%.*]], [[WIDENABLE_COND]]
675 ; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0]], [[COND_1:%.*]]
676 ; CHECK-NEXT: [[GUARD_CHK:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
677 ; CHECK-NEXT: br i1 [[GUARD_CHK]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
679 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
680 ; CHECK-NEXT: ret void
682 ; CHECK-NEXT: br label [[INNER:%.*]]
684 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
685 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]]
686 ; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
688 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
689 ; CHECK-NEXT: ret void
691 ; CHECK-NEXT: br i1 undef, label [[INNER]], label [[OUTER_LATCH:%.*]]
692 ; CHECK: outer_latch:
693 ; CHECK-NEXT: br i1 undef, label [[OUTER_HEADER]], label [[EXIT:%.*]]
695 ; CHECK-NEXT: ret void
698 br label %outer_header
700 outer_header: ; preds = %outer_latch, %entry
701 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
702 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
703 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
705 deopt: ; preds = %outer_header
706 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
709 guarded: ; preds = %outer_header
712 inner: ; preds = %guarded1, %guarded
713 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
714 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3
715 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
717 deopt2: ; preds = %inner
718 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
721 guarded1: ; preds = %inner
722 br i1 undef, label %inner, label %outer_latch
724 outer_latch: ; preds = %guarded1
725 br i1 undef, label %outer_header, label %exit
727 exit: ; preds = %outer_latch
731 ; Checks that we are adequately guarded against exponential-time
732 ; behavior when hoisting code.
733 define void @f_12(i32 %a0) {
734 ; CHECK-LABEL: @f_12(
736 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
737 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 true, [[WIDENABLE_COND]]
738 ; CHECK-NEXT: [[A1:%.*]] = mul i32 [[A0:%.*]], [[A0]]
739 ; CHECK-NEXT: [[A2:%.*]] = mul i32 [[A1]], [[A1]]
740 ; CHECK-NEXT: [[A3:%.*]] = mul i32 [[A2]], [[A2]]
741 ; CHECK-NEXT: [[A4:%.*]] = mul i32 [[A3]], [[A3]]
742 ; CHECK-NEXT: [[A5:%.*]] = mul i32 [[A4]], [[A4]]
743 ; CHECK-NEXT: [[A6:%.*]] = mul i32 [[A5]], [[A5]]
744 ; CHECK-NEXT: [[A7:%.*]] = mul i32 [[A6]], [[A6]]
745 ; CHECK-NEXT: [[A8:%.*]] = mul i32 [[A7]], [[A7]]
746 ; CHECK-NEXT: [[A9:%.*]] = mul i32 [[A8]], [[A8]]
747 ; CHECK-NEXT: [[A10:%.*]] = mul i32 [[A9]], [[A9]]
748 ; CHECK-NEXT: [[A11:%.*]] = mul i32 [[A10]], [[A10]]
749 ; CHECK-NEXT: [[A12:%.*]] = mul i32 [[A11]], [[A11]]
750 ; CHECK-NEXT: [[A13:%.*]] = mul i32 [[A12]], [[A12]]
751 ; CHECK-NEXT: [[A14:%.*]] = mul i32 [[A13]], [[A13]]
752 ; CHECK-NEXT: [[A15:%.*]] = mul i32 [[A14]], [[A14]]
753 ; CHECK-NEXT: [[A16:%.*]] = mul i32 [[A15]], [[A15]]
754 ; CHECK-NEXT: [[A17:%.*]] = mul i32 [[A16]], [[A16]]
755 ; CHECK-NEXT: [[A18:%.*]] = mul i32 [[A17]], [[A17]]
756 ; CHECK-NEXT: [[A19:%.*]] = mul i32 [[A18]], [[A18]]
757 ; CHECK-NEXT: [[A20:%.*]] = mul i32 [[A19]], [[A19]]
758 ; CHECK-NEXT: [[A21:%.*]] = mul i32 [[A20]], [[A20]]
759 ; CHECK-NEXT: [[A22:%.*]] = mul i32 [[A21]], [[A21]]
760 ; CHECK-NEXT: [[A23:%.*]] = mul i32 [[A22]], [[A22]]
761 ; CHECK-NEXT: [[A24:%.*]] = mul i32 [[A23]], [[A23]]
762 ; CHECK-NEXT: [[A25:%.*]] = mul i32 [[A24]], [[A24]]
763 ; CHECK-NEXT: [[A26:%.*]] = mul i32 [[A25]], [[A25]]
764 ; CHECK-NEXT: [[A27:%.*]] = mul i32 [[A26]], [[A26]]
765 ; CHECK-NEXT: [[A28:%.*]] = mul i32 [[A27]], [[A27]]
766 ; CHECK-NEXT: [[A29:%.*]] = mul i32 [[A28]], [[A28]]
767 ; CHECK-NEXT: [[A30:%.*]] = mul i32 [[A29]], [[A29]]
768 ; CHECK-NEXT: [[COND:%.*]] = trunc i32 [[A30]] to i1
769 ; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 true, [[COND]]
770 ; CHECK-NEXT: [[GUARD_CHK:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
771 ; CHECK-NEXT: br i1 [[GUARD_CHK]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
773 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
774 ; CHECK-NEXT: ret void
776 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
777 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND]], [[WIDENABLE_COND3]]
778 ; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
780 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
781 ; CHECK-NEXT: ret void
783 ; CHECK-NEXT: ret void
786 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
787 %exiplicit_guard_cond = and i1 true, %widenable_cond
788 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
790 deopt: ; preds = %entry
791 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
794 guarded: ; preds = %entry
795 %a1 = mul i32 %a0, %a0
796 %a2 = mul i32 %a1, %a1
797 %a3 = mul i32 %a2, %a2
798 %a4 = mul i32 %a3, %a3
799 %a5 = mul i32 %a4, %a4
800 %a6 = mul i32 %a5, %a5
801 %a7 = mul i32 %a6, %a6
802 %a8 = mul i32 %a7, %a7
803 %a9 = mul i32 %a8, %a8
804 %a10 = mul i32 %a9, %a9
805 %a11 = mul i32 %a10, %a10
806 %a12 = mul i32 %a11, %a11
807 %a13 = mul i32 %a12, %a12
808 %a14 = mul i32 %a13, %a13
809 %a15 = mul i32 %a14, %a14
810 %a16 = mul i32 %a15, %a15
811 %a17 = mul i32 %a16, %a16
812 %a18 = mul i32 %a17, %a17
813 %a19 = mul i32 %a18, %a18
814 %a20 = mul i32 %a19, %a19
815 %a21 = mul i32 %a20, %a20
816 %a22 = mul i32 %a21, %a21
817 %a23 = mul i32 %a22, %a22
818 %a24 = mul i32 %a23, %a23
819 %a25 = mul i32 %a24, %a24
820 %a26 = mul i32 %a25, %a25
821 %a27 = mul i32 %a26, %a26
822 %a28 = mul i32 %a27, %a27
823 %a29 = mul i32 %a28, %a28
824 %a30 = mul i32 %a29, %a29
825 %cond = trunc i32 %a30 to i1
826 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
827 %exiplicit_guard_cond4 = and i1 %cond, %widenable_cond3
828 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
830 deopt2: ; preds = %guarded
831 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
834 guarded1: ; preds = %guarded
838 define void @f_13(i32 %a) {
839 ; CHECK-LABEL: @f_13(
841 ; CHECK-NEXT: [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 14
842 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
843 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0]], [[WIDENABLE_COND]]
844 ; CHECK-NEXT: [[WIDE_CHK:%.*]] = icmp ult i32 [[A]], 10
845 ; CHECK-NEXT: [[GUARD_CHK:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
846 ; CHECK-NEXT: br i1 [[GUARD_CHK]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
848 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
849 ; CHECK-NEXT: ret void
851 ; CHECK-NEXT: br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]]
853 ; CHECK-NEXT: [[COND_1:%.*]] = icmp slt i32 [[A]], 10
854 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
855 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]]
856 ; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
858 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
859 ; CHECK-NEXT: ret void
861 ; CHECK-NEXT: ret void
863 ; CHECK-NEXT: ret void
866 %cond_0 = icmp ult i32 %a, 14
867 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
868 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
869 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
871 deopt: ; preds = %entry
872 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
875 guarded: ; preds = %entry
876 br i1 undef, label %left, label %right
878 left: ; preds = %guarded
879 %cond_1 = icmp slt i32 %a, 10
880 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
881 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3
882 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
884 deopt2: ; preds = %left
885 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
888 guarded1: ; preds = %left
891 right: ; preds = %guarded
895 define void @f_14(i32 %a) {
896 ; CHECK-LABEL: @f_14(
898 ; CHECK-NEXT: [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 14
899 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
900 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0]], [[WIDENABLE_COND]]
901 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
903 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
904 ; CHECK-NEXT: ret void
906 ; CHECK-NEXT: br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]]
908 ; CHECK-NEXT: [[COND_1:%.*]] = icmp sgt i32 [[A]], 10
909 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
910 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]]
911 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
913 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
914 ; CHECK-NEXT: ret void
916 ; CHECK-NEXT: ret void
918 ; CHECK-NEXT: ret void
921 %cond_0 = icmp ult i32 %a, 14
922 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
923 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
924 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
926 deopt: ; preds = %entry
927 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
930 guarded: ; preds = %entry
931 br i1 undef, label %left, label %right
933 left: ; preds = %guarded
934 %cond_1 = icmp sgt i32 %a, 10
935 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
936 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3
937 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
939 deopt2: ; preds = %left
940 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
943 guarded1: ; preds = %left
946 right: ; preds = %guarded
950 ; Make sure we do not widen guard by trivial true conditions into something.
951 define void @f_15(i1 %cond_0, i1 %cond_1) {
952 ; CHECK-LABEL: @f_15(
954 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
955 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0:%.*]], [[WIDENABLE_COND]]
956 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
958 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
959 ; CHECK-NEXT: ret void
961 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
962 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 true, [[WIDENABLE_COND3]]
963 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
965 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
966 ; CHECK-NEXT: ret void
968 ; CHECK-NEXT: ret void
971 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
972 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
973 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
975 deopt: ; preds = %entry
976 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
979 guarded: ; preds = %entry
980 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
981 %exiplicit_guard_cond4 = and i1 true, %widenable_cond3
982 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
984 deopt2: ; preds = %guarded
985 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
988 guarded1: ; preds = %guarded
992 ; Make sure we do not widen guard by trivial false conditions into something.
993 define void @f_16(i1 %cond_0, i1 %cond_1) {
994 ; CHECK-LABEL: @f_16(
996 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
997 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0:%.*]], [[WIDENABLE_COND]]
998 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof !0
1000 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
1001 ; CHECK-NEXT: ret void
1003 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
1004 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 false, [[WIDENABLE_COND3]]
1005 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof !0
1007 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
1008 ; CHECK-NEXT: ret void
1010 ; CHECK-NEXT: ret void
1013 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
1014 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
1015 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
1017 deopt: ; preds = %entry
1018 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
1021 guarded: ; preds = %entry
1022 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
1023 %exiplicit_guard_cond4 = and i1 false, %widenable_cond3
1024 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
1026 deopt2: ; preds = %guarded
1027 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
1030 guarded1: ; preds = %guarded
1034 declare void @llvm.experimental.deoptimize.isVoid(...)
1036 ; Function Attrs: inaccessiblememonly nounwind
1037 declare i1 @llvm.experimental.widenable.condition() #0
1039 attributes #0 = { inaccessiblememonly nounwind }
1041 !0 = !{!"branch_weights", i32 1048576, i32 1}