1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -sink-common-insts -S | FileCheck %s 3; RUN: opt < %s -passes='simplifycfg<sink-common-insts>' -S | FileCheck %s 4 5target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" 6target triple = "x86_64-pc-linux-gnu" 7 8define zeroext i1 @test1(i1 zeroext %flag, i32 %blksA, i32 %blksB, i32 %nblks) { 9; CHECK-LABEL: @test1( 10; CHECK-NEXT: entry: 11; CHECK-NEXT: [[ADD:%.*]] = add i32 [[NBLKS:%.*]], [[BLKSB:%.*]] 12; CHECK-NEXT: [[CMP2:%.*]] = icmp ule i32 [[ADD]], [[BLKSA:%.*]] 13; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[BLKSA]], [[NBLKS]] 14; CHECK-NEXT: [[CMP2_SINK:%.*]] = select i1 [[FLAG:%.*]], i1 [[CMP]], i1 [[CMP2]] 15; CHECK-NEXT: [[FROMBOOL3:%.*]] = zext i1 [[CMP2_SINK]] to i8 16; CHECK-NEXT: [[TOBOOL4:%.*]] = icmp ne i8 [[FROMBOOL3]], 0 17; CHECK-NEXT: ret i1 [[TOBOOL4]] 18; 19entry: 20 br i1 %flag, label %if.then, label %if.else 21 22if.then: 23 %cmp = icmp uge i32 %blksA, %nblks 24 %frombool1 = zext i1 %cmp to i8 25 br label %if.end 26 27if.else: 28 %add = add i32 %nblks, %blksB 29 %cmp2 = icmp ule i32 %add, %blksA 30 %frombool3 = zext i1 %cmp2 to i8 31 br label %if.end 32 33if.end: 34 %obeys.0 = phi i8 [ %frombool1, %if.then ], [ %frombool3, %if.else ] 35 %tobool4 = icmp ne i8 %obeys.0, 0 36 ret i1 %tobool4 37} 38 39define zeroext i1 @test2(i1 zeroext %flag, i32 %blksA, i32 %blksB, i32 %nblks) { 40; CHECK-LABEL: @test2( 41; CHECK-NEXT: entry: 42; CHECK-NEXT: [[ADD:%.*]] = add i32 [[NBLKS:%.*]], [[BLKSB:%.*]] 43; CHECK-NEXT: [[ADD_SINK:%.*]] = select i1 [[FLAG:%.*]], i32 [[NBLKS]], i32 [[ADD]] 44; CHECK-NEXT: [[CMP2:%.*]] = icmp uge i32 [[BLKSA:%.*]], [[ADD_SINK]] 45; CHECK-NEXT: [[FROMBOOL3:%.*]] = zext i1 [[CMP2]] to i8 46; CHECK-NEXT: [[TOBOOL4:%.*]] = icmp ne i8 [[FROMBOOL3]], 0 47; CHECK-NEXT: ret i1 [[TOBOOL4]] 48; 49entry: 50 br i1 %flag, label %if.then, label %if.else 51 52if.then: 53 %cmp = icmp uge i32 %blksA, %nblks 54 %frombool1 = zext i1 %cmp to i8 55 br label %if.end 56 57if.else: 58 %add = add i32 %nblks, %blksB 59 %cmp2 = icmp uge i32 %blksA, %add 60 %frombool3 = zext i1 %cmp2 to i8 61 br label %if.end 62 63if.end: 64 %obeys.0 = phi i8 [ %frombool1, %if.then ], [ %frombool3, %if.else ] 65 %tobool4 = icmp ne i8 %obeys.0, 0 66 ret i1 %tobool4 67} 68 69declare i32 @foo(i32, i32) nounwind readnone 70 71define i32 @test3(i1 zeroext %flag, i32 %x, i32 %y) { 72; CHECK-LABEL: @test3( 73; CHECK-NEXT: entry: 74; CHECK-NEXT: [[X_Y:%.*]] = select i1 [[FLAG:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]] 75; CHECK-NEXT: [[X1:%.*]] = call i32 @foo(i32 [[X_Y]], i32 0) #[[ATTR0:[0-9]+]] 76; CHECK-NEXT: [[Y1:%.*]] = call i32 @foo(i32 [[X_Y]], i32 1) #[[ATTR0]] 77; CHECK-NEXT: [[RET:%.*]] = add i32 [[X1]], [[Y1]] 78; CHECK-NEXT: ret i32 [[RET]] 79; 80entry: 81 br i1 %flag, label %if.then, label %if.else 82 83if.then: 84 %x0 = call i32 @foo(i32 %x, i32 0) nounwind readnone 85 %y0 = call i32 @foo(i32 %x, i32 1) nounwind readnone 86 br label %if.end 87 88if.else: 89 %x1 = call i32 @foo(i32 %y, i32 0) nounwind readnone 90 %y1 = call i32 @foo(i32 %y, i32 1) nounwind readnone 91 br label %if.end 92 93if.end: 94 %xx = phi i32 [ %x0, %if.then ], [ %x1, %if.else ] 95 %yy = phi i32 [ %y0, %if.then ], [ %y1, %if.else ] 96 %ret = add i32 %xx, %yy 97 ret i32 %ret 98} 99 100 101define i32 @test4(i1 zeroext %flag, i32 %x, i32* %y) { 102; CHECK-LABEL: @test4( 103; CHECK-NEXT: entry: 104; CHECK-NEXT: [[DOT:%.*]] = select i1 [[FLAG:%.*]], i32 5, i32 7 105; CHECK-NEXT: [[B:%.*]] = add i32 [[X:%.*]], [[DOT]] 106; CHECK-NEXT: store i32 [[B]], i32* [[Y:%.*]], align 4 107; CHECK-NEXT: ret i32 1 108; 109entry: 110 br i1 %flag, label %if.then, label %if.else 111 112if.then: 113 %a = add i32 %x, 5 114 store i32 %a, i32* %y 115 br label %if.end 116 117if.else: 118 %b = add i32 %x, 7 119 store i32 %b, i32* %y 120 br label %if.end 121 122if.end: 123 ret i32 1 124} 125 126 127define i32 @test5(i1 zeroext %flag, i32 %x, i32* %y) { 128; CHECK-LABEL: @test5( 129; CHECK-NEXT: entry: 130; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 131; CHECK: if.then: 132; CHECK-NEXT: [[A:%.*]] = add i32 [[X:%.*]], 5 133; CHECK-NEXT: store volatile i32 [[A]], i32* [[Y:%.*]], align 4 134; CHECK-NEXT: br label [[IF_END:%.*]] 135; CHECK: if.else: 136; CHECK-NEXT: [[B:%.*]] = add i32 [[X]], 7 137; CHECK-NEXT: store i32 [[B]], i32* [[Y]], align 4 138; CHECK-NEXT: br label [[IF_END]] 139; CHECK: if.end: 140; CHECK-NEXT: ret i32 1 141; 142entry: 143 br i1 %flag, label %if.then, label %if.else 144 145if.then: 146 %a = add i32 %x, 5 147 store volatile i32 %a, i32* %y 148 br label %if.end 149 150if.else: 151 %b = add i32 %x, 7 152 store i32 %b, i32* %y 153 br label %if.end 154 155if.end: 156 ret i32 1 157} 158 159 160define i32 @test6(i1 zeroext %flag, i32 %x, i32* %y) { 161; CHECK-LABEL: @test6( 162; CHECK-NEXT: entry: 163; CHECK-NEXT: [[DOT:%.*]] = select i1 [[FLAG:%.*]], i32 5, i32 7 164; CHECK-NEXT: [[B:%.*]] = add i32 [[X:%.*]], [[DOT]] 165; CHECK-NEXT: store volatile i32 [[B]], i32* [[Y:%.*]], align 4 166; CHECK-NEXT: ret i32 1 167; 168entry: 169 br i1 %flag, label %if.then, label %if.else 170 171if.then: 172 %a = add i32 %x, 5 173 store volatile i32 %a, i32* %y 174 br label %if.end 175 176if.else: 177 %b = add i32 %x, 7 178 store volatile i32 %b, i32* %y 179 br label %if.end 180 181if.end: 182 ret i32 1 183} 184 185 186define i32 @test7(i1 zeroext %flag, i32 %x, i32* %y) { 187; CHECK-LABEL: @test7( 188; CHECK-NEXT: entry: 189; CHECK-NEXT: [[DOT:%.*]] = select i1 [[FLAG:%.*]], i32 5, i32 7 190; CHECK-NEXT: [[W:%.*]] = load volatile i32, i32* [[Y:%.*]], align 4 191; CHECK-NEXT: [[B:%.*]] = add i32 [[W]], [[DOT]] 192; CHECK-NEXT: store volatile i32 [[B]], i32* [[Y]], align 4 193; CHECK-NEXT: ret i32 1 194; 195entry: 196 br i1 %flag, label %if.then, label %if.else 197 198if.then: 199 %z = load volatile i32, i32* %y 200 %a = add i32 %z, 5 201 store volatile i32 %a, i32* %y 202 br label %if.end 203 204if.else: 205 %w = load volatile i32, i32* %y 206 %b = add i32 %w, 7 207 store volatile i32 %b, i32* %y 208 br label %if.end 209 210if.end: 211 ret i32 1 212} 213 214 215; %z and %w are in different blocks. We shouldn't sink the add because 216; there may be intervening memory instructions. 217define i32 @test8(i1 zeroext %flag, i32 %x, i32* %y) { 218; CHECK-LABEL: @test8( 219; CHECK-NEXT: entry: 220; CHECK-NEXT: [[Z:%.*]] = load volatile i32, i32* [[Y:%.*]], align 4 221; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 222; CHECK: if.then: 223; CHECK-NEXT: [[A:%.*]] = add i32 [[Z]], 5 224; CHECK-NEXT: br label [[IF_END:%.*]] 225; CHECK: if.else: 226; CHECK-NEXT: [[W:%.*]] = load volatile i32, i32* [[Y]], align 4 227; CHECK-NEXT: [[B:%.*]] = add i32 [[W]], 7 228; CHECK-NEXT: br label [[IF_END]] 229; CHECK: if.end: 230; CHECK-NEXT: [[B_SINK:%.*]] = phi i32 [ [[B]], [[IF_ELSE]] ], [ [[A]], [[IF_THEN]] ] 231; CHECK-NEXT: store volatile i32 [[B_SINK]], i32* [[Y]], align 4 232; CHECK-NEXT: ret i32 1 233; 234entry: 235 %z = load volatile i32, i32* %y 236 br i1 %flag, label %if.then, label %if.else 237 238if.then: 239 %a = add i32 %z, 5 240 store volatile i32 %a, i32* %y 241 br label %if.end 242 243if.else: 244 %w = load volatile i32, i32* %y 245 %b = add i32 %w, 7 246 store volatile i32 %b, i32* %y 247 br label %if.end 248 249if.end: 250 ret i32 1 251} 252 253 254; The extra store in %if.then means %z and %w are not equivalent. 255define i32 @test9(i1 zeroext %flag, i32 %x, i32* %y, i32* %p) { 256; CHECK-LABEL: @test9( 257; CHECK-NEXT: entry: 258; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 259; CHECK: if.then: 260; CHECK-NEXT: store i32 7, i32* [[P:%.*]], align 4 261; CHECK-NEXT: [[Z:%.*]] = load volatile i32, i32* [[Y:%.*]], align 4 262; CHECK-NEXT: store i32 6, i32* [[P]], align 4 263; CHECK-NEXT: [[A:%.*]] = add i32 [[Z]], 5 264; CHECK-NEXT: br label [[IF_END:%.*]] 265; CHECK: if.else: 266; CHECK-NEXT: [[W:%.*]] = load volatile i32, i32* [[Y]], align 4 267; CHECK-NEXT: [[B:%.*]] = add i32 [[W]], 7 268; CHECK-NEXT: br label [[IF_END]] 269; CHECK: if.end: 270; CHECK-NEXT: [[B_SINK:%.*]] = phi i32 [ [[B]], [[IF_ELSE]] ], [ [[A]], [[IF_THEN]] ] 271; CHECK-NEXT: store volatile i32 [[B_SINK]], i32* [[Y]], align 4 272; CHECK-NEXT: ret i32 1 273; 274entry: 275 br i1 %flag, label %if.then, label %if.else 276 277if.then: 278 store i32 7, i32* %p 279 %z = load volatile i32, i32* %y 280 store i32 6, i32* %p 281 %a = add i32 %z, 5 282 store volatile i32 %a, i32* %y 283 br label %if.end 284 285if.else: 286 %w = load volatile i32, i32* %y 287 %b = add i32 %w, 7 288 store volatile i32 %b, i32* %y 289 br label %if.end 290 291if.end: 292 ret i32 1 293} 294 295 296%struct.anon = type { i32, i32 } 297 298; The GEP indexes a struct type so cannot have a variable last index. 299define i32 @test10(i1 zeroext %flag, i32 %x, i32* %y, %struct.anon* %s) { 300; CHECK-LABEL: @test10( 301; CHECK-NEXT: entry: 302; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 303; CHECK: if.then: 304; CHECK-NEXT: [[DUMMY:%.*]] = add i32 [[X:%.*]], 5 305; CHECK-NEXT: [[GEPA:%.*]] = getelementptr inbounds [[STRUCT_ANON:%.*]], %struct.anon* [[S:%.*]], i32 0, i32 0 306; CHECK-NEXT: br label [[IF_END:%.*]] 307; CHECK: if.else: 308; CHECK-NEXT: [[DUMMY1:%.*]] = add i32 [[X]], 6 309; CHECK-NEXT: [[GEPB:%.*]] = getelementptr inbounds [[STRUCT_ANON]], %struct.anon* [[S]], i32 0, i32 1 310; CHECK-NEXT: br label [[IF_END]] 311; CHECK: if.end: 312; CHECK-NEXT: [[GEPB_SINK:%.*]] = phi i32* [ [[GEPB]], [[IF_ELSE]] ], [ [[GEPA]], [[IF_THEN]] ] 313; CHECK-NEXT: store volatile i32 [[X]], i32* [[GEPB_SINK]], align 4 314; CHECK-NEXT: ret i32 1 315; 316entry: 317 br i1 %flag, label %if.then, label %if.else 318 319if.then: 320 %dummy = add i32 %x, 5 321 %gepa = getelementptr inbounds %struct.anon, %struct.anon* %s, i32 0, i32 0 322 store volatile i32 %x, i32* %gepa 323 br label %if.end 324 325if.else: 326 %dummy1 = add i32 %x, 6 327 %gepb = getelementptr inbounds %struct.anon, %struct.anon* %s, i32 0, i32 1 328 store volatile i32 %x, i32* %gepb 329 br label %if.end 330 331if.end: 332 ret i32 1 333} 334 335 336; The shufflevector's mask operand cannot be merged in a PHI. 337define i32 @test11(i1 zeroext %flag, i32 %w, <2 x i32> %x, <2 x i32> %y) { 338; CHECK-LABEL: @test11( 339; CHECK-NEXT: entry: 340; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 341; CHECK: if.then: 342; CHECK-NEXT: [[DUMMY:%.*]] = add i32 [[W:%.*]], 5 343; CHECK-NEXT: [[SV1:%.*]] = shufflevector <2 x i32> [[X:%.*]], <2 x i32> [[Y:%.*]], <2 x i32> <i32 0, i32 1> 344; CHECK-NEXT: br label [[IF_END:%.*]] 345; CHECK: if.else: 346; CHECK-NEXT: [[DUMMY1:%.*]] = add i32 [[W]], 6 347; CHECK-NEXT: [[SV2:%.*]] = shufflevector <2 x i32> [[X]], <2 x i32> [[Y]], <2 x i32> <i32 1, i32 0> 348; CHECK-NEXT: br label [[IF_END]] 349; CHECK: if.end: 350; CHECK-NEXT: [[P:%.*]] = phi <2 x i32> [ [[SV1]], [[IF_THEN]] ], [ [[SV2]], [[IF_ELSE]] ] 351; CHECK-NEXT: ret i32 1 352; 353entry: 354 br i1 %flag, label %if.then, label %if.else 355 356if.then: 357 %dummy = add i32 %w, 5 358 %sv1 = shufflevector <2 x i32> %x, <2 x i32> %y, <2 x i32> <i32 0, i32 1> 359 br label %if.end 360 361if.else: 362 %dummy1 = add i32 %w, 6 363 %sv2 = shufflevector <2 x i32> %x, <2 x i32> %y, <2 x i32> <i32 1, i32 0> 364 br label %if.end 365 366if.end: 367 %p = phi <2 x i32> [ %sv1, %if.then ], [ %sv2, %if.else ] 368 ret i32 1 369} 370 371 372; We can't common an intrinsic! 373define i32 @test12(i1 zeroext %flag, i32 %w, i32 %x, i32 %y) { 374; CHECK-LABEL: @test12( 375; CHECK-NEXT: entry: 376; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 377; CHECK: if.then: 378; CHECK-NEXT: [[DUMMY:%.*]] = add i32 [[W:%.*]], 5 379; CHECK-NEXT: [[SV1:%.*]] = call i32 @llvm.ctlz.i32(i32 [[X:%.*]], i1 false) 380; CHECK-NEXT: br label [[IF_END:%.*]] 381; CHECK: if.else: 382; CHECK-NEXT: [[DUMMY1:%.*]] = add i32 [[W]], 6 383; CHECK-NEXT: [[SV2:%.*]] = call i32 @llvm.cttz.i32(i32 [[X]], i1 false) 384; CHECK-NEXT: br label [[IF_END]] 385; CHECK: if.end: 386; CHECK-NEXT: [[P:%.*]] = phi i32 [ [[SV1]], [[IF_THEN]] ], [ [[SV2]], [[IF_ELSE]] ] 387; CHECK-NEXT: ret i32 1 388; 389entry: 390 br i1 %flag, label %if.then, label %if.else 391 392if.then: 393 %dummy = add i32 %w, 5 394 %sv1 = call i32 @llvm.ctlz.i32(i32 %x, i1 false) 395 br label %if.end 396 397if.else: 398 %dummy1 = add i32 %w, 6 399 %sv2 = call i32 @llvm.cttz.i32(i32 %x, i1 false) 400 br label %if.end 401 402if.end: 403 %p = phi i32 [ %sv1, %if.then ], [ %sv2, %if.else ] 404 ret i32 1 405} 406 407declare i32 @llvm.ctlz.i32(i32 %x, i1 immarg) readnone 408declare i32 @llvm.cttz.i32(i32 %x, i1 immarg) readnone 409 410 411; The TBAA metadata should be properly combined. 412define i32 @test13(i1 zeroext %flag, i32 %x, i32* %y) { 413; CHECK-LABEL: @test13( 414; CHECK-NEXT: entry: 415; CHECK-NEXT: [[DOT:%.*]] = select i1 [[FLAG:%.*]], i32 5, i32 7 416; CHECK-NEXT: [[W:%.*]] = load volatile i32, i32* [[Y:%.*]], align 4 417; CHECK-NEXT: [[B:%.*]] = add i32 [[W]], [[DOT]] 418; CHECK-NEXT: store volatile i32 [[B]], i32* [[Y]], align 4, !tbaa [[TBAA4:![0-9]+]] 419; CHECK-NEXT: ret i32 1 420; 421entry: 422 br i1 %flag, label %if.then, label %if.else 423 424if.then: 425 %z = load volatile i32, i32* %y 426 %a = add i32 %z, 5 427 store volatile i32 %a, i32* %y, !tbaa !3 428 br label %if.end 429 430if.else: 431 %w = load volatile i32, i32* %y 432 %b = add i32 %w, 7 433 store volatile i32 %b, i32* %y, !tbaa !4 434 br label %if.end 435 436if.end: 437 ret i32 1 438} 439 440!0 = !{ !"an example type tree" } 441!1 = !{ !"int", !0 } 442!2 = !{ !"float", !0 } 443!3 = !{ !"const float", !2, i64 0 } 444!4 = !{ !"special float", !2, i64 1 } 445 446 447; The call should be commoned. 448define i32 @test13a(i1 zeroext %flag, i32 %w, i32 %x, i32 %y) { 449; CHECK-LABEL: @test13a( 450; CHECK-NEXT: entry: 451; CHECK-NEXT: [[X_Y:%.*]] = select i1 [[FLAG:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]] 452; CHECK-NEXT: [[SV2:%.*]] = call i32 @bar(i32 [[X_Y]]) 453; CHECK-NEXT: ret i32 1 454; 455entry: 456 br i1 %flag, label %if.then, label %if.else 457 458if.then: 459 %sv1 = call i32 @bar(i32 %x) 460 br label %if.end 461 462if.else: 463 %sv2 = call i32 @bar(i32 %y) 464 br label %if.end 465 466if.end: 467 %p = phi i32 [ %sv1, %if.then ], [ %sv2, %if.else ] 468 ret i32 1 469} 470declare i32 @bar(i32) 471 472 473; The load should be commoned. 474define i32 @test14(i1 zeroext %flag, i32 %w, i32 %x, i32 %y, %struct.anon* %s) { 475; CHECK-LABEL: @test14( 476; CHECK-NEXT: entry: 477; CHECK-NEXT: [[DOT:%.*]] = select i1 [[FLAG:%.*]], i32 1, i32 4 478; CHECK-NEXT: [[DOT2:%.*]] = select i1 [[FLAG]], i32 56, i32 57 479; CHECK-NEXT: [[DUMMY2:%.*]] = add i32 [[X:%.*]], [[DOT]] 480; CHECK-NEXT: [[GEPB:%.*]] = getelementptr inbounds [[STRUCT_ANON:%.*]], %struct.anon* [[S:%.*]], i32 0, i32 1 481; CHECK-NEXT: [[SV2:%.*]] = load i32, i32* [[GEPB]], align 4 482; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[SV2]], [[DOT2]] 483; CHECK-NEXT: ret i32 1 484; 485entry: 486 br i1 %flag, label %if.then, label %if.else 487 488if.then: 489 %dummy = add i32 %x, 1 490 %gepa = getelementptr inbounds %struct.anon, %struct.anon* %s, i32 0, i32 1 491 %sv1 = load i32, i32* %gepa 492 %cmp1 = icmp eq i32 %sv1, 56 493 br label %if.end 494 495if.else: 496 %dummy2 = add i32 %x, 4 497 %gepb = getelementptr inbounds %struct.anon, %struct.anon* %s, i32 0, i32 1 498 %sv2 = load i32, i32* %gepb 499 %cmp2 = icmp eq i32 %sv2, 57 500 call void @llvm.dbg.value(metadata i32 0, metadata !9, metadata !DIExpression()), !dbg !11 501 br label %if.end 502 503if.end: 504 %p = phi i1 [ %cmp1, %if.then ], [ %cmp2, %if.else ] 505 ret i32 1 506} 507 508declare void @llvm.dbg.value(metadata, metadata, metadata) 509!llvm.module.flags = !{!5, !6} 510!llvm.dbg.cu = !{!7} 511 512!5 = !{i32 2, !"Dwarf Version", i32 4} 513!6 = !{i32 2, !"Debug Info Version", i32 3} 514!7 = distinct !DICompileUnit(language: DW_LANG_C99, file: !10) 515!8 = distinct !DISubprogram(name: "foo", unit: !7) 516!9 = !DILocalVariable(name: "b", line: 1, arg: 2, scope: !8) 517!10 = !DIFile(filename: "a.c", directory: "a/b") 518!11 = !DILocation(line: 1, column: 14, scope: !8) 519 520 521; The load should be commoned. 522define i32 @test15(i1 zeroext %flag, i32 %w, i32 %x, i32 %y, %struct.anon* %s) { 523; CHECK-LABEL: @test15( 524; CHECK-NEXT: entry: 525; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 526; CHECK: if.then: 527; CHECK-NEXT: [[DUMMY:%.*]] = add i32 [[X:%.*]], 1 528; CHECK-NEXT: [[GEPA:%.*]] = getelementptr inbounds [[STRUCT_ANON:%.*]], %struct.anon* [[S:%.*]], i32 0, i32 0 529; CHECK-NEXT: br label [[IF_END:%.*]] 530; CHECK: if.else: 531; CHECK-NEXT: [[DUMMY2:%.*]] = add i32 [[X]], 4 532; CHECK-NEXT: [[GEPB:%.*]] = getelementptr inbounds [[STRUCT_ANON]], %struct.anon* [[S]], i32 0, i32 1 533; CHECK-NEXT: br label [[IF_END]] 534; CHECK: if.end: 535; CHECK-NEXT: [[GEPB_SINK:%.*]] = phi i32* [ [[GEPB]], [[IF_ELSE]] ], [ [[GEPA]], [[IF_THEN]] ] 536; CHECK-NEXT: [[DOTSINK:%.*]] = phi i64 [ 57, [[IF_ELSE]] ], [ 56, [[IF_THEN]] ] 537; CHECK-NEXT: [[SV2:%.*]] = load i32, i32* [[GEPB_SINK]], align 4 538; CHECK-NEXT: [[EXT2:%.*]] = zext i32 [[SV2]] to i64 539; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i64 [[EXT2]], [[DOTSINK]] 540; CHECK-NEXT: ret i32 1 541; 542entry: 543 br i1 %flag, label %if.then, label %if.else 544 545if.then: 546 %dummy = add i32 %x, 1 547 %gepa = getelementptr inbounds %struct.anon, %struct.anon* %s, i32 0, i32 0 548 %sv1 = load i32, i32* %gepa 549 %ext1 = zext i32 %sv1 to i64 550 %cmp1 = icmp eq i64 %ext1, 56 551 br label %if.end 552 553if.else: 554 %dummy2 = add i32 %x, 4 555 %gepb = getelementptr inbounds %struct.anon, %struct.anon* %s, i32 0, i32 1 556 %sv2 = load i32, i32* %gepb 557 %ext2 = zext i32 %sv2 to i64 558 %cmp2 = icmp eq i64 %ext2, 57 559 br label %if.end 560 561if.end: 562 %p = phi i1 [ %cmp1, %if.then ], [ %cmp2, %if.else ] 563 ret i32 1 564} 565 566 567define zeroext i1 @test_crash(i1 zeroext %flag, i32* %i4, i32* %m, i32* %n) { 568; CHECK-LABEL: @test_crash( 569; CHECK-NEXT: entry: 570; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 571; CHECK: if.then: 572; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[I4:%.*]], align 4 573; CHECK-NEXT: br label [[IF_END:%.*]] 574; CHECK: if.else: 575; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[M:%.*]], align 4 576; CHECK-NEXT: [[TMP4:%.*]] = load i32, i32* [[N:%.*]], align 4 577; CHECK-NEXT: br label [[IF_END]] 578; CHECK: if.end: 579; CHECK-NEXT: [[TMP4_SINK:%.*]] = phi i32 [ [[TMP4]], [[IF_ELSE]] ], [ -1, [[IF_THEN]] ] 580; CHECK-NEXT: [[TMP3_SINK:%.*]] = phi i32 [ [[TMP3]], [[IF_ELSE]] ], [ [[TMP1]], [[IF_THEN]] ] 581; CHECK-NEXT: [[TMP5:%.*]] = add i32 [[TMP3_SINK]], [[TMP4_SINK]] 582; CHECK-NEXT: store i32 [[TMP5]], i32* [[I4]], align 4 583; CHECK-NEXT: ret i1 true 584; 585entry: 586 br i1 %flag, label %if.then, label %if.else 587 588if.then: 589 %tmp1 = load i32, i32* %i4 590 %tmp2 = add i32 %tmp1, -1 591 store i32 %tmp2, i32* %i4 592 br label %if.end 593 594if.else: 595 %tmp3 = load i32, i32* %m 596 %tmp4 = load i32, i32* %n 597 %tmp5 = add i32 %tmp3, %tmp4 598 store i32 %tmp5, i32* %i4 599 br label %if.end 600 601if.end: 602 ret i1 true 603} 604 605; No checks for test_crash - just ensure it doesn't crash! 606 607define zeroext i1 @test16(i1 zeroext %flag, i1 zeroext %flag2, i32 %blksA, i32 %blksB, i32 %nblks) { 608; CHECK-LABEL: @test16( 609; CHECK-NEXT: entry: 610; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 611; CHECK: if.then: 612; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[BLKSA:%.*]], [[NBLKS:%.*]] 613; CHECK-NEXT: [[FROMBOOL1:%.*]] = zext i1 [[CMP]] to i8 614; CHECK-NEXT: br label [[IF_END:%.*]] 615; CHECK: if.else: 616; CHECK-NEXT: br i1 [[FLAG2:%.*]], label [[IF_THEN2:%.*]], label [[IF_END]] 617; CHECK: if.then2: 618; CHECK-NEXT: [[ADD:%.*]] = add i32 [[NBLKS]], [[BLKSB:%.*]] 619; CHECK-NEXT: [[CMP2:%.*]] = icmp ule i32 [[ADD]], [[BLKSA]] 620; CHECK-NEXT: [[FROMBOOL3:%.*]] = zext i1 [[CMP2]] to i8 621; CHECK-NEXT: br label [[IF_END]] 622; CHECK: if.end: 623; CHECK-NEXT: [[OBEYS_0:%.*]] = phi i8 [ [[FROMBOOL1]], [[IF_THEN]] ], [ [[FROMBOOL3]], [[IF_THEN2]] ], [ 0, [[IF_ELSE]] ] 624; CHECK-NEXT: [[TOBOOL4:%.*]] = icmp ne i8 [[OBEYS_0]], 0 625; CHECK-NEXT: ret i1 [[TOBOOL4]] 626; 627entry: 628 br i1 %flag, label %if.then, label %if.else 629 630if.then: 631 %cmp = icmp uge i32 %blksA, %nblks 632 %frombool1 = zext i1 %cmp to i8 633 br label %if.end 634 635if.else: 636 br i1 %flag2, label %if.then2, label %if.end 637 638if.then2: 639 %add = add i32 %nblks, %blksB 640 %cmp2 = icmp ule i32 %add, %blksA 641 %frombool3 = zext i1 %cmp2 to i8 642 br label %if.end 643 644if.end: 645 %obeys.0 = phi i8 [ %frombool1, %if.then ], [ %frombool3, %if.then2 ], [ 0, %if.else ] 646 %tobool4 = icmp ne i8 %obeys.0, 0 647 ret i1 %tobool4 648} 649 650 651define zeroext i1 @test16a(i1 zeroext %flag, i1 zeroext %flag2, i32 %blksA, i32 %blksB, i32 %nblks, i8* %p) { 652; CHECK-LABEL: @test16a( 653; CHECK-NEXT: entry: 654; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 655; CHECK: if.then: 656; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[BLKSA:%.*]], [[NBLKS:%.*]] 657; CHECK-NEXT: br label [[IF_END_SINK_SPLIT:%.*]] 658; CHECK: if.else: 659; CHECK-NEXT: br i1 [[FLAG2:%.*]], label [[IF_THEN2:%.*]], label [[IF_END:%.*]] 660; CHECK: if.then2: 661; CHECK-NEXT: [[ADD:%.*]] = add i32 [[NBLKS]], [[BLKSB:%.*]] 662; CHECK-NEXT: [[CMP2:%.*]] = icmp ule i32 [[ADD]], [[BLKSA]] 663; CHECK-NEXT: br label [[IF_END_SINK_SPLIT]] 664; CHECK: if.end.sink.split: 665; CHECK-NEXT: [[CMP2_SINK:%.*]] = phi i1 [ [[CMP2]], [[IF_THEN2]] ], [ [[CMP]], [[IF_THEN]] ] 666; CHECK-NEXT: [[FROMBOOL3:%.*]] = zext i1 [[CMP2_SINK]] to i8 667; CHECK-NEXT: store i8 [[FROMBOOL3]], i8* [[P:%.*]], align 1 668; CHECK-NEXT: br label [[IF_END]] 669; CHECK: if.end: 670; CHECK-NEXT: ret i1 true 671; 672entry: 673 br i1 %flag, label %if.then, label %if.else 674 675if.then: 676 %cmp = icmp uge i32 %blksA, %nblks 677 %frombool1 = zext i1 %cmp to i8 678 store i8 %frombool1, i8* %p 679 br label %if.end 680 681if.else: 682 br i1 %flag2, label %if.then2, label %if.end 683 684if.then2: 685 %add = add i32 %nblks, %blksB 686 %cmp2 = icmp ule i32 %add, %blksA 687 %frombool3 = zext i1 %cmp2 to i8 688 store i8 %frombool3, i8* %p 689 br label %if.end 690 691if.end: 692 ret i1 true 693} 694 695 696define zeroext i1 @test17(i32 %flag, i32 %blksA, i32 %blksB, i32 %nblks) { 697; CHECK-LABEL: @test17( 698; CHECK-NEXT: entry: 699; CHECK-NEXT: switch i32 [[FLAG:%.*]], label [[IF_END:%.*]] [ 700; CHECK-NEXT: i32 0, label [[IF_THEN:%.*]] 701; CHECK-NEXT: i32 1, label [[IF_THEN2:%.*]] 702; CHECK-NEXT: ] 703; CHECK: if.then: 704; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[BLKSA:%.*]], [[NBLKS:%.*]] 705; CHECK-NEXT: br label [[IF_END_SINK_SPLIT:%.*]] 706; CHECK: if.then2: 707; CHECK-NEXT: [[ADD:%.*]] = add i32 [[NBLKS]], [[BLKSB:%.*]] 708; CHECK-NEXT: [[CMP2:%.*]] = icmp ule i32 [[ADD]], [[BLKSA]] 709; CHECK-NEXT: br label [[IF_END_SINK_SPLIT]] 710; CHECK: if.end.sink.split: 711; CHECK-NEXT: [[CMP2_SINK:%.*]] = phi i1 [ [[CMP2]], [[IF_THEN2]] ], [ [[CMP]], [[IF_THEN]] ] 712; CHECK-NEXT: [[FROMBOOL3:%.*]] = call i8 @i1toi8(i1 [[CMP2_SINK]]) 713; CHECK-NEXT: br label [[IF_END]] 714; CHECK: if.end: 715; CHECK-NEXT: [[OBEYS_0:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[FROMBOOL3]], [[IF_END_SINK_SPLIT]] ] 716; CHECK-NEXT: [[TOBOOL4:%.*]] = icmp ne i8 [[OBEYS_0]], 0 717; CHECK-NEXT: ret i1 [[TOBOOL4]] 718; 719entry: 720 switch i32 %flag, label %if.end [ 721 i32 0, label %if.then 722 i32 1, label %if.then2 723 ] 724 725if.then: 726 %cmp = icmp uge i32 %blksA, %nblks 727 %frombool1 = call i8 @i1toi8(i1 %cmp) 728 br label %if.end 729 730if.then2: 731 %add = add i32 %nblks, %blksB 732 %cmp2 = icmp ule i32 %add, %blksA 733 %frombool3 = call i8 @i1toi8(i1 %cmp2) 734 br label %if.end 735 736if.end: 737 %obeys.0 = phi i8 [ %frombool1, %if.then ], [ %frombool3, %if.then2 ], [ 0, %entry ] 738 %tobool4 = icmp ne i8 %obeys.0, 0 739 ret i1 %tobool4 740} 741declare i8 @i1toi8(i1) 742 743 744 745 746 747define zeroext i1 @test18(i32 %flag, i32 %blksA, i32 %blksB, i32 %nblks) { 748; CHECK-LABEL: @test18( 749; CHECK-NEXT: entry: 750; CHECK-NEXT: switch i32 [[FLAG:%.*]], label [[IF_THEN3:%.*]] [ 751; CHECK-NEXT: i32 0, label [[IF_THEN:%.*]] 752; CHECK-NEXT: i32 1, label [[IF_THEN2:%.*]] 753; CHECK-NEXT: ] 754; CHECK: if.then: 755; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[BLKSA:%.*]], [[NBLKS:%.*]] 756; CHECK-NEXT: br label [[IF_END:%.*]] 757; CHECK: if.then2: 758; CHECK-NEXT: [[ADD:%.*]] = add i32 [[NBLKS]], [[BLKSB:%.*]] 759; CHECK-NEXT: [[CMP2:%.*]] = icmp ule i32 [[ADD]], [[BLKSA]] 760; CHECK-NEXT: br label [[IF_END]] 761; CHECK: if.then3: 762; CHECK-NEXT: [[ADD2:%.*]] = add i32 [[NBLKS]], [[BLKSA]] 763; CHECK-NEXT: [[CMP3:%.*]] = icmp ule i32 [[ADD2]], [[BLKSA]] 764; CHECK-NEXT: br label [[IF_END]] 765; CHECK: if.end: 766; CHECK-NEXT: [[CMP3_SINK:%.*]] = phi i1 [ [[CMP3]], [[IF_THEN3]] ], [ [[CMP2]], [[IF_THEN2]] ], [ [[CMP]], [[IF_THEN]] ] 767; CHECK-NEXT: [[FROMBOOL4:%.*]] = zext i1 [[CMP3_SINK]] to i8 768; CHECK-NEXT: [[TOBOOL4:%.*]] = icmp ne i8 [[FROMBOOL4]], 0 769; CHECK-NEXT: ret i1 [[TOBOOL4]] 770; 771entry: 772 switch i32 %flag, label %if.then3 [ 773 i32 0, label %if.then 774 i32 1, label %if.then2 775 ] 776 777if.then: 778 %cmp = icmp uge i32 %blksA, %nblks 779 %frombool1 = zext i1 %cmp to i8 780 br label %if.end 781 782if.then2: 783 %add = add i32 %nblks, %blksB 784 %cmp2 = icmp ule i32 %add, %blksA 785 %frombool3 = zext i1 %cmp2 to i8 786 br label %if.end 787 788if.then3: 789 %add2 = add i32 %nblks, %blksA 790 %cmp3 = icmp ule i32 %add2, %blksA 791 %frombool4 = zext i1 %cmp3 to i8 792 br label %if.end 793 794if.end: 795 %obeys.0 = phi i8 [ %frombool1, %if.then ], [ %frombool3, %if.then2 ], [ %frombool4, %if.then3 ] 796 %tobool4 = icmp ne i8 %obeys.0, 0 797 ret i1 %tobool4 798} 799 800 801define i32 @test_pr30188(i1 zeroext %flag, i32 %x) { 802; CHECK-LABEL: @test_pr30188( 803; CHECK-NEXT: entry: 804; CHECK-NEXT: [[Y:%.*]] = alloca i32, align 4 805; CHECK-NEXT: [[Z:%.*]] = alloca i32, align 4 806; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 807; CHECK: if.then: 808; CHECK-NEXT: store i32 [[X:%.*]], i32* [[Y]], align 4 809; CHECK-NEXT: br label [[IF_END:%.*]] 810; CHECK: if.else: 811; CHECK-NEXT: store i32 [[X]], i32* [[Z]], align 4 812; CHECK-NEXT: br label [[IF_END]] 813; CHECK: if.end: 814; CHECK-NEXT: ret i32 1 815; 816entry: 817 %y = alloca i32 818 %z = alloca i32 819 br i1 %flag, label %if.then, label %if.else 820 821if.then: 822 store i32 %x, i32* %y 823 br label %if.end 824 825if.else: 826 store i32 %x, i32* %z 827 br label %if.end 828 829if.end: 830 ret i32 1 831} 832 833 834define i32 @test_pr30188a(i1 zeroext %flag, i32 %x) { 835; CHECK-LABEL: @test_pr30188a( 836; CHECK-NEXT: entry: 837; CHECK-NEXT: [[Y:%.*]] = alloca i32, align 4 838; CHECK-NEXT: [[Z:%.*]] = alloca i32, align 4 839; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 840; CHECK: if.then: 841; CHECK-NEXT: call void @g() 842; CHECK-NEXT: [[ONE:%.*]] = load i32, i32* [[Y]], align 4 843; CHECK-NEXT: [[TWO:%.*]] = add i32 [[ONE]], 2 844; CHECK-NEXT: store i32 [[TWO]], i32* [[Y]], align 4 845; CHECK-NEXT: br label [[IF_END:%.*]] 846; CHECK: if.else: 847; CHECK-NEXT: [[THREE:%.*]] = load i32, i32* [[Z]], align 4 848; CHECK-NEXT: [[FOUR:%.*]] = add i32 [[THREE]], 2 849; CHECK-NEXT: store i32 [[FOUR]], i32* [[Y]], align 4 850; CHECK-NEXT: br label [[IF_END]] 851; CHECK: if.end: 852; CHECK-NEXT: ret i32 1 853; 854entry: 855 %y = alloca i32 856 %z = alloca i32 857 br i1 %flag, label %if.then, label %if.else 858 859if.then: 860 call void @g() 861 %one = load i32, i32* %y 862 %two = add i32 %one, 2 863 store i32 %two, i32* %y 864 br label %if.end 865 866if.else: 867 %three = load i32, i32* %z 868 %four = add i32 %three, 2 869 store i32 %four, i32* %y 870 br label %if.end 871 872if.end: 873 ret i32 1 874} 875 876 877; The phi is confusing - both add instructions are used by it, but 878; not on their respective unconditional arcs. It should not be 879; optimized. 880define void @test_pr30292(i1 %cond, i1 %cond2, i32 %a, i32 %b) { 881; CHECK-LABEL: @test_pr30292( 882; CHECK-NEXT: entry: 883; CHECK-NEXT: [[ADD1:%.*]] = add i32 [[A:%.*]], 1 884; CHECK-NEXT: br label [[SUCC:%.*]] 885; CHECK: two: 886; CHECK-NEXT: call void @g() 887; CHECK-NEXT: [[ADD2:%.*]] = add i32 [[A]], 1 888; CHECK-NEXT: br label [[SUCC]] 889; CHECK: succ: 890; CHECK-NEXT: [[P:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD1]], [[SUCC]] ], [ [[ADD2]], [[TWO:%.*]] ] 891; CHECK-NEXT: br i1 [[COND:%.*]], label [[TWO]], label [[SUCC]] 892; 893entry: 894 %add1 = add i32 %a, 1 895 br label %succ 896 897one: 898 br i1 %cond, label %two, label %succ 899 900two: 901 call void @g() 902 %add2 = add i32 %a, 1 903 br label %succ 904 905succ: 906 %p = phi i32 [ 0, %entry ], [ %add1, %one ], [ %add2, %two ] 907 br label %one 908} 909declare void @g() 910 911 912define zeroext i1 @test_pr30244(i1 zeroext %flag, i1 zeroext %flag2, i32 %blksA, i32 %blksB, i32 %nblks) { 913; CHECK-LABEL: @test_pr30244( 914; CHECK-NEXT: entry: 915; CHECK-NEXT: [[P:%.*]] = alloca i8, align 1 916; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 917; CHECK: if.then: 918; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[BLKSA:%.*]], [[NBLKS:%.*]] 919; CHECK-NEXT: [[FROMBOOL1:%.*]] = zext i1 [[CMP]] to i8 920; CHECK-NEXT: store i8 [[FROMBOOL1]], i8* [[P]], align 1 921; CHECK-NEXT: br label [[IF_END:%.*]] 922; CHECK: if.else: 923; CHECK-NEXT: br i1 [[FLAG2:%.*]], label [[IF_THEN2:%.*]], label [[IF_END]] 924; CHECK: if.then2: 925; CHECK-NEXT: [[ADD:%.*]] = add i32 [[NBLKS]], [[BLKSB:%.*]] 926; CHECK-NEXT: [[CMP2:%.*]] = icmp ule i32 [[ADD]], [[BLKSA]] 927; CHECK-NEXT: [[FROMBOOL3:%.*]] = zext i1 [[CMP2]] to i8 928; CHECK-NEXT: store i8 [[FROMBOOL3]], i8* [[P]], align 1 929; CHECK-NEXT: br label [[IF_END]] 930; CHECK: if.end: 931; CHECK-NEXT: ret i1 true 932; 933entry: 934 %p = alloca i8 935 br i1 %flag, label %if.then, label %if.else 936 937if.then: 938 %cmp = icmp uge i32 %blksA, %nblks 939 %frombool1 = zext i1 %cmp to i8 940 store i8 %frombool1, i8* %p 941 br label %if.end 942 943if.else: 944 br i1 %flag2, label %if.then2, label %if.end 945 946if.then2: 947 %add = add i32 %nblks, %blksB 948 %cmp2 = icmp ule i32 %add, %blksA 949 %frombool3 = zext i1 %cmp2 to i8 950 store i8 %frombool3, i8* %p 951 br label %if.end 952 953if.end: 954 ret i1 true 955} 956 957 958define i32 @test_pr30373a(i1 zeroext %flag, i32 %x, i32 %y) { 959; CHECK-LABEL: @test_pr30373a( 960; CHECK-NEXT: entry: 961; CHECK-NEXT: [[X_Y:%.*]] = select i1 [[FLAG:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]] 962; CHECK-NEXT: [[X1:%.*]] = call i32 @foo(i32 [[X_Y]], i32 0) #[[ATTR0]] 963; CHECK-NEXT: [[Y1:%.*]] = call i32 @foo(i32 [[X_Y]], i32 1) #[[ATTR0]] 964; CHECK-NEXT: [[Z1:%.*]] = lshr i32 [[Y1]], 8 965; CHECK-NEXT: [[RET:%.*]] = add i32 [[X1]], [[Z1]] 966; CHECK-NEXT: ret i32 [[RET]] 967; 968entry: 969 br i1 %flag, label %if.then, label %if.else 970 971if.then: 972 %x0 = call i32 @foo(i32 %x, i32 0) nounwind readnone 973 %y0 = call i32 @foo(i32 %x, i32 1) nounwind readnone 974 %z0 = lshr i32 %y0, 8 975 br label %if.end 976 977if.else: 978 %x1 = call i32 @foo(i32 %y, i32 0) nounwind readnone 979 %y1 = call i32 @foo(i32 %y, i32 1) nounwind readnone 980 %z1 = lshr exact i32 %y1, 8 981 br label %if.end 982 983if.end: 984 %xx = phi i32 [ %x0, %if.then ], [ %x1, %if.else ] 985 %yy = phi i32 [ %z0, %if.then ], [ %z1, %if.else ] 986 %ret = add i32 %xx, %yy 987 ret i32 %ret 988} 989 990 991define i32 @test_pr30373b(i1 zeroext %flag, i32 %x, i32 %y) { 992; CHECK-LABEL: @test_pr30373b( 993; CHECK-NEXT: entry: 994; CHECK-NEXT: [[X_Y:%.*]] = select i1 [[FLAG:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]] 995; CHECK-NEXT: [[X1:%.*]] = call i32 @foo(i32 [[X_Y]], i32 0) #[[ATTR0]] 996; CHECK-NEXT: [[Y1:%.*]] = call i32 @foo(i32 [[X_Y]], i32 1) #[[ATTR0]] 997; CHECK-NEXT: [[Z1:%.*]] = lshr i32 [[Y1]], 8 998; CHECK-NEXT: [[RET:%.*]] = add i32 [[X1]], [[Z1]] 999; CHECK-NEXT: ret i32 [[RET]] 1000; 1001entry: 1002 br i1 %flag, label %if.then, label %if.else 1003 1004if.then: 1005 %x0 = call i32 @foo(i32 %x, i32 0) nounwind readnone 1006 %y0 = call i32 @foo(i32 %x, i32 1) nounwind readnone 1007 %z0 = lshr exact i32 %y0, 8 1008 br label %if.end 1009 1010if.else: 1011 %x1 = call i32 @foo(i32 %y, i32 0) nounwind readnone 1012 %y1 = call i32 @foo(i32 %y, i32 1) nounwind readnone 1013 %z1 = lshr i32 %y1, 8 1014 br label %if.end 1015 1016if.end: 1017 %xx = phi i32 [ %x0, %if.then ], [ %x1, %if.else ] 1018 %yy = phi i32 [ %z0, %if.then ], [ %z1, %if.else ] 1019 %ret = add i32 %xx, %yy 1020 ret i32 %ret 1021} 1022 1023 1024 1025; FIXME: Should turn into select 1026define float @allow_intrinsic_remove_constant(i1 zeroext %flag, float %w, float %x, float %y) { 1027; CHECK-LABEL: @allow_intrinsic_remove_constant( 1028; CHECK-NEXT: entry: 1029; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 1030; CHECK: if.then: 1031; CHECK-NEXT: [[DUMMY:%.*]] = fadd float [[W:%.*]], 4.000000e+00 1032; CHECK-NEXT: [[SV1:%.*]] = call float @llvm.fma.f32(float [[DUMMY]], float 2.000000e+00, float 1.000000e+00) 1033; CHECK-NEXT: br label [[IF_END:%.*]] 1034; CHECK: if.else: 1035; CHECK-NEXT: [[DUMMY1:%.*]] = fadd float [[W]], 8.000000e+00 1036; CHECK-NEXT: [[SV2:%.*]] = call float @llvm.fma.f32(float 2.000000e+00, float [[DUMMY1]], float 1.000000e+00) 1037; CHECK-NEXT: br label [[IF_END]] 1038; CHECK: if.end: 1039; CHECK-NEXT: [[P:%.*]] = phi float [ [[SV1]], [[IF_THEN]] ], [ [[SV2]], [[IF_ELSE]] ] 1040; CHECK-NEXT: ret float [[P]] 1041; 1042entry: 1043 br i1 %flag, label %if.then, label %if.else 1044 1045if.then: 1046 %dummy = fadd float %w, 4.0 1047 %sv1 = call float @llvm.fma.f32(float %dummy, float 2.0, float 1.0) 1048 br label %if.end 1049 1050if.else: 1051 %dummy1 = fadd float %w, 8.0 1052 %sv2 = call float @llvm.fma.f32(float 2.0, float %dummy1, float 1.0) 1053 br label %if.end 1054 1055if.end: 1056 %p = phi float [ %sv1, %if.then ], [ %sv2, %if.else ] 1057 ret float %p 1058} 1059 1060declare float @llvm.fma.f32(float, float, float) 1061 1062define i32 @no_remove_constant_immarg(i1 zeroext %flag, i32 %w, i32 %x, i32 %y) { 1063; CHECK-LABEL: @no_remove_constant_immarg( 1064; CHECK-NEXT: entry: 1065; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 1066; CHECK: if.then: 1067; CHECK-NEXT: [[DUMMY:%.*]] = add i32 [[W:%.*]], 5 1068; CHECK-NEXT: [[SV1:%.*]] = call i32 @llvm.ctlz.i32(i32 [[X:%.*]], i1 true) 1069; CHECK-NEXT: br label [[IF_END:%.*]] 1070; CHECK: if.else: 1071; CHECK-NEXT: [[DUMMY1:%.*]] = add i32 [[W]], 6 1072; CHECK-NEXT: [[SV2:%.*]] = call i32 @llvm.ctlz.i32(i32 [[X]], i1 false) 1073; CHECK-NEXT: br label [[IF_END]] 1074; CHECK: if.end: 1075; CHECK-NEXT: [[P:%.*]] = phi i32 [ [[SV1]], [[IF_THEN]] ], [ [[SV2]], [[IF_ELSE]] ] 1076; CHECK-NEXT: ret i32 1 1077; 1078entry: 1079 br i1 %flag, label %if.then, label %if.else 1080 1081if.then: 1082 %dummy = add i32 %w, 5 1083 %sv1 = call i32 @llvm.ctlz.i32(i32 %x, i1 true) 1084 br label %if.end 1085 1086if.else: 1087 %dummy1 = add i32 %w, 6 1088 %sv2 = call i32 @llvm.ctlz.i32(i32 %x, i1 false) 1089 br label %if.end 1090 1091if.end: 1092 %p = phi i32 [ %sv1, %if.then ], [ %sv2, %if.else ] 1093 ret i32 1 1094} 1095 1096declare void @llvm.memcpy.p1i8.p1i8.i64(i8 addrspace(1)* nocapture, i8 addrspace(1)* nocapture readonly, i64, i1) 1097 1098; Make sure a memcpy size isn't replaced with a variable 1099define void @no_replace_memcpy_size(i1 zeroext %flag, i8 addrspace(1)* %dst, i8 addrspace(1)* %src) { 1100; CHECK-LABEL: @no_replace_memcpy_size( 1101; CHECK-NEXT: entry: 1102; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 1103; CHECK: if.then: 1104; CHECK-NEXT: call void @llvm.memcpy.p1i8.p1i8.i64(i8 addrspace(1)* [[DST:%.*]], i8 addrspace(1)* [[SRC:%.*]], i64 1024, i1 false) 1105; CHECK-NEXT: br label [[IF_END:%.*]] 1106; CHECK: if.else: 1107; CHECK-NEXT: call void @llvm.memcpy.p1i8.p1i8.i64(i8 addrspace(1)* [[DST]], i8 addrspace(1)* [[SRC]], i64 4096, i1 false) 1108; CHECK-NEXT: br label [[IF_END]] 1109; CHECK: if.end: 1110; CHECK-NEXT: ret void 1111; 1112entry: 1113 br i1 %flag, label %if.then, label %if.else 1114 1115if.then: 1116 call void @llvm.memcpy.p1i8.p1i8.i64(i8 addrspace(1)* %dst, i8 addrspace(1)* %src, i64 1024, i1 false) 1117 br label %if.end 1118 1119if.else: 1120 call void @llvm.memcpy.p1i8.p1i8.i64(i8 addrspace(1)* %dst, i8 addrspace(1)* %src, i64 4096, i1 false) 1121 br label %if.end 1122 1123if.end: 1124 ret void 1125} 1126 1127declare void @llvm.memmove.p1i8.p1i8.i64(i8 addrspace(1)* nocapture, i8 addrspace(1)* nocapture readonly, i64, i1) 1128 1129; Make sure a memmove size isn't replaced with a variable 1130define void @no_replace_memmove_size(i1 zeroext %flag, i8 addrspace(1)* %dst, i8 addrspace(1)* %src) { 1131; CHECK-LABEL: @no_replace_memmove_size( 1132; CHECK-NEXT: entry: 1133; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 1134; CHECK: if.then: 1135; CHECK-NEXT: call void @llvm.memmove.p1i8.p1i8.i64(i8 addrspace(1)* [[DST:%.*]], i8 addrspace(1)* [[SRC:%.*]], i64 1024, i1 false) 1136; CHECK-NEXT: br label [[IF_END:%.*]] 1137; CHECK: if.else: 1138; CHECK-NEXT: call void @llvm.memmove.p1i8.p1i8.i64(i8 addrspace(1)* [[DST]], i8 addrspace(1)* [[SRC]], i64 4096, i1 false) 1139; CHECK-NEXT: br label [[IF_END]] 1140; CHECK: if.end: 1141; CHECK-NEXT: ret void 1142; 1143entry: 1144 br i1 %flag, label %if.then, label %if.else 1145 1146if.then: 1147 call void @llvm.memmove.p1i8.p1i8.i64(i8 addrspace(1)* %dst, i8 addrspace(1)* %src, i64 1024, i1 false) 1148 br label %if.end 1149 1150if.else: 1151 call void @llvm.memmove.p1i8.p1i8.i64(i8 addrspace(1)* %dst, i8 addrspace(1)* %src, i64 4096, i1 false) 1152 br label %if.end 1153 1154if.end: 1155 ret void 1156} 1157 1158declare void @llvm.memset.p1i8.i64(i8 addrspace(1)* nocapture, i8, i64, i1) 1159 1160; Make sure a memset size isn't replaced with a variable 1161define void @no_replace_memset_size(i1 zeroext %flag, i8 addrspace(1)* %dst) { 1162; CHECK-LABEL: @no_replace_memset_size( 1163; CHECK-NEXT: entry: 1164; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 1165; CHECK: if.then: 1166; CHECK-NEXT: call void @llvm.memset.p1i8.i64(i8 addrspace(1)* [[DST:%.*]], i8 0, i64 1024, i1 false) 1167; CHECK-NEXT: br label [[IF_END:%.*]] 1168; CHECK: if.else: 1169; CHECK-NEXT: call void @llvm.memset.p1i8.i64(i8 addrspace(1)* [[DST]], i8 0, i64 4096, i1 false) 1170; CHECK-NEXT: br label [[IF_END]] 1171; CHECK: if.end: 1172; CHECK-NEXT: ret void 1173; 1174entry: 1175 br i1 %flag, label %if.then, label %if.else 1176 1177if.then: 1178 call void @llvm.memset.p1i8.i64(i8 addrspace(1)* %dst, i8 0, i64 1024, i1 false) 1179 br label %if.end 1180 1181if.else: 1182 call void @llvm.memset.p1i8.i64(i8 addrspace(1)* %dst, i8 0, i64 4096, i1 false) 1183 br label %if.end 1184 1185if.end: 1186 ret void 1187} 1188 1189; Check that simplifycfg doesn't sink and merge inline-asm instructions. 1190 1191define i32 @test_inline_asm1(i32 %c, i32 %r6) { 1192; CHECK-LABEL: @test_inline_asm1( 1193; CHECK-NEXT: entry: 1194; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[C:%.*]], 0 1195; CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]] 1196; CHECK: if.then: 1197; CHECK-NEXT: [[TMP0:%.*]] = call i32 asm "rorl $2, $0", "=&r,0,n,~{dirflag},~{fpsr},~{flags}"(i32 [[R6:%.*]], i32 8) 1198; CHECK-NEXT: br label [[IF_END:%.*]] 1199; CHECK: if.else: 1200; CHECK-NEXT: [[TMP1:%.*]] = call i32 asm "rorl $2, $0", "=&r,0,n,~{dirflag},~{fpsr},~{flags}"(i32 [[R6]], i32 6) 1201; CHECK-NEXT: br label [[IF_END]] 1202; CHECK: if.end: 1203; CHECK-NEXT: [[R6_ADDR_0:%.*]] = phi i32 [ [[TMP0]], [[IF_THEN]] ], [ [[TMP1]], [[IF_ELSE]] ] 1204; CHECK-NEXT: ret i32 [[R6_ADDR_0]] 1205; 1206entry: 1207 %tobool = icmp eq i32 %c, 0 1208 br i1 %tobool, label %if.else, label %if.then 1209 1210if.then: 1211 %0 = call i32 asm "rorl $2, $0", "=&r,0,n,~{dirflag},~{fpsr},~{flags}"(i32 %r6, i32 8) 1212 br label %if.end 1213 1214if.else: 1215 %1 = call i32 asm "rorl $2, $0", "=&r,0,n,~{dirflag},~{fpsr},~{flags}"(i32 %r6, i32 6) 1216 br label %if.end 1217 1218if.end: 1219 %r6.addr.0 = phi i32 [ %0, %if.then ], [ %1, %if.else ] 1220 ret i32 %r6.addr.0 1221} 1222 1223 1224declare i32 @call_target() 1225 1226define void @test_operand_bundles(i1 %cond, i32* %ptr) { 1227; CHECK-LABEL: @test_operand_bundles( 1228; CHECK-NEXT: entry: 1229; CHECK-NEXT: br i1 [[COND:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]] 1230; CHECK: left: 1231; CHECK-NEXT: [[VAL0:%.*]] = call i32 @call_target() [ "deopt"(i32 10) ] 1232; CHECK-NEXT: br label [[MERGE:%.*]] 1233; CHECK: right: 1234; CHECK-NEXT: [[VAL1:%.*]] = call i32 @call_target() [ "deopt"(i32 20) ] 1235; CHECK-NEXT: br label [[MERGE]] 1236; CHECK: merge: 1237; CHECK-NEXT: [[VAL1_SINK:%.*]] = phi i32 [ [[VAL1]], [[RIGHT]] ], [ [[VAL0]], [[LEFT]] ] 1238; CHECK-NEXT: store i32 [[VAL1_SINK]], i32* [[PTR:%.*]], align 4 1239; CHECK-NEXT: ret void 1240; 1241entry: 1242 br i1 %cond, label %left, label %right 1243 1244left: 1245 %val0 = call i32 @call_target() [ "deopt"(i32 10) ] 1246 store i32 %val0, i32* %ptr 1247 br label %merge 1248 1249right: 1250 %val1 = call i32 @call_target() [ "deopt"(i32 20) ] 1251 store i32 %val1, i32* %ptr 1252 br label %merge 1253 1254merge: 1255 ret void 1256} 1257 1258 1259%TP = type {i32, i32} 1260 1261define i32 @test_insertvalue(i1 zeroext %flag, %TP %P) { 1262; CHECK-LABEL: @test_insertvalue( 1263; CHECK-NEXT: entry: 1264; CHECK-NEXT: [[DOT:%.*]] = select i1 [[FLAG:%.*]], i32 0, i32 1 1265; CHECK-NEXT: [[I2:%.*]] = insertvalue [[TP:%.*]] [[P:%.*]], i32 [[DOT]], 0 1266; CHECK-NEXT: ret i32 1 1267; 1268entry: 1269 br i1 %flag, label %if.then, label %if.else 1270 1271if.then: 1272 %i1 = insertvalue %TP %P, i32 0, 0 1273 br label %if.end 1274 1275if.else: 1276 %i2 = insertvalue %TP %P, i32 1, 0 1277 br label %if.end 1278 1279if.end: 1280 %i = phi %TP [%i1, %if.then], [%i2, %if.else] 1281 ret i32 1 1282} 1283 1284 1285 1286declare void @baz(i32) 1287 1288define void @test_sink_void_calls(i32 %x) { 1289; CHECK-LABEL: @test_sink_void_calls( 1290; CHECK-NEXT: entry: 1291; CHECK-NEXT: switch i32 [[X:%.*]], label [[DEFAULT:%.*]] [ 1292; CHECK-NEXT: i32 0, label [[RETURN:%.*]] 1293; CHECK-NEXT: i32 1, label [[BB1:%.*]] 1294; CHECK-NEXT: i32 2, label [[BB2:%.*]] 1295; CHECK-NEXT: i32 3, label [[BB3:%.*]] 1296; CHECK-NEXT: i32 4, label [[BB4:%.*]] 1297; CHECK-NEXT: ] 1298; CHECK: bb1: 1299; CHECK-NEXT: br label [[RETURN]] 1300; CHECK: bb2: 1301; CHECK-NEXT: br label [[RETURN]] 1302; CHECK: bb3: 1303; CHECK-NEXT: br label [[RETURN]] 1304; CHECK: bb4: 1305; CHECK-NEXT: br label [[RETURN]] 1306; CHECK: default: 1307; CHECK-NEXT: unreachable 1308; CHECK: return: 1309; CHECK-NEXT: [[DOTSINK:%.*]] = phi i32 [ 90, [[BB4]] ], [ 78, [[BB3]] ], [ 56, [[BB2]] ], [ 34, [[BB1]] ], [ 12, [[ENTRY:%.*]] ] 1310; CHECK-NEXT: call void @baz(i32 [[DOTSINK]]) 1311; CHECK-NEXT: ret void 1312; 1313entry: 1314 switch i32 %x, label %default [ 1315 i32 0, label %bb0 1316 i32 1, label %bb1 1317 i32 2, label %bb2 1318 i32 3, label %bb3 1319 i32 4, label %bb4 1320 ] 1321bb0: 1322 call void @baz(i32 12) 1323 br label %return 1324bb1: 1325 call void @baz(i32 34) 1326 br label %return 1327bb2: 1328 call void @baz(i32 56) 1329 br label %return 1330bb3: 1331 call void @baz(i32 78) 1332 br label %return 1333bb4: 1334 call void @baz(i32 90) 1335 br label %return 1336default: 1337 unreachable 1338return: 1339 ret void 1340 1341; Check that the calls get sunk to the return block. 1342; We would previously not sink calls without uses, see PR41259. 1343} 1344 1345define i32 @test_not_sink_lifetime_marker(i1 zeroext %flag, i32 %x) { 1346; CHECK-LABEL: @test_not_sink_lifetime_marker( 1347; CHECK-NEXT: entry: 1348; CHECK-NEXT: [[Y:%.*]] = alloca i32, align 4 1349; CHECK-NEXT: [[Z:%.*]] = alloca i32, align 4 1350; CHECK-NEXT: br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 1351; CHECK: if.then: 1352; CHECK-NEXT: [[Y_CAST:%.*]] = bitcast i32* [[Y]] to i8* 1353; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 4, i8* [[Y_CAST]]) 1354; CHECK-NEXT: br label [[IF_END:%.*]] 1355; CHECK: if.else: 1356; CHECK-NEXT: [[Z_CAST:%.*]] = bitcast i32* [[Z]] to i8* 1357; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 4, i8* [[Z_CAST]]) 1358; CHECK-NEXT: br label [[IF_END]] 1359; CHECK: if.end: 1360; CHECK-NEXT: ret i32 1 1361; 1362entry: 1363 %y = alloca i32 1364 %z = alloca i32 1365 br i1 %flag, label %if.then, label %if.else 1366 1367if.then: 1368 %y.cast = bitcast i32* %y to i8* 1369 call void @llvm.lifetime.end.p0i8(i64 4, i8* %y.cast) 1370 br label %if.end 1371 1372if.else: 1373 %z.cast = bitcast i32* %z to i8* 1374 call void @llvm.lifetime.end.p0i8(i64 4, i8* %z.cast) 1375 br label %if.end 1376 1377if.end: 1378 ret i32 1 1379} 1380 1381define void @direct_caller(i1 %c) { 1382; CHECK-LABEL: @direct_caller( 1383; CHECK-NEXT: br i1 [[C:%.*]], label [[CALL_FOO:%.*]], label [[CALL_BAR:%.*]] 1384; CHECK: call_foo: 1385; CHECK-NEXT: call void @direct_callee() 1386; CHECK-NEXT: br label [[END:%.*]] 1387; CHECK: call_bar: 1388; CHECK-NEXT: call void @direct_callee2() 1389; CHECK-NEXT: br label [[END]] 1390; CHECK: end: 1391; CHECK-NEXT: ret void 1392; 1393 br i1 %c, label %call_foo, label %call_bar 1394 1395call_foo: 1396 call void @direct_callee() 1397 br label %end 1398 1399call_bar: 1400 call void @direct_callee2() 1401 br label %end 1402 1403end: 1404 ret void 1405} 1406 1407define void @indirect_caller(i1 %c, i32 %v, void (i32)* %foo, void (i32)* %bar) { 1408; CHECK-LABEL: @indirect_caller( 1409; CHECK-NEXT: end: 1410; CHECK-NEXT: [[FOO_BAR:%.*]] = select i1 [[C:%.*]], void (i32)* [[FOO:%.*]], void (i32)* [[BAR:%.*]] 1411; CHECK-NEXT: tail call void [[FOO_BAR]](i32 [[V:%.*]]) 1412; CHECK-NEXT: ret void 1413; 1414 br i1 %c, label %call_foo, label %call_bar 1415 1416call_foo: 1417 tail call void %foo(i32 %v) 1418 br label %end 1419 1420call_bar: 1421 tail call void %bar(i32 %v) 1422 br label %end 1423 1424end: 1425 ret void 1426} 1427 1428define void @maybe_indirect_caller(void ()* %fun) { 1429; CHECK-LABEL: @maybe_indirect_caller( 1430; CHECK-NEXT: [[C:%.*]] = icmp eq void ()* [[FUN:%.*]], @direct_callee 1431; CHECK-NEXT: br i1 [[C]], label [[IF_TRUE_DIRECT_TARG:%.*]], label [[IF_FALSE_ORIG_INDIRECT:%.*]] 1432; CHECK: if.true.direct_targ: 1433; CHECK-NEXT: tail call void @direct_callee() 1434; CHECK-NEXT: br label [[IF_END_ICP:%.*]] 1435; CHECK: if.false.orig_indirect: 1436; CHECK-NEXT: tail call void [[FUN]]() 1437; CHECK-NEXT: br label [[IF_END_ICP]] 1438; CHECK: if.end.icp: 1439; CHECK-NEXT: ret void 1440; 1441 %c = icmp eq void ()* %fun, @direct_callee 1442 br i1 %c, label %if.true.direct_targ, label %if.false.orig_indirect 1443 1444if.true.direct_targ: 1445 tail call void @direct_callee() 1446 br label %if.end.icp 1447 1448if.false.orig_indirect: 1449 tail call void %fun() 1450 br label %if.end.icp 1451 1452if.end.icp: 1453 ret void 1454} 1455define void @maybe_indirect_caller2(void ()* %fun) { 1456; CHECK-LABEL: @maybe_indirect_caller2( 1457; CHECK-NEXT: [[C:%.*]] = icmp eq void ()* [[FUN:%.*]], @direct_callee 1458; CHECK-NEXT: br i1 [[C]], label [[IF_TRUE_DIRECT_TARG:%.*]], label [[IF_FALSE_ORIG_INDIRECT:%.*]] 1459; CHECK: if.false.orig_indirect: 1460; CHECK-NEXT: tail call void [[FUN]]() 1461; CHECK-NEXT: br label [[IF_END_ICP:%.*]] 1462; CHECK: if.true.direct_targ: 1463; CHECK-NEXT: tail call void @direct_callee() 1464; CHECK-NEXT: br label [[IF_END_ICP]] 1465; CHECK: if.end.icp: 1466; CHECK-NEXT: ret void 1467; 1468 %c = icmp eq void ()* %fun, @direct_callee 1469 br i1 %c, label %if.true.direct_targ, label %if.false.orig_indirect 1470 1471if.false.orig_indirect: 1472 tail call void %fun() 1473 br label %if.end.icp 1474 1475if.true.direct_targ: 1476 tail call void @direct_callee() 1477 br label %if.end.icp 1478 1479if.end.icp: 1480 ret void 1481} 1482declare void @direct_callee() 1483declare void @direct_callee2() 1484declare void @direct_callee3() 1485 1486declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) 1487declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) 1488 1489define void @creating_too_many_phis(i1 %cond, i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h) { 1490; CHECK-LABEL: @creating_too_many_phis( 1491; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB0:%.*]], label [[BB1:%.*]] 1492; CHECK: bb0: 1493; CHECK-NEXT: [[V0:%.*]] = add i32 [[A:%.*]], [[B:%.*]] 1494; CHECK-NEXT: [[V1:%.*]] = add i32 [[V0]], [[C:%.*]] 1495; CHECK-NEXT: [[V2:%.*]] = add i32 [[D:%.*]], [[E:%.*]] 1496; CHECK-NEXT: [[R3:%.*]] = add i32 [[V1]], [[V2]] 1497; CHECK-NEXT: br label [[END:%.*]] 1498; CHECK: bb1: 1499; CHECK-NEXT: [[V4:%.*]] = add i32 [[A]], [[B]] 1500; CHECK-NEXT: [[V5:%.*]] = add i32 [[V4]], [[C]] 1501; CHECK-NEXT: [[V6:%.*]] = add i32 [[G:%.*]], [[H:%.*]] 1502; CHECK-NEXT: [[R7:%.*]] = add i32 [[V5]], [[V6]] 1503; CHECK-NEXT: br label [[END]] 1504; CHECK: end: 1505; CHECK-NEXT: [[R7_SINK:%.*]] = phi i32 [ [[R7]], [[BB1]] ], [ [[R3]], [[BB0]] ] 1506; CHECK-NEXT: call void @use32(i32 [[R7_SINK]]) 1507; CHECK-NEXT: ret void 1508; 1509 br i1 %cond, label %bb0, label %bb1 1510 1511bb0: 1512 %v0 = add i32 %a, %b 1513 %v1 = add i32 %v0, %c 1514 %v2 = add i32 %d, %e 1515 %r3 = add i32 %v1, %v2 1516 call void @use32(i32 %r3) 1517 br label %end 1518 1519bb1: 1520 %v4 = add i32 %a, %b 1521 %v5 = add i32 %v4, %c 1522 %v6 = add i32 %g, %h 1523 %r7 = add i32 %v5, %v6 1524 call void @use32(i32 %r7) 1525 br label %end 1526 1527end: 1528 ret void 1529} 1530declare void @use32(i32) 1531 1532define void @multiple_cond_preds(i1 %c0, i1 %c1, i1 %c2) { 1533; CHECK-LABEL: @multiple_cond_preds( 1534; CHECK-NEXT: dispatch0: 1535; CHECK-NEXT: br i1 [[C0:%.*]], label [[DISPATCH1:%.*]], label [[DISPATCH2:%.*]] 1536; CHECK: dispatch1: 1537; CHECK-NEXT: call void @direct_callee2() 1538; CHECK-NEXT: br i1 [[C1:%.*]], label [[END_SINK_SPLIT:%.*]], label [[END:%.*]] 1539; CHECK: dispatch2: 1540; CHECK-NEXT: call void @direct_callee3() 1541; CHECK-NEXT: br i1 [[C2:%.*]], label [[END_SINK_SPLIT]], label [[END]] 1542; CHECK: end.sink.split: 1543; CHECK-NEXT: call void @direct_callee() 1544; CHECK-NEXT: br label [[END]] 1545; CHECK: end: 1546; CHECK-NEXT: ret void 1547; 1548dispatch0: 1549 br i1 %c0, label %dispatch1, label %dispatch2 1550 1551dispatch1: 1552 call void @direct_callee2() 1553 br i1 %c1, label %uncond_pred0, label %end 1554 1555dispatch2: 1556 call void @direct_callee3() 1557 br i1 %c2, label %uncond_pred1, label %end 1558 1559uncond_pred0: 1560 call void @direct_callee() 1561 br label %end 1562 1563uncond_pred1: 1564 call void @direct_callee() 1565 br label %end 1566 1567end: 1568 ret void 1569} 1570