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