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 4 5; Basic test case: we wide the first check to check both the 6; conditions. 7define void @f_0(i1 %cond_0, i1 %cond_1) { 8; CHECK-LABEL: @f_0( 9; CHECK-NEXT: entry: 10; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() 11; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]] 12; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]] 13; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0:![0-9]+]] 14; CHECK: deopt: 15; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 16; CHECK-NEXT: ret void 17; CHECK: guarded: 18; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition() 19; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]] 20; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] 21; CHECK: deopt2: 22; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 23; CHECK-NEXT: ret void 24; CHECK: guarded1: 25; CHECK-NEXT: ret void 26; 27entry: 28 %widenable_cond = call i1 @llvm.experimental.widenable.condition() 29 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond 30 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0 31 32deopt: ; preds = %entry 33 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 34 ret void 35 36guarded: ; preds = %entry 37 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition() 38 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3 39 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0 40 41deopt2: ; preds = %guarded 42 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 43 ret void 44 45guarded1: ; preds = %guarded 46 ret void 47} 48 49; Same as @f_0, but with using a more general notion of postdominance. 50define void @f_1(i1 %cond_0, i1 %cond_1) { 51; CHECK-LABEL: @f_1( 52; CHECK-NEXT: entry: 53; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() 54; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]] 55; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]] 56; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] 57; CHECK: deopt: 58; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 59; CHECK-NEXT: ret void 60; CHECK: guarded: 61; CHECK-NEXT: br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]] 62; CHECK: left: 63; CHECK-NEXT: br label [[MERGE:%.*]] 64; CHECK: right: 65; CHECK-NEXT: br label [[MERGE]] 66; CHECK: merge: 67; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition() 68; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]] 69; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] 70; CHECK: deopt2: 71; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 72; CHECK-NEXT: ret void 73; CHECK: guarded1: 74; CHECK-NEXT: ret void 75; 76entry: 77 %widenable_cond = call i1 @llvm.experimental.widenable.condition() 78 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond 79 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0 80 81deopt: ; preds = %entry 82 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 83 ret void 84 85guarded: ; preds = %entry 86 br i1 undef, label %left, label %right 87 88left: ; preds = %guarded 89 br label %merge 90 91right: ; preds = %guarded 92 br label %merge 93 94merge: ; preds = %right, %left 95 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition() 96 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3 97 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0 98 99deopt2: ; preds = %merge 100 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 101 ret void 102 103guarded1: ; preds = %merge 104 ret void 105} 106 107; Like @f_1, but we have some code we need to hoist before we can 108; widen a dominanting check. 109define void @f_2(i32 %a, i32 %b) { 110; CHECK-LABEL: @f_2( 111; CHECK-NEXT: entry: 112; CHECK-NEXT: [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 10 113; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() 114; CHECK-NEXT: [[COND_1:%.*]] = icmp ult i32 [[B:%.*]], 10 115; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0]], [[COND_1]] 116; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]] 117; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] 118; CHECK: deopt: 119; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 120; CHECK-NEXT: ret void 121; CHECK: guarded: 122; CHECK-NEXT: br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]] 123; CHECK: left: 124; CHECK-NEXT: br label [[MERGE:%.*]] 125; CHECK: right: 126; CHECK-NEXT: br label [[MERGE]] 127; CHECK: merge: 128; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition() 129; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]] 130; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] 131; CHECK: deopt2: 132; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 133; CHECK-NEXT: ret void 134; CHECK: guarded1: 135; CHECK-NEXT: ret void 136; 137entry: 138 %cond_0 = icmp ult i32 %a, 10 139 %widenable_cond = call i1 @llvm.experimental.widenable.condition() 140 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond 141 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0 142 143deopt: ; preds = %entry 144 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 145 ret void 146 147guarded: ; preds = %entry 148 br i1 undef, label %left, label %right 149 150left: ; preds = %guarded 151 br label %merge 152 153right: ; preds = %guarded 154 br label %merge 155 156merge: ; preds = %right, %left 157 %cond_1 = icmp ult i32 %b, 10 158 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition() 159 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3 160 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0 161 162deopt2: ; preds = %merge 163 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 164 ret void 165 166guarded1: ; preds = %merge 167 ret void 168} 169 170; Negative test: don't hoist stuff out of control flow 171; indiscriminately, since that can make us do more work than needed. 172define void @f_3(i32 %a, i32 %b) { 173; CHECK-LABEL: @f_3( 174; CHECK-NEXT: entry: 175; CHECK-NEXT: [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 10 176; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() 177; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0]], [[WIDENABLE_COND]] 178; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] 179; CHECK: deopt: 180; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 181; CHECK-NEXT: ret void 182; CHECK: guarded: 183; CHECK-NEXT: br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]] 184; CHECK: left: 185; CHECK-NEXT: [[COND_1:%.*]] = icmp ult i32 [[B:%.*]], 10 186; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition() 187; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]] 188; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] 189; CHECK: deopt2: 190; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 191; CHECK-NEXT: ret void 192; CHECK: guarded1: 193; CHECK-NEXT: ret void 194; CHECK: right: 195; CHECK-NEXT: ret void 196; 197entry: 198 %cond_0 = icmp ult i32 %a, 10 199 %widenable_cond = call i1 @llvm.experimental.widenable.condition() 200 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond 201 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0 202 203deopt: ; preds = %entry 204 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 205 ret void 206 207guarded: ; preds = %entry 208 br i1 undef, label %left, label %right 209 210left: ; preds = %guarded 211 %cond_1 = icmp ult i32 %b, 10 212 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition() 213 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3 214 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0 215 216deopt2: ; preds = %left 217 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 218 ret void 219 220guarded1: ; preds = %left 221 ret void 222 223right: ; preds = %guarded 224 ret void 225} 226 227; But hoisting out of control flow is fine if it makes a loop computed 228; condition loop invariant. This behavior may require some tuning in 229; the future. 230define void @f_4(i32 %a, i32 %b) { 231; CHECK-LABEL: @f_4( 232; CHECK-NEXT: entry: 233; CHECK-NEXT: [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 10 234; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() 235; CHECK-NEXT: [[COND_1:%.*]] = icmp ult i32 [[B:%.*]], 10 236; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0]], [[COND_1]] 237; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]] 238; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] 239; CHECK: deopt: 240; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 241; CHECK-NEXT: ret void 242; CHECK: guarded: 243; CHECK-NEXT: br i1 undef, label [[LOOP:%.*]], label [[LEAVE:%.*]] 244; CHECK: loop: 245; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition() 246; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]] 247; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] 248; CHECK: deopt2: 249; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 250; CHECK-NEXT: ret void 251; CHECK: guarded1: 252; CHECK-NEXT: br i1 undef, label [[LOOP]], label [[LEAVE]] 253; CHECK: leave: 254; CHECK-NEXT: ret void 255; 256entry: 257 %cond_0 = icmp ult i32 %a, 10 258 %widenable_cond = call i1 @llvm.experimental.widenable.condition() 259 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond 260 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0 261 262deopt: ; preds = %entry 263 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 264 ret void 265 266guarded: ; preds = %entry 267 br i1 undef, label %loop, label %leave 268 269loop: ; preds = %guarded1, %guarded 270 %cond_1 = icmp ult i32 %b, 10 271 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition() 272 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3 273 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0 274 275deopt2: ; preds = %loop 276 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 277 ret void 278 279guarded1: ; preds = %loop 280 br i1 undef, label %loop, label %leave 281 282leave: ; preds = %guarded1, %guarded 283 ret void 284} 285 286; Hoisting out of control flow is also fine if we can widen the 287; dominating check without doing any extra work. 288define void @f_5(i32 %a) { 289; CHECK-LABEL: @f_5( 290; CHECK-NEXT: entry: 291; CHECK-NEXT: [[COND_0:%.*]] = icmp ugt i32 [[A:%.*]], 7 292; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() 293; CHECK-NEXT: [[WIDE_CHK:%.*]] = icmp uge i32 [[A]], 11 294; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]] 295; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] 296; CHECK: deopt: 297; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 298; CHECK-NEXT: ret void 299; CHECK: guarded: 300; CHECK-NEXT: br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]] 301; CHECK: left: 302; CHECK-NEXT: [[COND_1:%.*]] = icmp ugt i32 [[A]], 10 303; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition() 304; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]] 305; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] 306; CHECK: deopt2: 307; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 308; CHECK-NEXT: ret void 309; CHECK: guarded1: 310; CHECK-NEXT: ret void 311; CHECK: right: 312; CHECK-NEXT: ret void 313; 314entry: 315 %cond_0 = icmp ugt i32 %a, 7 316 %widenable_cond = call i1 @llvm.experimental.widenable.condition() 317 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond 318 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0 319 320deopt: ; preds = %entry 321 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 322 ret void 323 324guarded: ; preds = %entry 325 br i1 undef, label %left, label %right 326 327left: ; preds = %guarded 328 %cond_1 = icmp ugt i32 %a, 10 329 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition() 330 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3 331 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0 332 333deopt2: ; preds = %left 334 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 335 ret void 336 337guarded1: ; preds = %left 338 ret void 339 340right: ; preds = %guarded 341 ret void 342} 343 344; Negative test: the load from %a can be safely speculated to before 345; the first guard, but there is no guarantee that it will produce the 346; same value. 347define void @f_6(i1* dereferenceable(32) %a, i1* %b, i1 %unknown) { 348; CHECK-LABEL: @f_6( 349; CHECK-NEXT: entry: 350; CHECK-NEXT: [[COND_0:%.*]] = load i1, i1* [[A:%.*]], align 1 351; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() 352; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0]], [[WIDENABLE_COND]] 353; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] 354; CHECK: deopt: 355; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 356; CHECK-NEXT: ret void 357; CHECK: guarded: 358; CHECK-NEXT: store i1 [[UNKNOWN:%.*]], i1* [[B:%.*]], align 1 359; CHECK-NEXT: [[COND_1:%.*]] = load i1, i1* [[A]], align 1 360; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition() 361; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]] 362; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] 363; CHECK: deopt2: 364; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 365; CHECK-NEXT: ret void 366; CHECK: guarded1: 367; CHECK-NEXT: ret void 368; 369entry: 370 %cond_0 = load i1, i1* %a 371 %widenable_cond = call i1 @llvm.experimental.widenable.condition() 372 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond 373 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0 374 375deopt: ; preds = %entry 376 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 377 ret void 378 379guarded: ; preds = %entry 380 store i1 %unknown, i1* %b 381 %cond_1 = load i1, i1* %a 382 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition() 383 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3 384 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0 385 386deopt2: ; preds = %guarded 387 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 388 ret void 389 390guarded1: ; preds = %guarded 391 ret void 392} 393 394; All else equal, we try to widen the earliest guard we can. This 395; heuristic can use some tuning. 396define void @f_7(i32 %a, i1* %cond_buf) { 397; CHECK-LABEL: @f_7( 398; CHECK-NEXT: entry: 399; CHECK-NEXT: [[COND_1:%.*]] = load volatile i1, i1* [[COND_BUF:%.*]], align 1 400; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() 401; CHECK-NEXT: [[COND_3:%.*]] = icmp ult i32 [[A:%.*]], 7 402; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_1]], [[COND_3]] 403; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]] 404; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] 405; CHECK: deopt: 406; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 407; CHECK-NEXT: ret void 408; CHECK: guarded: 409; CHECK-NEXT: [[COND_2:%.*]] = load volatile i1, i1* [[COND_BUF]], align 1 410; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition() 411; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_2]], [[WIDENABLE_COND3]] 412; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] 413; CHECK: deopt2: 414; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 415; CHECK-NEXT: ret void 416; CHECK: guarded1: 417; CHECK-NEXT: br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]] 418; CHECK: left: 419; CHECK-NEXT: [[WIDENABLE_COND7:%.*]] = call i1 @llvm.experimental.widenable.condition() 420; CHECK-NEXT: [[EXIPLICIT_GUARD_COND8:%.*]] = and i1 [[COND_3]], [[WIDENABLE_COND7]] 421; CHECK-NEXT: br i1 true, label [[GUARDED5:%.*]], label [[DEOPT6:%.*]], !prof [[PROF0]] 422; CHECK: deopt6: 423; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 424; CHECK-NEXT: ret void 425; CHECK: guarded5: 426; CHECK-NEXT: br label [[LEFT]] 427; CHECK: right: 428; CHECK-NEXT: ret void 429; 430entry: 431 %cond_1 = load volatile i1, i1* %cond_buf 432 %widenable_cond = call i1 @llvm.experimental.widenable.condition() 433 %exiplicit_guard_cond = and i1 %cond_1, %widenable_cond 434 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0 435 436deopt: ; preds = %entry 437 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 438 ret void 439 440guarded: ; preds = %entry 441 %cond_2 = load volatile i1, i1* %cond_buf 442 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition() 443 %exiplicit_guard_cond4 = and i1 %cond_2, %widenable_cond3 444 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0 445 446deopt2: ; preds = %guarded 447 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 448 ret void 449 450guarded1: ; preds = %guarded 451 br i1 undef, label %left, label %right 452 453left: ; preds = %guarded5, %guarded1 454 %cond_3 = icmp ult i32 %a, 7 455 %widenable_cond7 = call i1 @llvm.experimental.widenable.condition() 456 %exiplicit_guard_cond8 = and i1 %cond_3, %widenable_cond7 457 br i1 %exiplicit_guard_cond8, label %guarded5, label %deopt6, !prof !0 458 459deopt6: ; preds = %left 460 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 461 ret void 462 463guarded5: ; preds = %left 464 br label %left 465 466right: ; preds = %guarded1 467 ret void 468} 469 470; In this case the earliest dominating guard is in a loop, and we 471; don't want to put extra work in there. This heuristic can use some 472; tuning. 473define void @f_8(i32 %a, i1 %cond_1, i1 %cond_2) { 474; CHECK-LABEL: @f_8( 475; CHECK-NEXT: entry: 476; CHECK-NEXT: br label [[LOOP:%.*]] 477; CHECK: loop: 478; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() 479; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_1:%.*]], [[WIDENABLE_COND]] 480; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] 481; CHECK: deopt: 482; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 483; CHECK-NEXT: ret void 484; CHECK: guarded: 485; CHECK-NEXT: br i1 undef, label [[LOOP]], label [[LEAVE:%.*]] 486; CHECK: leave: 487; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition() 488; CHECK-NEXT: [[COND_3:%.*]] = icmp ult i32 [[A:%.*]], 7 489; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_2:%.*]], [[COND_3]] 490; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND3]] 491; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] 492; CHECK: deopt2: 493; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 494; CHECK-NEXT: ret void 495; CHECK: guarded1: 496; CHECK-NEXT: br i1 undef, label [[LOOP2:%.*]], label [[LEAVE2:%.*]] 497; CHECK: loop2: 498; CHECK-NEXT: [[WIDENABLE_COND7:%.*]] = call i1 @llvm.experimental.widenable.condition() 499; CHECK-NEXT: [[EXIPLICIT_GUARD_COND8:%.*]] = and i1 [[COND_3]], [[WIDENABLE_COND7]] 500; CHECK-NEXT: br i1 true, label [[GUARDED5:%.*]], label [[DEOPT6:%.*]], !prof [[PROF0]] 501; CHECK: deopt6: 502; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 503; CHECK-NEXT: ret void 504; CHECK: guarded5: 505; CHECK-NEXT: br label [[LOOP2]] 506; CHECK: leave2: 507; CHECK-NEXT: ret void 508; 509entry: 510 br label %loop 511 512loop: ; preds = %guarded, %entry 513 %widenable_cond = call i1 @llvm.experimental.widenable.condition() 514 %exiplicit_guard_cond = and i1 %cond_1, %widenable_cond 515 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0 516 517deopt: ; preds = %loop 518 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 519 ret void 520 521guarded: ; preds = %loop 522 br i1 undef, label %loop, label %leave 523 524leave: ; preds = %guarded 525 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition() 526 %exiplicit_guard_cond4 = and i1 %cond_2, %widenable_cond3 527 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0 528 529deopt2: ; preds = %leave 530 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 531 ret void 532 533guarded1: ; preds = %leave 534 br i1 undef, label %loop2, label %leave2 535 536loop2: ; preds = %guarded5, %guarded1 537 %cond_3 = icmp ult i32 %a, 7 538 %widenable_cond7 = call i1 @llvm.experimental.widenable.condition() 539 %exiplicit_guard_cond8 = and i1 %cond_3, %widenable_cond7 540 br i1 %exiplicit_guard_cond8, label %guarded5, label %deopt6, !prof !0 541 542deopt6: ; preds = %loop2 543 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 544 ret void 545 546guarded5: ; preds = %loop2 547 br label %loop2 548 549leave2: ; preds = %guarded1 550 ret void 551} 552 553; In cases like these where there isn't any "obviously profitable" 554; widening sites, we refuse to do anything. 555define void @f_9(i32 %a, i1 %cond_0, i1 %cond_1) { 556; CHECK-LABEL: @f_9( 557; CHECK-NEXT: entry: 558; CHECK-NEXT: br label [[FIRST_LOOP:%.*]] 559; CHECK: first_loop: 560; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() 561; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0:%.*]], [[WIDENABLE_COND]] 562; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] 563; CHECK: deopt: 564; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 565; CHECK-NEXT: ret void 566; CHECK: guarded: 567; CHECK-NEXT: br i1 undef, label [[FIRST_LOOP]], label [[SECOND_LOOP:%.*]] 568; CHECK: second_loop: 569; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition() 570; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1:%.*]], [[WIDENABLE_COND3]] 571; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] 572; CHECK: deopt2: 573; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 574; CHECK-NEXT: ret void 575; CHECK: guarded1: 576; CHECK-NEXT: br label [[SECOND_LOOP]] 577; 578entry: 579 br label %first_loop 580 581first_loop: ; preds = %guarded, %entry 582 %widenable_cond = call i1 @llvm.experimental.widenable.condition() 583 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond 584 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0 585 586deopt: ; preds = %first_loop 587 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 588 ret void 589 590guarded: ; preds = %first_loop 591 br i1 undef, label %first_loop, label %second_loop 592 593second_loop: ; preds = %guarded1, %guarded 594 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition() 595 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3 596 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0 597 598deopt2: ; preds = %second_loop 599 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 600 ret void 601 602guarded1: ; preds = %second_loop 603 br label %second_loop 604} 605 606; Same situation as in @f_9: no "obviously profitable" widening sites, 607; so we refuse to do anything. 608define void @f_10(i32 %a, i1 %cond_0, i1 %cond_1) { 609; CHECK-LABEL: @f_10( 610; CHECK-NEXT: entry: 611; CHECK-NEXT: br label [[LOOP:%.*]] 612; CHECK: loop: 613; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() 614; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0:%.*]], [[WIDENABLE_COND]] 615; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] 616; CHECK: deopt: 617; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 618; CHECK-NEXT: ret void 619; CHECK: guarded: 620; CHECK-NEXT: br i1 undef, label [[LOOP]], label [[NO_LOOP:%.*]] 621; CHECK: no_loop: 622; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition() 623; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1:%.*]], [[WIDENABLE_COND3]] 624; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] 625; CHECK: deopt2: 626; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 627; CHECK-NEXT: ret void 628; CHECK: guarded1: 629; CHECK-NEXT: ret void 630; 631entry: 632 br label %loop 633 634loop: ; preds = %guarded, %entry 635 %widenable_cond = call i1 @llvm.experimental.widenable.condition() 636 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond 637 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0 638 639deopt: ; preds = %loop 640 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 641 ret void 642 643guarded: ; preds = %loop 644 br i1 undef, label %loop, label %no_loop 645 646no_loop: ; preds = %guarded 647 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition() 648 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3 649 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0 650 651deopt2: ; preds = %no_loop 652 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 653 ret void 654 655guarded1: ; preds = %no_loop 656 ret void 657} 658 659; With guards in loops, we're okay hoisting out the guard into the 660; containing loop. 661define void @f_11(i32 %a, i1 %cond_0, i1 %cond_1) { 662; CHECK-LABEL: @f_11( 663; CHECK-NEXT: entry: 664; CHECK-NEXT: br label [[OUTER_HEADER:%.*]] 665; CHECK: outer_header: 666; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() 667; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]] 668; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]] 669; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] 670; CHECK: deopt: 671; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 672; CHECK-NEXT: ret void 673; CHECK: guarded: 674; CHECK-NEXT: br label [[INNER:%.*]] 675; CHECK: inner: 676; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition() 677; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]] 678; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] 679; CHECK: deopt2: 680; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 681; CHECK-NEXT: ret void 682; CHECK: guarded1: 683; CHECK-NEXT: br i1 undef, label [[INNER]], label [[OUTER_LATCH:%.*]] 684; CHECK: outer_latch: 685; CHECK-NEXT: br i1 undef, label [[OUTER_HEADER]], label [[EXIT:%.*]] 686; CHECK: exit: 687; CHECK-NEXT: ret void 688; 689entry: 690 br label %outer_header 691 692outer_header: ; preds = %outer_latch, %entry 693 %widenable_cond = call i1 @llvm.experimental.widenable.condition() 694 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond 695 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0 696 697deopt: ; preds = %outer_header 698 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 699 ret void 700 701guarded: ; preds = %outer_header 702 br label %inner 703 704inner: ; preds = %guarded1, %guarded 705 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition() 706 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3 707 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0 708 709deopt2: ; preds = %inner 710 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 711 ret void 712 713guarded1: ; preds = %inner 714 br i1 undef, label %inner, label %outer_latch 715 716outer_latch: ; preds = %guarded1 717 br i1 undef, label %outer_header, label %exit 718 719exit: ; preds = %outer_latch 720 ret void 721} 722 723; Checks that we are adequately guarded against exponential-time 724; behavior when hoisting code. 725define void @f_12(i32 %a0) { 726; CHECK-LABEL: @f_12( 727; CHECK-NEXT: entry: 728; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() 729; CHECK-NEXT: [[A1:%.*]] = mul i32 [[A0:%.*]], [[A0]] 730; CHECK-NEXT: [[A2:%.*]] = mul i32 [[A1]], [[A1]] 731; CHECK-NEXT: [[A3:%.*]] = mul i32 [[A2]], [[A2]] 732; CHECK-NEXT: [[A4:%.*]] = mul i32 [[A3]], [[A3]] 733; CHECK-NEXT: [[A5:%.*]] = mul i32 [[A4]], [[A4]] 734; CHECK-NEXT: [[A6:%.*]] = mul i32 [[A5]], [[A5]] 735; CHECK-NEXT: [[A7:%.*]] = mul i32 [[A6]], [[A6]] 736; CHECK-NEXT: [[A8:%.*]] = mul i32 [[A7]], [[A7]] 737; CHECK-NEXT: [[A9:%.*]] = mul i32 [[A8]], [[A8]] 738; CHECK-NEXT: [[A10:%.*]] = mul i32 [[A9]], [[A9]] 739; CHECK-NEXT: [[A11:%.*]] = mul i32 [[A10]], [[A10]] 740; CHECK-NEXT: [[A12:%.*]] = mul i32 [[A11]], [[A11]] 741; CHECK-NEXT: [[A13:%.*]] = mul i32 [[A12]], [[A12]] 742; CHECK-NEXT: [[A14:%.*]] = mul i32 [[A13]], [[A13]] 743; CHECK-NEXT: [[A15:%.*]] = mul i32 [[A14]], [[A14]] 744; CHECK-NEXT: [[A16:%.*]] = mul i32 [[A15]], [[A15]] 745; CHECK-NEXT: [[A17:%.*]] = mul i32 [[A16]], [[A16]] 746; CHECK-NEXT: [[A18:%.*]] = mul i32 [[A17]], [[A17]] 747; CHECK-NEXT: [[A19:%.*]] = mul i32 [[A18]], [[A18]] 748; CHECK-NEXT: [[A20:%.*]] = mul i32 [[A19]], [[A19]] 749; CHECK-NEXT: [[A21:%.*]] = mul i32 [[A20]], [[A20]] 750; CHECK-NEXT: [[A22:%.*]] = mul i32 [[A21]], [[A21]] 751; CHECK-NEXT: [[A23:%.*]] = mul i32 [[A22]], [[A22]] 752; CHECK-NEXT: [[A24:%.*]] = mul i32 [[A23]], [[A23]] 753; CHECK-NEXT: [[A25:%.*]] = mul i32 [[A24]], [[A24]] 754; CHECK-NEXT: [[A26:%.*]] = mul i32 [[A25]], [[A25]] 755; CHECK-NEXT: [[A27:%.*]] = mul i32 [[A26]], [[A26]] 756; CHECK-NEXT: [[A28:%.*]] = mul i32 [[A27]], [[A27]] 757; CHECK-NEXT: [[A29:%.*]] = mul i32 [[A28]], [[A28]] 758; CHECK-NEXT: [[A30:%.*]] = mul i32 [[A29]], [[A29]] 759; CHECK-NEXT: [[COND:%.*]] = trunc i32 [[A30]] to i1 760; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 true, [[COND]] 761; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]] 762; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] 763; CHECK: deopt: 764; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 765; CHECK-NEXT: ret void 766; CHECK: guarded: 767; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition() 768; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND]], [[WIDENABLE_COND3]] 769; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] 770; CHECK: deopt2: 771; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 772; CHECK-NEXT: ret void 773; CHECK: guarded1: 774; CHECK-NEXT: ret void 775; 776entry: 777 %widenable_cond = call i1 @llvm.experimental.widenable.condition() 778 %exiplicit_guard_cond = and i1 true, %widenable_cond 779 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0 780 781deopt: ; preds = %entry 782 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 783 ret void 784 785guarded: ; preds = %entry 786 %a1 = mul i32 %a0, %a0 787 %a2 = mul i32 %a1, %a1 788 %a3 = mul i32 %a2, %a2 789 %a4 = mul i32 %a3, %a3 790 %a5 = mul i32 %a4, %a4 791 %a6 = mul i32 %a5, %a5 792 %a7 = mul i32 %a6, %a6 793 %a8 = mul i32 %a7, %a7 794 %a9 = mul i32 %a8, %a8 795 %a10 = mul i32 %a9, %a9 796 %a11 = mul i32 %a10, %a10 797 %a12 = mul i32 %a11, %a11 798 %a13 = mul i32 %a12, %a12 799 %a14 = mul i32 %a13, %a13 800 %a15 = mul i32 %a14, %a14 801 %a16 = mul i32 %a15, %a15 802 %a17 = mul i32 %a16, %a16 803 %a18 = mul i32 %a17, %a17 804 %a19 = mul i32 %a18, %a18 805 %a20 = mul i32 %a19, %a19 806 %a21 = mul i32 %a20, %a20 807 %a22 = mul i32 %a21, %a21 808 %a23 = mul i32 %a22, %a22 809 %a24 = mul i32 %a23, %a23 810 %a25 = mul i32 %a24, %a24 811 %a26 = mul i32 %a25, %a25 812 %a27 = mul i32 %a26, %a26 813 %a28 = mul i32 %a27, %a27 814 %a29 = mul i32 %a28, %a28 815 %a30 = mul i32 %a29, %a29 816 %cond = trunc i32 %a30 to i1 817 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition() 818 %exiplicit_guard_cond4 = and i1 %cond, %widenable_cond3 819 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0 820 821deopt2: ; preds = %guarded 822 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 823 ret void 824 825guarded1: ; preds = %guarded 826 ret void 827} 828 829define void @f_13(i32 %a) { 830; CHECK-LABEL: @f_13( 831; CHECK-NEXT: entry: 832; CHECK-NEXT: [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 14 833; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() 834; CHECK-NEXT: [[WIDE_CHK:%.*]] = icmp ult i32 [[A]], 10 835; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]] 836; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] 837; CHECK: deopt: 838; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 839; CHECK-NEXT: ret void 840; CHECK: guarded: 841; CHECK-NEXT: br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]] 842; CHECK: left: 843; CHECK-NEXT: [[COND_1:%.*]] = icmp slt i32 [[A]], 10 844; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition() 845; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]] 846; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] 847; CHECK: deopt2: 848; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 849; CHECK-NEXT: ret void 850; CHECK: guarded1: 851; CHECK-NEXT: ret void 852; CHECK: right: 853; CHECK-NEXT: ret void 854; 855entry: 856 %cond_0 = icmp ult i32 %a, 14 857 %widenable_cond = call i1 @llvm.experimental.widenable.condition() 858 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond 859 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0 860 861deopt: ; preds = %entry 862 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 863 ret void 864 865guarded: ; preds = %entry 866 br i1 undef, label %left, label %right 867 868left: ; preds = %guarded 869 %cond_1 = icmp slt i32 %a, 10 870 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition() 871 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3 872 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0 873 874deopt2: ; preds = %left 875 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 876 ret void 877 878guarded1: ; preds = %left 879 ret void 880 881right: ; preds = %guarded 882 ret void 883} 884 885define void @f_14(i32 %a) { 886; CHECK-LABEL: @f_14( 887; CHECK-NEXT: entry: 888; CHECK-NEXT: [[COND_0:%.*]] = icmp ult i32 [[A:%.*]], 14 889; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() 890; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0]], [[WIDENABLE_COND]] 891; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] 892; CHECK: deopt: 893; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 894; CHECK-NEXT: ret void 895; CHECK: guarded: 896; CHECK-NEXT: br i1 undef, label [[LEFT:%.*]], label [[RIGHT:%.*]] 897; CHECK: left: 898; CHECK-NEXT: [[COND_1:%.*]] = icmp sgt i32 [[A]], 10 899; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition() 900; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]] 901; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] 902; CHECK: deopt2: 903; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 904; CHECK-NEXT: ret void 905; CHECK: guarded1: 906; CHECK-NEXT: ret void 907; CHECK: right: 908; CHECK-NEXT: ret void 909; 910entry: 911 %cond_0 = icmp ult i32 %a, 14 912 %widenable_cond = call i1 @llvm.experimental.widenable.condition() 913 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond 914 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0 915 916deopt: ; preds = %entry 917 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 918 ret void 919 920guarded: ; preds = %entry 921 br i1 undef, label %left, label %right 922 923left: ; preds = %guarded 924 %cond_1 = icmp sgt i32 %a, 10 925 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition() 926 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3 927 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0 928 929deopt2: ; preds = %left 930 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 931 ret void 932 933guarded1: ; preds = %left 934 ret void 935 936right: ; preds = %guarded 937 ret void 938} 939 940; Make sure we do not widen guard by trivial true conditions into something. 941define void @f_15(i1 %cond_0, i1 %cond_1) { 942; CHECK-LABEL: @f_15( 943; CHECK-NEXT: entry: 944; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() 945; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0:%.*]], [[WIDENABLE_COND]] 946; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] 947; CHECK: deopt: 948; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 949; CHECK-NEXT: ret void 950; CHECK: guarded: 951; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition() 952; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 true, [[WIDENABLE_COND3]] 953; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] 954; CHECK: deopt2: 955; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 956; CHECK-NEXT: ret void 957; CHECK: guarded1: 958; CHECK-NEXT: ret void 959; 960entry: 961 %widenable_cond = call i1 @llvm.experimental.widenable.condition() 962 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond 963 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0 964 965deopt: ; preds = %entry 966 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 967 ret void 968 969guarded: ; preds = %entry 970 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition() 971 %exiplicit_guard_cond4 = and i1 true, %widenable_cond3 972 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0 973 974deopt2: ; preds = %guarded 975 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 976 ret void 977 978guarded1: ; preds = %guarded 979 ret void 980} 981 982; Make sure we do not widen guard by trivial false conditions into something. 983define void @f_16(i1 %cond_0, i1 %cond_1) { 984; CHECK-LABEL: @f_16( 985; CHECK-NEXT: entry: 986; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() 987; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[COND_0:%.*]], [[WIDENABLE_COND]] 988; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] 989; CHECK: deopt: 990; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 991; CHECK-NEXT: ret void 992; CHECK: guarded: 993; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition() 994; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 false, [[WIDENABLE_COND3]] 995; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND4]], label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] 996; CHECK: deopt2: 997; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 998; CHECK-NEXT: ret void 999; CHECK: guarded1: 1000; CHECK-NEXT: ret void 1001; 1002entry: 1003 %widenable_cond = call i1 @llvm.experimental.widenable.condition() 1004 %exiplicit_guard_cond = and i1 %cond_0, %widenable_cond 1005 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0 1006 1007deopt: ; preds = %entry 1008 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 1009 ret void 1010 1011guarded: ; preds = %entry 1012 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition() 1013 %exiplicit_guard_cond4 = and i1 false, %widenable_cond3 1014 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0 1015 1016deopt2: ; preds = %guarded 1017 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 1018 ret void 1019 1020guarded1: ; preds = %guarded 1021 ret void 1022} 1023 1024 1025define void @swapped_wb(i1 %cond_0, i1 %cond_1) { 1026; CHECK-LABEL: @swapped_wb( 1027; CHECK-NEXT: entry: 1028; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() 1029; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 [[COND_0:%.*]], [[COND_1:%.*]] 1030; CHECK-NEXT: [[EXIPLICIT_GUARD_COND:%.*]] = and i1 [[WIDENABLE_COND]], [[WIDE_CHK]] 1031; CHECK-NEXT: br i1 [[EXIPLICIT_GUARD_COND]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] 1032; CHECK: deopt: 1033; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 1034; CHECK-NEXT: ret void 1035; CHECK: guarded: 1036; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition() 1037; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_1]], [[WIDENABLE_COND3]] 1038; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] 1039; CHECK: deopt2: 1040; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 1041; CHECK-NEXT: ret void 1042; CHECK: guarded1: 1043; CHECK-NEXT: ret void 1044; 1045entry: 1046 %widenable_cond = call i1 @llvm.experimental.widenable.condition() 1047 %exiplicit_guard_cond = and i1 %widenable_cond, %cond_0 1048 br i1 %exiplicit_guard_cond, label %guarded, label %deopt, !prof !0 1049 1050deopt: ; preds = %entry 1051 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 1052 ret void 1053 1054guarded: ; preds = %entry 1055 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition() 1056 %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3 1057 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0 1058 1059deopt2: ; preds = %guarded 1060 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 1061 ret void 1062 1063guarded1: ; preds = %guarded 1064 ret void 1065} 1066 1067define void @trivial_wb(i1 %cond_0) { 1068; CHECK-LABEL: @trivial_wb( 1069; CHECK-NEXT: entry: 1070; CHECK-NEXT: [[WIDENABLE_COND:%.*]] = call i1 @llvm.experimental.widenable.condition() 1071; CHECK-NEXT: [[WIDE_CHK:%.*]] = and i1 true, [[COND_0:%.*]] 1072; CHECK-NEXT: [[TMP0:%.*]] = and i1 [[WIDE_CHK]], [[WIDENABLE_COND]] 1073; CHECK-NEXT: br i1 [[TMP0]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]] 1074; CHECK: deopt: 1075; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 1076; CHECK-NEXT: ret void 1077; CHECK: guarded: 1078; CHECK-NEXT: [[WIDENABLE_COND3:%.*]] = call i1 @llvm.experimental.widenable.condition() 1079; CHECK-NEXT: [[EXIPLICIT_GUARD_COND4:%.*]] = and i1 [[COND_0]], [[WIDENABLE_COND3]] 1080; CHECK-NEXT: br i1 true, label [[GUARDED1:%.*]], label [[DEOPT2:%.*]], !prof [[PROF0]] 1081; CHECK: deopt2: 1082; CHECK-NEXT: call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 1083; CHECK-NEXT: ret void 1084; CHECK: guarded1: 1085; CHECK-NEXT: ret void 1086; 1087entry: 1088 %widenable_cond = call i1 @llvm.experimental.widenable.condition() 1089 br i1 %widenable_cond, label %guarded, label %deopt, !prof !0 1090 1091deopt: ; preds = %entry 1092 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 1093 ret void 1094 1095guarded: ; preds = %entry 1096 %widenable_cond3 = call i1 @llvm.experimental.widenable.condition() 1097 %exiplicit_guard_cond4 = and i1 %cond_0, %widenable_cond3 1098 br i1 %exiplicit_guard_cond4, label %guarded1, label %deopt2, !prof !0 1099 1100deopt2: ; preds = %guarded 1101 call void (...) @llvm.experimental.deoptimize.isVoid() [ "deopt"() ] 1102 ret void 1103 1104guarded1: ; preds = %guarded 1105 ret void 1106} 1107 1108 1109declare void @llvm.experimental.deoptimize.isVoid(...) 1110 1111; Function Attrs: inaccessiblememonly nounwind 1112declare i1 @llvm.experimental.widenable.condition() #0 1113 1114attributes #0 = { inaccessiblememonly nounwind } 1115 1116!0 = !{!"branch_weights", i32 1048576, i32 1} 1117