1; RUN: opt -basicaa -objc-arc -S < %s | FileCheck %s 2 3target datalayout = "e-p:64:64:64" 4 5declare i8* @objc_retain(i8*) 6declare i8* @objc_retainAutoreleasedReturnValue(i8*) 7declare void @objc_release(i8*) 8declare i8* @objc_autorelease(i8*) 9declare i8* @objc_autoreleaseReturnValue(i8*) 10declare void @objc_autoreleasePoolPop(i8*) 11declare i8* @objc_autoreleasePoolPush() 12declare i8* @objc_retainBlock(i8*) 13 14declare i8* @objc_retainedObject(i8*) 15declare i8* @objc_unretainedObject(i8*) 16declare i8* @objc_unretainedPointer(i8*) 17 18declare void @use_pointer(i8*) 19declare void @callee() 20declare void @callee_fnptr(void ()*) 21declare void @invokee() 22declare i8* @returner() 23declare void @bar(i32 ()*) 24 25declare void @llvm.dbg.value(metadata, i64, metadata) 26 27declare i8* @objc_msgSend(i8*, i8*, ...) 28 29; Simple retain+release pair deletion, with some intervening control 30; flow and harmless instructions. 31 32; CHECK: define void @test0_precise(i32* %x, i1 %p) [[NUW:#[0-9]+]] { 33; CHECK: @objc_retain 34; CHECK: @objc_release 35; CHECK: } 36define void @test0_precise(i32* %x, i1 %p) nounwind { 37entry: 38 %a = bitcast i32* %x to i8* 39 %0 = call i8* @objc_retain(i8* %a) nounwind 40 br i1 %p, label %t, label %f 41 42t: 43 store i8 3, i8* %a 44 %b = bitcast i32* %x to float* 45 store float 2.0, float* %b 46 br label %return 47 48f: 49 store i32 7, i32* %x 50 br label %return 51 52return: 53 %c = bitcast i32* %x to i8* 54 call void @objc_release(i8* %c) nounwind 55 ret void 56} 57 58; CHECK: define void @test0_imprecise(i32* %x, i1 %p) [[NUW]] { 59; CHECK-NOT: @objc_ 60; CHECK: } 61define void @test0_imprecise(i32* %x, i1 %p) nounwind { 62entry: 63 %a = bitcast i32* %x to i8* 64 %0 = call i8* @objc_retain(i8* %a) nounwind 65 br i1 %p, label %t, label %f 66 67t: 68 store i8 3, i8* %a 69 %b = bitcast i32* %x to float* 70 store float 2.0, float* %b 71 br label %return 72 73f: 74 store i32 7, i32* %x 75 br label %return 76 77return: 78 %c = bitcast i32* %x to i8* 79 call void @objc_release(i8* %c) nounwind, !clang.imprecise_release !0 80 ret void 81} 82 83; Like test0 but the release isn't always executed when the retain is, 84; so the optimization is not safe. 85 86; TODO: Make the objc_release's argument be %0. 87 88; CHECK: define void @test1_precise(i32* %x, i1 %p, i1 %q) [[NUW]] { 89; CHECK: @objc_retain(i8* %a) 90; CHECK: @objc_release 91; CHECK: } 92define void @test1_precise(i32* %x, i1 %p, i1 %q) nounwind { 93entry: 94 %a = bitcast i32* %x to i8* 95 %0 = call i8* @objc_retain(i8* %a) nounwind 96 br i1 %p, label %t, label %f 97 98t: 99 store i8 3, i8* %a 100 %b = bitcast i32* %x to float* 101 store float 2.0, float* %b 102 br label %return 103 104f: 105 store i32 7, i32* %x 106 call void @callee() 107 br i1 %q, label %return, label %alt_return 108 109return: 110 %c = bitcast i32* %x to i8* 111 call void @objc_release(i8* %c) nounwind 112 ret void 113 114alt_return: 115 ret void 116} 117 118; CHECK: define void @test1_imprecise(i32* %x, i1 %p, i1 %q) [[NUW]] { 119; CHECK: @objc_retain(i8* %a) 120; CHECK: @objc_release 121; CHECK: } 122define void @test1_imprecise(i32* %x, i1 %p, i1 %q) nounwind { 123entry: 124 %a = bitcast i32* %x to i8* 125 %0 = call i8* @objc_retain(i8* %a) nounwind 126 br i1 %p, label %t, label %f 127 128t: 129 store i8 3, i8* %a 130 %b = bitcast i32* %x to float* 131 store float 2.0, float* %b 132 br label %return 133 134f: 135 store i32 7, i32* %x 136 call void @callee() 137 br i1 %q, label %return, label %alt_return 138 139return: 140 %c = bitcast i32* %x to i8* 141 call void @objc_release(i8* %c) nounwind, !clang.imprecise_release !0 142 ret void 143 144alt_return: 145 ret void 146} 147 148 149; Don't do partial elimination into two different CFG diamonds. 150 151; CHECK: define void @test1b_precise(i8* %x, i1 %p, i1 %q) { 152; CHECK: entry: 153; CHECK: tail call i8* @objc_retain(i8* %x) [[NUW]] 154; CHECK-NOT: @objc_ 155; CHECK: if.end5: 156; CHECK: tail call void @objc_release(i8* %x) [[NUW]] 157; CHECK-NOT: @objc_ 158; CHECK: } 159define void @test1b_precise(i8* %x, i1 %p, i1 %q) { 160entry: 161 tail call i8* @objc_retain(i8* %x) nounwind 162 br i1 %p, label %if.then, label %if.end 163 164if.then: ; preds = %entry 165 tail call void @callee() 166 br label %if.end 167 168if.end: ; preds = %if.then, %entry 169 br i1 %q, label %if.then3, label %if.end5 170 171if.then3: ; preds = %if.end 172 tail call void @use_pointer(i8* %x) 173 br label %if.end5 174 175if.end5: ; preds = %if.then3, %if.end 176 tail call void @objc_release(i8* %x) nounwind 177 ret void 178} 179 180; CHECK-LABEL: define void @test1b_imprecise( 181; CHECK: entry: 182; CHECK: tail call i8* @objc_retain(i8* %x) [[NUW:#[0-9]+]] 183; CHECK-NOT: @objc_ 184; CHECK: if.end5: 185; CHECK: tail call void @objc_release(i8* %x) [[NUW]], !clang.imprecise_release ![[RELEASE:[0-9]+]] 186; CHECK-NOT: @objc_ 187; CHECK: } 188define void @test1b_imprecise(i8* %x, i1 %p, i1 %q) { 189entry: 190 tail call i8* @objc_retain(i8* %x) nounwind 191 br i1 %p, label %if.then, label %if.end 192 193if.then: ; preds = %entry 194 tail call void @callee() 195 br label %if.end 196 197if.end: ; preds = %if.then, %entry 198 br i1 %q, label %if.then3, label %if.end5 199 200if.then3: ; preds = %if.end 201 tail call void @use_pointer(i8* %x) 202 br label %if.end5 203 204if.end5: ; preds = %if.then3, %if.end 205 tail call void @objc_release(i8* %x) nounwind, !clang.imprecise_release !0 206 ret void 207} 208 209 210; Like test0 but the pointer is passed to an intervening call, 211; so the optimization is not safe. 212 213; CHECK-LABEL: define void @test2_precise( 214; CHECK: @objc_retain(i8* %a) 215; CHECK: @objc_release 216; CHECK: } 217define void @test2_precise(i32* %x, i1 %p) nounwind { 218entry: 219 %a = bitcast i32* %x to i8* 220 %0 = call i8* @objc_retain(i8* %a) nounwind 221 br i1 %p, label %t, label %f 222 223t: 224 store i8 3, i8* %a 225 %b = bitcast i32* %x to float* 226 store float 2.0, float* %b 227 br label %return 228 229f: 230 store i32 7, i32* %x 231 call void @use_pointer(i8* %0) 232 %d = bitcast i32* %x to float* 233 store float 3.0, float* %d 234 br label %return 235 236return: 237 %c = bitcast i32* %x to i8* 238 call void @objc_release(i8* %c) nounwind 239 ret void 240} 241 242; CHECK-LABEL: define void @test2_imprecise( 243; CHECK: @objc_retain(i8* %a) 244; CHECK: @objc_release 245; CHECK: } 246define void @test2_imprecise(i32* %x, i1 %p) nounwind { 247entry: 248 %a = bitcast i32* %x to i8* 249 %0 = call i8* @objc_retain(i8* %a) nounwind 250 br i1 %p, label %t, label %f 251 252t: 253 store i8 3, i8* %a 254 %b = bitcast i32* %x to float* 255 store float 2.0, float* %b 256 br label %return 257 258f: 259 store i32 7, i32* %x 260 call void @use_pointer(i8* %0) 261 %d = bitcast i32* %x to float* 262 store float 3.0, float* %d 263 br label %return 264 265return: 266 %c = bitcast i32* %x to i8* 267 call void @objc_release(i8* %c) nounwind, !clang.imprecise_release !0 268 ret void 269} 270 271; Like test0 but the release is in a loop, 272; so the optimization is not safe. 273 274; TODO: For now, assume this can't happen. 275 276; CHECK-LABEL: define void @test3_precise( 277; TODO: @objc_retain(i8* %a) 278; TODO: @objc_release 279; CHECK: } 280define void @test3_precise(i32* %x, i1* %q) nounwind { 281entry: 282 %a = bitcast i32* %x to i8* 283 %0 = call i8* @objc_retain(i8* %a) nounwind 284 br label %loop 285 286loop: 287 %c = bitcast i32* %x to i8* 288 call void @objc_release(i8* %c) nounwind 289 %j = load volatile i1* %q 290 br i1 %j, label %loop, label %return 291 292return: 293 ret void 294} 295 296; CHECK-LABEL: define void @test3_imprecise( 297; TODO: @objc_retain(i8* %a) 298; TODO: @objc_release 299; CHECK: } 300define void @test3_imprecise(i32* %x, i1* %q) nounwind { 301entry: 302 %a = bitcast i32* %x to i8* 303 %0 = call i8* @objc_retain(i8* %a) nounwind 304 br label %loop 305 306loop: 307 %c = bitcast i32* %x to i8* 308 call void @objc_release(i8* %c) nounwind, !clang.imprecise_release !0 309 %j = load volatile i1* %q 310 br i1 %j, label %loop, label %return 311 312return: 313 ret void 314} 315 316 317; TODO: For now, assume this can't happen. 318 319; Like test0 but the retain is in a loop, 320; so the optimization is not safe. 321 322; CHECK-LABEL: define void @test4_precise( 323; TODO: @objc_retain(i8* %a) 324; TODO: @objc_release 325; CHECK: } 326define void @test4_precise(i32* %x, i1* %q) nounwind { 327entry: 328 br label %loop 329 330loop: 331 %a = bitcast i32* %x to i8* 332 %0 = call i8* @objc_retain(i8* %a) nounwind 333 %j = load volatile i1* %q 334 br i1 %j, label %loop, label %return 335 336return: 337 %c = bitcast i32* %x to i8* 338 call void @objc_release(i8* %c) nounwind 339 ret void 340} 341 342; CHECK-LABEL: define void @test4_imprecise( 343; TODO: @objc_retain(i8* %a) 344; TODO: @objc_release 345; CHECK: } 346define void @test4_imprecise(i32* %x, i1* %q) nounwind { 347entry: 348 br label %loop 349 350loop: 351 %a = bitcast i32* %x to i8* 352 %0 = call i8* @objc_retain(i8* %a) nounwind 353 %j = load volatile i1* %q 354 br i1 %j, label %loop, label %return 355 356return: 357 %c = bitcast i32* %x to i8* 358 call void @objc_release(i8* %c) nounwind, !clang.imprecise_release !0 359 ret void 360} 361 362 363; Like test0 but the pointer is conditionally passed to an intervening call, 364; so the optimization is not safe. 365 366; CHECK-LABEL: define void @test5a( 367; CHECK: @objc_retain(i8* 368; CHECK: @objc_release 369; CHECK: } 370define void @test5a(i32* %x, i1 %q, i8* %y) nounwind { 371entry: 372 %a = bitcast i32* %x to i8* 373 %0 = call i8* @objc_retain(i8* %a) nounwind 374 %s = select i1 %q, i8* %y, i8* %0 375 call void @use_pointer(i8* %s) 376 store i32 7, i32* %x 377 %c = bitcast i32* %x to i8* 378 call void @objc_release(i8* %c) nounwind 379 ret void 380} 381 382; CHECK-LABEL: define void @test5b( 383; CHECK: @objc_retain(i8* 384; CHECK: @objc_release 385; CHECK: } 386define void @test5b(i32* %x, i1 %q, i8* %y) nounwind { 387entry: 388 %a = bitcast i32* %x to i8* 389 %0 = call i8* @objc_retain(i8* %a) nounwind 390 %s = select i1 %q, i8* %y, i8* %0 391 call void @use_pointer(i8* %s) 392 store i32 7, i32* %x 393 %c = bitcast i32* %x to i8* 394 call void @objc_release(i8* %c) nounwind, !clang.imprecise_release !0 395 ret void 396} 397 398 399; retain+release pair deletion, where the release happens on two different 400; flow paths. 401 402; CHECK-LABEL: define void @test6a( 403; CHECK: entry: 404; CHECK: tail call i8* @objc_retain( 405; CHECK: t: 406; CHECK: call void @objc_release( 407; CHECK: f: 408; CHECK: call void @objc_release( 409; CHECK: return: 410; CHECK: } 411define void @test6a(i32* %x, i1 %p) nounwind { 412entry: 413 %a = bitcast i32* %x to i8* 414 %0 = call i8* @objc_retain(i8* %a) nounwind 415 br i1 %p, label %t, label %f 416 417t: 418 store i8 3, i8* %a 419 %b = bitcast i32* %x to float* 420 store float 2.0, float* %b 421 %ct = bitcast i32* %x to i8* 422 call void @objc_release(i8* %ct) nounwind 423 br label %return 424 425f: 426 store i32 7, i32* %x 427 call void @callee() 428 %cf = bitcast i32* %x to i8* 429 call void @objc_release(i8* %cf) nounwind 430 br label %return 431 432return: 433 ret void 434} 435 436; CHECK-LABEL: define void @test6b( 437; CHECK-NOT: @objc_ 438; CHECK: } 439define void @test6b(i32* %x, i1 %p) nounwind { 440entry: 441 %a = bitcast i32* %x to i8* 442 %0 = call i8* @objc_retain(i8* %a) nounwind 443 br i1 %p, label %t, label %f 444 445t: 446 store i8 3, i8* %a 447 %b = bitcast i32* %x to float* 448 store float 2.0, float* %b 449 %ct = bitcast i32* %x to i8* 450 call void @objc_release(i8* %ct) nounwind, !clang.imprecise_release !0 451 br label %return 452 453f: 454 store i32 7, i32* %x 455 call void @callee() 456 %cf = bitcast i32* %x to i8* 457 call void @objc_release(i8* %cf) nounwind, !clang.imprecise_release !0 458 br label %return 459 460return: 461 ret void 462} 463 464; CHECK-LABEL: define void @test6c( 465; CHECK: entry: 466; CHECK: tail call i8* @objc_retain( 467; CHECK: t: 468; CHECK: call void @objc_release( 469; CHECK: f: 470; CHECK: call void @objc_release( 471; CHECK: return: 472; CHECK: } 473define void @test6c(i32* %x, i1 %p) nounwind { 474entry: 475 %a = bitcast i32* %x to i8* 476 %0 = call i8* @objc_retain(i8* %a) nounwind 477 br i1 %p, label %t, label %f 478 479t: 480 store i8 3, i8* %a 481 %b = bitcast i32* %x to float* 482 store float 2.0, float* %b 483 %ct = bitcast i32* %x to i8* 484 call void @objc_release(i8* %ct) nounwind 485 br label %return 486 487f: 488 store i32 7, i32* %x 489 call void @callee() 490 %cf = bitcast i32* %x to i8* 491 call void @objc_release(i8* %cf) nounwind, !clang.imprecise_release !0 492 br label %return 493 494return: 495 ret void 496} 497 498; CHECK-LABEL: define void @test6d( 499; CHECK: entry: 500; CHECK: tail call i8* @objc_retain( 501; CHECK: t: 502; CHECK: call void @objc_release( 503; CHECK: f: 504; CHECK: call void @objc_release( 505; CHECK: return: 506; CHECK: } 507define void @test6d(i32* %x, i1 %p) nounwind { 508entry: 509 %a = bitcast i32* %x to i8* 510 %0 = call i8* @objc_retain(i8* %a) nounwind 511 br i1 %p, label %t, label %f 512 513t: 514 store i8 3, i8* %a 515 %b = bitcast i32* %x to float* 516 store float 2.0, float* %b 517 %ct = bitcast i32* %x to i8* 518 call void @objc_release(i8* %ct) nounwind, !clang.imprecise_release !0 519 br label %return 520 521f: 522 store i32 7, i32* %x 523 call void @callee() 524 %cf = bitcast i32* %x to i8* 525 call void @objc_release(i8* %cf) nounwind 526 br label %return 527 528return: 529 ret void 530} 531 532 533; retain+release pair deletion, where the retain happens on two different 534; flow paths. 535 536; CHECK-LABEL: define void @test7( 537; CHECK: entry: 538; CHECK-NOT: objc_ 539; CHECK: t: 540; CHECK: call i8* @objc_retain 541; CHECK: f: 542; CHECK: call i8* @objc_retain 543; CHECK: return: 544; CHECK: call void @objc_release 545; CHECK: } 546define void @test7(i32* %x, i1 %p) nounwind { 547entry: 548 %a = bitcast i32* %x to i8* 549 br i1 %p, label %t, label %f 550 551t: 552 %0 = call i8* @objc_retain(i8* %a) nounwind 553 store i8 3, i8* %a 554 %b = bitcast i32* %x to float* 555 store float 2.0, float* %b 556 br label %return 557 558f: 559 %1 = call i8* @objc_retain(i8* %a) nounwind 560 store i32 7, i32* %x 561 call void @callee() 562 br label %return 563 564return: 565 %c = bitcast i32* %x to i8* 566 call void @objc_release(i8* %c) nounwind 567 ret void 568} 569 570; CHECK-LABEL: define void @test7b( 571; CHECK-NOT: @objc_ 572; CHECK: } 573define void @test7b(i32* %x, i1 %p) nounwind { 574entry: 575 %a = bitcast i32* %x to i8* 576 br i1 %p, label %t, label %f 577 578t: 579 %0 = call i8* @objc_retain(i8* %a) nounwind 580 store i8 3, i8* %a 581 %b = bitcast i32* %x to float* 582 store float 2.0, float* %b 583 br label %return 584 585f: 586 %1 = call i8* @objc_retain(i8* %a) nounwind 587 store i32 7, i32* %x 588 call void @callee() 589 br label %return 590 591return: 592 %c = bitcast i32* %x to i8* 593 call void @objc_release(i8* %c) nounwind, !clang.imprecise_release !0 594 ret void 595} 596 597; Like test7, but there's a retain/retainBlock mismatch. Don't delete! 598 599; CHECK-LABEL: define void @test7c( 600; CHECK: t: 601; CHECK: call i8* @objc_retainBlock 602; CHECK: f: 603; CHECK: call i8* @objc_retain 604; CHECK: return: 605; CHECK: call void @objc_release 606; CHECK: } 607define void @test7c(i32* %x, i1 %p) nounwind { 608entry: 609 %a = bitcast i32* %x to i8* 610 br i1 %p, label %t, label %f 611 612t: 613 %0 = call i8* @objc_retainBlock(i8* %a) nounwind 614 store i8 3, i8* %a 615 %b = bitcast i32* %x to float* 616 store float 2.0, float* %b 617 br label %return 618 619f: 620 %1 = call i8* @objc_retain(i8* %a) nounwind 621 store i32 7, i32* %x 622 call void @callee() 623 br label %return 624 625return: 626 %c = bitcast i32* %x to i8* 627 call void @objc_release(i8* %c) nounwind 628 ret void 629} 630 631; retain+release pair deletion, where the retain and release both happen on 632; different flow paths. Wild! 633 634; CHECK-LABEL: define void @test8a( 635; CHECK: entry: 636; CHECK: t: 637; CHECK: @objc_retain 638; CHECK: f: 639; CHECK: @objc_retain 640; CHECK: mid: 641; CHECK: u: 642; CHECK: @objc_release 643; CHECK: g: 644; CHECK: @objc_release 645; CHECK: return: 646; CHECK: } 647define void @test8a(i32* %x, i1 %p, i1 %q) nounwind { 648entry: 649 %a = bitcast i32* %x to i8* 650 br i1 %p, label %t, label %f 651 652t: 653 %0 = call i8* @objc_retain(i8* %a) nounwind 654 store i8 3, i8* %a 655 %b = bitcast i32* %x to float* 656 store float 2.0, float* %b 657 br label %mid 658 659f: 660 %1 = call i8* @objc_retain(i8* %a) nounwind 661 store i32 7, i32* %x 662 br label %mid 663 664mid: 665 br i1 %q, label %u, label %g 666 667u: 668 call void @callee() 669 %cu = bitcast i32* %x to i8* 670 call void @objc_release(i8* %cu) nounwind 671 br label %return 672 673g: 674 %cg = bitcast i32* %x to i8* 675 call void @objc_release(i8* %cg) nounwind 676 br label %return 677 678return: 679 ret void 680} 681 682; CHECK-LABEL: define void @test8b( 683; CHECK-NOT: @objc_ 684; CHECK: } 685define void @test8b(i32* %x, i1 %p, i1 %q) nounwind { 686entry: 687 %a = bitcast i32* %x to i8* 688 br i1 %p, label %t, label %f 689 690t: 691 %0 = call i8* @objc_retain(i8* %a) nounwind 692 store i8 3, i8* %a 693 %b = bitcast i32* %x to float* 694 store float 2.0, float* %b 695 br label %mid 696 697f: 698 %1 = call i8* @objc_retain(i8* %a) nounwind 699 store i32 7, i32* %x 700 br label %mid 701 702mid: 703 br i1 %q, label %u, label %g 704 705u: 706 call void @callee() 707 %cu = bitcast i32* %x to i8* 708 call void @objc_release(i8* %cu) nounwind, !clang.imprecise_release !0 709 br label %return 710 711g: 712 %cg = bitcast i32* %x to i8* 713 call void @objc_release(i8* %cg) nounwind, !clang.imprecise_release !0 714 br label %return 715 716return: 717 ret void 718} 719 720; CHECK-LABEL: define void @test8c( 721; CHECK: entry: 722; CHECK: t: 723; CHECK: @objc_retain 724; CHECK: f: 725; CHECK: @objc_retain 726; CHECK: mid: 727; CHECK: u: 728; CHECK: @objc_release 729; CHECK: g: 730; CHECK: @objc_release 731; CHECK: return: 732; CHECK: } 733define void @test8c(i32* %x, i1 %p, i1 %q) nounwind { 734entry: 735 %a = bitcast i32* %x to i8* 736 br i1 %p, label %t, label %f 737 738t: 739 %0 = call i8* @objc_retain(i8* %a) nounwind 740 store i8 3, i8* %a 741 %b = bitcast i32* %x to float* 742 store float 2.0, float* %b 743 br label %mid 744 745f: 746 %1 = call i8* @objc_retain(i8* %a) nounwind 747 store i32 7, i32* %x 748 br label %mid 749 750mid: 751 br i1 %q, label %u, label %g 752 753u: 754 call void @callee() 755 %cu = bitcast i32* %x to i8* 756 call void @objc_release(i8* %cu) nounwind 757 br label %return 758 759g: 760 %cg = bitcast i32* %x to i8* 761 call void @objc_release(i8* %cg) nounwind, !clang.imprecise_release !0 762 br label %return 763 764return: 765 ret void 766} 767 768; CHECK-LABEL: define void @test8d( 769; CHECK: entry: 770; CHECK: t: 771; CHECK: @objc_retain 772; CHECK: f: 773; CHECK: @objc_retain 774; CHECK: mid: 775; CHECK: u: 776; CHECK: @objc_release 777; CHECK: g: 778; CHECK: @objc_release 779; CHECK: return: 780; CHECK: } 781define void @test8d(i32* %x, i1 %p, i1 %q) nounwind { 782entry: 783 %a = bitcast i32* %x to i8* 784 br i1 %p, label %t, label %f 785 786t: 787 %0 = call i8* @objc_retain(i8* %a) nounwind 788 store i8 3, i8* %a 789 %b = bitcast i32* %x to float* 790 store float 2.0, float* %b 791 br label %mid 792 793f: 794 %1 = call i8* @objc_retain(i8* %a) nounwind 795 store i32 7, i32* %x 796 br label %mid 797 798mid: 799 br i1 %q, label %u, label %g 800 801u: 802 call void @callee() 803 %cu = bitcast i32* %x to i8* 804 call void @objc_release(i8* %cu) nounwind, !clang.imprecise_release !0 805 br label %return 806 807g: 808 %cg = bitcast i32* %x to i8* 809 call void @objc_release(i8* %cg) nounwind 810 br label %return 811 812return: 813 ret void 814} 815 816; Trivial retain+release pair deletion. 817 818; CHECK-LABEL: define void @test9( 819; CHECK-NOT: @objc_ 820; CHECK: } 821define void @test9(i8* %x) nounwind { 822entry: 823 %0 = call i8* @objc_retain(i8* %x) nounwind 824 call void @objc_release(i8* %0) nounwind 825 ret void 826} 827 828; Retain+release pair, but on an unknown pointer relationship. Don't delete! 829 830; CHECK-LABEL: define void @test9b( 831; CHECK: @objc_retain(i8* %x) 832; CHECK: @objc_release(i8* %s) 833; CHECK: } 834define void @test9b(i8* %x, i1 %j, i8* %p) nounwind { 835entry: 836 %0 = call i8* @objc_retain(i8* %x) nounwind 837 %s = select i1 %j, i8* %x, i8* %p 838 call void @objc_release(i8* %s) nounwind 839 ret void 840} 841 842; Trivial retain+release pair with intervening calls - don't delete! 843 844; CHECK-LABEL: define void @test10( 845; CHECK: @objc_retain(i8* %x) 846; CHECK: @callee 847; CHECK: @use_pointer 848; CHECK: @objc_release 849; CHECK: } 850define void @test10(i8* %x) nounwind { 851entry: 852 %0 = call i8* @objc_retain(i8* %x) nounwind 853 call void @callee() 854 call void @use_pointer(i8* %x) 855 call void @objc_release(i8* %0) nounwind 856 ret void 857} 858 859; Trivial retain+autoreleaserelease pair. Don't delete! 860; Also, add a tail keyword, since objc_retain can never be passed 861; a stack argument. 862 863; CHECK-LABEL: define void @test11( 864; CHECK: tail call i8* @objc_retain(i8* %x) [[NUW]] 865; CHECK: call i8* @objc_autorelease(i8* %0) [[NUW]] 866; CHECK: } 867define void @test11(i8* %x) nounwind { 868entry: 869 %0 = call i8* @objc_retain(i8* %x) nounwind 870 call i8* @objc_autorelease(i8* %0) nounwind 871 call void @use_pointer(i8* %x) 872 ret void 873} 874 875; Same as test11 but with no use_pointer call. Delete the pair! 876 877; CHECK-LABEL: define void @test11a( 878; CHECK: entry: 879; CHECK-NEXT: ret void 880; CHECK: } 881define void @test11a(i8* %x) nounwind { 882entry: 883 %0 = call i8* @objc_retain(i8* %x) nounwind 884 call i8* @objc_autorelease(i8* %0) nounwind 885 ret void 886} 887 888; Same as test11 but the value is returned. Do not perform an RV optimization 889; since if the frontend emitted code for an __autoreleasing variable, we may 890; want it to be in the autorelease pool. 891 892; CHECK-LABEL: define i8* @test11b( 893; CHECK: tail call i8* @objc_retain(i8* %x) [[NUW]] 894; CHECK: call i8* @objc_autorelease(i8* %0) [[NUW]] 895; CHECK: } 896define i8* @test11b(i8* %x) nounwind { 897entry: 898 %0 = call i8* @objc_retain(i8* %x) nounwind 899 call i8* @objc_autorelease(i8* %0) nounwind 900 ret i8* %x 901} 902 903; Trivial retain,release pair with intervening call, but it's dominated 904; by another retain - delete! 905 906; CHECK-LABEL: define void @test12( 907; CHECK-NEXT: entry: 908; CHECK-NEXT: @objc_retain(i8* %x) 909; CHECK-NOT: @objc_ 910; CHECK: } 911define void @test12(i8* %x, i64 %n) { 912entry: 913 call i8* @objc_retain(i8* %x) nounwind 914 call i8* @objc_retain(i8* %x) nounwind 915 call void @use_pointer(i8* %x) 916 call void @use_pointer(i8* %x) 917 call void @objc_release(i8* %x) nounwind 918 ret void 919} 920 921; Trivial retain,autorelease pair. Don't delete! 922 923; CHECK-LABEL: define void @test13( 924; CHECK: tail call i8* @objc_retain(i8* %x) [[NUW]] 925; CHECK: tail call i8* @objc_retain(i8* %x) [[NUW]] 926; CHECK: @use_pointer(i8* %x) 927; CHECK: call i8* @objc_autorelease(i8* %x) [[NUW]] 928; CHECK: } 929define void @test13(i8* %x, i64 %n) { 930entry: 931 call i8* @objc_retain(i8* %x) nounwind 932 call i8* @objc_retain(i8* %x) nounwind 933 call void @use_pointer(i8* %x) 934 call i8* @objc_autorelease(i8* %x) nounwind 935 ret void 936} 937 938; Delete the retain+release pair. 939 940; CHECK-LABEL: define void @test13b( 941; CHECK-NEXT: entry: 942; CHECK-NEXT: @objc_retain(i8* %x) 943; CHECK-NEXT: @use_pointer 944; CHECK-NEXT: @use_pointer 945; CHECK-NEXT: ret void 946; CHECK-NEXT: } 947define void @test13b(i8* %x, i64 %n) { 948entry: 949 call i8* @objc_retain(i8* %x) nounwind 950 call i8* @objc_retain(i8* %x) nounwind 951 call void @use_pointer(i8* %x) 952 call void @use_pointer(i8* %x) 953 call void @objc_release(i8* %x) nounwind 954 ret void 955} 956 957; Don't delete the retain+release pair because there's an 958; autoreleasePoolPop in the way. 959 960; CHECK-LABEL: define void @test13c( 961; CHECK: @objc_retain(i8* %x) 962; CHECK: @objc_autoreleasePoolPop 963; CHECK: @objc_retain(i8* %x) 964; CHECK: @use_pointer 965; CHECK: @objc_release 966; CHECK: } 967define void @test13c(i8* %x, i64 %n) { 968entry: 969 call i8* @objc_retain(i8* %x) nounwind 970 call void @objc_autoreleasePoolPop(i8* undef) 971 call i8* @objc_retain(i8* %x) nounwind 972 call void @use_pointer(i8* %x) 973 call void @use_pointer(i8* %x) 974 call void @objc_release(i8* %x) nounwind 975 ret void 976} 977 978; Like test13c, but there's an autoreleasePoolPush in the way, but that 979; doesn't matter. 980 981; CHECK-LABEL: define void @test13d( 982; CHECK-NEXT: entry: 983; CHECK-NEXT: @objc_retain(i8* %x) 984; CHECK-NEXT: @objc_autoreleasePoolPush 985; CHECK-NEXT: @use_pointer 986; CHECK-NEXT: @use_pointer 987; CHECK-NEXT: ret void 988; CHECK-NEXT: } 989define void @test13d(i8* %x, i64 %n) { 990entry: 991 call i8* @objc_retain(i8* %x) nounwind 992 call i8* @objc_autoreleasePoolPush() 993 call i8* @objc_retain(i8* %x) nounwind 994 call void @use_pointer(i8* %x) 995 call void @use_pointer(i8* %x) 996 call void @objc_release(i8* %x) nounwind 997 ret void 998} 999 1000; Trivial retain,release pair with intervening call, but it's post-dominated 1001; by another release - delete! 1002 1003; CHECK-LABEL: define void @test14( 1004; CHECK-NEXT: entry: 1005; CHECK-NEXT: @use_pointer 1006; CHECK-NEXT: @use_pointer 1007; CHECK-NEXT: @objc_release 1008; CHECK-NEXT: ret void 1009; CHECK-NEXT: } 1010define void @test14(i8* %x, i64 %n) { 1011entry: 1012 call i8* @objc_retain(i8* %x) nounwind 1013 call void @use_pointer(i8* %x) 1014 call void @use_pointer(i8* %x) 1015 call void @objc_release(i8* %x) nounwind 1016 call void @objc_release(i8* %x) nounwind 1017 ret void 1018} 1019 1020; Trivial retain,autorelease pair with intervening call, but it's post-dominated 1021; by another release. Don't delete anything. 1022 1023; CHECK-LABEL: define void @test15( 1024; CHECK-NEXT: entry: 1025; CHECK-NEXT: @objc_retain(i8* %x) 1026; CHECK-NEXT: @use_pointer 1027; CHECK-NEXT: @objc_autorelease(i8* %x) 1028; CHECK-NEXT: @objc_release 1029; CHECK-NEXT: ret void 1030; CHECK-NEXT: } 1031define void @test15(i8* %x, i64 %n) { 1032entry: 1033 call i8* @objc_retain(i8* %x) nounwind 1034 call void @use_pointer(i8* %x) 1035 call i8* @objc_autorelease(i8* %x) nounwind 1036 call void @objc_release(i8* %x) nounwind 1037 ret void 1038} 1039 1040; Trivial retain,autorelease pair, post-dominated 1041; by another release. Delete the retain and release. 1042 1043; CHECK-LABEL: define void @test15b( 1044; CHECK-NEXT: entry: 1045; CHECK-NEXT: @objc_retain 1046; CHECK-NEXT: @objc_autorelease 1047; CHECK-NEXT: @objc_release 1048; CHECK-NEXT: ret void 1049; CHECK-NEXT: } 1050define void @test15b(i8* %x, i64 %n) { 1051entry: 1052 call i8* @objc_retain(i8* %x) nounwind 1053 call i8* @objc_autorelease(i8* %x) nounwind 1054 call void @objc_release(i8* %x) nounwind 1055 ret void 1056} 1057 1058; CHECK-LABEL: define void @test15c( 1059; CHECK-NEXT: entry: 1060; CHECK-NEXT: @objc_autorelease 1061; CHECK-NEXT: ret void 1062; CHECK-NEXT: } 1063define void @test15c(i8* %x, i64 %n) { 1064entry: 1065 call i8* @objc_retain(i8* %x) nounwind 1066 call i8* @objc_autorelease(i8* %x) nounwind 1067 call void @objc_release(i8* %x) nounwind, !clang.imprecise_release !0 1068 ret void 1069} 1070 1071; Retain+release pairs in diamonds, all dominated by a retain. 1072 1073; CHECK-LABEL: define void @test16a( 1074; CHECK: @objc_retain(i8* %x) 1075; CHECK-NOT: @objc 1076; CHECK: } 1077define void @test16a(i1 %a, i1 %b, i8* %x) { 1078entry: 1079 call i8* @objc_retain(i8* %x) nounwind 1080 br i1 %a, label %red, label %orange 1081 1082red: 1083 call i8* @objc_retain(i8* %x) nounwind 1084 br label %yellow 1085 1086orange: 1087 call i8* @objc_retain(i8* %x) nounwind 1088 br label %yellow 1089 1090yellow: 1091 call void @use_pointer(i8* %x) 1092 call void @use_pointer(i8* %x) 1093 br i1 %b, label %green, label %blue 1094 1095green: 1096 call void @objc_release(i8* %x) nounwind 1097 br label %purple 1098 1099blue: 1100 call void @objc_release(i8* %x) nounwind 1101 br label %purple 1102 1103purple: 1104 ret void 1105} 1106 1107; CHECK-LABEL: define void @test16b( 1108; CHECK: @objc_retain(i8* %x) 1109; CHECK-NOT: @objc 1110; CHECK: } 1111define void @test16b(i1 %a, i1 %b, i8* %x) { 1112entry: 1113 call i8* @objc_retain(i8* %x) nounwind 1114 br i1 %a, label %red, label %orange 1115 1116red: 1117 call i8* @objc_retain(i8* %x) nounwind 1118 br label %yellow 1119 1120orange: 1121 call i8* @objc_retain(i8* %x) nounwind 1122 br label %yellow 1123 1124yellow: 1125 call void @use_pointer(i8* %x) 1126 call void @use_pointer(i8* %x) 1127 br i1 %b, label %green, label %blue 1128 1129green: 1130 call void @objc_release(i8* %x) nounwind, !clang.imprecise_release !0 1131 br label %purple 1132 1133blue: 1134 call void @objc_release(i8* %x) nounwind 1135 br label %purple 1136 1137purple: 1138 ret void 1139} 1140 1141; CHECK-LABEL: define void @test16c( 1142; CHECK: @objc_retain(i8* %x) 1143; CHECK-NOT: @objc 1144; CHECK: } 1145define void @test16c(i1 %a, i1 %b, i8* %x) { 1146entry: 1147 call i8* @objc_retain(i8* %x) nounwind 1148 br i1 %a, label %red, label %orange 1149 1150red: 1151 call i8* @objc_retain(i8* %x) nounwind 1152 br label %yellow 1153 1154orange: 1155 call i8* @objc_retain(i8* %x) nounwind 1156 br label %yellow 1157 1158yellow: 1159 call void @use_pointer(i8* %x) 1160 call void @use_pointer(i8* %x) 1161 br i1 %b, label %green, label %blue 1162 1163green: 1164 call void @objc_release(i8* %x) nounwind, !clang.imprecise_release !0 1165 br label %purple 1166 1167blue: 1168 call void @objc_release(i8* %x) nounwind, !clang.imprecise_release !0 1169 br label %purple 1170 1171purple: 1172 ret void 1173} 1174 1175; CHECK-LABEL: define void @test16d( 1176; CHECK: @objc_retain(i8* %x) 1177; CHECK-NOT: @objc 1178; CHECK: } 1179define void @test16d(i1 %a, i1 %b, i8* %x) { 1180entry: 1181 call i8* @objc_retain(i8* %x) nounwind 1182 br i1 %a, label %red, label %orange 1183 1184red: 1185 call i8* @objc_retain(i8* %x) nounwind 1186 br label %yellow 1187 1188orange: 1189 call i8* @objc_retain(i8* %x) nounwind 1190 br label %yellow 1191 1192yellow: 1193 call void @use_pointer(i8* %x) 1194 call void @use_pointer(i8* %x) 1195 br i1 %b, label %green, label %blue 1196 1197green: 1198 call void @objc_release(i8* %x) nounwind 1199 br label %purple 1200 1201blue: 1202 call void @objc_release(i8* %x) nounwind, !clang.imprecise_release !0 1203 br label %purple 1204 1205purple: 1206 ret void 1207} 1208 1209 1210; Retain+release pairs in diamonds, all post-dominated by a release. 1211 1212; CHECK-LABEL: define void @test17( 1213; CHECK-NOT: @objc_ 1214; CHECK: purple: 1215; CHECK: @objc_release 1216; CHECK: } 1217define void @test17(i1 %a, i1 %b, i8* %x) { 1218entry: 1219 br i1 %a, label %red, label %orange 1220 1221red: 1222 call i8* @objc_retain(i8* %x) nounwind 1223 br label %yellow 1224 1225orange: 1226 call i8* @objc_retain(i8* %x) nounwind 1227 br label %yellow 1228 1229yellow: 1230 call void @use_pointer(i8* %x) 1231 call void @use_pointer(i8* %x) 1232 br i1 %b, label %green, label %blue 1233 1234green: 1235 call void @objc_release(i8* %x) nounwind 1236 br label %purple 1237 1238blue: 1239 call void @objc_release(i8* %x) nounwind 1240 br label %purple 1241 1242purple: 1243 call void @objc_release(i8* %x) nounwind 1244 ret void 1245} 1246 1247; Delete no-ops. 1248 1249; CHECK-LABEL: define void @test18( 1250; CHECK-NOT: @objc_ 1251; CHECK: } 1252define void @test18() { 1253 call i8* @objc_retain(i8* null) 1254 call void @objc_release(i8* null) 1255 call i8* @objc_autorelease(i8* null) 1256 ret void 1257} 1258 1259; Delete no-ops where undef can be assumed to be null. 1260 1261; CHECK-LABEL: define void @test18b( 1262; CHECK-NOT: @objc_ 1263; CHECK: } 1264define void @test18b() { 1265 call i8* @objc_retain(i8* undef) 1266 call void @objc_release(i8* undef) 1267 call i8* @objc_autorelease(i8* undef) 1268 ret void 1269} 1270 1271; Replace uses of arguments with uses of return values, to reduce 1272; register pressure. 1273 1274; CHECK: define void @test19(i32* %y) { 1275; CHECK: %z = bitcast i32* %y to i8* 1276; CHECK: %0 = bitcast i32* %y to i8* 1277; CHECK: %1 = tail call i8* @objc_retain(i8* %0) 1278; CHECK: call void @use_pointer(i8* %z) 1279; CHECK: call void @use_pointer(i8* %z) 1280; CHECK: %2 = bitcast i32* %y to i8* 1281; CHECK: call void @objc_release(i8* %2) 1282; CHECK: ret void 1283; CHECK: } 1284define void @test19(i32* %y) { 1285entry: 1286 %x = bitcast i32* %y to i8* 1287 %0 = call i8* @objc_retain(i8* %x) nounwind 1288 %z = bitcast i32* %y to i8* 1289 call void @use_pointer(i8* %z) 1290 call void @use_pointer(i8* %z) 1291 call void @objc_release(i8* %x) 1292 ret void 1293} 1294 1295; Bitcast insertion 1296 1297; CHECK-LABEL: define void @test20( 1298; CHECK: %tmp1 = tail call i8* @objc_retain(i8* %tmp) [[NUW]] 1299; CHECK-NEXT: invoke 1300; CHECK: } 1301define void @test20(double* %self) { 1302if.then12: 1303 %tmp = bitcast double* %self to i8* 1304 %tmp1 = call i8* @objc_retain(i8* %tmp) nounwind 1305 invoke void @invokee() 1306 to label %invoke.cont23 unwind label %lpad20 1307 1308invoke.cont23: ; preds = %if.then12 1309 invoke void @invokee() 1310 to label %if.end unwind label %lpad20 1311 1312lpad20: ; preds = %invoke.cont23, %if.then12 1313 %tmp502 = phi double* [ undef, %invoke.cont23 ], [ %self, %if.then12 ] 1314 %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 1315 cleanup 1316 unreachable 1317 1318if.end: ; preds = %invoke.cont23 1319 ret void 1320} 1321 1322; Delete a redundant retain,autorelease when forwaring a call result 1323; directly to a return value. 1324 1325; CHECK-LABEL: define i8* @test21( 1326; CHECK: call i8* @returner() 1327; CHECK-NEXT: ret i8* %call 1328; CHECK-NEXT: } 1329define i8* @test21() { 1330entry: 1331 %call = call i8* @returner() 1332 %0 = call i8* @objc_retain(i8* %call) nounwind 1333 %1 = call i8* @objc_autorelease(i8* %0) nounwind 1334 ret i8* %1 1335} 1336 1337; Move an objc call up through a phi that has null operands. 1338 1339; CHECK-LABEL: define void @test22( 1340; CHECK: B: 1341; CHECK: %1 = bitcast double* %p to i8* 1342; CHECK: call void @objc_release(i8* %1) 1343; CHECK: br label %C 1344; CHECK: C: ; preds = %B, %A 1345; CHECK-NOT: @objc_release 1346; CHECK: } 1347define void @test22(double* %p, i1 %a) { 1348 br i1 %a, label %A, label %B 1349A: 1350 br label %C 1351B: 1352 br label %C 1353C: 1354 %h = phi double* [ null, %A ], [ %p, %B ] 1355 %c = bitcast double* %h to i8* 1356 call void @objc_release(i8* %c) 1357 ret void 1358} 1359 1360; Any call can decrement a retain count. 1361 1362; CHECK-LABEL: define void @test24( 1363; CHECK: @objc_retain(i8* %a) 1364; CHECK: @objc_release 1365; CHECK: } 1366define void @test24(i8* %r, i8* %a) { 1367 call i8* @objc_retain(i8* %a) 1368 call void @use_pointer(i8* %r) 1369 %q = load i8* %a 1370 call void @objc_release(i8* %a) 1371 ret void 1372} 1373 1374; Don't move a retain/release pair if the release can be moved 1375; but the retain can't be moved to balance it. 1376 1377; CHECK-LABEL: define void @test25( 1378; CHECK: entry: 1379; CHECK: call i8* @objc_retain(i8* %p) 1380; CHECK: true: 1381; CHECK: done: 1382; CHECK: call void @objc_release(i8* %p) 1383; CHECK: } 1384define void @test25(i8* %p, i1 %x) { 1385entry: 1386 %f0 = call i8* @objc_retain(i8* %p) 1387 call void @callee() 1388 br i1 %x, label %true, label %done 1389 1390true: 1391 store i8 0, i8* %p 1392 br label %done 1393 1394done: 1395 call void @objc_release(i8* %p) 1396 ret void 1397} 1398 1399; Don't move a retain/release pair if the retain can be moved 1400; but the release can't be moved to balance it. 1401 1402; CHECK-LABEL: define void @test26( 1403; CHECK: entry: 1404; CHECK: call i8* @objc_retain(i8* %p) 1405; CHECK: true: 1406; CHECK: done: 1407; CHECK: call void @objc_release(i8* %p) 1408; CHECK: } 1409define void @test26(i8* %p, i1 %x) { 1410entry: 1411 %f0 = call i8* @objc_retain(i8* %p) 1412 br i1 %x, label %true, label %done 1413 1414true: 1415 call void @callee() 1416 br label %done 1417 1418done: 1419 store i8 0, i8* %p 1420 call void @objc_release(i8* %p) 1421 ret void 1422} 1423 1424; Don't sink the retain,release into the loop. 1425 1426; CHECK-LABEL: define void @test27( 1427; CHECK: entry: 1428; CHECK: call i8* @objc_retain(i8* %p) 1429; CHECK: loop: 1430; CHECK-NOT: @objc_ 1431; CHECK: done: 1432; CHECK: call void @objc_release 1433; CHECK: } 1434define void @test27(i8* %p, i1 %x, i1 %y) { 1435entry: 1436 %f0 = call i8* @objc_retain(i8* %p) 1437 br i1 %x, label %loop, label %done 1438 1439loop: 1440 call void @callee() 1441 store i8 0, i8* %p 1442 br i1 %y, label %done, label %loop 1443 1444done: 1445 call void @objc_release(i8* %p) 1446 ret void 1447} 1448 1449; Trivial code motion case: Triangle. 1450 1451; CHECK-LABEL: define void @test28( 1452; CHECK-NOT: @objc_ 1453; CHECK: true: 1454; CHECK: call i8* @objc_retain( 1455; CHECK: call void @callee() 1456; CHECK: store 1457; CHECK: call void @objc_release 1458; CHECK: done: 1459; CHECK-NOT: @objc_ 1460; CHECK: } 1461define void @test28(i8* %p, i1 %x) { 1462entry: 1463 %f0 = call i8* @objc_retain(i8* %p) 1464 br i1 %x, label %true, label %done 1465 1466true: 1467 call void @callee() 1468 store i8 0, i8* %p 1469 br label %done 1470 1471done: 1472 call void @objc_release(i8* %p), !clang.imprecise_release !0 1473 ret void 1474} 1475 1476; Trivial code motion case: Triangle, but no metadata. Don't move past 1477; unrelated memory references! 1478 1479; CHECK-LABEL: define void @test28b( 1480; CHECK: call i8* @objc_retain( 1481; CHECK: true: 1482; CHECK-NOT: @objc_ 1483; CHECK: call void @callee() 1484; CHECK-NOT: @objc_ 1485; CHECK: store 1486; CHECK-NOT: @objc_ 1487; CHECK: done: 1488; CHECK: @objc_release 1489; CHECK: } 1490define void @test28b(i8* %p, i1 %x, i8* noalias %t) { 1491entry: 1492 %f0 = call i8* @objc_retain(i8* %p) 1493 br i1 %x, label %true, label %done 1494 1495true: 1496 call void @callee() 1497 store i8 0, i8* %p 1498 br label %done 1499 1500done: 1501 store i8 0, i8* %t 1502 call void @objc_release(i8* %p) 1503 ret void 1504} 1505 1506; Trivial code motion case: Triangle, with metadata. Do move past 1507; unrelated memory references! And preserve the metadata. 1508 1509; CHECK-LABEL: define void @test28c( 1510; CHECK-NOT: @objc_ 1511; CHECK: true: 1512; CHECK: call i8* @objc_retain( 1513; CHECK: call void @callee() 1514; CHECK: store 1515; CHECK: call void @objc_release(i8* %p) [[NUW]], !clang.imprecise_release 1516; CHECK: done: 1517; CHECK-NOT: @objc_ 1518; CHECK: } 1519define void @test28c(i8* %p, i1 %x, i8* noalias %t) { 1520entry: 1521 %f0 = call i8* @objc_retain(i8* %p) 1522 br i1 %x, label %true, label %done 1523 1524true: 1525 call void @callee() 1526 store i8 0, i8* %p 1527 br label %done 1528 1529done: 1530 store i8 0, i8* %t 1531 call void @objc_release(i8* %p), !clang.imprecise_release !0 1532 ret void 1533} 1534 1535; Like test28. but with two releases. 1536 1537; CHECK-LABEL: define void @test29( 1538; CHECK-NOT: @objc_ 1539; CHECK: true: 1540; CHECK: call i8* @objc_retain( 1541; CHECK: call void @callee() 1542; CHECK: store 1543; CHECK: call void @objc_release 1544; CHECK-NOT: @objc_release 1545; CHECK: done: 1546; CHECK-NOT: @objc_ 1547; CHECK: ohno: 1548; CHECK-NOT: @objc_ 1549; CHECK: } 1550define void @test29(i8* %p, i1 %x, i1 %y) { 1551entry: 1552 %f0 = call i8* @objc_retain(i8* %p) 1553 br i1 %x, label %true, label %done 1554 1555true: 1556 call void @callee() 1557 store i8 0, i8* %p 1558 br i1 %y, label %done, label %ohno 1559 1560done: 1561 call void @objc_release(i8* %p) 1562 ret void 1563 1564ohno: 1565 call void @objc_release(i8* %p) 1566 ret void 1567} 1568 1569; Basic case with the use and call in a diamond 1570; with an extra release. 1571 1572; CHECK-LABEL: define void @test30( 1573; CHECK-NOT: @objc_ 1574; CHECK: true: 1575; CHECK: call i8* @objc_retain( 1576; CHECK: call void @callee() 1577; CHECK: store 1578; CHECK: call void @objc_release 1579; CHECK-NOT: @objc_release 1580; CHECK: false: 1581; CHECK-NOT: @objc_ 1582; CHECK: done: 1583; CHECK-NOT: @objc_ 1584; CHECK: ohno: 1585; CHECK-NOT: @objc_ 1586; CHECK: } 1587define void @test30(i8* %p, i1 %x, i1 %y, i1 %z) { 1588entry: 1589 %f0 = call i8* @objc_retain(i8* %p) 1590 br i1 %x, label %true, label %false 1591 1592true: 1593 call void @callee() 1594 store i8 0, i8* %p 1595 br i1 %y, label %done, label %ohno 1596 1597false: 1598 br i1 %z, label %done, label %ohno 1599 1600done: 1601 call void @objc_release(i8* %p) 1602 ret void 1603 1604ohno: 1605 call void @objc_release(i8* %p) 1606 ret void 1607} 1608 1609; Basic case with a mergeable release. 1610 1611; CHECK-LABEL: define void @test31( 1612; CHECK: call i8* @objc_retain(i8* %p) 1613; CHECK: call void @callee() 1614; CHECK: store 1615; CHECK: call void @objc_release 1616; CHECK-NOT: @objc_release 1617; CHECK: true: 1618; CHECK-NOT: @objc_release 1619; CHECK: false: 1620; CHECK-NOT: @objc_release 1621; CHECK: ret void 1622; CHECK-NOT: @objc_release 1623; CHECK: } 1624define void @test31(i8* %p, i1 %x) { 1625entry: 1626 %f0 = call i8* @objc_retain(i8* %p) 1627 call void @callee() 1628 store i8 0, i8* %p 1629 br i1 %x, label %true, label %false 1630true: 1631 call void @objc_release(i8* %p) 1632 ret void 1633false: 1634 call void @objc_release(i8* %p) 1635 ret void 1636} 1637 1638; Don't consider bitcasts or getelementptrs direct uses. 1639 1640; CHECK-LABEL: define void @test32( 1641; CHECK-NOT: @objc_ 1642; CHECK: true: 1643; CHECK: call i8* @objc_retain( 1644; CHECK: call void @callee() 1645; CHECK: store 1646; CHECK: call void @objc_release 1647; CHECK: done: 1648; CHECK-NOT: @objc_ 1649; CHECK: } 1650define void @test32(i8* %p, i1 %x) { 1651entry: 1652 %f0 = call i8* @objc_retain(i8* %p) 1653 br i1 %x, label %true, label %done 1654 1655true: 1656 call void @callee() 1657 store i8 0, i8* %p 1658 br label %done 1659 1660done: 1661 %g = bitcast i8* %p to i8* 1662 %h = getelementptr i8* %g, i64 0 1663 call void @objc_release(i8* %g) 1664 ret void 1665} 1666 1667; Do consider icmps to be direct uses. 1668 1669; CHECK-LABEL: define void @test33( 1670; CHECK-NOT: @objc_ 1671; CHECK: true: 1672; CHECK: call i8* @objc_retain( 1673; CHECK: call void @callee() 1674; CHECK: icmp 1675; CHECK: call void @objc_release 1676; CHECK: done: 1677; CHECK-NOT: @objc_ 1678; CHECK: } 1679define void @test33(i8* %p, i1 %x, i8* %y) { 1680entry: 1681 %f0 = call i8* @objc_retain(i8* %p) 1682 br i1 %x, label %true, label %done 1683 1684true: 1685 call void @callee() 1686 %v = icmp eq i8* %p, %y 1687 br label %done 1688 1689done: 1690 %g = bitcast i8* %p to i8* 1691 %h = getelementptr i8* %g, i64 0 1692 call void @objc_release(i8* %g) 1693 ret void 1694} 1695 1696; Delete retain,release if there's just a possible dec and we have imprecise 1697; releases. 1698 1699; CHECK-LABEL: define void @test34a( 1700; CHECK: call i8* @objc_retain 1701; CHECK: true: 1702; CHECK: done: 1703; CHECK: call void @objc_release 1704; CHECK: } 1705define void @test34a(i8* %p, i1 %x, i8* %y) { 1706entry: 1707 %f0 = call i8* @objc_retain(i8* %p) 1708 br i1 %x, label %true, label %done 1709 1710true: 1711 call void @callee() 1712 br label %done 1713 1714done: 1715 %g = bitcast i8* %p to i8* 1716 %h = getelementptr i8* %g, i64 0 1717 call void @objc_release(i8* %g) 1718 ret void 1719} 1720 1721; CHECK-LABEL: define void @test34b( 1722; CHECK-NOT: @objc_ 1723; CHECK: } 1724define void @test34b(i8* %p, i1 %x, i8* %y) { 1725entry: 1726 %f0 = call i8* @objc_retain(i8* %p) 1727 br i1 %x, label %true, label %done 1728 1729true: 1730 call void @callee() 1731 br label %done 1732 1733done: 1734 %g = bitcast i8* %p to i8* 1735 %h = getelementptr i8* %g, i64 0 1736 call void @objc_release(i8* %g), !clang.imprecise_release !0 1737 ret void 1738} 1739 1740 1741; Delete retain,release if there's just a use and we do not have a precise 1742; release. 1743 1744; Precise. 1745; CHECK-LABEL: define void @test35a( 1746; CHECK: entry: 1747; CHECK: call i8* @objc_retain 1748; CHECK: true: 1749; CHECK: done: 1750; CHECK: call void @objc_release 1751; CHECK: } 1752define void @test35a(i8* %p, i1 %x, i8* %y) { 1753entry: 1754 %f0 = call i8* @objc_retain(i8* %p) 1755 br i1 %x, label %true, label %done 1756 1757true: 1758 %v = icmp eq i8* %p, %y 1759 br label %done 1760 1761done: 1762 %g = bitcast i8* %p to i8* 1763 %h = getelementptr i8* %g, i64 0 1764 call void @objc_release(i8* %g) 1765 ret void 1766} 1767 1768; Imprecise. 1769; CHECK-LABEL: define void @test35b( 1770; CHECK-NOT: @objc_ 1771; CHECK: } 1772define void @test35b(i8* %p, i1 %x, i8* %y) { 1773entry: 1774 %f0 = call i8* @objc_retain(i8* %p) 1775 br i1 %x, label %true, label %done 1776 1777true: 1778 %v = icmp eq i8* %p, %y 1779 br label %done 1780 1781done: 1782 %g = bitcast i8* %p to i8* 1783 %h = getelementptr i8* %g, i64 0 1784 call void @objc_release(i8* %g), !clang.imprecise_release !0 1785 ret void 1786} 1787 1788; Delete a retain,release if there's no actual use and we have precise release. 1789 1790; CHECK-LABEL: define void @test36a( 1791; CHECK: @objc_retain 1792; CHECK: call void @callee() 1793; CHECK-NOT: @objc_ 1794; CHECK: call void @callee() 1795; CHECK: @objc_release 1796; CHECK: } 1797define void @test36a(i8* %p) { 1798entry: 1799 call i8* @objc_retain(i8* %p) 1800 call void @callee() 1801 call void @callee() 1802 call void @objc_release(i8* %p) 1803 ret void 1804} 1805 1806; Like test36, but with metadata. 1807 1808; CHECK-LABEL: define void @test36b( 1809; CHECK-NOT: @objc_ 1810; CHECK: } 1811define void @test36b(i8* %p) { 1812entry: 1813 call i8* @objc_retain(i8* %p) 1814 call void @callee() 1815 call void @callee() 1816 call void @objc_release(i8* %p), !clang.imprecise_release !0 1817 ret void 1818} 1819 1820; Be aggressive about analyzing phis to eliminate possible uses. 1821 1822; CHECK-LABEL: define void @test38( 1823; CHECK-NOT: @objc_ 1824; CHECK: } 1825define void @test38(i8* %p, i1 %u, i1 %m, i8* %z, i8* %y, i8* %x, i8* %w) { 1826entry: 1827 call i8* @objc_retain(i8* %p) 1828 br i1 %u, label %true, label %false 1829true: 1830 br i1 %m, label %a, label %b 1831false: 1832 br i1 %m, label %c, label %d 1833a: 1834 br label %e 1835b: 1836 br label %e 1837c: 1838 br label %f 1839d: 1840 br label %f 1841e: 1842 %j = phi i8* [ %z, %a ], [ %y, %b ] 1843 br label %g 1844f: 1845 %k = phi i8* [ %w, %c ], [ %x, %d ] 1846 br label %g 1847g: 1848 %h = phi i8* [ %j, %e ], [ %k, %f ] 1849 call void @use_pointer(i8* %h) 1850 call void @objc_release(i8* %p), !clang.imprecise_release !0 1851 ret void 1852} 1853 1854; Delete retain,release pairs around loops. 1855 1856; CHECK-LABEL: define void @test39( 1857; CHECK-NOT: @objc_ 1858; CHECK: } 1859define void @test39(i8* %p) { 1860entry: 1861 %0 = call i8* @objc_retain(i8* %p) 1862 br label %loop 1863 1864loop: ; preds = %loop, %entry 1865 br i1 undef, label %loop, label %exit 1866 1867exit: ; preds = %loop 1868 call void @objc_release(i8* %0), !clang.imprecise_release !0 1869 ret void 1870} 1871 1872; Delete retain,release pairs around loops containing uses. 1873 1874; CHECK-LABEL: define void @test39b( 1875; CHECK-NOT: @objc_ 1876; CHECK: } 1877define void @test39b(i8* %p) { 1878entry: 1879 %0 = call i8* @objc_retain(i8* %p) 1880 br label %loop 1881 1882loop: ; preds = %loop, %entry 1883 store i8 0, i8* %0 1884 br i1 undef, label %loop, label %exit 1885 1886exit: ; preds = %loop 1887 call void @objc_release(i8* %0), !clang.imprecise_release !0 1888 ret void 1889} 1890 1891; Delete retain,release pairs around loops containing potential decrements. 1892 1893; CHECK-LABEL: define void @test39c( 1894; CHECK-NOT: @objc_ 1895; CHECK: } 1896define void @test39c(i8* %p) { 1897entry: 1898 %0 = call i8* @objc_retain(i8* %p) 1899 br label %loop 1900 1901loop: ; preds = %loop, %entry 1902 call void @use_pointer(i8* %0) 1903 br i1 undef, label %loop, label %exit 1904 1905exit: ; preds = %loop 1906 call void @objc_release(i8* %0), !clang.imprecise_release !0 1907 ret void 1908} 1909 1910; Delete retain,release pairs around loops even if 1911; the successors are in a different order. 1912 1913; CHECK-LABEL: define void @test40( 1914; CHECK-NOT: @objc_ 1915; CHECK: } 1916define void @test40(i8* %p) { 1917entry: 1918 %0 = call i8* @objc_retain(i8* %p) 1919 br label %loop 1920 1921loop: ; preds = %loop, %entry 1922 call void @use_pointer(i8* %0) 1923 br i1 undef, label %exit, label %loop 1924 1925exit: ; preds = %loop 1926 call void @objc_release(i8* %0), !clang.imprecise_release !0 1927 ret void 1928} 1929 1930; Do the known-incremented retain+release elimination even if the pointer 1931; is also autoreleased. 1932 1933; CHECK-LABEL: define void @test42( 1934; CHECK-NEXT: entry: 1935; CHECK-NEXT: call i8* @objc_retain(i8* %p) 1936; CHECK-NEXT: call i8* @objc_autorelease(i8* %p) 1937; CHECK-NEXT: call void @use_pointer(i8* %p) 1938; CHECK-NEXT: call void @use_pointer(i8* %p) 1939; CHECK-NEXT: ret void 1940; CHECK-NEXT: } 1941define void @test42(i8* %p) { 1942entry: 1943 call i8* @objc_retain(i8* %p) 1944 call i8* @objc_autorelease(i8* %p) 1945 call i8* @objc_retain(i8* %p) 1946 call void @use_pointer(i8* %p) 1947 call void @use_pointer(i8* %p) 1948 call void @objc_release(i8* %p) 1949 ret void 1950} 1951 1952; Don't the known-incremented retain+release elimination if the pointer is 1953; autoreleased and there's an autoreleasePoolPop. 1954 1955; CHECK-LABEL: define void @test43( 1956; CHECK-NEXT: entry: 1957; CHECK-NEXT: call i8* @objc_retain(i8* %p) 1958; CHECK-NEXT: call i8* @objc_autorelease(i8* %p) 1959; CHECK-NEXT: call i8* @objc_retain 1960; CHECK-NEXT: call void @use_pointer(i8* %p) 1961; CHECK-NEXT: call void @use_pointer(i8* %p) 1962; CHECK-NEXT: call void @objc_autoreleasePoolPop(i8* undef) 1963; CHECK-NEXT: call void @objc_release 1964; CHECK-NEXT: ret void 1965; CHECK-NEXT: } 1966define void @test43(i8* %p) { 1967entry: 1968 call i8* @objc_retain(i8* %p) 1969 call i8* @objc_autorelease(i8* %p) 1970 call i8* @objc_retain(i8* %p) 1971 call void @use_pointer(i8* %p) 1972 call void @use_pointer(i8* %p) 1973 call void @objc_autoreleasePoolPop(i8* undef) 1974 call void @objc_release(i8* %p) 1975 ret void 1976} 1977 1978; Do the known-incremented retain+release elimination if the pointer is 1979; autoreleased and there's an autoreleasePoolPush. 1980 1981; CHECK-LABEL: define void @test43b( 1982; CHECK-NEXT: entry: 1983; CHECK-NEXT: call i8* @objc_retain(i8* %p) 1984; CHECK-NEXT: call i8* @objc_autorelease(i8* %p) 1985; CHECK-NEXT: call void @use_pointer(i8* %p) 1986; CHECK-NEXT: call void @use_pointer(i8* %p) 1987; CHECK-NEXT: call i8* @objc_autoreleasePoolPush() 1988; CHECK-NEXT: ret void 1989; CHECK-NEXT: } 1990define void @test43b(i8* %p) { 1991entry: 1992 call i8* @objc_retain(i8* %p) 1993 call i8* @objc_autorelease(i8* %p) 1994 call i8* @objc_retain(i8* %p) 1995 call void @use_pointer(i8* %p) 1996 call void @use_pointer(i8* %p) 1997 call i8* @objc_autoreleasePoolPush() 1998 call void @objc_release(i8* %p) 1999 ret void 2000} 2001 2002; Do retain+release elimination for non-provenance pointers. 2003 2004; CHECK-LABEL: define void @test44( 2005; CHECK-NOT: objc_ 2006; CHECK: } 2007define void @test44(i8** %pp) { 2008 %p = load i8** %pp 2009 %q = call i8* @objc_retain(i8* %p) 2010 call void @objc_release(i8* %q) 2011 ret void 2012} 2013 2014; Don't delete retain+release with an unknown-provenance 2015; may-alias objc_release between them. 2016 2017; CHECK-LABEL: define void @test45( 2018; CHECK: call i8* @objc_retain(i8* %p) 2019; CHECK: call void @objc_release(i8* %q) 2020; CHECK: call void @use_pointer(i8* %p) 2021; CHECK: call void @objc_release(i8* %p) 2022; CHECK: } 2023define void @test45(i8** %pp, i8** %qq) { 2024 %p = load i8** %pp 2025 %q = load i8** %qq 2026 call i8* @objc_retain(i8* %p) 2027 call void @objc_release(i8* %q) 2028 call void @use_pointer(i8* %p) 2029 call void @objc_release(i8* %p) 2030 ret void 2031} 2032 2033; Don't delete retain and autorelease here. 2034 2035; CHECK-LABEL: define void @test46( 2036; CHECK: tail call i8* @objc_retain(i8* %p) [[NUW]] 2037; CHECK: true: 2038; CHECK: call i8* @objc_autorelease(i8* %p) [[NUW]] 2039; CHECK: } 2040define void @test46(i8* %p, i1 %a) { 2041entry: 2042 call i8* @objc_retain(i8* %p) 2043 br i1 %a, label %true, label %false 2044 2045true: 2046 call i8* @objc_autorelease(i8* %p) 2047 call void @use_pointer(i8* %p) 2048 ret void 2049 2050false: 2051 ret void 2052} 2053 2054; Delete no-op cast calls. 2055 2056; CHECK-LABEL: define i8* @test47( 2057; CHECK-NOT: call 2058; CHECK: ret i8* %p 2059; CHECK: } 2060define i8* @test47(i8* %p) nounwind { 2061 %x = call i8* @objc_retainedObject(i8* %p) 2062 ret i8* %x 2063} 2064 2065; Delete no-op cast calls. 2066 2067; CHECK-LABEL: define i8* @test48( 2068; CHECK-NOT: call 2069; CHECK: ret i8* %p 2070; CHECK: } 2071define i8* @test48(i8* %p) nounwind { 2072 %x = call i8* @objc_unretainedObject(i8* %p) 2073 ret i8* %x 2074} 2075 2076; Delete no-op cast calls. 2077 2078; CHECK-LABEL: define i8* @test49( 2079; CHECK-NOT: call 2080; CHECK: ret i8* %p 2081; CHECK: } 2082define i8* @test49(i8* %p) nounwind { 2083 %x = call i8* @objc_unretainedPointer(i8* %p) 2084 ret i8* %x 2085} 2086 2087; Do delete retain+release with intervening stores of the address value if we 2088; have imprecise release attached to objc_release. 2089 2090; CHECK-LABEL: define void @test50a( 2091; CHECK-NEXT: call i8* @objc_retain 2092; CHECK-NEXT: call void @callee 2093; CHECK-NEXT: store 2094; CHECK-NEXT: call void @objc_release 2095; CHECK-NEXT: ret void 2096; CHECK-NEXT: } 2097define void @test50a(i8* %p, i8** %pp) { 2098 call i8* @objc_retain(i8* %p) 2099 call void @callee() 2100 store i8* %p, i8** %pp 2101 call void @objc_release(i8* %p) 2102 ret void 2103} 2104 2105; CHECK-LABEL: define void @test50b( 2106; CHECK-NOT: @objc_ 2107; CHECK: } 2108define void @test50b(i8* %p, i8** %pp) { 2109 call i8* @objc_retain(i8* %p) 2110 call void @callee() 2111 store i8* %p, i8** %pp 2112 call void @objc_release(i8* %p), !clang.imprecise_release !0 2113 ret void 2114} 2115 2116 2117; Don't delete retain+release with intervening stores through the 2118; address value. 2119 2120; CHECK-LABEL: define void @test51a( 2121; CHECK: call i8* @objc_retain(i8* %p) 2122; CHECK: call void @objc_release(i8* %p) 2123; CHECK: ret void 2124; CHECK: } 2125define void @test51a(i8* %p) { 2126 call i8* @objc_retain(i8* %p) 2127 call void @callee() 2128 store i8 0, i8* %p 2129 call void @objc_release(i8* %p) 2130 ret void 2131} 2132 2133; CHECK-LABEL: define void @test51b( 2134; CHECK: call i8* @objc_retain(i8* %p) 2135; CHECK: call void @objc_release(i8* %p) 2136; CHECK: ret void 2137; CHECK: } 2138define void @test51b(i8* %p) { 2139 call i8* @objc_retain(i8* %p) 2140 call void @callee() 2141 store i8 0, i8* %p 2142 call void @objc_release(i8* %p), !clang.imprecise_release !0 2143 ret void 2144} 2145 2146; Don't delete retain+release with intervening use of a pointer of 2147; unknown provenance. 2148 2149; CHECK-LABEL: define void @test52a( 2150; CHECK: call i8* @objc_retain 2151; CHECK: call void @callee() 2152; CHECK: call void @use_pointer(i8* %z) 2153; CHECK: call void @objc_release 2154; CHECK: ret void 2155; CHECK: } 2156define void @test52a(i8** %zz, i8** %pp) { 2157 %p = load i8** %pp 2158 %1 = call i8* @objc_retain(i8* %p) 2159 call void @callee() 2160 %z = load i8** %zz 2161 call void @use_pointer(i8* %z) 2162 call void @objc_release(i8* %p) 2163 ret void 2164} 2165 2166; CHECK-LABEL: define void @test52b( 2167; CHECK: call i8* @objc_retain 2168; CHECK: call void @callee() 2169; CHECK: call void @use_pointer(i8* %z) 2170; CHECK: call void @objc_release 2171; CHECK: ret void 2172; CHECK: } 2173define void @test52b(i8** %zz, i8** %pp) { 2174 %p = load i8** %pp 2175 %1 = call i8* @objc_retain(i8* %p) 2176 call void @callee() 2177 %z = load i8** %zz 2178 call void @use_pointer(i8* %z) 2179 call void @objc_release(i8* %p), !clang.imprecise_release !0 2180 ret void 2181} 2182 2183; Like test52, but the pointer has function type, so it's assumed to 2184; be not reference counted. 2185; Oops. That's wrong. Clang sometimes uses function types gratuitously. 2186; See rdar://10551239. 2187 2188; CHECK-LABEL: define void @test53( 2189; CHECK: @objc_ 2190; CHECK: } 2191define void @test53(void ()** %zz, i8** %pp) { 2192 %p = load i8** %pp 2193 %1 = call i8* @objc_retain(i8* %p) 2194 call void @callee() 2195 %z = load void ()** %zz 2196 call void @callee_fnptr(void ()* %z) 2197 call void @objc_release(i8* %p) 2198 ret void 2199} 2200 2201; Convert autorelease to release if the value is unused. 2202 2203; CHECK-LABEL: define void @test54( 2204; CHECK: call i8* @returner() 2205; CHECK-NEXT: call void @objc_release(i8* %t) [[NUW]], !clang.imprecise_release ![[RELEASE]] 2206; CHECK-NEXT: ret void 2207; CHECK: } 2208define void @test54() { 2209 %t = call i8* @returner() 2210 call i8* @objc_autorelease(i8* %t) 2211 ret void 2212} 2213 2214; Nested retain+release pairs. Delete them both. 2215 2216; CHECK-LABEL: define void @test55( 2217; CHECK-NOT: @objc 2218; CHECK: } 2219define void @test55(i8* %x) { 2220entry: 2221 %0 = call i8* @objc_retain(i8* %x) nounwind 2222 %1 = call i8* @objc_retain(i8* %x) nounwind 2223 call void @objc_release(i8* %x) nounwind 2224 call void @objc_release(i8* %x) nounwind 2225 ret void 2226} 2227 2228; Nested retain+release pairs where the inner pair depends 2229; on the outer pair to be removed, and then the outer pair 2230; can be partially eliminated. Plus an extra outer pair to 2231; eliminate, for fun. 2232 2233; CHECK-LABEL: define void @test56( 2234; CHECK-NOT: @objc 2235; CHECK: if.then: 2236; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %x) [[NUW]] 2237; CHECK-NEXT: tail call void @use_pointer(i8* %x) 2238; CHECK-NEXT: tail call void @use_pointer(i8* %x) 2239; CHECK-NEXT: tail call void @objc_release(i8* %x) [[NUW]], !clang.imprecise_release ![[RELEASE]] 2240; CHECK-NEXT: br label %if.end 2241; CHECK-NOT: @objc 2242; CHECK: } 2243define void @test56(i8* %x, i32 %n) { 2244entry: 2245 %0 = tail call i8* @objc_retain(i8* %x) nounwind 2246 %1 = tail call i8* @objc_retain(i8* %0) nounwind 2247 %tobool = icmp eq i32 %n, 0 2248 br i1 %tobool, label %if.end, label %if.then 2249 2250if.then: ; preds = %entry 2251 %2 = tail call i8* @objc_retain(i8* %1) nounwind 2252 tail call void @use_pointer(i8* %2) 2253 tail call void @use_pointer(i8* %2) 2254 tail call void @objc_release(i8* %2) nounwind, !clang.imprecise_release !0 2255 br label %if.end 2256 2257if.end: ; preds = %entry, %if.then 2258 tail call void @objc_release(i8* %1) nounwind, !clang.imprecise_release !0 2259 tail call void @objc_release(i8* %0) nounwind, !clang.imprecise_release !0 2260 ret void 2261} 2262 2263; When there are adjacent retain+release pairs, the first one is 2264; known unnecessary because the presence of the second one means that 2265; the first one won't be deleting the object. 2266 2267; CHECK-LABEL: define void @test57( 2268; CHECK-NEXT: entry: 2269; CHECK-NEXT: call void @use_pointer(i8* %x) 2270; CHECK-NEXT: call void @use_pointer(i8* %x) 2271; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %x) [[NUW]] 2272; CHECK-NEXT: call void @use_pointer(i8* %x) 2273; CHECK-NEXT: call void @use_pointer(i8* %x) 2274; CHECK-NEXT: call void @objc_release(i8* %x) [[NUW]] 2275; CHECK-NEXT: ret void 2276; CHECK-NEXT: } 2277define void @test57(i8* %x) nounwind { 2278entry: 2279 call i8* @objc_retain(i8* %x) nounwind 2280 call void @use_pointer(i8* %x) 2281 call void @use_pointer(i8* %x) 2282 call void @objc_release(i8* %x) nounwind 2283 call i8* @objc_retain(i8* %x) nounwind 2284 call void @use_pointer(i8* %x) 2285 call void @use_pointer(i8* %x) 2286 call void @objc_release(i8* %x) nounwind 2287 ret void 2288} 2289 2290; An adjacent retain+release pair is sufficient even if it will be 2291; removed itself. 2292 2293; CHECK-LABEL: define void @test58( 2294; CHECK-NEXT: entry: 2295; CHECK-NEXT: call void @use_pointer(i8* %x) 2296; CHECK-NEXT: call void @use_pointer(i8* %x) 2297; CHECK-NEXT: ret void 2298; CHECK-NEXT: } 2299define void @test58(i8* %x) nounwind { 2300entry: 2301 call i8* @objc_retain(i8* %x) nounwind 2302 call void @use_pointer(i8* %x) 2303 call void @use_pointer(i8* %x) 2304 call void @objc_release(i8* %x) nounwind 2305 call i8* @objc_retain(i8* %x) nounwind 2306 call void @objc_release(i8* %x) nounwind 2307 ret void 2308} 2309 2310; Don't delete the second retain+release pair in an adjacent set. 2311 2312; CHECK-LABEL: define void @test59( 2313; CHECK-NEXT: entry: 2314; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %x) [[NUW]] 2315; CHECK-NEXT: call void @use_pointer(i8* %x) 2316; CHECK-NEXT: call void @use_pointer(i8* %x) 2317; CHECK-NEXT: call void @objc_release(i8* %x) [[NUW]] 2318; CHECK-NEXT: ret void 2319; CHECK-NEXT: } 2320define void @test59(i8* %x) nounwind { 2321entry: 2322 %a = call i8* @objc_retain(i8* %x) nounwind 2323 call void @objc_release(i8* %x) nounwind 2324 %b = call i8* @objc_retain(i8* %x) nounwind 2325 call void @use_pointer(i8* %x) 2326 call void @use_pointer(i8* %x) 2327 call void @objc_release(i8* %x) nounwind 2328 ret void 2329} 2330 2331; Constant pointers to objects don't need reference counting. 2332 2333@constptr = external constant i8* 2334@something = external global i8* 2335 2336; We have a precise lifetime retain/release here. We can not remove them since 2337; @something is not constant. 2338 2339; CHECK-LABEL: define void @test60a( 2340; CHECK: call i8* @objc_retain 2341; CHECK: call void @objc_release 2342; CHECK: } 2343define void @test60a() { 2344 %t = load i8** @constptr 2345 %s = load i8** @something 2346 call i8* @objc_retain(i8* %s) 2347 call void @callee() 2348 call void @use_pointer(i8* %t) 2349 call void @objc_release(i8* %s) 2350 ret void 2351} 2352 2353; CHECK-LABEL: define void @test60b( 2354; CHECK: call i8* @objc_retain 2355; CHECK-NOT: call i8* @objc_retain 2356; CHECK-NOT: call i8* @objc_rrelease 2357; CHECK: } 2358define void @test60b() { 2359 %t = load i8** @constptr 2360 %s = load i8** @something 2361 call i8* @objc_retain(i8* %s) 2362 call i8* @objc_retain(i8* %s) 2363 call void @callee() 2364 call void @use_pointer(i8* %t) 2365 call void @objc_release(i8* %s) 2366 ret void 2367} 2368 2369; CHECK-LABEL: define void @test60c( 2370; CHECK-NOT: @objc_ 2371; CHECK: } 2372define void @test60c() { 2373 %t = load i8** @constptr 2374 %s = load i8** @something 2375 call i8* @objc_retain(i8* %s) 2376 call void @callee() 2377 call void @use_pointer(i8* %t) 2378 call void @objc_release(i8* %s), !clang.imprecise_release !0 2379 ret void 2380} 2381 2382; CHECK-LABEL: define void @test60d( 2383; CHECK-NOT: @objc_ 2384; CHECK: } 2385define void @test60d() { 2386 %t = load i8** @constptr 2387 %s = load i8** @something 2388 call i8* @objc_retain(i8* %t) 2389 call void @callee() 2390 call void @use_pointer(i8* %s) 2391 call void @objc_release(i8* %t) 2392 ret void 2393} 2394 2395; CHECK-LABEL: define void @test60e( 2396; CHECK-NOT: @objc_ 2397; CHECK: } 2398define void @test60e() { 2399 %t = load i8** @constptr 2400 %s = load i8** @something 2401 call i8* @objc_retain(i8* %t) 2402 call void @callee() 2403 call void @use_pointer(i8* %s) 2404 call void @objc_release(i8* %t), !clang.imprecise_release !0 2405 ret void 2406} 2407 2408; Constant pointers to objects don't need to be considered related to other 2409; pointers. 2410 2411; CHECK-LABEL: define void @test61( 2412; CHECK-NOT: @objc_ 2413; CHECK: } 2414define void @test61() { 2415 %t = load i8** @constptr 2416 call i8* @objc_retain(i8* %t) 2417 call void @callee() 2418 call void @use_pointer(i8* %t) 2419 call void @objc_release(i8* %t) 2420 ret void 2421} 2422 2423; Delete a retain matched by releases when one is inside the loop and the 2424; other is outside the loop. 2425 2426; CHECK-LABEL: define void @test62( 2427; CHECK-NOT: @objc_ 2428; CHECK: } 2429define void @test62(i8* %x, i1* %p) nounwind { 2430entry: 2431 br label %loop 2432 2433loop: 2434 call i8* @objc_retain(i8* %x) 2435 %q = load i1* %p 2436 br i1 %q, label %loop.more, label %exit 2437 2438loop.more: 2439 call void @objc_release(i8* %x) 2440 br label %loop 2441 2442exit: 2443 call void @objc_release(i8* %x) 2444 ret void 2445} 2446 2447; Like test62 but with no release in exit. 2448; Don't delete anything! 2449 2450; CHECK-LABEL: define void @test63( 2451; CHECK: loop: 2452; CHECK: tail call i8* @objc_retain(i8* %x) 2453; CHECK: loop.more: 2454; CHECK: call void @objc_release(i8* %x) 2455; CHECK: } 2456define void @test63(i8* %x, i1* %p) nounwind { 2457entry: 2458 br label %loop 2459 2460loop: 2461 call i8* @objc_retain(i8* %x) 2462 %q = load i1* %p 2463 br i1 %q, label %loop.more, label %exit 2464 2465loop.more: 2466 call void @objc_release(i8* %x) 2467 br label %loop 2468 2469exit: 2470 ret void 2471} 2472 2473; Like test62 but with no release in loop.more. 2474; Don't delete anything! 2475 2476; CHECK-LABEL: define void @test64( 2477; CHECK: loop: 2478; CHECK: tail call i8* @objc_retain(i8* %x) 2479; CHECK: exit: 2480; CHECK: call void @objc_release(i8* %x) 2481; CHECK: } 2482define void @test64(i8* %x, i1* %p) nounwind { 2483entry: 2484 br label %loop 2485 2486loop: 2487 call i8* @objc_retain(i8* %x) 2488 %q = load i1* %p 2489 br i1 %q, label %loop.more, label %exit 2490 2491loop.more: 2492 br label %loop 2493 2494exit: 2495 call void @objc_release(i8* %x) 2496 ret void 2497} 2498 2499; Move an autorelease past a phi with a null. 2500 2501; CHECK-LABEL: define i8* @test65( 2502; CHECK: if.then: 2503; CHECK: call i8* @objc_autorelease( 2504; CHECK: return: 2505; CHECK-NOT: @objc_autorelease 2506; CHECK: } 2507define i8* @test65(i1 %x) { 2508entry: 2509 br i1 %x, label %return, label %if.then 2510 2511if.then: ; preds = %entry 2512 %c = call i8* @returner() 2513 %s = call i8* @objc_retainAutoreleasedReturnValue(i8* %c) nounwind 2514 br label %return 2515 2516return: ; preds = %if.then, %entry 2517 %retval = phi i8* [ %s, %if.then ], [ null, %entry ] 2518 %q = call i8* @objc_autorelease(i8* %retval) nounwind 2519 ret i8* %retval 2520} 2521 2522; Don't move an autorelease past an autorelease pool boundary. 2523 2524; CHECK-LABEL: define i8* @test65b( 2525; CHECK: if.then: 2526; CHECK-NOT: @objc_autorelease 2527; CHECK: return: 2528; CHECK: call i8* @objc_autorelease( 2529; CHECK: } 2530define i8* @test65b(i1 %x) { 2531entry: 2532 %t = call i8* @objc_autoreleasePoolPush() 2533 br i1 %x, label %return, label %if.then 2534 2535if.then: ; preds = %entry 2536 %c = call i8* @returner() 2537 %s = call i8* @objc_retainAutoreleasedReturnValue(i8* %c) nounwind 2538 br label %return 2539 2540return: ; preds = %if.then, %entry 2541 %retval = phi i8* [ %s, %if.then ], [ null, %entry ] 2542 call void @objc_autoreleasePoolPop(i8* %t) 2543 %q = call i8* @objc_autorelease(i8* %retval) nounwind 2544 ret i8* %retval 2545} 2546 2547; Don't move an autoreleaseReuturnValue, which would break 2548; the RV optimization. 2549 2550; CHECK-LABEL: define i8* @test65c( 2551; CHECK: if.then: 2552; CHECK-NOT: @objc_autorelease 2553; CHECK: return: 2554; CHECK: call i8* @objc_autoreleaseReturnValue( 2555; CHECK: } 2556define i8* @test65c(i1 %x) { 2557entry: 2558 br i1 %x, label %return, label %if.then 2559 2560if.then: ; preds = %entry 2561 %c = call i8* @returner() 2562 %s = call i8* @objc_retainAutoreleasedReturnValue(i8* %c) nounwind 2563 br label %return 2564 2565return: ; preds = %if.then, %entry 2566 %retval = phi i8* [ %s, %if.then ], [ null, %entry ] 2567 %q = call i8* @objc_autoreleaseReturnValue(i8* %retval) nounwind 2568 ret i8* %retval 2569} 2570 2571; An objc_retain can serve as a may-use for a different pointer. 2572; rdar://11931823 2573 2574; CHECK-LABEL: define void @test66a( 2575; CHECK: tail call i8* @objc_retain(i8* %cond) [[NUW]] 2576; CHECK: tail call void @objc_release(i8* %call) [[NUW]] 2577; CHECK: tail call i8* @objc_retain(i8* %tmp8) [[NUW]] 2578; CHECK: tail call void @objc_release(i8* %cond) [[NUW]] 2579; CHECK: } 2580define void @test66a(i8* %tmp5, i8* %bar, i1 %tobool, i1 %tobool1, i8* %call) { 2581entry: 2582 br i1 %tobool, label %cond.true, label %cond.end 2583 2584cond.true: 2585 br label %cond.end 2586 2587cond.end: ; preds = %cond.true, %entry 2588 %cond = phi i8* [ %tmp5, %cond.true ], [ %call, %entry ] 2589 %tmp7 = tail call i8* @objc_retain(i8* %cond) nounwind 2590 tail call void @objc_release(i8* %call) nounwind 2591 %tmp8 = select i1 %tobool1, i8* %cond, i8* %bar 2592 %tmp9 = tail call i8* @objc_retain(i8* %tmp8) nounwind 2593 tail call void @objc_release(i8* %cond) nounwind 2594 ret void 2595} 2596 2597; CHECK-LABEL: define void @test66b( 2598; CHECK: tail call i8* @objc_retain(i8* %cond) [[NUW]] 2599; CHECK: tail call void @objc_release(i8* %call) [[NUW]] 2600; CHECK: tail call i8* @objc_retain(i8* %tmp8) [[NUW]] 2601; CHECK: tail call void @objc_release(i8* %cond) [[NUW]] 2602; CHECK: } 2603define void @test66b(i8* %tmp5, i8* %bar, i1 %tobool, i1 %tobool1, i8* %call) { 2604entry: 2605 br i1 %tobool, label %cond.true, label %cond.end 2606 2607cond.true: 2608 br label %cond.end 2609 2610cond.end: ; preds = %cond.true, %entry 2611 %cond = phi i8* [ %tmp5, %cond.true ], [ %call, %entry ] 2612 %tmp7 = tail call i8* @objc_retain(i8* %cond) nounwind 2613 tail call void @objc_release(i8* %call) nounwind, !clang.imprecise_release !0 2614 %tmp8 = select i1 %tobool1, i8* %cond, i8* %bar 2615 %tmp9 = tail call i8* @objc_retain(i8* %tmp8) nounwind 2616 tail call void @objc_release(i8* %cond) nounwind 2617 ret void 2618} 2619 2620; CHECK-LABEL: define void @test66c( 2621; CHECK: tail call i8* @objc_retain(i8* %cond) [[NUW]] 2622; CHECK: tail call void @objc_release(i8* %call) [[NUW]] 2623; CHECK: tail call i8* @objc_retain(i8* %tmp8) [[NUW]] 2624; CHECK: tail call void @objc_release(i8* %cond) [[NUW]] 2625; CHECK: } 2626define void @test66c(i8* %tmp5, i8* %bar, i1 %tobool, i1 %tobool1, i8* %call) { 2627entry: 2628 br i1 %tobool, label %cond.true, label %cond.end 2629 2630cond.true: 2631 br label %cond.end 2632 2633cond.end: ; preds = %cond.true, %entry 2634 %cond = phi i8* [ %tmp5, %cond.true ], [ %call, %entry ] 2635 %tmp7 = tail call i8* @objc_retain(i8* %cond) nounwind 2636 tail call void @objc_release(i8* %call) nounwind 2637 %tmp8 = select i1 %tobool1, i8* %cond, i8* %bar 2638 %tmp9 = tail call i8* @objc_retain(i8* %tmp8) nounwind, !clang.imprecise_release !0 2639 tail call void @objc_release(i8* %cond) nounwind 2640 ret void 2641} 2642 2643; CHECK-LABEL: define void @test66d( 2644; CHECK: tail call i8* @objc_retain(i8* %cond) [[NUW]] 2645; CHECK: tail call void @objc_release(i8* %call) [[NUW]] 2646; CHECK: tail call i8* @objc_retain(i8* %tmp8) [[NUW]] 2647; CHECK: tail call void @objc_release(i8* %cond) [[NUW]] 2648; CHECK: } 2649define void @test66d(i8* %tmp5, i8* %bar, i1 %tobool, i1 %tobool1, i8* %call) { 2650entry: 2651 br i1 %tobool, label %cond.true, label %cond.end 2652 2653cond.true: 2654 br label %cond.end 2655 2656cond.end: ; preds = %cond.true, %entry 2657 %cond = phi i8* [ %tmp5, %cond.true ], [ %call, %entry ] 2658 %tmp7 = tail call i8* @objc_retain(i8* %cond) nounwind 2659 tail call void @objc_release(i8* %call) nounwind, !clang.imprecise_release !0 2660 %tmp8 = select i1 %tobool1, i8* %cond, i8* %bar 2661 %tmp9 = tail call i8* @objc_retain(i8* %tmp8) nounwind 2662 tail call void @objc_release(i8* %cond) nounwind, !clang.imprecise_release !0 2663 ret void 2664} 2665 2666; A few real-world testcases. 2667 2668@.str4 = private unnamed_addr constant [33 x i8] c"-[A z] = { %f, %f, { %f, %f } }\0A\00" 2669@"OBJC_IVAR_$_A.myZ" = global i64 20, section "__DATA, __objc_const", align 8 2670declare i32 @printf(i8* nocapture, ...) nounwind 2671declare i32 @puts(i8* nocapture) nounwind 2672@str = internal constant [16 x i8] c"-[ Top0 _getX ]\00" 2673 2674; CHECK: define { <2 x float>, <2 x float> } @"\01-[A z]"({}* %self, i8* nocapture %_cmd) [[NUW]] { 2675; CHECK-NOT: @objc_ 2676; CHECK: } 2677 2678define {<2 x float>, <2 x float>} @"\01-[A z]"({}* %self, i8* nocapture %_cmd) nounwind { 2679invoke.cont: 2680 %0 = bitcast {}* %self to i8* 2681 %1 = tail call i8* @objc_retain(i8* %0) nounwind 2682 tail call void @llvm.dbg.value(metadata !{{}* %self}, i64 0, metadata !0) 2683 tail call void @llvm.dbg.value(metadata !{{}* %self}, i64 0, metadata !0) 2684 %ivar = load i64* @"OBJC_IVAR_$_A.myZ", align 8 2685 %add.ptr = getelementptr i8* %0, i64 %ivar 2686 %tmp1 = bitcast i8* %add.ptr to float* 2687 %tmp2 = load float* %tmp1, align 4 2688 %conv = fpext float %tmp2 to double 2689 %add.ptr.sum = add i64 %ivar, 4 2690 %tmp6 = getelementptr inbounds i8* %0, i64 %add.ptr.sum 2691 %2 = bitcast i8* %tmp6 to float* 2692 %tmp7 = load float* %2, align 4 2693 %conv8 = fpext float %tmp7 to double 2694 %add.ptr.sum36 = add i64 %ivar, 8 2695 %tmp12 = getelementptr inbounds i8* %0, i64 %add.ptr.sum36 2696 %arrayidx = bitcast i8* %tmp12 to float* 2697 %tmp13 = load float* %arrayidx, align 4 2698 %conv14 = fpext float %tmp13 to double 2699 %tmp12.sum = add i64 %ivar, 12 2700 %arrayidx19 = getelementptr inbounds i8* %0, i64 %tmp12.sum 2701 %3 = bitcast i8* %arrayidx19 to float* 2702 %tmp20 = load float* %3, align 4 2703 %conv21 = fpext float %tmp20 to double 2704 %call = tail call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([33 x i8]* @.str4, i64 0, i64 0), double %conv, double %conv8, double %conv14, double %conv21) 2705 %ivar23 = load i64* @"OBJC_IVAR_$_A.myZ", align 8 2706 %add.ptr24 = getelementptr i8* %0, i64 %ivar23 2707 %4 = bitcast i8* %add.ptr24 to i128* 2708 %srcval = load i128* %4, align 4 2709 tail call void @objc_release(i8* %0) nounwind 2710 %tmp29 = trunc i128 %srcval to i64 2711 %tmp30 = bitcast i64 %tmp29 to <2 x float> 2712 %tmp31 = insertvalue {<2 x float>, <2 x float>} undef, <2 x float> %tmp30, 0 2713 %tmp32 = lshr i128 %srcval, 64 2714 %tmp33 = trunc i128 %tmp32 to i64 2715 %tmp34 = bitcast i64 %tmp33 to <2 x float> 2716 %tmp35 = insertvalue {<2 x float>, <2 x float>} %tmp31, <2 x float> %tmp34, 1 2717 ret {<2 x float>, <2 x float>} %tmp35 2718} 2719 2720; CHECK: @"\01-[Top0 _getX]"({}* %self, i8* nocapture %_cmd) [[NUW]] { 2721; CHECK-NOT: @objc_ 2722; CHECK: } 2723 2724define i32 @"\01-[Top0 _getX]"({}* %self, i8* nocapture %_cmd) nounwind { 2725invoke.cont: 2726 %0 = bitcast {}* %self to i8* 2727 %1 = tail call i8* @objc_retain(i8* %0) nounwind 2728 %puts = tail call i32 @puts(i8* getelementptr inbounds ([16 x i8]* @str, i64 0, i64 0)) 2729 tail call void @objc_release(i8* %0) nounwind 2730 ret i32 0 2731} 2732 2733@"\01L_OBJC_METH_VAR_NAME_" = internal global [5 x i8] c"frob\00", section "__TEXT,__cstring,cstring_literals", align 1@"\01L_OBJC_SELECTOR_REFERENCES_" = internal global i8* getelementptr inbounds ([5 x i8]* @"\01L_OBJC_METH_VAR_NAME_", i64 0, i64 0), section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2734@"\01L_OBJC_IMAGE_INFO" = internal constant [2 x i32] [i32 0, i32 16], section "__DATA, __objc_imageinfo, regular, no_dead_strip" 2735@llvm.used = appending global [3 x i8*] [i8* getelementptr inbounds ([5 x i8]* @"\01L_OBJC_METH_VAR_NAME_", i32 0, i32 0), i8* bitcast (i8** @"\01L_OBJC_SELECTOR_REFERENCES_" to i8*), i8* bitcast ([2 x i32]* @"\01L_OBJC_IMAGE_INFO" to i8*)], section "llvm.metadata" 2736 2737; A simple loop. Eliminate the retain and release inside of it! 2738 2739; CHECK: define void @loop(i8* %x, i64 %n) { 2740; CHECK: for.body: 2741; CHECK-NOT: @objc_ 2742; CHECK: @objc_msgSend 2743; CHECK-NOT: @objc_ 2744; CHECK: for.end: 2745; CHECK: } 2746define void @loop(i8* %x, i64 %n) { 2747entry: 2748 %0 = tail call i8* @objc_retain(i8* %x) nounwind 2749 %cmp9 = icmp sgt i64 %n, 0 2750 br i1 %cmp9, label %for.body, label %for.end 2751 2752for.body: ; preds = %entry, %for.body 2753 %i.010 = phi i64 [ %inc, %for.body ], [ 0, %entry ] 2754 %1 = tail call i8* @objc_retain(i8* %x) nounwind 2755 %tmp5 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8 2756 %call = tail call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %1, i8* %tmp5) 2757 tail call void @objc_release(i8* %1) nounwind, !clang.imprecise_release !0 2758 %inc = add nsw i64 %i.010, 1 2759 %exitcond = icmp eq i64 %inc, %n 2760 br i1 %exitcond, label %for.end, label %for.body 2761 2762for.end: ; preds = %for.body, %entry 2763 tail call void @objc_release(i8* %x) nounwind, !clang.imprecise_release !0 2764 ret void 2765} 2766 2767; ObjCARCOpt can delete the retain,release on self. 2768 2769; CHECK: define void @TextEditTest(%2* %self, %3* %pboard) { 2770; CHECK-NOT: call i8* @objc_retain(i8* %tmp7) 2771; CHECK: } 2772 2773%0 = type { i8* (i8*, %struct._message_ref_t*, ...)*, i8* } 2774%1 = type opaque 2775%2 = type opaque 2776%3 = type opaque 2777%4 = type opaque 2778%5 = type opaque 2779%struct.NSConstantString = type { i32*, i32, i8*, i64 } 2780%struct._NSRange = type { i64, i64 } 2781%struct.__CFString = type opaque 2782%struct.__method_list_t = type { i32, i32, [0 x %struct._objc_method] } 2783%struct._class_ro_t = type { i32, i32, i32, i8*, i8*, %struct.__method_list_t*, %struct._objc_protocol_list*, %struct._ivar_list_t*, i8*, %struct._prop_list_t* } 2784%struct._class_t = type { %struct._class_t*, %struct._class_t*, %struct._objc_cache*, i8* (i8*, i8*)**, %struct._class_ro_t* } 2785%struct._ivar_list_t = type { i32, i32, [0 x %struct._ivar_t] } 2786%struct._ivar_t = type { i64*, i8*, i8*, i32, i32 } 2787%struct._message_ref_t = type { i8*, i8* } 2788%struct._objc_cache = type opaque 2789%struct._objc_method = type { i8*, i8*, i8* } 2790%struct._objc_protocol_list = type { i64, [0 x %struct._protocol_t*] } 2791%struct._prop_list_t = type { i32, i32, [0 x %struct._message_ref_t] } 2792%struct._protocol_t = type { i8*, i8*, %struct._objc_protocol_list*, %struct.__method_list_t*, %struct.__method_list_t*, %struct.__method_list_t*, %struct.__method_list_t*, %struct._prop_list_t*, i32, i32 } 2793 2794@"\01L_OBJC_CLASSLIST_REFERENCES_$_17" = external hidden global %struct._class_t*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8 2795@kUTTypePlainText = external constant %struct.__CFString* 2796@"\01L_OBJC_SELECTOR_REFERENCES_19" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2797@"\01L_OBJC_SELECTOR_REFERENCES_21" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2798@"\01L_OBJC_SELECTOR_REFERENCES_23" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2799@"\01L_OBJC_SELECTOR_REFERENCES_25" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2800@"\01L_OBJC_CLASSLIST_REFERENCES_$_26" = external hidden global %struct._class_t*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8 2801@"\01L_OBJC_SELECTOR_REFERENCES_28" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2802@"\01L_OBJC_CLASSLIST_REFERENCES_$_29" = external hidden global %struct._class_t*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8 2803@"\01L_OBJC_SELECTOR_REFERENCES_31" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2804@"\01L_OBJC_SELECTOR_REFERENCES_33" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2805@"\01L_OBJC_SELECTOR_REFERENCES_35" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2806@"\01L_OBJC_SELECTOR_REFERENCES_37" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2807@"\01L_OBJC_CLASSLIST_REFERENCES_$_38" = external hidden global %struct._class_t*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8 2808@"\01L_OBJC_SELECTOR_REFERENCES_40" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2809@"\01L_OBJC_SELECTOR_REFERENCES_42" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2810@_unnamed_cfstring_44 = external hidden constant %struct.NSConstantString, section "__DATA,__cfstring" 2811@"\01L_OBJC_SELECTOR_REFERENCES_46" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2812@"\01L_OBJC_SELECTOR_REFERENCES_48" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2813@"\01l_objc_msgSend_fixup_isEqual_" = external hidden global %0, section "__DATA, __objc_msgrefs, coalesced", align 16 2814@"\01L_OBJC_CLASSLIST_REFERENCES_$_50" = external hidden global %struct._class_t*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8 2815@NSCocoaErrorDomain = external constant %1* 2816@"\01L_OBJC_CLASSLIST_REFERENCES_$_51" = external hidden global %struct._class_t*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8 2817@NSFilePathErrorKey = external constant %1* 2818@"\01L_OBJC_SELECTOR_REFERENCES_53" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2819@"\01L_OBJC_SELECTOR_REFERENCES_55" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2820@"\01L_OBJC_CLASSLIST_REFERENCES_$_56" = external hidden global %struct._class_t*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8 2821@"\01L_OBJC_SELECTOR_REFERENCES_58" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2822@"\01L_OBJC_SELECTOR_REFERENCES_60" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2823 2824declare %1* @truncatedString(%1*, i64) 2825define void @TextEditTest(%2* %self, %3* %pboard) { 2826entry: 2827 %err = alloca %4*, align 8 2828 %tmp7 = bitcast %2* %self to i8* 2829 %tmp8 = call i8* @objc_retain(i8* %tmp7) nounwind 2830 store %4* null, %4** %err, align 8 2831 %tmp1 = load %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_17", align 8 2832 %tmp2 = load %struct.__CFString** @kUTTypePlainText, align 8 2833 %tmp3 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_19", align 8 2834 %tmp4 = bitcast %struct._class_t* %tmp1 to i8* 2835 %call5 = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %tmp4, i8* %tmp3, %struct.__CFString* %tmp2) 2836 %tmp5 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_21", align 8 2837 %tmp6 = bitcast %3* %pboard to i8* 2838 %call76 = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %tmp6, i8* %tmp5, i8* %call5) 2839 %tmp9 = call i8* @objc_retain(i8* %call76) nounwind 2840 %tobool = icmp eq i8* %tmp9, null 2841 br i1 %tobool, label %end, label %land.lhs.true 2842 2843land.lhs.true: ; preds = %entry 2844 %tmp11 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_23", align 8 2845 %call137 = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %tmp6, i8* %tmp11, i8* %tmp9) 2846 %tmp = bitcast i8* %call137 to %1* 2847 %tmp10 = call i8* @objc_retain(i8* %call137) nounwind 2848 call void @objc_release(i8* null) nounwind 2849 %tmp12 = call i8* @objc_retain(i8* %call137) nounwind 2850 call void @objc_release(i8* null) nounwind 2851 %tobool16 = icmp eq i8* %call137, null 2852 br i1 %tobool16, label %end, label %if.then 2853 2854if.then: ; preds = %land.lhs.true 2855 %tmp19 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_25", align 8 2856 %call21 = call signext i8 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8 (i8*, i8*)*)(i8* %call137, i8* %tmp19) 2857 %tobool22 = icmp eq i8 %call21, 0 2858 br i1 %tobool22, label %if.then44, label %land.lhs.true23 2859 2860land.lhs.true23: ; preds = %if.then 2861 %tmp24 = load %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_26", align 8 2862 %tmp26 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_28", align 8 2863 %tmp27 = bitcast %struct._class_t* %tmp24 to i8* 2864 %call2822 = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %tmp27, i8* %tmp26, i8* %call137) 2865 %tmp13 = bitcast i8* %call2822 to %5* 2866 %tmp14 = call i8* @objc_retain(i8* %call2822) nounwind 2867 call void @objc_release(i8* null) nounwind 2868 %tobool30 = icmp eq i8* %call2822, null 2869 br i1 %tobool30, label %if.then44, label %if.end 2870 2871if.end: ; preds = %land.lhs.true23 2872 %tmp32 = load %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_29", align 8 2873 %tmp33 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_31", align 8 2874 %tmp34 = bitcast %struct._class_t* %tmp32 to i8* 2875 %call35 = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %tmp34, i8* %tmp33) 2876 %tmp37 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_33", align 8 2877 %call3923 = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %call35, i8* %tmp37, i8* %call2822, i32 signext 1, %4** %err) 2878 %cmp = icmp eq i8* %call3923, null 2879 br i1 %cmp, label %if.then44, label %end 2880 2881if.then44: ; preds = %if.end, %land.lhs.true23, %if.then 2882 %url.025 = phi %5* [ %tmp13, %if.end ], [ %tmp13, %land.lhs.true23 ], [ null, %if.then ] 2883 %tmp49 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_35", align 8 2884 %call51 = call %struct._NSRange bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to %struct._NSRange (i8*, i8*, i64, i64)*)(i8* %call137, i8* %tmp49, i64 0, i64 0) 2885 %call513 = extractvalue %struct._NSRange %call51, 0 2886 %call514 = extractvalue %struct._NSRange %call51, 1 2887 %tmp52 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_37", align 8 2888 %call548 = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %call137, i8* %tmp52, i64 %call513, i64 %call514) 2889 %tmp55 = load %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_38", align 8 2890 %tmp56 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_40", align 8 2891 %tmp57 = bitcast %struct._class_t* %tmp55 to i8* 2892 %call58 = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %tmp57, i8* %tmp56) 2893 %tmp59 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_42", align 8 2894 %call6110 = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %call548, i8* %tmp59, i8* %call58) 2895 %tmp15 = call i8* @objc_retain(i8* %call6110) nounwind 2896 call void @objc_release(i8* %call137) nounwind 2897 %tmp64 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_46", align 8 2898 %call66 = call signext i8 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8 (i8*, i8*, %1*)*)(i8* %call6110, i8* %tmp64, %1* bitcast (%struct.NSConstantString* @_unnamed_cfstring_44 to %1*)) 2899 %tobool67 = icmp eq i8 %call66, 0 2900 br i1 %tobool67, label %if.end74, label %if.then68 2901 2902if.then68: ; preds = %if.then44 2903 %tmp70 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_48", align 8 2904 %call7220 = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %call6110, i8* %tmp70) 2905 %tmp16 = call i8* @objc_retain(i8* %call7220) nounwind 2906 call void @objc_release(i8* %call6110) nounwind 2907 br label %if.end74 2908 2909if.end74: ; preds = %if.then68, %if.then44 2910 %filename.0.in = phi i8* [ %call7220, %if.then68 ], [ %call6110, %if.then44 ] 2911 %filename.0 = bitcast i8* %filename.0.in to %1* 2912 %tmp17 = load i8** bitcast (%0* @"\01l_objc_msgSend_fixup_isEqual_" to i8**), align 16 2913 %tmp18 = bitcast i8* %tmp17 to i8 (i8*, %struct._message_ref_t*, i8*, ...)* 2914 %call78 = call signext i8 (i8*, %struct._message_ref_t*, i8*, ...)* %tmp18(i8* %call137, %struct._message_ref_t* bitcast (%0* @"\01l_objc_msgSend_fixup_isEqual_" to %struct._message_ref_t*), i8* %filename.0.in) 2915 %tobool79 = icmp eq i8 %call78, 0 2916 br i1 %tobool79, label %land.lhs.true80, label %if.then109 2917 2918land.lhs.true80: ; preds = %if.end74 2919 %tmp82 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_25", align 8 2920 %call84 = call signext i8 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8 (i8*, i8*)*)(i8* %filename.0.in, i8* %tmp82) 2921 %tobool86 = icmp eq i8 %call84, 0 2922 br i1 %tobool86, label %if.then109, label %if.end106 2923 2924if.end106: ; preds = %land.lhs.true80 2925 %tmp88 = load %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_26", align 8 2926 %tmp90 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_28", align 8 2927 %tmp91 = bitcast %struct._class_t* %tmp88 to i8* 2928 %call9218 = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %tmp91, i8* %tmp90, i8* %filename.0.in) 2929 %tmp20 = bitcast i8* %call9218 to %5* 2930 %tmp21 = call i8* @objc_retain(i8* %call9218) nounwind 2931 %tmp22 = bitcast %5* %url.025 to i8* 2932 call void @objc_release(i8* %tmp22) nounwind 2933 %tmp94 = load %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_29", align 8 2934 %tmp95 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_31", align 8 2935 %tmp96 = bitcast %struct._class_t* %tmp94 to i8* 2936 %call97 = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %tmp96, i8* %tmp95) 2937 %tmp99 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_33", align 8 2938 %call10119 = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %call97, i8* %tmp99, i8* %call9218, i32 signext 1, %4** %err) 2939 %phitmp = icmp eq i8* %call10119, null 2940 br i1 %phitmp, label %if.then109, label %end 2941 2942if.then109: ; preds = %if.end106, %land.lhs.true80, %if.end74 2943 %url.129 = phi %5* [ %tmp20, %if.end106 ], [ %url.025, %if.end74 ], [ %url.025, %land.lhs.true80 ] 2944 %tmp110 = load %4** %err, align 8 2945 %tobool111 = icmp eq %4* %tmp110, null 2946 br i1 %tobool111, label %if.then112, label %if.end125 2947 2948if.then112: ; preds = %if.then109 2949 %tmp113 = load %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_50", align 8 2950 %tmp114 = load %1** @NSCocoaErrorDomain, align 8 2951 %tmp115 = load %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_51", align 8 2952 %call117 = call %1* @truncatedString(%1* %filename.0, i64 1034) 2953 %tmp118 = load %1** @NSFilePathErrorKey, align 8 2954 %tmp119 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_53", align 8 2955 %tmp120 = bitcast %struct._class_t* %tmp115 to i8* 2956 %call12113 = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %tmp120, i8* %tmp119, %1* %call117, %1* %tmp118, i8* null) 2957 %tmp122 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_55", align 8 2958 %tmp123 = bitcast %struct._class_t* %tmp113 to i8* 2959 %call12414 = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %tmp123, i8* %tmp122, %1* %tmp114, i64 258, i8* %call12113) 2960 %tmp23 = call i8* @objc_retain(i8* %call12414) nounwind 2961 %tmp25 = call i8* @objc_autorelease(i8* %tmp23) nounwind 2962 %tmp28 = bitcast i8* %tmp25 to %4* 2963 store %4* %tmp28, %4** %err, align 8 2964 br label %if.end125 2965 2966if.end125: ; preds = %if.then112, %if.then109 2967 %tmp127 = phi %4* [ %tmp110, %if.then109 ], [ %tmp28, %if.then112 ] 2968 %tmp126 = load %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_56", align 8 2969 %tmp128 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_58", align 8 2970 %tmp129 = bitcast %struct._class_t* %tmp126 to i8* 2971 %call13015 = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %tmp129, i8* %tmp128, %4* %tmp127) 2972 %tmp131 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_60", align 8 2973 %call13317 = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %call13015, i8* %tmp131) 2974 br label %end 2975 2976end: ; preds = %if.end125, %if.end106, %if.end, %land.lhs.true, %entry 2977 %filename.2 = phi %1* [ %filename.0, %if.end106 ], [ %filename.0, %if.end125 ], [ %tmp, %land.lhs.true ], [ null, %entry ], [ %tmp, %if.end ] 2978 %origFilename.0 = phi %1* [ %tmp, %if.end106 ], [ %tmp, %if.end125 ], [ %tmp, %land.lhs.true ], [ null, %entry ], [ %tmp, %if.end ] 2979 %url.2 = phi %5* [ %tmp20, %if.end106 ], [ %url.129, %if.end125 ], [ null, %land.lhs.true ], [ null, %entry ], [ %tmp13, %if.end ] 2980 call void @objc_release(i8* %tmp9) nounwind, !clang.imprecise_release !0 2981 %tmp29 = bitcast %5* %url.2 to i8* 2982 call void @objc_release(i8* %tmp29) nounwind, !clang.imprecise_release !0 2983 %tmp30 = bitcast %1* %origFilename.0 to i8* 2984 call void @objc_release(i8* %tmp30) nounwind, !clang.imprecise_release !0 2985 %tmp31 = bitcast %1* %filename.2 to i8* 2986 call void @objc_release(i8* %tmp31) nounwind, !clang.imprecise_release !0 2987 call void @objc_release(i8* %tmp7) nounwind, !clang.imprecise_release !0 2988 ret void 2989} 2990 2991declare i32 @__gxx_personality_v0(...) 2992 2993declare i32 @objc_sync_enter(i8*) 2994declare i32 @objc_sync_exit(i8*) 2995 2996; Make sure that we understand that objc_sync_{enter,exit} are IC_User not 2997; IC_Call/IC_CallOrUser. 2998 2999; CHECK-LABEL: define void @test67( 3000; CHECK-NEXT: call i32 @objc_sync_enter(i8* %x) 3001; CHECK-NEXT: call i32 @objc_sync_exit(i8* %x) 3002; CHECK-NEXT: ret void 3003; CHECK-NEXT: } 3004define void @test67(i8* %x) { 3005 call i8* @objc_retain(i8* %x) 3006 call i32 @objc_sync_enter(i8* %x) 3007 call i32 @objc_sync_exit(i8* %x) 3008 call void @objc_release(i8* %x), !clang.imprecise_release !0 3009 ret void 3010} 3011 3012!llvm.module.flags = !{!1} 3013 3014!0 = metadata !{} 3015!1 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} 3016 3017; CHECK: attributes #0 = { nounwind readnone } 3018; CHECK: attributes [[NUW]] = { nounwind } 3019; CHECK: ![[RELEASE]] = metadata !{} 3020