1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -guard-widening-widen-branch-guards=true -passes=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: [[COND_1_GW_FR:%.*]] = freeze i1 [[COND_1:%.*]]
11 ; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1_GW_FR]]
12 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
13 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
14 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0:![0-9]+]]
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_GW_FR]], [[WIDENABLE_COND3]]
21 ; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]]
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, i1 %arg) {
54 ; CHECK-NEXT: [[COND_1_GW_FR:%.*]] = freeze i1 [[COND_1:%.*]]
55 ; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1_GW_FR]]
56 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
57 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
58 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
60 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
61 ; CHECK-NEXT: ret void
63 ; CHECK-NEXT: br i1 %arg, 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_GW_FR]], [[WIDENABLE_COND3]]
71 ; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]]
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 %arg, 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, i1 %arg) {
114 ; CHECK-NEXT: [[B_GW_FR:%.*]] = freeze i32 [[B:%.*]]
115 ; CHECK-NEXT: [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 10
116 ; CHECK-NEXT: [[COND_1:%.*]] = icmp ult i32 [[B_GW_FR]], 10
117 ; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0]], [[COND_1]]
118 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
119 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
120 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
122 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
123 ; CHECK-NEXT: ret void
125 ; CHECK-NEXT: br i1 %arg, 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 [[PROF0]]
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 %arg, 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, i1 %arg) {
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 [[PROF0]]
183 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
184 ; CHECK-NEXT: ret void
186 ; CHECK-NEXT: br i1 %arg, 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 [[PROF0]]
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 %arg, 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, i1 %arg) {
236 ; CHECK-NEXT: [[B_GW_FR:%.*]] = freeze i32 [[B:%.*]]
237 ; CHECK-NEXT: [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 10
238 ; CHECK-NEXT: [[COND_1:%.*]] = icmp ult i32 [[B_GW_FR]], 10
239 ; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0]], [[COND_1]]
240 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
241 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
242 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
244 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
245 ; CHECK-NEXT: ret void
247 ; CHECK-NEXT: br i1 %arg, 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 [[PROF0]]
253 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
254 ; CHECK-NEXT: ret void
256 ; CHECK-NEXT: br i1 %arg, 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 %arg, 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 %arg, 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, i1 %arg) {
295 ; CHECK-NEXT: [[COND_0:%.*]] = icmp ugt i32 [[A:%.*]], 7
296 ; CHECK-NEXT: [[WIDE_CHK:%.*]] = icmp uge i32 [[A]], 11
297 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
298 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
299 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
301 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
302 ; CHECK-NEXT: ret void
304 ; CHECK-NEXT: br i1 %arg, label [[LEFT:%.*]], label [[RIGHT:%.*]]
306 ; CHECK-NEXT: [[COND_1:%.*]] = icmp ugt i32 [[A]], 10
307 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
308 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]]
309 ; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]]
311 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
312 ; CHECK-NEXT: ret void
314 ; CHECK-NEXT: ret void
316 ; CHECK-NEXT: ret void
319 %cond_0 = icmp ugt i32 %a, 7
320 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
321 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
322 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
324 deopt: ; preds = %entry
325 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
328 guarded: ; preds = %entry
329 br i1 %arg, label %left, label %right
331 left: ; preds = %guarded
332 %cond_1 = icmp ugt i32 %a, 10
333 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
334 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3
335 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
337 deopt2: ; preds = %left
338 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
341 guarded1: ; preds = %left
344 right: ; preds = %guarded
348 ; Negative test: the load from %a can be safely speculated to before
349 ; the first guard, but there is no guarantee that it will produce the
351 define void @f_6(ptr dereferenceable(32) %a, ptr %b, i1 %unknown) {
354 ; CHECK-NEXT: [[COND_0:%.*]] = load i1, ptr [[A:%.*]], align 1
355 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
356 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0]], [[WIDENABLE_COND]]
357 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
359 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
360 ; CHECK-NEXT: ret void
362 ; CHECK-NEXT: store i1 [[UNKNOWN:%.*]], ptr [[B:%.*]], align 1
363 ; CHECK-NEXT: [[COND_1:%.*]] = load i1, ptr [[A]], align 1
364 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
365 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]]
366 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]]
368 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
369 ; CHECK-NEXT: ret void
371 ; CHECK-NEXT: ret void
374 %cond_0 = load i1, ptr %a
375 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
376 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
377 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
379 deopt: ; preds = %entry
380 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
383 guarded: ; preds = %entry
384 store i1 %unknown, ptr %b
385 %cond_1 = load i1, ptr %a
386 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
387 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3
388 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
390 deopt2: ; preds = %guarded
391 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
394 guarded1: ; preds = %guarded
398 ; All else equal, we try to widen the earliest guard we can. This
399 ; heuristic can use some tuning.
400 define void @f_7(i32 %a, ptr %cond_buf, i1 %arg) {
403 ; CHECK-NEXT: [[A_GW_FR:%.*]] = freeze i32 [[A:%.*]]
404 ; CHECK-NEXT: [[COND_1:%.*]] = load volatile i1, ptr [[COND_BUF:%.*]], align 1
405 ; CHECK-NEXT: [[COND_3:%.*]] = icmp ult i32 [[A_GW_FR]], 7
406 ; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_3]]
407 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
408 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
409 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
411 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
412 ; CHECK-NEXT: ret void
414 ; CHECK-NEXT: [[COND_2:%.*]] = load volatile i1, ptr [[COND_BUF]], align 1
415 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
416 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_2]], [[WIDENABLE_COND3]]
417 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]]
419 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
420 ; CHECK-NEXT: ret void
422 ; CHECK-NEXT: br i1 %arg, label [[LEFT:%.*]], label [[RIGHT:%.*]]
424 ; CHECK-NEXT: [[WIDENABLE_COND7:%.*]] = call i1 @llvm.experimental.widenable.condition()
425 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND8:%.*]] = and i1 [[COND_3]], [[WIDENABLE_COND7]]
426 ; CHECK-NEXT: br i1 true, label [[GUARDED5:%.*]], label [[DEOPT6:%.*]], !prof [[PROF0]]
428 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
429 ; CHECK-NEXT: ret void
431 ; CHECK-NEXT: br label [[LEFT]]
433 ; CHECK-NEXT: ret void
436 %cond_1 = load volatile i1, ptr %cond_buf
437 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
438 %exiplicit_guard_cond = and i1 %cond_1, %widenable_cond
439 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
441 deopt: ; preds = %entry
442 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
445 guarded: ; preds = %entry
446 %cond_2 = load volatile i1, ptr %cond_buf
447 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
448 %exiplicit_guard_cond4 = and i1 %cond_2, %widenable_cond3
449 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
451 deopt2: ; preds = %guarded
452 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
455 guarded1: ; preds = %guarded
456 br i1 %arg, label %left, label %right
458 left: ; preds = %guarded5, %guarded1
459 %cond_3 = icmp ult i32 %a, 7
460 %widenable_cond7 = call i1 @llvm.experimental.widenable.condition()
461 %exiplicit_guard_cond8 = and i1 %cond_3, %widenable_cond7
462 br i1 %exiplicit_guard_cond8, label %guarded5, label %deopt6, !prof !0
464 deopt6: ; preds = %left
465 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
468 guarded5: ; preds = %left
471 right: ; preds = %guarded1
475 ; In this case the earliest dominating guard is in a loop, and we
476 ; don't want to put extra work in there. This heuristic can use some
478 define void @f_8(i32 %a, i1 %cond_1, i1 %cond_2, i1 %arg) {
481 ; CHECK-NEXT: [[A_GW_FR:%.*]] = freeze i32 [[A:%.*]]
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 [[PROF0]]
488 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
489 ; CHECK-NEXT: ret void
491 ; CHECK-NEXT: br i1 %arg, label [[LOOP]], label [[LEAVE:%.*]]
493 ; CHECK-NEXT: [[COND_3:%.*]] = icmp ult i32 [[A_GW_FR]], 7
494 ; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_2:%.*]], [[COND_3]]
495 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
496 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND3]]
497 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]]
499 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
500 ; CHECK-NEXT: ret void
502 ; CHECK-NEXT: br i1 %arg, label [[LOOP2:%.*]], label [[LEAVE2:%.*]]
504 ; CHECK-NEXT: [[WIDENABLE_COND7:%.*]] = call i1 @llvm.experimental.widenable.condition()
505 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND8:%.*]] = and i1 [[COND_3]], [[WIDENABLE_COND7]]
506 ; CHECK-NEXT: br i1 true, label [[GUARDED5:%.*]], label [[DEOPT6:%.*]], !prof [[PROF0]]
508 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
509 ; CHECK-NEXT: ret void
511 ; CHECK-NEXT: br label [[LOOP2]]
513 ; CHECK-NEXT: ret void
518 loop: ; preds = %guarded, %entry
519 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
520 %exiplicit_guard_cond = and i1 %cond_1, %widenable_cond
521 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
523 deopt: ; preds = %loop
524 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
527 guarded: ; preds = %loop
528 br i1 %arg, label %loop, label %leave
530 leave: ; preds = %guarded
531 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
532 %exiplicit_guard_cond4 = and i1 %cond_2, %widenable_cond3
533 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
535 deopt2: ; preds = %leave
536 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
539 guarded1: ; preds = %leave
540 br i1 %arg, label %loop2, label %leave2
542 loop2: ; preds = %guarded5, %guarded1
543 %cond_3 = icmp ult i32 %a, 7
544 %widenable_cond7 = call i1 @llvm.experimental.widenable.condition()
545 %exiplicit_guard_cond8 = and i1 %cond_3, %widenable_cond7
546 br i1 %exiplicit_guard_cond8, label %guarded5, label %deopt6, !prof !0
548 deopt6: ; preds = %loop2
549 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
552 guarded5: ; preds = %loop2
555 leave2: ; preds = %guarded1
559 ; In cases like these where there isn't any "obviously profitable"
560 ; widening sites, we refuse to do anything.
561 define void @f_9(i32 %a, i1 %cond_0, i1 %cond_1, i1 %arg) {
564 ; CHECK-NEXT: br label [[FIRST_LOOP:%.*]]
566 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
567 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0:%.*]], [[WIDENABLE_COND]]
568 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
570 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
571 ; CHECK-NEXT: ret void
573 ; CHECK-NEXT: br i1 %arg, label [[FIRST_LOOP]], label [[SECOND_LOOP:%.*]]
574 ; CHECK: second_loop:
575 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
576 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1:%.*]], [[WIDENABLE_COND3]]
577 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]]
579 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
580 ; CHECK-NEXT: ret void
582 ; CHECK-NEXT: br label [[SECOND_LOOP]]
587 first_loop: ; preds = %guarded, %entry
588 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
589 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
590 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
592 deopt: ; preds = %first_loop
593 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
596 guarded: ; preds = %first_loop
597 br i1 %arg, label %first_loop, label %second_loop
599 second_loop: ; preds = %guarded1, %guarded
600 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
601 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3
602 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
604 deopt2: ; preds = %second_loop
605 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
608 guarded1: ; preds = %second_loop
609 br label %second_loop
612 ; Same situation as in @f_9: no "obviously profitable" widening sites,
613 ; so we refuse to do anything.
614 define void @f_10(i32 %a, i1 %cond_0, i1 %cond_1, i1 %arg) {
615 ; CHECK-LABEL: @f_10(
617 ; CHECK-NEXT: br label [[LOOP:%.*]]
619 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
620 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0:%.*]], [[WIDENABLE_COND]]
621 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
623 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
624 ; CHECK-NEXT: ret void
626 ; CHECK-NEXT: br i1 %arg, label [[LOOP]], label [[NO_LOOP:%.*]]
628 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
629 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1:%.*]], [[WIDENABLE_COND3]]
630 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]]
632 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
633 ; CHECK-NEXT: ret void
635 ; CHECK-NEXT: ret void
640 loop: ; preds = %guarded, %entry
641 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
642 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
643 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
645 deopt: ; preds = %loop
646 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
649 guarded: ; preds = %loop
650 br i1 %arg, label %loop, label %no_loop
652 no_loop: ; preds = %guarded
653 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
654 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3
655 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
657 deopt2: ; preds = %no_loop
658 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
661 guarded1: ; preds = %no_loop
665 ; With guards in loops, we're okay hoisting out the guard into the
667 define void @f_11(i32 %a, i1 %cond_0, i1 %cond_1, i1 %arg) {
668 ; CHECK-LABEL: @f_11(
670 ; CHECK-NEXT: [[COND_1_GW_FR:%.*]] = freeze i1 [[COND_1:%.*]]
671 ; CHECK-NEXT: br label [[OUTER_HEADER:%.*]]
672 ; CHECK: outer_header:
673 ; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1_GW_FR]]
674 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
675 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
676 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
678 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
679 ; CHECK-NEXT: ret void
681 ; CHECK-NEXT: br label [[INNER:%.*]]
683 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
684 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1_GW_FR]], [[WIDENABLE_COND3]]
685 ; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]]
687 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
688 ; CHECK-NEXT: ret void
690 ; CHECK-NEXT: br i1 %arg, label [[INNER]], label [[OUTER_LATCH:%.*]]
691 ; CHECK: outer_latch:
692 ; CHECK-NEXT: br i1 %arg, label [[OUTER_HEADER]], label [[EXIT:%.*]]
694 ; CHECK-NEXT: ret void
697 br label %outer_header
699 outer_header: ; preds = %outer_latch, %entry
700 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
701 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
702 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
704 deopt: ; preds = %outer_header
705 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
708 guarded: ; preds = %outer_header
711 inner: ; preds = %guarded1, %guarded
712 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
713 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3
714 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
716 deopt2: ; preds = %inner
717 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
720 guarded1: ; preds = %inner
721 br i1 %arg, label %inner, label %outer_latch
723 outer_latch: ; preds = %guarded1
724 br i1 %arg, label %outer_header, label %exit
726 exit: ; preds = %outer_latch
730 ; Checks that we are adequately guarded against exponential-time
731 ; behavior when hoisting code.
732 define void @f_12(i32 %a0) {
733 ; CHECK-LABEL: @f_12(
735 ; CHECK-NEXT: [[A0_GW_FR:%.*]] = freeze i32 [[A0:%.*]]
736 ; CHECK-NEXT: [[A1:%.*]] = mul i32 [[A0_GW_FR]], [[A0_GW_FR]]
737 ; CHECK-NEXT: [[A2:%.*]] = mul i32 [[A1]], [[A1]]
738 ; CHECK-NEXT: [[A3:%.*]] = mul i32 [[A2]], [[A2]]
739 ; CHECK-NEXT: [[A4:%.*]] = mul i32 [[A3]], [[A3]]
740 ; CHECK-NEXT: [[A5:%.*]] = mul i32 [[A4]], [[A4]]
741 ; CHECK-NEXT: [[A6:%.*]] = mul i32 [[A5]], [[A5]]
742 ; CHECK-NEXT: [[A7:%.*]] = mul i32 [[A6]], [[A6]]
743 ; CHECK-NEXT: [[A8:%.*]] = mul i32 [[A7]], [[A7]]
744 ; CHECK-NEXT: [[A9:%.*]] = mul i32 [[A8]], [[A8]]
745 ; CHECK-NEXT: [[A10:%.*]] = mul i32 [[A9]], [[A9]]
746 ; CHECK-NEXT: [[A11:%.*]] = mul i32 [[A10]], [[A10]]
747 ; CHECK-NEXT: [[A12:%.*]] = mul i32 [[A11]], [[A11]]
748 ; CHECK-NEXT: [[A13:%.*]] = mul i32 [[A12]], [[A12]]
749 ; CHECK-NEXT: [[A14:%.*]] = mul i32 [[A13]], [[A13]]
750 ; CHECK-NEXT: [[A15:%.*]] = mul i32 [[A14]], [[A14]]
751 ; CHECK-NEXT: [[A16:%.*]] = mul i32 [[A15]], [[A15]]
752 ; CHECK-NEXT: [[A17:%.*]] = mul i32 [[A16]], [[A16]]
753 ; CHECK-NEXT: [[A18:%.*]] = mul i32 [[A17]], [[A17]]
754 ; CHECK-NEXT: [[A19:%.*]] = mul i32 [[A18]], [[A18]]
755 ; CHECK-NEXT: [[A20:%.*]] = mul i32 [[A19]], [[A19]]
756 ; CHECK-NEXT: [[A21:%.*]] = mul i32 [[A20]], [[A20]]
757 ; CHECK-NEXT: [[A22:%.*]] = mul i32 [[A21]], [[A21]]
758 ; CHECK-NEXT: [[A23:%.*]] = mul i32 [[A22]], [[A22]]
759 ; CHECK-NEXT: [[A24:%.*]] = mul i32 [[A23]], [[A23]]
760 ; CHECK-NEXT: [[A25:%.*]] = mul i32 [[A24]], [[A24]]
761 ; CHECK-NEXT: [[A26:%.*]] = mul i32 [[A25]], [[A25]]
762 ; CHECK-NEXT: [[A27:%.*]] = mul i32 [[A26]], [[A26]]
763 ; CHECK-NEXT: [[A28:%.*]] = mul i32 [[A27]], [[A27]]
764 ; CHECK-NEXT: [[A29:%.*]] = mul i32 [[A28]], [[A28]]
765 ; CHECK-NEXT: [[A30:%.*]] = mul i32 [[A29]], [[A29]]
766 ; CHECK-NEXT: [[COND:%.*]] = trunc i32 [[A30]] to i1
767 ; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 true, [[COND]]
768 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
769 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
770 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
772 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
773 ; CHECK-NEXT: ret void
775 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
776 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND]], [[WIDENABLE_COND3]]
777 ; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]]
779 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
780 ; CHECK-NEXT: ret void
782 ; CHECK-NEXT: ret void
785 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
786 %exiplicit_guard_cond = and i1 true, %widenable_cond
787 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
789 deopt: ; preds = %entry
790 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
793 guarded: ; preds = %entry
794 %a1 = mul i32 %a0, %a0
795 %a2 = mul i32 %a1, %a1
796 %a3 = mul i32 %a2, %a2
797 %a4 = mul i32 %a3, %a3
798 %a5 = mul i32 %a4, %a4
799 %a6 = mul i32 %a5, %a5
800 %a7 = mul i32 %a6, %a6
801 %a8 = mul i32 %a7, %a7
802 %a9 = mul i32 %a8, %a8
803 %a10 = mul i32 %a9, %a9
804 %a11 = mul i32 %a10, %a10
805 %a12 = mul i32 %a11, %a11
806 %a13 = mul i32 %a12, %a12
807 %a14 = mul i32 %a13, %a13
808 %a15 = mul i32 %a14, %a14
809 %a16 = mul i32 %a15, %a15
810 %a17 = mul i32 %a16, %a16
811 %a18 = mul i32 %a17, %a17
812 %a19 = mul i32 %a18, %a18
813 %a20 = mul i32 %a19, %a19
814 %a21 = mul i32 %a20, %a20
815 %a22 = mul i32 %a21, %a21
816 %a23 = mul i32 %a22, %a22
817 %a24 = mul i32 %a23, %a23
818 %a25 = mul i32 %a24, %a24
819 %a26 = mul i32 %a25, %a25
820 %a27 = mul i32 %a26, %a26
821 %a28 = mul i32 %a27, %a27
822 %a29 = mul i32 %a28, %a28
823 %a30 = mul i32 %a29, %a29
824 %cond = trunc i32 %a30 to i1
825 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
826 %exiplicit_guard_cond4 = and i1 %cond, %widenable_cond3
827 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
829 deopt2: ; preds = %guarded
830 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
833 guarded1: ; preds = %guarded
837 define void @f_13(i32 %a, i1 %arg) {
838 ; CHECK-LABEL: @f_13(
840 ; CHECK-NEXT: [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 14
841 ; CHECK-NEXT: [[WIDE_CHK:%.*]] = icmp ult i32 [[A]], 10
842 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
843 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
844 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
846 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
847 ; CHECK-NEXT: ret void
849 ; CHECK-NEXT: br i1 %arg, label [[LEFT:%.*]], label [[RIGHT:%.*]]
851 ; CHECK-NEXT: [[COND_1:%.*]] = icmp slt i32 [[A]], 10
852 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
853 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]]
854 ; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]]
856 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
857 ; CHECK-NEXT: ret void
859 ; CHECK-NEXT: ret void
861 ; CHECK-NEXT: ret void
864 %cond_0 = icmp ult i32 %a, 14
865 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
866 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
867 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
869 deopt: ; preds = %entry
870 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
873 guarded: ; preds = %entry
874 br i1 %arg, label %left, label %right
876 left: ; preds = %guarded
877 %cond_1 = icmp slt i32 %a, 10
878 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
879 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3
880 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
882 deopt2: ; preds = %left
883 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
886 guarded1: ; preds = %left
889 right: ; preds = %guarded
893 define void @f_14(i32 %a, i1 %arg) {
894 ; CHECK-LABEL: @f_14(
896 ; CHECK-NEXT: [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 14
897 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
898 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0]], [[WIDENABLE_COND]]
899 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
901 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
902 ; CHECK-NEXT: ret void
904 ; CHECK-NEXT: br i1 %arg, label [[LEFT:%.*]], label [[RIGHT:%.*]]
906 ; CHECK-NEXT: [[COND_1:%.*]] = icmp sgt i32 [[A]], 10
907 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
908 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]]
909 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]]
911 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
912 ; CHECK-NEXT: ret void
914 ; CHECK-NEXT: ret void
916 ; CHECK-NEXT: ret void
919 %cond_0 = icmp ult i32 %a, 14
920 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
921 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
922 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
924 deopt: ; preds = %entry
925 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
928 guarded: ; preds = %entry
929 br i1 %arg, label %left, label %right
931 left: ; preds = %guarded
932 %cond_1 = icmp sgt i32 %a, 10
933 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
934 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3
935 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
937 deopt2: ; preds = %left
938 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
941 guarded1: ; preds = %left
944 right: ; preds = %guarded
948 ; Make sure we do not widen guard by trivial true conditions into something.
949 define void @f_15(i1 %cond_0, i1 %cond_1) {
950 ; CHECK-LABEL: @f_15(
952 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
953 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0:%.*]], [[WIDENABLE_COND]]
954 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
956 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
957 ; CHECK-NEXT: ret void
959 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
960 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 true, [[WIDENABLE_COND3]]
961 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]]
963 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
964 ; CHECK-NEXT: ret void
966 ; CHECK-NEXT: ret void
969 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
970 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
971 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
973 deopt: ; preds = %entry
974 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
977 guarded: ; preds = %entry
978 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
979 %exiplicit_guard_cond4 = and i1 true, %widenable_cond3
980 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
982 deopt2: ; preds = %guarded
983 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
986 guarded1: ; preds = %guarded
990 ; Make sure we do not widen guard by trivial false conditions into something.
991 define void @f_16(i1 %cond_0, i1 %cond_1) {
992 ; CHECK-LABEL: @f_16(
994 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
995 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0:%.*]], [[WIDENABLE_COND]]
996 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
998 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
999 ; CHECK-NEXT: ret void
1001 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
1002 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 false, [[WIDENABLE_COND3]]
1003 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]]
1005 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
1006 ; CHECK-NEXT: ret void
1008 ; CHECK-NEXT: ret void
1011 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
1012 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond
1013 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
1015 deopt: ; preds = %entry
1016 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
1019 guarded: ; preds = %entry
1020 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
1021 %exiplicit_guard_cond4 = and i1 false, %widenable_cond3
1022 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
1024 deopt2: ; preds = %guarded
1025 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
1028 guarded1: ; preds = %guarded
1033 define void @swapped_wb(i1 %cond_0, i1 %cond_1) {
1034 ; CHECK-LABEL: @swapped_wb(
1035 ; CHECK-NEXT: entry:
1036 ; CHECK-NEXT: [[COND_1_GW_FR:%.*]] = freeze i1 [[COND_1:%.*]]
1037 ; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1_GW_FR]]
1038 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
1039 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDENABLE_COND]], [[WIDE_CHK]]
1040 ; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
1042 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
1043 ; CHECK-NEXT: ret void
1045 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
1046 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1_GW_FR]], [[WIDENABLE_COND3]]
1047 ; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]]
1049 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
1050 ; CHECK-NEXT: ret void
1052 ; CHECK-NEXT: ret void
1055 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
1056 %exiplicit_guard_cond = and i1 %widenable_cond, %cond_0
1057 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0
1059 deopt: ; preds = %entry
1060 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
1063 guarded: ; preds = %entry
1064 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
1065 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3
1066 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
1068 deopt2: ; preds = %guarded
1069 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
1072 guarded1: ; preds = %guarded
1076 define void @trivial_wb(i1 %cond_0) {
1077 ; CHECK-LABEL: @trivial_wb(
1078 ; CHECK-NEXT: entry:
1079 ; CHECK-NEXT: [[COND_0_GW_FR:%.*]] = freeze i1 [[COND_0:%.*]]
1080 ; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 true, [[COND_0_GW_FR]]
1081 ; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition()
1082 ; CHECK-NEXT: [[TMP0:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]]
1083 ; CHECK-NEXT: br i1 [[TMP0]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
1085 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
1086 ; CHECK-NEXT: ret void
1088 ; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition()
1089 ; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_0_GW_FR]], [[WIDENABLE_COND3]]
1090 ; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]]
1092 ; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
1093 ; CHECK-NEXT: ret void
1095 ; CHECK-NEXT: ret void
1098 %widenable_cond = call i1 @llvm.experimental.widenable.condition()
1099 br i1 %widenable_cond, label %guarded, label %deopt, !prof !0
1101 deopt: ; preds = %entry
1102 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
1105 guarded: ; preds = %entry
1106 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
1107 %exiplicit_guard_cond4 = and i1 %cond_0, %widenable_cond3
1108 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0
1110 deopt2: ; preds = %guarded
1111 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]
1114 guarded1: ; preds = %guarded
1119 declare void @llvm.experimental.deoptimize.isVoid(...)
1121 ; Function Attrs: inaccessiblememonly nounwind
1122 declare i1 @llvm.experimental.widenable.condition() #0
1124 attributes #0 = { inaccessiblememonly nounwind }
1126 !0 = !{!"branch_weights", i32 1048576, i32 1}