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