1127 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -S -guard-widening-widen-branch-guards=true -passes=guard-widening < %s | FileCheck %s3; RUN: opt -S -guard-widening-widen-branch-guards=true -passes=guard-widening < %s | FileCheck %s4 5; Basic test case: we wide the first check to check both the6; conditions.7define void @f_0(i1 %cond_0, i1 %cond_1) {8; CHECK-LABEL: @f_0(9; CHECK-NEXT: entry: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]+]]15; CHECK: deopt:16; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]17; CHECK-NEXT: ret void18; CHECK: guarded: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]]22; CHECK: deopt2:23; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]24; CHECK-NEXT: ret void25; CHECK: guarded1:26; CHECK-NEXT: ret void27;28entry:29 %widenable_cond = call i1 @llvm.experimental.widenable.condition()30 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond31 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !032 33deopt: ; preds = %entry34 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]35 ret void36 37guarded: ; preds = %entry38 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()39 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond340 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !041 42deopt2: ; preds = %guarded43 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]44 ret void45 46guarded1: ; preds = %guarded47 ret void48}49 50; Same as @f_0, but with using a more general notion of postdominance.51define void @f_1(i1 %cond_0, i1 %cond_1, i1 %arg) {52; CHECK-LABEL: @f_1(53; CHECK-NEXT: entry: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]]59; CHECK: deopt:60; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]61; CHECK-NEXT: ret void62; CHECK: guarded:63; CHECK-NEXT: br i1 %arg, label [[LEFT:%.*]], label [[RIGHT:%.*]]64; CHECK: left:65; CHECK-NEXT: br label [[MERGE:%.*]]66; CHECK: right:67; CHECK-NEXT: br label [[MERGE]]68; CHECK: 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]]72; CHECK: deopt2:73; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]74; CHECK-NEXT: ret void75; CHECK: guarded1:76; CHECK-NEXT: ret void77;78entry:79 %widenable_cond = call i1 @llvm.experimental.widenable.condition()80 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond81 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !082 83deopt: ; preds = %entry84 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]85 ret void86 87guarded: ; preds = %entry88 br i1 %arg, label %left, label %right89 90left: ; preds = %guarded91 br label %merge92 93right: ; preds = %guarded94 br label %merge95 96merge: ; preds = %right, %left97 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()98 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond399 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0100 101deopt2: ; preds = %merge102 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]103 ret void104 105guarded1: ; preds = %merge106 ret void107}108 109; Like @f_1, but we have some code we need to hoist before we can110; widen a dominanting check.111define void @f_2(i32 %a, i32 %b, i1 %arg) {112; CHECK-LABEL: @f_2(113; CHECK-NEXT: entry:114; CHECK-NEXT: [[B_GW_FR:%.*]] = freeze i32 [[B:%.*]]115; CHECK-NEXT: [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 10116; CHECK-NEXT: [[COND_1:%.*]] = icmp ult i32 [[B_GW_FR]], 10117; 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]]121; CHECK: deopt:122; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]123; CHECK-NEXT: ret void124; CHECK: guarded:125; CHECK-NEXT: br i1 %arg, label [[LEFT:%.*]], label [[RIGHT:%.*]]126; CHECK: left:127; CHECK-NEXT: br label [[MERGE:%.*]]128; CHECK: right:129; CHECK-NEXT: br label [[MERGE]]130; CHECK: 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]]134; CHECK: deopt2:135; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]136; CHECK-NEXT: ret void137; CHECK: guarded1:138; CHECK-NEXT: ret void139;140entry:141 %cond_0 = icmp ult i32 %a, 10142 %widenable_cond = call i1 @llvm.experimental.widenable.condition()143 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond144 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0145 146deopt: ; preds = %entry147 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]148 ret void149 150guarded: ; preds = %entry151 br i1 %arg, label %left, label %right152 153left: ; preds = %guarded154 br label %merge155 156right: ; preds = %guarded157 br label %merge158 159merge: ; preds = %right, %left160 %cond_1 = icmp ult i32 %b, 10161 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()162 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3163 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0164 165deopt2: ; preds = %merge166 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]167 ret void168 169guarded1: ; preds = %merge170 ret void171}172 173; Negative test: don't hoist stuff out of control flow174; indiscriminately, since that can make us do more work than needed.175define void @f_3(i32 %a, i32 %b, i1 %arg) {176; CHECK-LABEL: @f_3(177; CHECK-NEXT: entry:178; CHECK-NEXT: [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 10179; 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]]182; CHECK: deopt:183; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]184; CHECK-NEXT: ret void185; CHECK: guarded:186; CHECK-NEXT: br i1 %arg, label [[LEFT:%.*]], label [[RIGHT:%.*]]187; CHECK: left:188; CHECK-NEXT: [[COND_1:%.*]] = icmp ult i32 [[B:%.*]], 10189; 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]]192; CHECK: deopt2:193; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]194; CHECK-NEXT: ret void195; CHECK: guarded1:196; CHECK-NEXT: ret void197; CHECK: right:198; CHECK-NEXT: ret void199;200entry:201 %cond_0 = icmp ult i32 %a, 10202 %widenable_cond = call i1 @llvm.experimental.widenable.condition()203 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond204 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0205 206deopt: ; preds = %entry207 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]208 ret void209 210guarded: ; preds = %entry211 br i1 %arg, label %left, label %right212 213left: ; preds = %guarded214 %cond_1 = icmp ult i32 %b, 10215 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()216 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3217 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0218 219deopt2: ; preds = %left220 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]221 ret void222 223guarded1: ; preds = %left224 ret void225 226right: ; preds = %guarded227 ret void228}229 230; But hoisting out of control flow is fine if it makes a loop computed231; condition loop invariant. This behavior may require some tuning in232; the future.233define void @f_4(i32 %a, i32 %b, i1 %arg) {234; CHECK-LABEL: @f_4(235; CHECK-NEXT: entry:236; CHECK-NEXT: [[B_GW_FR:%.*]] = freeze i32 [[B:%.*]]237; CHECK-NEXT: [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 10238; CHECK-NEXT: [[COND_1:%.*]] = icmp ult i32 [[B_GW_FR]], 10239; 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]]243; CHECK: deopt:244; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]245; CHECK-NEXT: ret void246; CHECK: guarded:247; CHECK-NEXT: br i1 %arg, label [[LOOP:%.*]], label [[LEAVE:%.*]]248; CHECK: loop: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]]252; CHECK: deopt2:253; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]254; CHECK-NEXT: ret void255; CHECK: guarded1:256; CHECK-NEXT: br i1 %arg, label [[LOOP]], label [[LEAVE]]257; CHECK: leave:258; CHECK-NEXT: ret void259;260entry:261 %cond_0 = icmp ult i32 %a, 10262 %widenable_cond = call i1 @llvm.experimental.widenable.condition()263 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond264 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0265 266deopt: ; preds = %entry267 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]268 ret void269 270guarded: ; preds = %entry271 br i1 %arg, label %loop, label %leave272 273loop: ; preds = %guarded1, %guarded274 %cond_1 = icmp ult i32 %b, 10275 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()276 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3277 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0278 279deopt2: ; preds = %loop280 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]281 ret void282 283guarded1: ; preds = %loop284 br i1 %arg, label %loop, label %leave285 286leave: ; preds = %guarded1, %guarded287 ret void288}289 290; Hoisting out of control flow is also fine if we can widen the291; dominating check without doing any extra work.292define void @f_5(i32 %a, i1 %arg) {293; CHECK-LABEL: @f_5(294; CHECK-NEXT: entry:295; CHECK-NEXT: [[COND_0:%.*]] = icmp ugt i32 [[A:%.*]], 7296; CHECK-NEXT: [[WIDE_CHK:%.*]] = icmp uge i32 [[A]], 11297; 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]]300; CHECK: deopt:301; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]302; CHECK-NEXT: ret void303; CHECK: guarded:304; CHECK-NEXT: br i1 %arg, label [[LEFT:%.*]], label [[RIGHT:%.*]]305; CHECK: left:306; CHECK-NEXT: [[COND_1:%.*]] = icmp ugt i32 [[A]], 10307; 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]]310; CHECK: deopt2:311; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]312; CHECK-NEXT: ret void313; CHECK: guarded1:314; CHECK-NEXT: ret void315; CHECK: right:316; CHECK-NEXT: ret void317;318entry:319 %cond_0 = icmp ugt i32 %a, 7320 %widenable_cond = call i1 @llvm.experimental.widenable.condition()321 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond322 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0323 324deopt: ; preds = %entry325 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]326 ret void327 328guarded: ; preds = %entry329 br i1 %arg, label %left, label %right330 331left: ; preds = %guarded332 %cond_1 = icmp ugt i32 %a, 10333 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()334 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3335 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0336 337deopt2: ; preds = %left338 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]339 ret void340 341guarded1: ; preds = %left342 ret void343 344right: ; preds = %guarded345 ret void346}347 348; Negative test: the load from %a can be safely speculated to before349; the first guard, but there is no guarantee that it will produce the350; same value.351define void @f_6(ptr dereferenceable(32) %a, ptr %b, i1 %unknown) {352; CHECK-LABEL: @f_6(353; CHECK-NEXT: entry:354; CHECK-NEXT: [[COND_0:%.*]] = load i1, ptr [[A:%.*]], align 1355; 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]]358; CHECK: deopt:359; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]360; CHECK-NEXT: ret void361; CHECK: guarded:362; CHECK-NEXT: store i1 [[UNKNOWN:%.*]], ptr [[B:%.*]], align 1363; CHECK-NEXT: [[COND_1:%.*]] = load i1, ptr [[A]], align 1364; 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]]367; CHECK: deopt2:368; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]369; CHECK-NEXT: ret void370; CHECK: guarded1:371; CHECK-NEXT: ret void372;373entry:374 %cond_0 = load i1, ptr %a375 %widenable_cond = call i1 @llvm.experimental.widenable.condition()376 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond377 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0378 379deopt: ; preds = %entry380 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]381 ret void382 383guarded: ; preds = %entry384 store i1 %unknown, ptr %b385 %cond_1 = load i1, ptr %a386 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()387 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3388 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0389 390deopt2: ; preds = %guarded391 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]392 ret void393 394guarded1: ; preds = %guarded395 ret void396}397 398; All else equal, we try to widen the earliest guard we can. This399; heuristic can use some tuning.400define void @f_7(i32 %a, ptr %cond_buf, i1 %arg) {401; CHECK-LABEL: @f_7(402; CHECK-NEXT: entry:403; CHECK-NEXT: [[A_GW_FR:%.*]] = freeze i32 [[A:%.*]]404; CHECK-NEXT: [[COND_1:%.*]] = load volatile i1, ptr [[COND_BUF:%.*]], align 1405; CHECK-NEXT: [[COND_3:%.*]] = icmp ult i32 [[A_GW_FR]], 7406; 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]]410; CHECK: deopt:411; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]412; CHECK-NEXT: ret void413; CHECK: guarded:414; CHECK-NEXT: [[COND_2:%.*]] = load volatile i1, ptr [[COND_BUF]], align 1415; 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]]418; CHECK: deopt2:419; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]420; CHECK-NEXT: ret void421; CHECK: guarded1:422; CHECK-NEXT: br i1 %arg, label [[LEFT:%.*]], label [[RIGHT:%.*]]423; CHECK: left: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]]427; CHECK: deopt6:428; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]429; CHECK-NEXT: ret void430; CHECK: guarded5:431; CHECK-NEXT: br label [[LEFT]]432; CHECK: right:433; CHECK-NEXT: ret void434;435entry:436 %cond_1 = load volatile i1, ptr %cond_buf437 %widenable_cond = call i1 @llvm.experimental.widenable.condition()438 %exiplicit_guard_cond = and i1 %cond_1, %widenable_cond439 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0440 441deopt: ; preds = %entry442 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]443 ret void444 445guarded: ; preds = %entry446 %cond_2 = load volatile i1, ptr %cond_buf447 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()448 %exiplicit_guard_cond4 = and i1 %cond_2, %widenable_cond3449 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0450 451deopt2: ; preds = %guarded452 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]453 ret void454 455guarded1: ; preds = %guarded456 br i1 %arg, label %left, label %right457 458left: ; preds = %guarded5, %guarded1459 %cond_3 = icmp ult i32 %a, 7460 %widenable_cond7 = call i1 @llvm.experimental.widenable.condition()461 %exiplicit_guard_cond8 = and i1 %cond_3, %widenable_cond7462 br i1 %exiplicit_guard_cond8, label %guarded5, label %deopt6, !prof !0463 464deopt6: ; preds = %left465 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]466 ret void467 468guarded5: ; preds = %left469 br label %left470 471right: ; preds = %guarded1472 ret void473}474 475; In this case the earliest dominating guard is in a loop, and we476; don't want to put extra work in there. This heuristic can use some477; tuning.478define void @f_8(i32 %a, i1 %cond_1, i1 %cond_2, i1 %arg) {479; CHECK-LABEL: @f_8(480; CHECK-NEXT: entry:481; CHECK-NEXT: [[A_GW_FR:%.*]] = freeze i32 [[A:%.*]]482; CHECK-NEXT: br label [[LOOP:%.*]]483; CHECK: 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]]487; CHECK: deopt:488; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]489; CHECK-NEXT: ret void490; CHECK: guarded:491; CHECK-NEXT: br i1 %arg, label [[LOOP]], label [[LEAVE:%.*]]492; CHECK: leave:493; CHECK-NEXT: [[COND_3:%.*]] = icmp ult i32 [[A_GW_FR]], 7494; 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]]498; CHECK: deopt2:499; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]500; CHECK-NEXT: ret void501; CHECK: guarded1:502; CHECK-NEXT: br i1 %arg, label [[LOOP2:%.*]], label [[LEAVE2:%.*]]503; CHECK: loop2: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]]507; CHECK: deopt6:508; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]509; CHECK-NEXT: ret void510; CHECK: guarded5:511; CHECK-NEXT: br label [[LOOP2]]512; CHECK: leave2:513; CHECK-NEXT: ret void514;515entry:516 br label %loop517 518loop: ; preds = %guarded, %entry519 %widenable_cond = call i1 @llvm.experimental.widenable.condition()520 %exiplicit_guard_cond = and i1 %cond_1, %widenable_cond521 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0522 523deopt: ; preds = %loop524 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]525 ret void526 527guarded: ; preds = %loop528 br i1 %arg, label %loop, label %leave529 530leave: ; preds = %guarded531 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()532 %exiplicit_guard_cond4 = and i1 %cond_2, %widenable_cond3533 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0534 535deopt2: ; preds = %leave536 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]537 ret void538 539guarded1: ; preds = %leave540 br i1 %arg, label %loop2, label %leave2541 542loop2: ; preds = %guarded5, %guarded1543 %cond_3 = icmp ult i32 %a, 7544 %widenable_cond7 = call i1 @llvm.experimental.widenable.condition()545 %exiplicit_guard_cond8 = and i1 %cond_3, %widenable_cond7546 br i1 %exiplicit_guard_cond8, label %guarded5, label %deopt6, !prof !0547 548deopt6: ; preds = %loop2549 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]550 ret void551 552guarded5: ; preds = %loop2553 br label %loop2554 555leave2: ; preds = %guarded1556 ret void557}558 559; In cases like these where there isn't any "obviously profitable"560; widening sites, we refuse to do anything.561define void @f_9(i32 %a, i1 %cond_0, i1 %cond_1, i1 %arg) {562; CHECK-LABEL: @f_9(563; CHECK-NEXT: entry:564; CHECK-NEXT: br label [[FIRST_LOOP:%.*]]565; CHECK: 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]]569; CHECK: deopt:570; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]571; CHECK-NEXT: ret void572; CHECK: guarded: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]]578; CHECK: deopt2:579; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]580; CHECK-NEXT: ret void581; CHECK: guarded1:582; CHECK-NEXT: br label [[SECOND_LOOP]]583;584entry:585 br label %first_loop586 587first_loop: ; preds = %guarded, %entry588 %widenable_cond = call i1 @llvm.experimental.widenable.condition()589 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond590 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0591 592deopt: ; preds = %first_loop593 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]594 ret void595 596guarded: ; preds = %first_loop597 br i1 %arg, label %first_loop, label %second_loop598 599second_loop: ; preds = %guarded1, %guarded600 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()601 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3602 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0603 604deopt2: ; preds = %second_loop605 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]606 ret void607 608guarded1: ; preds = %second_loop609 br label %second_loop610}611 612; Same situation as in @f_9: no "obviously profitable" widening sites,613; so we refuse to do anything.614define void @f_10(i32 %a, i1 %cond_0, i1 %cond_1, i1 %arg) {615; CHECK-LABEL: @f_10(616; CHECK-NEXT: entry:617; CHECK-NEXT: br label [[LOOP:%.*]]618; CHECK: 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]]622; CHECK: deopt:623; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]624; CHECK-NEXT: ret void625; CHECK: guarded:626; CHECK-NEXT: br i1 %arg, label [[LOOP]], label [[NO_LOOP:%.*]]627; CHECK: 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]]631; CHECK: deopt2:632; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]633; CHECK-NEXT: ret void634; CHECK: guarded1:635; CHECK-NEXT: ret void636;637entry:638 br label %loop639 640loop: ; preds = %guarded, %entry641 %widenable_cond = call i1 @llvm.experimental.widenable.condition()642 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond643 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0644 645deopt: ; preds = %loop646 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]647 ret void648 649guarded: ; preds = %loop650 br i1 %arg, label %loop, label %no_loop651 652no_loop: ; preds = %guarded653 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()654 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3655 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0656 657deopt2: ; preds = %no_loop658 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]659 ret void660 661guarded1: ; preds = %no_loop662 ret void663}664 665; With guards in loops, we're okay hoisting out the guard into the666; containing loop.667define void @f_11(i32 %a, i1 %cond_0, i1 %cond_1, i1 %arg) {668; CHECK-LABEL: @f_11(669; CHECK-NEXT: entry: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]]677; CHECK: deopt:678; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]679; CHECK-NEXT: ret void680; CHECK: guarded:681; CHECK-NEXT: br label [[INNER:%.*]]682; CHECK: 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]]686; CHECK: deopt2:687; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]688; CHECK-NEXT: ret void689; CHECK: guarded1: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:%.*]]693; CHECK: exit:694; CHECK-NEXT: ret void695;696entry:697 br label %outer_header698 699outer_header: ; preds = %outer_latch, %entry700 %widenable_cond = call i1 @llvm.experimental.widenable.condition()701 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond702 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0703 704deopt: ; preds = %outer_header705 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]706 ret void707 708guarded: ; preds = %outer_header709 br label %inner710 711inner: ; preds = %guarded1, %guarded712 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()713 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3714 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0715 716deopt2: ; preds = %inner717 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]718 ret void719 720guarded1: ; preds = %inner721 br i1 %arg, label %inner, label %outer_latch722 723outer_latch: ; preds = %guarded1724 br i1 %arg, label %outer_header, label %exit725 726exit: ; preds = %outer_latch727 ret void728}729 730; Checks that we are adequately guarded against exponential-time731; behavior when hoisting code.732define void @f_12(i32 %a0) {733; CHECK-LABEL: @f_12(734; CHECK-NEXT: entry: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 i1767; 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]]771; CHECK: deopt:772; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]773; CHECK-NEXT: ret void774; CHECK: guarded: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]]778; CHECK: deopt2:779; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]780; CHECK-NEXT: ret void781; CHECK: guarded1:782; CHECK-NEXT: ret void783;784entry:785 %widenable_cond = call i1 @llvm.experimental.widenable.condition()786 %exiplicit_guard_cond = and i1 true, %widenable_cond787 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0788 789deopt: ; preds = %entry790 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]791 ret void792 793guarded: ; preds = %entry794 %a1 = mul i32 %a0, %a0795 %a2 = mul i32 %a1, %a1796 %a3 = mul i32 %a2, %a2797 %a4 = mul i32 %a3, %a3798 %a5 = mul i32 %a4, %a4799 %a6 = mul i32 %a5, %a5800 %a7 = mul i32 %a6, %a6801 %a8 = mul i32 %a7, %a7802 %a9 = mul i32 %a8, %a8803 %a10 = mul i32 %a9, %a9804 %a11 = mul i32 %a10, %a10805 %a12 = mul i32 %a11, %a11806 %a13 = mul i32 %a12, %a12807 %a14 = mul i32 %a13, %a13808 %a15 = mul i32 %a14, %a14809 %a16 = mul i32 %a15, %a15810 %a17 = mul i32 %a16, %a16811 %a18 = mul i32 %a17, %a17812 %a19 = mul i32 %a18, %a18813 %a20 = mul i32 %a19, %a19814 %a21 = mul i32 %a20, %a20815 %a22 = mul i32 %a21, %a21816 %a23 = mul i32 %a22, %a22817 %a24 = mul i32 %a23, %a23818 %a25 = mul i32 %a24, %a24819 %a26 = mul i32 %a25, %a25820 %a27 = mul i32 %a26, %a26821 %a28 = mul i32 %a27, %a27822 %a29 = mul i32 %a28, %a28823 %a30 = mul i32 %a29, %a29824 %cond = trunc i32 %a30 to i1825 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()826 %exiplicit_guard_cond4 = and i1 %cond, %widenable_cond3827 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0828 829deopt2: ; preds = %guarded830 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]831 ret void832 833guarded1: ; preds = %guarded834 ret void835}836 837define void @f_13(i32 %a, i1 %arg) {838; CHECK-LABEL: @f_13(839; CHECK-NEXT: entry:840; CHECK-NEXT: [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 14841; CHECK-NEXT: [[WIDE_CHK:%.*]] = icmp ult i32 [[A]], 10842; 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]]845; CHECK: deopt:846; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]847; CHECK-NEXT: ret void848; CHECK: guarded:849; CHECK-NEXT: br i1 %arg, label [[LEFT:%.*]], label [[RIGHT:%.*]]850; CHECK: left:851; CHECK-NEXT: [[COND_1:%.*]] = icmp slt i32 [[A]], 10852; 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]]855; CHECK: deopt2:856; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]857; CHECK-NEXT: ret void858; CHECK: guarded1:859; CHECK-NEXT: ret void860; CHECK: right:861; CHECK-NEXT: ret void862;863entry:864 %cond_0 = icmp ult i32 %a, 14865 %widenable_cond = call i1 @llvm.experimental.widenable.condition()866 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond867 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0868 869deopt: ; preds = %entry870 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]871 ret void872 873guarded: ; preds = %entry874 br i1 %arg, label %left, label %right875 876left: ; preds = %guarded877 %cond_1 = icmp slt i32 %a, 10878 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()879 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3880 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0881 882deopt2: ; preds = %left883 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]884 ret void885 886guarded1: ; preds = %left887 ret void888 889right: ; preds = %guarded890 ret void891}892 893define void @f_14(i32 %a, i1 %arg) {894; CHECK-LABEL: @f_14(895; CHECK-NEXT: entry:896; CHECK-NEXT: [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 14897; 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]]900; CHECK: deopt:901; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]902; CHECK-NEXT: ret void903; CHECK: guarded:904; CHECK-NEXT: br i1 %arg, label [[LEFT:%.*]], label [[RIGHT:%.*]]905; CHECK: left:906; CHECK-NEXT: [[COND_1:%.*]] = icmp sgt i32 [[A]], 10907; 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]]910; CHECK: deopt2:911; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]912; CHECK-NEXT: ret void913; CHECK: guarded1:914; CHECK-NEXT: ret void915; CHECK: right:916; CHECK-NEXT: ret void917;918entry:919 %cond_0 = icmp ult i32 %a, 14920 %widenable_cond = call i1 @llvm.experimental.widenable.condition()921 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond922 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0923 924deopt: ; preds = %entry925 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]926 ret void927 928guarded: ; preds = %entry929 br i1 %arg, label %left, label %right930 931left: ; preds = %guarded932 %cond_1 = icmp sgt i32 %a, 10933 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()934 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3935 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0936 937deopt2: ; preds = %left938 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]939 ret void940 941guarded1: ; preds = %left942 ret void943 944right: ; preds = %guarded945 ret void946}947 948; Make sure we do not widen guard by trivial true conditions into something.949define void @f_15(i1 %cond_0, i1 %cond_1) {950; CHECK-LABEL: @f_15(951; CHECK-NEXT: entry: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]]955; CHECK: deopt:956; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]957; CHECK-NEXT: ret void958; CHECK: guarded: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]]962; CHECK: deopt2:963; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]964; CHECK-NEXT: ret void965; CHECK: guarded1:966; CHECK-NEXT: ret void967;968entry:969 %widenable_cond = call i1 @llvm.experimental.widenable.condition()970 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond971 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0972 973deopt: ; preds = %entry974 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]975 ret void976 977guarded: ; preds = %entry978 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()979 %exiplicit_guard_cond4 = and i1 true, %widenable_cond3980 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0981 982deopt2: ; preds = %guarded983 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]984 ret void985 986guarded1: ; preds = %guarded987 ret void988}989 990; Make sure we do not widen guard by trivial false conditions into something.991define void @f_16(i1 %cond_0, i1 %cond_1) {992; CHECK-LABEL: @f_16(993; CHECK-NEXT: entry: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]]997; CHECK: deopt:998; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]999; CHECK-NEXT: ret void1000; CHECK: guarded: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]]1004; CHECK: deopt2:1005; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]1006; CHECK-NEXT: ret void1007; CHECK: guarded1:1008; CHECK-NEXT: ret void1009;1010entry:1011 %widenable_cond = call i1 @llvm.experimental.widenable.condition()1012 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond1013 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !01014 1015deopt: ; preds = %entry1016 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]1017 ret void1018 1019guarded: ; preds = %entry1020 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()1021 %exiplicit_guard_cond4 = and i1 false, %widenable_cond31022 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !01023 1024deopt2: ; preds = %guarded1025 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]1026 ret void1027 1028guarded1: ; preds = %guarded1029 ret void1030}1031 1032 1033define 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]]1041; CHECK: deopt:1042; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]1043; CHECK-NEXT: ret void1044; CHECK: guarded: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]]1048; CHECK: deopt2:1049; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]1050; CHECK-NEXT: ret void1051; CHECK: guarded1:1052; CHECK-NEXT: ret void1053;1054entry:1055 %widenable_cond = call i1 @llvm.experimental.widenable.condition()1056 %exiplicit_guard_cond = and i1 %widenable_cond, %cond_01057 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !01058 1059deopt: ; preds = %entry1060 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]1061 ret void1062 1063guarded: ; preds = %entry1064 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()1065 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond31066 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !01067 1068deopt2: ; preds = %guarded1069 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]1070 ret void1071 1072guarded1: ; preds = %guarded1073 ret void1074}1075 1076define 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]]1084; CHECK: deopt:1085; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]1086; CHECK-NEXT: ret void1087; CHECK: guarded: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]]1091; CHECK: deopt2:1092; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]1093; CHECK-NEXT: ret void1094; CHECK: guarded1:1095; CHECK-NEXT: ret void1096;1097entry:1098 %widenable_cond = call i1 @llvm.experimental.widenable.condition()1099 br i1 %widenable_cond, label %guarded, label %deopt, !prof !01100 1101deopt: ; preds = %entry1102 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]1103 ret void1104 1105guarded: ; preds = %entry1106 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()1107 %exiplicit_guard_cond4 = and i1 %cond_0, %widenable_cond31108 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !01109 1110deopt2: ; preds = %guarded1111 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ]1112 ret void1113 1114guarded1: ; preds = %guarded1115 ret void1116}1117 1118 1119declare void @llvm.experimental.deoptimize.isVoid(...)1120 1121; Function Attrs: inaccessiblememonly nounwind1122declare i1 @llvm.experimental.widenable.condition() #01123 1124attributes #0 = { inaccessiblememonly nounwind }1125 1126!0 = !{!"branch_weights", i32 1048576, i32 1}1127