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, 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, 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, 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, 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, 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; We can not delete this retain, release since we do not have a post-dominating 904; use of the release. 905 906; CHECK-LABEL: define void @test12( 907; CHECK-NEXT: entry: 908; CHECK-NEXT: @objc_retain(i8* %x) 909; CHECK-NEXT: @objc_retain 910; CHECK: @objc_release 911; CHECK: } 912define void @test12(i8* %x, i64 %n) { 913entry: 914 call i8* @objc_retain(i8* %x) nounwind 915 call i8* @objc_retain(i8* %x) nounwind 916 call void @use_pointer(i8* %x) 917 call void @use_pointer(i8* %x) 918 call void @objc_release(i8* %x) nounwind 919 ret void 920} 921 922; Trivial retain,autorelease pair. Don't delete! 923 924; CHECK-LABEL: define void @test13( 925; CHECK: tail call i8* @objc_retain(i8* %x) [[NUW]] 926; CHECK: tail call i8* @objc_retain(i8* %x) [[NUW]] 927; CHECK: @use_pointer(i8* %x) 928; CHECK: call i8* @objc_autorelease(i8* %x) [[NUW]] 929; CHECK: } 930define void @test13(i8* %x, i64 %n) { 931entry: 932 call i8* @objc_retain(i8* %x) nounwind 933 call i8* @objc_retain(i8* %x) nounwind 934 call void @use_pointer(i8* %x) 935 call i8* @objc_autorelease(i8* %x) nounwind 936 ret void 937} 938 939; Delete the retain+release pair. 940 941; CHECK-LABEL: define void @test13b( 942; CHECK-NEXT: entry: 943; CHECK-NEXT: @objc_retain(i8* %x) 944; CHECK-NEXT: @use_pointer 945; CHECK-NEXT: @use_pointer 946; CHECK-NEXT: @use_pointer 947; CHECK-NEXT: @objc_release 948; CHECK-NEXT: ret void 949; CHECK-NEXT: } 950define void @test13b(i8* %x, i64 %n) { 951entry: 952 call i8* @objc_retain(i8* %x) nounwind 953 call i8* @objc_retain(i8* %x) nounwind 954 call void @use_pointer(i8* %x) 955 call void @use_pointer(i8* %x) 956 call void @objc_release(i8* %x) nounwind 957 call void @use_pointer(i8* %x) 958 call void @objc_release(i8* %x) nounwind 959 ret void 960} 961 962; Don't delete the retain+release pair because there's an 963; autoreleasePoolPop in the way. 964 965; CHECK-LABEL: define void @test13c( 966; CHECK: @objc_retain(i8* %x) 967; CHECK: @objc_autoreleasePoolPop 968; CHECK: @objc_retain(i8* %x) 969; CHECK: @use_pointer 970; CHECK: @objc_release 971; CHECK: } 972define void @test13c(i8* %x, i64 %n) { 973entry: 974 call i8* @objc_retain(i8* %x) nounwind 975 call void @objc_autoreleasePoolPop(i8* undef) 976 call i8* @objc_retain(i8* %x) nounwind 977 call void @use_pointer(i8* %x) 978 call void @use_pointer(i8* %x) 979 call void @objc_release(i8* %x) nounwind 980 ret void 981} 982 983; Like test13c, but there's an autoreleasePoolPush in the way, but that 984; doesn't matter. 985 986; CHECK-LABEL: define void @test13d( 987; CHECK-NEXT: entry: 988; CHECK-NEXT: @objc_retain(i8* %x) 989; CHECK-NEXT: @objc_autoreleasePoolPush 990; CHECK-NEXT: @use_pointer 991; CHECK-NEXT: @use_pointer 992; CHECK-NEXT: @use_pointer 993; CHECK-NEXT: @objc_release 994; CHECK-NEXT: ret void 995; CHECK-NEXT: } 996define void @test13d(i8* %x, i64 %n) { 997entry: 998 call i8* @objc_retain(i8* %x) nounwind 999 call i8* @objc_autoreleasePoolPush() 1000 call i8* @objc_retain(i8* %x) nounwind 1001 call void @use_pointer(i8* %x) 1002 call void @use_pointer(i8* %x) 1003 call void @objc_release(i8* %x) nounwind 1004 call void @use_pointer(i8* %x) 1005 call void @objc_release(i8* %x) nounwind 1006 ret void 1007} 1008 1009; Trivial retain,release pair with intervening call, and it's post-dominated by 1010; another release. But it is not known safe in the top down direction. We can 1011; not eliminate it. 1012 1013; CHECK-LABEL: define void @test14( 1014; CHECK-NEXT: entry: 1015; CHECK-NEXT: @objc_retain 1016; CHECK-NEXT: @use_pointer 1017; CHECK-NEXT: @use_pointer 1018; CHECK-NEXT: @objc_release 1019; CHECK-NEXT: @objc_release 1020; CHECK-NEXT: ret void 1021; CHECK-NEXT: } 1022define void @test14(i8* %x, i64 %n) { 1023entry: 1024 call i8* @objc_retain(i8* %x) nounwind 1025 call void @use_pointer(i8* %x) 1026 call void @use_pointer(i8* %x) 1027 call void @objc_release(i8* %x) nounwind 1028 call void @objc_release(i8* %x) nounwind 1029 ret void 1030} 1031 1032; Trivial retain,autorelease pair with intervening call, but it's post-dominated 1033; by another release. Don't delete anything. 1034 1035; CHECK-LABEL: define void @test15( 1036; CHECK-NEXT: entry: 1037; CHECK-NEXT: @objc_retain(i8* %x) 1038; CHECK-NEXT: @use_pointer 1039; CHECK-NEXT: @objc_autorelease(i8* %x) 1040; CHECK-NEXT: @objc_release 1041; CHECK-NEXT: ret void 1042; CHECK-NEXT: } 1043define void @test15(i8* %x, i64 %n) { 1044entry: 1045 call i8* @objc_retain(i8* %x) nounwind 1046 call void @use_pointer(i8* %x) 1047 call i8* @objc_autorelease(i8* %x) nounwind 1048 call void @objc_release(i8* %x) nounwind 1049 ret void 1050} 1051 1052; Trivial retain,autorelease pair, post-dominated 1053; by another release. Delete the retain and release. 1054 1055; CHECK-LABEL: define void @test15b( 1056; CHECK-NEXT: entry: 1057; CHECK-NEXT: @objc_retain 1058; CHECK-NEXT: @objc_autorelease 1059; CHECK-NEXT: @objc_release 1060; CHECK-NEXT: ret void 1061; CHECK-NEXT: } 1062define void @test15b(i8* %x, i64 %n) { 1063entry: 1064 call i8* @objc_retain(i8* %x) nounwind 1065 call i8* @objc_autorelease(i8* %x) nounwind 1066 call void @objc_release(i8* %x) nounwind 1067 ret void 1068} 1069 1070; CHECK-LABEL: define void @test15c( 1071; CHECK-NEXT: entry: 1072; CHECK-NEXT: @objc_autorelease 1073; CHECK-NEXT: ret void 1074; CHECK-NEXT: } 1075define void @test15c(i8* %x, i64 %n) { 1076entry: 1077 call i8* @objc_retain(i8* %x) nounwind 1078 call i8* @objc_autorelease(i8* %x) nounwind 1079 call void @objc_release(i8* %x) nounwind, !clang.imprecise_release !0 1080 ret void 1081} 1082 1083; Retain+release pairs in diamonds, all dominated by a retain. 1084 1085; CHECK-LABEL: define void @test16a( 1086; CHECK: @objc_retain(i8* %x) 1087; CHECK-NOT: @objc 1088; CHECK: purple: 1089; CHECK: @use_pointer 1090; CHECK: @objc_release 1091; CHECK: } 1092define void @test16a(i1 %a, i1 %b, i8* %x) { 1093entry: 1094 call i8* @objc_retain(i8* %x) nounwind 1095 br i1 %a, label %red, label %orange 1096 1097red: 1098 call i8* @objc_retain(i8* %x) nounwind 1099 br label %yellow 1100 1101orange: 1102 call i8* @objc_retain(i8* %x) nounwind 1103 br label %yellow 1104 1105yellow: 1106 call void @use_pointer(i8* %x) 1107 call void @use_pointer(i8* %x) 1108 br i1 %b, label %green, label %blue 1109 1110green: 1111 call void @objc_release(i8* %x) nounwind 1112 br label %purple 1113 1114blue: 1115 call void @objc_release(i8* %x) nounwind 1116 br label %purple 1117 1118purple: 1119 call void @use_pointer(i8* %x) 1120 call void @objc_release(i8* %x) nounwind 1121 ret void 1122} 1123 1124; CHECK-LABEL: define void @test16b( 1125; CHECK: @objc_retain(i8* %x) 1126; CHECK-NOT: @objc 1127; CHECK: purple: 1128; CHECK-NEXT: @use_pointer 1129; CHECK-NEXT: @use_pointer 1130; CHECK-NEXT: @objc_release 1131; CHECK: } 1132define void @test16b(i1 %a, i1 %b, i8* %x) { 1133entry: 1134 call i8* @objc_retain(i8* %x) nounwind 1135 br i1 %a, label %red, label %orange 1136 1137red: 1138 call i8* @objc_retain(i8* %x) nounwind 1139 br label %yellow 1140 1141orange: 1142 call i8* @objc_retain(i8* %x) nounwind 1143 br label %yellow 1144 1145yellow: 1146 call void @use_pointer(i8* %x) 1147 call void @use_pointer(i8* %x) 1148 br i1 %b, label %green, label %blue 1149 1150green: 1151 call void @objc_release(i8* %x) nounwind, !clang.imprecise_release !0 1152 br label %purple 1153 1154blue: 1155 call void @objc_release(i8* %x) nounwind 1156 br label %purple 1157 1158purple: 1159 call void @use_pointer(i8* %x) 1160 call void @use_pointer(i8* %x) 1161 call void @objc_release(i8* %x) nounwind 1162 ret void 1163} 1164 1165; CHECK-LABEL: define void @test16c( 1166; CHECK: @objc_retain(i8* %x) 1167; CHECK-NOT: @objc 1168; CHECK: purple: 1169; CHECK: @use_pointer 1170; CHECK: @objc_release 1171; CHECK: } 1172define void @test16c(i1 %a, i1 %b, i8* %x) { 1173entry: 1174 call i8* @objc_retain(i8* %x) nounwind 1175 br i1 %a, label %red, label %orange 1176 1177red: 1178 call i8* @objc_retain(i8* %x) nounwind 1179 br label %yellow 1180 1181orange: 1182 call i8* @objc_retain(i8* %x) nounwind 1183 br label %yellow 1184 1185yellow: 1186 call void @use_pointer(i8* %x) 1187 call void @use_pointer(i8* %x) 1188 br i1 %b, label %green, label %blue 1189 1190green: 1191 call void @objc_release(i8* %x) nounwind, !clang.imprecise_release !0 1192 br label %purple 1193 1194blue: 1195 call void @objc_release(i8* %x) nounwind, !clang.imprecise_release !0 1196 br label %purple 1197 1198purple: 1199 call void @use_pointer(i8* %x) 1200 call void @objc_release(i8* %x) nounwind, !clang.imprecise_release !0 1201 ret void 1202} 1203 1204; CHECK-LABEL: define void @test16d( 1205; CHECK: @objc_retain(i8* %x) 1206; CHECK: @objc 1207; CHECK: } 1208define void @test16d(i1 %a, i1 %b, i8* %x) { 1209entry: 1210 call i8* @objc_retain(i8* %x) nounwind 1211 br i1 %a, label %red, label %orange 1212 1213red: 1214 call i8* @objc_retain(i8* %x) nounwind 1215 br label %yellow 1216 1217orange: 1218 call i8* @objc_retain(i8* %x) nounwind 1219 br label %yellow 1220 1221yellow: 1222 call void @use_pointer(i8* %x) 1223 call void @use_pointer(i8* %x) 1224 br i1 %b, label %green, label %blue 1225 1226green: 1227 call void @objc_release(i8* %x) nounwind 1228 br label %purple 1229 1230blue: 1231 call void @objc_release(i8* %x) nounwind, !clang.imprecise_release !0 1232 br label %purple 1233 1234purple: 1235 ret void 1236} 1237 1238; Delete no-ops. 1239 1240; CHECK-LABEL: define void @test18( 1241; CHECK-NOT: @objc_ 1242; CHECK: } 1243define void @test18() { 1244 call i8* @objc_retain(i8* null) 1245 call void @objc_release(i8* null) 1246 call i8* @objc_autorelease(i8* null) 1247 ret void 1248} 1249 1250; Delete no-ops where undef can be assumed to be null. 1251 1252; CHECK-LABEL: define void @test18b( 1253; CHECK-NOT: @objc_ 1254; CHECK: } 1255define void @test18b() { 1256 call i8* @objc_retain(i8* undef) 1257 call void @objc_release(i8* undef) 1258 call i8* @objc_autorelease(i8* undef) 1259 ret void 1260} 1261 1262; Replace uses of arguments with uses of return values, to reduce 1263; register pressure. 1264 1265; CHECK: define void @test19(i32* %y) { 1266; CHECK: %z = bitcast i32* %y to i8* 1267; CHECK: %0 = bitcast i32* %y to i8* 1268; CHECK: %1 = tail call i8* @objc_retain(i8* %0) 1269; CHECK: call void @use_pointer(i8* %z) 1270; CHECK: call void @use_pointer(i8* %z) 1271; CHECK: %2 = bitcast i32* %y to i8* 1272; CHECK: call void @objc_release(i8* %2) 1273; CHECK: ret void 1274; CHECK: } 1275define void @test19(i32* %y) { 1276entry: 1277 %x = bitcast i32* %y to i8* 1278 %0 = call i8* @objc_retain(i8* %x) nounwind 1279 %z = bitcast i32* %y to i8* 1280 call void @use_pointer(i8* %z) 1281 call void @use_pointer(i8* %z) 1282 call void @objc_release(i8* %x) 1283 ret void 1284} 1285 1286; Bitcast insertion 1287 1288; CHECK-LABEL: define void @test20( 1289; CHECK: %tmp1 = tail call i8* @objc_retain(i8* %tmp) [[NUW]] 1290; CHECK-NEXT: invoke 1291; CHECK: } 1292define void @test20(double* %self) personality i32 (...)* @__gxx_personality_v0 { 1293if.then12: 1294 %tmp = bitcast double* %self to i8* 1295 %tmp1 = call i8* @objc_retain(i8* %tmp) nounwind 1296 invoke void @invokee() 1297 to label %invoke.cont23 unwind label %lpad20 1298 1299invoke.cont23: ; preds = %if.then12 1300 invoke void @invokee() 1301 to label %if.end unwind label %lpad20 1302 1303lpad20: ; preds = %invoke.cont23, %if.then12 1304 %tmp502 = phi double* [ undef, %invoke.cont23 ], [ %self, %if.then12 ] 1305 %exn = landingpad {i8*, i32} 1306 cleanup 1307 unreachable 1308 1309if.end: ; preds = %invoke.cont23 1310 ret void 1311} 1312 1313; Delete a redundant retain,autorelease when forwaring a call result 1314; directly to a return value. 1315 1316; CHECK-LABEL: define i8* @test21( 1317; CHECK: call i8* @returner() 1318; CHECK-NEXT: ret i8* %call 1319; CHECK-NEXT: } 1320define i8* @test21() { 1321entry: 1322 %call = call i8* @returner() 1323 %0 = call i8* @objc_retain(i8* %call) nounwind 1324 %1 = call i8* @objc_autorelease(i8* %0) nounwind 1325 ret i8* %1 1326} 1327 1328; Move an objc call up through a phi that has null operands. 1329 1330; CHECK-LABEL: define void @test22( 1331; CHECK: B: 1332; CHECK: %1 = bitcast double* %p to i8* 1333; CHECK: call void @objc_release(i8* %1) 1334; CHECK: br label %C 1335; CHECK: C: ; preds = %B, %A 1336; CHECK-NOT: @objc_release 1337; CHECK: } 1338define void @test22(double* %p, i1 %a) { 1339 br i1 %a, label %A, label %B 1340A: 1341 br label %C 1342B: 1343 br label %C 1344C: 1345 %h = phi double* [ null, %A ], [ %p, %B ] 1346 %c = bitcast double* %h to i8* 1347 call void @objc_release(i8* %c) 1348 ret void 1349} 1350 1351; Any call can decrement a retain count. 1352 1353; CHECK-LABEL: define void @test24( 1354; CHECK: @objc_retain(i8* %a) 1355; CHECK: @objc_release 1356; CHECK: } 1357define void @test24(i8* %r, i8* %a) { 1358 call i8* @objc_retain(i8* %a) 1359 call void @use_pointer(i8* %r) 1360 %q = load i8, i8* %a 1361 call void @objc_release(i8* %a) 1362 ret void 1363} 1364 1365; Don't move a retain/release pair if the release can be moved 1366; but the retain can't be moved to balance it. 1367 1368; CHECK-LABEL: define void @test25( 1369; CHECK: entry: 1370; CHECK: call i8* @objc_retain(i8* %p) 1371; CHECK: true: 1372; CHECK: done: 1373; CHECK: call void @objc_release(i8* %p) 1374; CHECK: } 1375define void @test25(i8* %p, i1 %x) { 1376entry: 1377 %f0 = call i8* @objc_retain(i8* %p) 1378 call void @callee() 1379 br i1 %x, label %true, label %done 1380 1381true: 1382 store i8 0, i8* %p 1383 br label %done 1384 1385done: 1386 call void @objc_release(i8* %p) 1387 ret void 1388} 1389 1390; Don't move a retain/release pair if the retain can be moved 1391; but the release can't be moved to balance it. 1392 1393; CHECK-LABEL: define void @test26( 1394; CHECK: entry: 1395; CHECK: call i8* @objc_retain(i8* %p) 1396; CHECK: true: 1397; CHECK: done: 1398; CHECK: call void @objc_release(i8* %p) 1399; CHECK: } 1400define void @test26(i8* %p, i1 %x) { 1401entry: 1402 %f0 = call i8* @objc_retain(i8* %p) 1403 br i1 %x, label %true, label %done 1404 1405true: 1406 call void @callee() 1407 br label %done 1408 1409done: 1410 store i8 0, i8* %p 1411 call void @objc_release(i8* %p) 1412 ret void 1413} 1414 1415; Don't sink the retain,release into the loop. 1416 1417; CHECK-LABEL: define void @test27( 1418; CHECK: entry: 1419; CHECK: call i8* @objc_retain(i8* %p) 1420; CHECK: loop: 1421; CHECK-NOT: @objc_ 1422; CHECK: done: 1423; CHECK: call void @objc_release 1424; CHECK: } 1425define void @test27(i8* %p, i1 %x, i1 %y) { 1426entry: 1427 %f0 = call i8* @objc_retain(i8* %p) 1428 br i1 %x, label %loop, label %done 1429 1430loop: 1431 call void @callee() 1432 store i8 0, i8* %p 1433 br i1 %y, label %done, label %loop 1434 1435done: 1436 call void @objc_release(i8* %p) 1437 ret void 1438} 1439 1440; Trivial code motion case: Triangle. 1441 1442; CHECK-LABEL: define void @test28( 1443; CHECK-NOT: @objc_ 1444; CHECK: true: 1445; CHECK: call i8* @objc_retain( 1446; CHECK: call void @callee() 1447; CHECK: store 1448; CHECK: call void @objc_release 1449; CHECK: done: 1450; CHECK-NOT: @objc_ 1451; CHECK: } 1452define void @test28(i8* %p, i1 %x) { 1453entry: 1454 %f0 = call i8* @objc_retain(i8* %p) 1455 br i1 %x, label %true, label %done 1456 1457true: 1458 call void @callee() 1459 store i8 0, i8* %p 1460 br label %done 1461 1462done: 1463 call void @objc_release(i8* %p), !clang.imprecise_release !0 1464 ret void 1465} 1466 1467; Trivial code motion case: Triangle, but no metadata. Don't move past 1468; unrelated memory references! 1469 1470; CHECK-LABEL: define void @test28b( 1471; CHECK: call i8* @objc_retain( 1472; CHECK: true: 1473; CHECK-NOT: @objc_ 1474; CHECK: call void @callee() 1475; CHECK-NOT: @objc_ 1476; CHECK: store 1477; CHECK-NOT: @objc_ 1478; CHECK: done: 1479; CHECK: @objc_release 1480; CHECK: } 1481define void @test28b(i8* %p, i1 %x, i8* noalias %t) { 1482entry: 1483 %f0 = call i8* @objc_retain(i8* %p) 1484 br i1 %x, label %true, label %done 1485 1486true: 1487 call void @callee() 1488 store i8 0, i8* %p 1489 br label %done 1490 1491done: 1492 store i8 0, i8* %t 1493 call void @objc_release(i8* %p) 1494 ret void 1495} 1496 1497; Trivial code motion case: Triangle, with metadata. Do move past 1498; unrelated memory references! And preserve the metadata. 1499 1500; CHECK-LABEL: define void @test28c( 1501; CHECK-NOT: @objc_ 1502; CHECK: true: 1503; CHECK: call i8* @objc_retain( 1504; CHECK: call void @callee() 1505; CHECK: store 1506; CHECK: call void @objc_release(i8* %p) [[NUW]], !clang.imprecise_release 1507; CHECK: done: 1508; CHECK-NOT: @objc_ 1509; CHECK: } 1510define void @test28c(i8* %p, i1 %x, i8* noalias %t) { 1511entry: 1512 %f0 = call i8* @objc_retain(i8* %p) 1513 br i1 %x, label %true, label %done 1514 1515true: 1516 call void @callee() 1517 store i8 0, i8* %p 1518 br label %done 1519 1520done: 1521 store i8 0, i8* %t 1522 call void @objc_release(i8* %p), !clang.imprecise_release !0 1523 ret void 1524} 1525 1526; Like test28. but with two releases. 1527 1528; CHECK-LABEL: define void @test29( 1529; CHECK-NOT: @objc_ 1530; CHECK: true: 1531; CHECK: call i8* @objc_retain( 1532; CHECK: call void @callee() 1533; CHECK: store 1534; CHECK: call void @objc_release 1535; CHECK-NOT: @objc_release 1536; CHECK: done: 1537; CHECK-NOT: @objc_ 1538; CHECK: ohno: 1539; CHECK-NOT: @objc_ 1540; CHECK: } 1541define void @test29(i8* %p, i1 %x, i1 %y) { 1542entry: 1543 %f0 = call i8* @objc_retain(i8* %p) 1544 br i1 %x, label %true, label %done 1545 1546true: 1547 call void @callee() 1548 store i8 0, i8* %p 1549 br i1 %y, label %done, label %ohno 1550 1551done: 1552 call void @objc_release(i8* %p) 1553 ret void 1554 1555ohno: 1556 call void @objc_release(i8* %p) 1557 ret void 1558} 1559 1560; Basic case with the use and call in a diamond 1561; with an extra release. 1562 1563; CHECK-LABEL: define void @test30( 1564; CHECK-NOT: @objc_ 1565; CHECK: true: 1566; CHECK: call i8* @objc_retain( 1567; CHECK: call void @callee() 1568; CHECK: store 1569; CHECK: call void @objc_release 1570; CHECK-NOT: @objc_release 1571; CHECK: false: 1572; CHECK-NOT: @objc_ 1573; CHECK: done: 1574; CHECK-NOT: @objc_ 1575; CHECK: ohno: 1576; CHECK-NOT: @objc_ 1577; CHECK: } 1578define void @test30(i8* %p, i1 %x, i1 %y, i1 %z) { 1579entry: 1580 %f0 = call i8* @objc_retain(i8* %p) 1581 br i1 %x, label %true, label %false 1582 1583true: 1584 call void @callee() 1585 store i8 0, i8* %p 1586 br i1 %y, label %done, label %ohno 1587 1588false: 1589 br i1 %z, label %done, label %ohno 1590 1591done: 1592 call void @objc_release(i8* %p) 1593 ret void 1594 1595ohno: 1596 call void @objc_release(i8* %p) 1597 ret void 1598} 1599 1600; Basic case with a mergeable release. 1601 1602; CHECK-LABEL: define void @test31( 1603; CHECK: call i8* @objc_retain(i8* %p) 1604; CHECK: call void @callee() 1605; CHECK: store 1606; CHECK: call void @objc_release 1607; CHECK-NOT: @objc_release 1608; CHECK: true: 1609; CHECK-NOT: @objc_release 1610; CHECK: false: 1611; CHECK-NOT: @objc_release 1612; CHECK: ret void 1613; CHECK-NOT: @objc_release 1614; CHECK: } 1615define void @test31(i8* %p, i1 %x) { 1616entry: 1617 %f0 = call i8* @objc_retain(i8* %p) 1618 call void @callee() 1619 store i8 0, i8* %p 1620 br i1 %x, label %true, label %false 1621true: 1622 call void @objc_release(i8* %p) 1623 ret void 1624false: 1625 call void @objc_release(i8* %p) 1626 ret void 1627} 1628 1629; Don't consider bitcasts or getelementptrs direct uses. 1630 1631; CHECK-LABEL: define void @test32( 1632; CHECK-NOT: @objc_ 1633; CHECK: true: 1634; CHECK: call i8* @objc_retain( 1635; CHECK: call void @callee() 1636; CHECK: store 1637; CHECK: call void @objc_release 1638; CHECK: done: 1639; CHECK-NOT: @objc_ 1640; CHECK: } 1641define void @test32(i8* %p, i1 %x) { 1642entry: 1643 %f0 = call i8* @objc_retain(i8* %p) 1644 br i1 %x, label %true, label %done 1645 1646true: 1647 call void @callee() 1648 store i8 0, i8* %p 1649 br label %done 1650 1651done: 1652 %g = bitcast i8* %p to i8* 1653 %h = getelementptr i8, i8* %g, i64 0 1654 call void @objc_release(i8* %g) 1655 ret void 1656} 1657 1658; Do consider icmps to be direct uses. 1659 1660; CHECK-LABEL: define void @test33( 1661; CHECK-NOT: @objc_ 1662; CHECK: true: 1663; CHECK: call i8* @objc_retain( 1664; CHECK: call void @callee() 1665; CHECK: icmp 1666; CHECK: call void @objc_release 1667; CHECK: done: 1668; CHECK-NOT: @objc_ 1669; CHECK: } 1670define void @test33(i8* %p, i1 %x, i8* %y) { 1671entry: 1672 %f0 = call i8* @objc_retain(i8* %p) 1673 br i1 %x, label %true, label %done 1674 1675true: 1676 call void @callee() 1677 %v = icmp eq i8* %p, %y 1678 br label %done 1679 1680done: 1681 %g = bitcast i8* %p to i8* 1682 %h = getelementptr i8, i8* %g, i64 0 1683 call void @objc_release(i8* %g) 1684 ret void 1685} 1686 1687; Delete retain,release if there's just a possible dec and we have imprecise 1688; releases. 1689 1690; CHECK-LABEL: define void @test34a( 1691; CHECK: call i8* @objc_retain 1692; CHECK: true: 1693; CHECK: done: 1694; CHECK: call void @objc_release 1695; CHECK: } 1696define void @test34a(i8* %p, i1 %x, i8* %y) { 1697entry: 1698 %f0 = call i8* @objc_retain(i8* %p) 1699 br i1 %x, label %true, label %done 1700 1701true: 1702 call void @callee() 1703 br label %done 1704 1705done: 1706 %g = bitcast i8* %p to i8* 1707 %h = getelementptr i8, i8* %g, i64 0 1708 call void @objc_release(i8* %g) 1709 ret void 1710} 1711 1712; CHECK-LABEL: define void @test34b( 1713; CHECK-NOT: @objc_ 1714; CHECK: } 1715define void @test34b(i8* %p, i1 %x, i8* %y) { 1716entry: 1717 %f0 = call i8* @objc_retain(i8* %p) 1718 br i1 %x, label %true, label %done 1719 1720true: 1721 call void @callee() 1722 br label %done 1723 1724done: 1725 %g = bitcast i8* %p to i8* 1726 %h = getelementptr i8, i8* %g, i64 0 1727 call void @objc_release(i8* %g), !clang.imprecise_release !0 1728 ret void 1729} 1730 1731 1732; Delete retain,release if there's just a use and we do not have a precise 1733; release. 1734 1735; Precise. 1736; CHECK-LABEL: define void @test35a( 1737; CHECK: entry: 1738; CHECK: call i8* @objc_retain 1739; CHECK: true: 1740; CHECK: done: 1741; CHECK: call void @objc_release 1742; CHECK: } 1743define void @test35a(i8* %p, i1 %x, i8* %y) { 1744entry: 1745 %f0 = call i8* @objc_retain(i8* %p) 1746 br i1 %x, label %true, label %done 1747 1748true: 1749 %v = icmp eq i8* %p, %y 1750 br label %done 1751 1752done: 1753 %g = bitcast i8* %p to i8* 1754 %h = getelementptr i8, i8* %g, i64 0 1755 call void @objc_release(i8* %g) 1756 ret void 1757} 1758 1759; Imprecise. 1760; CHECK-LABEL: define void @test35b( 1761; CHECK-NOT: @objc_ 1762; CHECK: } 1763define void @test35b(i8* %p, i1 %x, i8* %y) { 1764entry: 1765 %f0 = call i8* @objc_retain(i8* %p) 1766 br i1 %x, label %true, label %done 1767 1768true: 1769 %v = icmp eq i8* %p, %y 1770 br label %done 1771 1772done: 1773 %g = bitcast i8* %p to i8* 1774 %h = getelementptr i8, i8* %g, i64 0 1775 call void @objc_release(i8* %g), !clang.imprecise_release !0 1776 ret void 1777} 1778 1779; Delete a retain,release if there's no actual use and we have precise release. 1780 1781; CHECK-LABEL: define void @test36a( 1782; CHECK: @objc_retain 1783; CHECK: call void @callee() 1784; CHECK-NOT: @objc_ 1785; CHECK: call void @callee() 1786; CHECK: @objc_release 1787; CHECK: } 1788define void @test36a(i8* %p) { 1789entry: 1790 call i8* @objc_retain(i8* %p) 1791 call void @callee() 1792 call void @callee() 1793 call void @objc_release(i8* %p) 1794 ret void 1795} 1796 1797; Like test36, but with metadata. 1798 1799; CHECK-LABEL: define void @test36b( 1800; CHECK-NOT: @objc_ 1801; CHECK: } 1802define void @test36b(i8* %p) { 1803entry: 1804 call i8* @objc_retain(i8* %p) 1805 call void @callee() 1806 call void @callee() 1807 call void @objc_release(i8* %p), !clang.imprecise_release !0 1808 ret void 1809} 1810 1811; Be aggressive about analyzing phis to eliminate possible uses. 1812 1813; CHECK-LABEL: define void @test38( 1814; CHECK-NOT: @objc_ 1815; CHECK: } 1816define void @test38(i8* %p, i1 %u, i1 %m, i8* %z, i8* %y, i8* %x, i8* %w) { 1817entry: 1818 call i8* @objc_retain(i8* %p) 1819 br i1 %u, label %true, label %false 1820true: 1821 br i1 %m, label %a, label %b 1822false: 1823 br i1 %m, label %c, label %d 1824a: 1825 br label %e 1826b: 1827 br label %e 1828c: 1829 br label %f 1830d: 1831 br label %f 1832e: 1833 %j = phi i8* [ %z, %a ], [ %y, %b ] 1834 br label %g 1835f: 1836 %k = phi i8* [ %w, %c ], [ %x, %d ] 1837 br label %g 1838g: 1839 %h = phi i8* [ %j, %e ], [ %k, %f ] 1840 call void @use_pointer(i8* %h) 1841 call void @objc_release(i8* %p), !clang.imprecise_release !0 1842 ret void 1843} 1844 1845; Delete retain,release pairs around loops. 1846 1847; CHECK-LABEL: define void @test39( 1848; CHECK-NOT: @objc_ 1849; CHECK: } 1850define void @test39(i8* %p) { 1851entry: 1852 %0 = call i8* @objc_retain(i8* %p) 1853 br label %loop 1854 1855loop: ; preds = %loop, %entry 1856 br i1 undef, label %loop, label %exit 1857 1858exit: ; preds = %loop 1859 call void @objc_release(i8* %0), !clang.imprecise_release !0 1860 ret void 1861} 1862 1863; Delete retain,release pairs around loops containing uses. 1864 1865; CHECK-LABEL: define void @test39b( 1866; CHECK-NOT: @objc_ 1867; CHECK: } 1868define void @test39b(i8* %p) { 1869entry: 1870 %0 = call i8* @objc_retain(i8* %p) 1871 br label %loop 1872 1873loop: ; preds = %loop, %entry 1874 store i8 0, i8* %0 1875 br i1 undef, label %loop, label %exit 1876 1877exit: ; preds = %loop 1878 call void @objc_release(i8* %0), !clang.imprecise_release !0 1879 ret void 1880} 1881 1882; Delete retain,release pairs around loops containing potential decrements. 1883 1884; CHECK-LABEL: define void @test39c( 1885; CHECK-NOT: @objc_ 1886; CHECK: } 1887define void @test39c(i8* %p) { 1888entry: 1889 %0 = call i8* @objc_retain(i8* %p) 1890 br label %loop 1891 1892loop: ; preds = %loop, %entry 1893 call void @use_pointer(i8* %0) 1894 br i1 undef, label %loop, label %exit 1895 1896exit: ; preds = %loop 1897 call void @objc_release(i8* %0), !clang.imprecise_release !0 1898 ret void 1899} 1900 1901; Delete retain,release pairs around loops even if 1902; the successors are in a different order. 1903 1904; CHECK-LABEL: define void @test40( 1905; CHECK-NOT: @objc_ 1906; CHECK: } 1907define void @test40(i8* %p) { 1908entry: 1909 %0 = call i8* @objc_retain(i8* %p) 1910 br label %loop 1911 1912loop: ; preds = %loop, %entry 1913 call void @use_pointer(i8* %0) 1914 br i1 undef, label %exit, label %loop 1915 1916exit: ; preds = %loop 1917 call void @objc_release(i8* %0), !clang.imprecise_release !0 1918 ret void 1919} 1920 1921; Do the known-incremented retain+release elimination even if the pointer 1922; is also autoreleased. 1923 1924; CHECK-LABEL: define void @test42( 1925; CHECK-NEXT: entry: 1926; CHECK-NEXT: call i8* @objc_retain(i8* %p) 1927; CHECK-NEXT: call i8* @objc_autorelease(i8* %p) 1928; CHECK-NEXT: call void @use_pointer(i8* %p) 1929; CHECK-NEXT: call void @use_pointer(i8* %p) 1930; CHECK-NEXT: call void @use_pointer(i8* %p) 1931; CHECK-NEXT: call void @use_pointer(i8* %p) 1932; CHECK-NEXT: call void @objc_release(i8* %p) 1933; CHECK-NEXT: ret void 1934; CHECK-NEXT: } 1935define void @test42(i8* %p) { 1936entry: 1937 call i8* @objc_retain(i8* %p) 1938 call i8* @objc_autorelease(i8* %p) 1939 call i8* @objc_retain(i8* %p) 1940 call void @use_pointer(i8* %p) 1941 call void @use_pointer(i8* %p) 1942 call void @objc_release(i8* %p) 1943 call void @use_pointer(i8* %p) 1944 call void @use_pointer(i8* %p) 1945 call void @objc_release(i8* %p) 1946 ret void 1947} 1948 1949; Don't the known-incremented retain+release elimination if the pointer is 1950; autoreleased and there's an autoreleasePoolPop. 1951 1952; CHECK-LABEL: define void @test43( 1953; CHECK-NEXT: entry: 1954; CHECK-NEXT: call i8* @objc_retain(i8* %p) 1955; CHECK-NEXT: call i8* @objc_autorelease(i8* %p) 1956; CHECK-NEXT: call i8* @objc_retain 1957; CHECK-NEXT: call void @use_pointer(i8* %p) 1958; CHECK-NEXT: call void @use_pointer(i8* %p) 1959; CHECK-NEXT: call void @objc_autoreleasePoolPop(i8* undef) 1960; CHECK-NEXT: call void @objc_release 1961; CHECK-NEXT: ret void 1962; CHECK-NEXT: } 1963define void @test43(i8* %p) { 1964entry: 1965 call i8* @objc_retain(i8* %p) 1966 call i8* @objc_autorelease(i8* %p) 1967 call i8* @objc_retain(i8* %p) 1968 call void @use_pointer(i8* %p) 1969 call void @use_pointer(i8* %p) 1970 call void @objc_autoreleasePoolPop(i8* undef) 1971 call void @objc_release(i8* %p) 1972 ret void 1973} 1974 1975; Do the known-incremented retain+release elimination if the pointer is 1976; autoreleased and there's an autoreleasePoolPush. 1977 1978; CHECK-LABEL: define void @test43b( 1979; CHECK-NEXT: entry: 1980; CHECK-NEXT: call i8* @objc_retain(i8* %p) 1981; CHECK-NEXT: call i8* @objc_autorelease(i8* %p) 1982; CHECK-NEXT: call void @use_pointer(i8* %p) 1983; CHECK-NEXT: call void @use_pointer(i8* %p) 1984; CHECK-NEXT: call i8* @objc_autoreleasePoolPush() 1985; CHECK-NEXT: call void @use_pointer(i8* %p) 1986; CHECK-NEXT: call void @objc_release 1987; CHECK-NEXT: ret void 1988; CHECK-NEXT: } 1989define void @test43b(i8* %p) { 1990entry: 1991 call i8* @objc_retain(i8* %p) 1992 call i8* @objc_autorelease(i8* %p) 1993 call i8* @objc_retain(i8* %p) 1994 call void @use_pointer(i8* %p) 1995 call void @use_pointer(i8* %p) 1996 call i8* @objc_autoreleasePoolPush() 1997 call void @objc_release(i8* %p) 1998 call void @use_pointer(i8* %p) 1999 call void @objc_release(i8* %p) 2000 ret void 2001} 2002 2003; Do retain+release elimination for non-provenance pointers. 2004 2005; CHECK-LABEL: define void @test44( 2006; CHECK-NOT: objc_ 2007; CHECK: } 2008define void @test44(i8** %pp) { 2009 %p = load i8*, i8** %pp 2010 %q = call i8* @objc_retain(i8* %p) 2011 call void @objc_release(i8* %q) 2012 ret void 2013} 2014 2015; Don't delete retain+release with an unknown-provenance 2016; may-alias objc_release between them. 2017 2018; CHECK-LABEL: define void @test45( 2019; CHECK: call i8* @objc_retain(i8* %p) 2020; CHECK: call void @objc_release(i8* %q) 2021; CHECK: call void @use_pointer(i8* %p) 2022; CHECK: call void @objc_release(i8* %p) 2023; CHECK: } 2024define void @test45(i8** %pp, i8** %qq) { 2025 %p = load i8*, i8** %pp 2026 %q = load i8*, i8** %qq 2027 call i8* @objc_retain(i8* %p) 2028 call void @objc_release(i8* %q) 2029 call void @use_pointer(i8* %p) 2030 call void @objc_release(i8* %p) 2031 ret void 2032} 2033 2034; Don't delete retain and autorelease here. 2035 2036; CHECK-LABEL: define void @test46( 2037; CHECK: tail call i8* @objc_retain(i8* %p) [[NUW]] 2038; CHECK: true: 2039; CHECK: call i8* @objc_autorelease(i8* %p) [[NUW]] 2040; CHECK: } 2041define void @test46(i8* %p, i1 %a) { 2042entry: 2043 call i8* @objc_retain(i8* %p) 2044 br i1 %a, label %true, label %false 2045 2046true: 2047 call i8* @objc_autorelease(i8* %p) 2048 call void @use_pointer(i8* %p) 2049 ret void 2050 2051false: 2052 ret void 2053} 2054 2055; Delete no-op cast calls. 2056 2057; CHECK-LABEL: define i8* @test47( 2058; CHECK-NOT: call 2059; CHECK: ret i8* %p 2060; CHECK: } 2061define i8* @test47(i8* %p) nounwind { 2062 %x = call i8* @objc_retainedObject(i8* %p) 2063 ret i8* %x 2064} 2065 2066; Delete no-op cast calls. 2067 2068; CHECK-LABEL: define i8* @test48( 2069; CHECK-NOT: call 2070; CHECK: ret i8* %p 2071; CHECK: } 2072define i8* @test48(i8* %p) nounwind { 2073 %x = call i8* @objc_unretainedObject(i8* %p) 2074 ret i8* %x 2075} 2076 2077; Delete no-op cast calls. 2078 2079; CHECK-LABEL: define i8* @test49( 2080; CHECK-NOT: call 2081; CHECK: ret i8* %p 2082; CHECK: } 2083define i8* @test49(i8* %p) nounwind { 2084 %x = call i8* @objc_unretainedPointer(i8* %p) 2085 ret i8* %x 2086} 2087 2088; Do delete retain+release with intervening stores of the address value if we 2089; have imprecise release attached to objc_release. 2090 2091; CHECK-LABEL: define void @test50a( 2092; CHECK-NEXT: call i8* @objc_retain 2093; CHECK-NEXT: call void @callee 2094; CHECK-NEXT: store 2095; CHECK-NEXT: call void @objc_release 2096; CHECK-NEXT: ret void 2097; CHECK-NEXT: } 2098define void @test50a(i8* %p, i8** %pp) { 2099 call i8* @objc_retain(i8* %p) 2100 call void @callee() 2101 store i8* %p, i8** %pp 2102 call void @objc_release(i8* %p) 2103 ret void 2104} 2105 2106; CHECK-LABEL: define void @test50b( 2107; CHECK-NOT: @objc_ 2108; CHECK: } 2109define void @test50b(i8* %p, i8** %pp) { 2110 call i8* @objc_retain(i8* %p) 2111 call void @callee() 2112 store i8* %p, i8** %pp 2113 call void @objc_release(i8* %p), !clang.imprecise_release !0 2114 ret void 2115} 2116 2117 2118; Don't delete retain+release with intervening stores through the 2119; address value. 2120 2121; CHECK-LABEL: define void @test51a( 2122; CHECK: call i8* @objc_retain(i8* %p) 2123; CHECK: call void @objc_release(i8* %p) 2124; CHECK: ret void 2125; CHECK: } 2126define void @test51a(i8* %p) { 2127 call i8* @objc_retain(i8* %p) 2128 call void @callee() 2129 store i8 0, i8* %p 2130 call void @objc_release(i8* %p) 2131 ret void 2132} 2133 2134; CHECK-LABEL: define void @test51b( 2135; CHECK: call i8* @objc_retain(i8* %p) 2136; CHECK: call void @objc_release(i8* %p) 2137; CHECK: ret void 2138; CHECK: } 2139define void @test51b(i8* %p) { 2140 call i8* @objc_retain(i8* %p) 2141 call void @callee() 2142 store i8 0, i8* %p 2143 call void @objc_release(i8* %p), !clang.imprecise_release !0 2144 ret void 2145} 2146 2147; Don't delete retain+release with intervening use of a pointer of 2148; unknown provenance. 2149 2150; CHECK-LABEL: define void @test52a( 2151; CHECK: call i8* @objc_retain 2152; CHECK: call void @callee() 2153; CHECK: call void @use_pointer(i8* %z) 2154; CHECK: call void @objc_release 2155; CHECK: ret void 2156; CHECK: } 2157define void @test52a(i8** %zz, i8** %pp) { 2158 %p = load i8*, i8** %pp 2159 %1 = call i8* @objc_retain(i8* %p) 2160 call void @callee() 2161 %z = load i8*, i8** %zz 2162 call void @use_pointer(i8* %z) 2163 call void @objc_release(i8* %p) 2164 ret void 2165} 2166 2167; CHECK-LABEL: define void @test52b( 2168; CHECK: call i8* @objc_retain 2169; CHECK: call void @callee() 2170; CHECK: call void @use_pointer(i8* %z) 2171; CHECK: call void @objc_release 2172; CHECK: ret void 2173; CHECK: } 2174define void @test52b(i8** %zz, i8** %pp) { 2175 %p = load i8*, i8** %pp 2176 %1 = call i8* @objc_retain(i8* %p) 2177 call void @callee() 2178 %z = load i8*, i8** %zz 2179 call void @use_pointer(i8* %z) 2180 call void @objc_release(i8* %p), !clang.imprecise_release !0 2181 ret void 2182} 2183 2184; Like test52, but the pointer has function type, so it's assumed to 2185; be not reference counted. 2186; Oops. That's wrong. Clang sometimes uses function types gratuitously. 2187; See rdar://10551239. 2188 2189; CHECK-LABEL: define void @test53( 2190; CHECK: @objc_ 2191; CHECK: } 2192define void @test53(void ()** %zz, i8** %pp) { 2193 %p = load i8*, i8** %pp 2194 %1 = call i8* @objc_retain(i8* %p) 2195 call void @callee() 2196 %z = load void ()*, void ()** %zz 2197 call void @callee_fnptr(void ()* %z) 2198 call void @objc_release(i8* %p) 2199 ret void 2200} 2201 2202; Convert autorelease to release if the value is unused. 2203 2204; CHECK-LABEL: define void @test54( 2205; CHECK: call i8* @returner() 2206; CHECK-NEXT: call void @objc_release(i8* %t) [[NUW]], !clang.imprecise_release ![[RELEASE]] 2207; CHECK-NEXT: ret void 2208; CHECK: } 2209define void @test54() { 2210 %t = call i8* @returner() 2211 call i8* @objc_autorelease(i8* %t) 2212 ret void 2213} 2214 2215; Nested retain+release pairs. Delete them both. 2216 2217; CHECK-LABEL: define void @test55( 2218; CHECK-NOT: @objc 2219; CHECK: } 2220define void @test55(i8* %x) { 2221entry: 2222 %0 = call i8* @objc_retain(i8* %x) nounwind 2223 %1 = call i8* @objc_retain(i8* %x) nounwind 2224 call void @objc_release(i8* %x) nounwind 2225 call void @objc_release(i8* %x) nounwind 2226 ret void 2227} 2228 2229; Nested retain+release pairs where the inner pair depends 2230; on the outer pair to be removed, and then the outer pair 2231; can be partially eliminated. Plus an extra outer pair to 2232; eliminate, for fun. 2233 2234; CHECK-LABEL: define void @test56( 2235; CHECK-NOT: @objc 2236; CHECK: if.then: 2237; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %x) [[NUW]] 2238; CHECK-NEXT: tail call void @use_pointer(i8* %x) 2239; CHECK-NEXT: tail call void @use_pointer(i8* %x) 2240; CHECK-NEXT: tail call void @objc_release(i8* %x) [[NUW]], !clang.imprecise_release ![[RELEASE]] 2241; CHECK-NEXT: br label %if.end 2242; CHECK-NOT: @objc 2243; CHECK: } 2244define void @test56(i8* %x, i32 %n) { 2245entry: 2246 %0 = tail call i8* @objc_retain(i8* %x) nounwind 2247 %1 = tail call i8* @objc_retain(i8* %0) nounwind 2248 %tobool = icmp eq i32 %n, 0 2249 br i1 %tobool, label %if.end, label %if.then 2250 2251if.then: ; preds = %entry 2252 %2 = tail call i8* @objc_retain(i8* %1) nounwind 2253 tail call void @use_pointer(i8* %2) 2254 tail call void @use_pointer(i8* %2) 2255 tail call void @objc_release(i8* %2) nounwind, !clang.imprecise_release !0 2256 br label %if.end 2257 2258if.end: ; preds = %entry, %if.then 2259 tail call void @objc_release(i8* %1) nounwind, !clang.imprecise_release !0 2260 tail call void @objc_release(i8* %0) nounwind, !clang.imprecise_release !0 2261 ret void 2262} 2263 2264; When there are adjacent retain+release pairs, the first one is known 2265; unnecessary because the presence of the second one means that the first one 2266; won't be deleting the object. 2267 2268; CHECK-LABEL: define void @test57( 2269; CHECK-NEXT: entry: 2270; CHECK-NEXT: tail call i8* @objc_retain(i8* %x) [[NUW]] 2271; CHECK-NEXT: call void @use_pointer(i8* %x) 2272; CHECK-NEXT: call void @use_pointer(i8* %x) 2273; CHECK-NEXT: tail call i8* @objc_retain(i8* %x) [[NUW]] 2274; CHECK-NEXT: call void @use_pointer(i8* %x) 2275; CHECK-NEXT: call void @use_pointer(i8* %x) 2276; CHECK-NEXT: call void @objc_release(i8* %x) [[NUW]] 2277; CHECK-NEXT: ret void 2278; CHECK-NEXT: } 2279define void @test57(i8* %x) nounwind { 2280entry: 2281 call i8* @objc_retain(i8* %x) nounwind 2282 call i8* @objc_retain(i8* %x) nounwind 2283 call void @use_pointer(i8* %x) 2284 call void @use_pointer(i8* %x) 2285 call void @objc_release(i8* %x) nounwind 2286 call i8* @objc_retain(i8* %x) nounwind 2287 call void @use_pointer(i8* %x) 2288 call void @use_pointer(i8* %x) 2289 call void @objc_release(i8* %x) nounwind 2290 ret void 2291} 2292 2293; An adjacent retain+release pair is sufficient even if it will be 2294; removed itself. 2295 2296; CHECK-LABEL: define void @test58( 2297; CHECK-NEXT: entry: 2298; CHECK-NEXT: @objc_retain 2299; CHECK-NEXT: call void @use_pointer(i8* %x) 2300; CHECK-NEXT: call void @use_pointer(i8* %x) 2301; CHECK-NEXT: ret void 2302; CHECK-NEXT: } 2303define void @test58(i8* %x) nounwind { 2304entry: 2305 call i8* @objc_retain(i8* %x) nounwind 2306 call i8* @objc_retain(i8* %x) nounwind 2307 call void @use_pointer(i8* %x) 2308 call void @use_pointer(i8* %x) 2309 call void @objc_release(i8* %x) nounwind 2310 call i8* @objc_retain(i8* %x) nounwind 2311 call void @objc_release(i8* %x) nounwind 2312 ret void 2313} 2314 2315; Don't delete the second retain+release pair in an adjacent set. 2316 2317; CHECK-LABEL: define void @test59( 2318; CHECK-NEXT: entry: 2319; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %x) [[NUW]] 2320; CHECK-NEXT: call void @use_pointer(i8* %x) 2321; CHECK-NEXT: call void @use_pointer(i8* %x) 2322; CHECK-NEXT: call void @objc_release(i8* %x) [[NUW]] 2323; CHECK-NEXT: ret void 2324; CHECK-NEXT: } 2325define void @test59(i8* %x) nounwind { 2326entry: 2327 %a = call i8* @objc_retain(i8* %x) nounwind 2328 call void @objc_release(i8* %x) nounwind 2329 %b = call i8* @objc_retain(i8* %x) nounwind 2330 call void @use_pointer(i8* %x) 2331 call void @use_pointer(i8* %x) 2332 call void @objc_release(i8* %x) nounwind 2333 ret void 2334} 2335 2336; Constant pointers to objects don't need reference counting. 2337 2338@constptr = external constant i8* 2339@something = external global i8* 2340 2341; We have a precise lifetime retain/release here. We can not remove them since 2342; @something is not constant. 2343 2344; CHECK-LABEL: define void @test60a( 2345; CHECK: call i8* @objc_retain 2346; CHECK: call void @objc_release 2347; CHECK: } 2348define void @test60a() { 2349 %t = load i8*, i8** @constptr 2350 %s = load i8*, i8** @something 2351 call i8* @objc_retain(i8* %s) 2352 call void @callee() 2353 call void @use_pointer(i8* %t) 2354 call void @objc_release(i8* %s) 2355 ret void 2356} 2357 2358; CHECK-LABEL: define void @test60b( 2359; CHECK: call i8* @objc_retain 2360; CHECK-NOT: call i8* @objc_retain 2361; CHECK-NOT: call i8* @objc_release 2362; CHECK: } 2363define void @test60b() { 2364 %t = load i8*, i8** @constptr 2365 %s = load i8*, i8** @something 2366 call i8* @objc_retain(i8* %t) 2367 call i8* @objc_retain(i8* %t) 2368 call void @callee() 2369 call void @use_pointer(i8* %s) 2370 call void @objc_release(i8* %t) 2371 ret void 2372} 2373 2374; CHECK-LABEL: define void @test60c( 2375; CHECK-NOT: @objc_ 2376; CHECK: } 2377define void @test60c() { 2378 %t = load i8*, i8** @constptr 2379 %s = load i8*, i8** @something 2380 call i8* @objc_retain(i8* %t) 2381 call void @callee() 2382 call void @use_pointer(i8* %s) 2383 call void @objc_release(i8* %t), !clang.imprecise_release !0 2384 ret void 2385} 2386 2387; CHECK-LABEL: define void @test60d( 2388; CHECK-NOT: @objc_ 2389; CHECK: } 2390define void @test60d() { 2391 %t = load i8*, i8** @constptr 2392 %s = load i8*, i8** @something 2393 call i8* @objc_retain(i8* %t) 2394 call void @callee() 2395 call void @use_pointer(i8* %s) 2396 call void @objc_release(i8* %t) 2397 ret void 2398} 2399 2400; CHECK-LABEL: define void @test60e( 2401; CHECK-NOT: @objc_ 2402; CHECK: } 2403define void @test60e() { 2404 %t = load i8*, i8** @constptr 2405 %s = load i8*, i8** @something 2406 call i8* @objc_retain(i8* %t) 2407 call void @callee() 2408 call void @use_pointer(i8* %s) 2409 call void @objc_release(i8* %t), !clang.imprecise_release !0 2410 ret void 2411} 2412 2413; Constant pointers to objects don't need to be considered related to other 2414; pointers. 2415 2416; CHECK-LABEL: define void @test61( 2417; CHECK-NOT: @objc_ 2418; CHECK: } 2419define void @test61() { 2420 %t = load i8*, i8** @constptr 2421 call i8* @objc_retain(i8* %t) 2422 call void @callee() 2423 call void @use_pointer(i8* %t) 2424 call void @objc_release(i8* %t) 2425 ret void 2426} 2427 2428; Delete a retain matched by releases when one is inside the loop and the 2429; other is outside the loop. 2430 2431; CHECK-LABEL: define void @test62( 2432; CHECK-NOT: @objc_ 2433; CHECK: } 2434define void @test62(i8* %x, i1* %p) nounwind { 2435entry: 2436 br label %loop 2437 2438loop: 2439 call i8* @objc_retain(i8* %x) 2440 %q = load i1, i1* %p 2441 br i1 %q, label %loop.more, label %exit 2442 2443loop.more: 2444 call void @objc_release(i8* %x) 2445 br label %loop 2446 2447exit: 2448 call void @objc_release(i8* %x) 2449 ret void 2450} 2451 2452; Like test62 but with no release in exit. 2453; Don't delete anything! 2454 2455; CHECK-LABEL: define void @test63( 2456; CHECK: loop: 2457; CHECK: tail call i8* @objc_retain(i8* %x) 2458; CHECK: loop.more: 2459; CHECK: call void @objc_release(i8* %x) 2460; CHECK: } 2461define void @test63(i8* %x, i1* %p) nounwind { 2462entry: 2463 br label %loop 2464 2465loop: 2466 call i8* @objc_retain(i8* %x) 2467 %q = load i1, i1* %p 2468 br i1 %q, label %loop.more, label %exit 2469 2470loop.more: 2471 call void @objc_release(i8* %x) 2472 br label %loop 2473 2474exit: 2475 ret void 2476} 2477 2478; Like test62 but with no release in loop.more. 2479; Don't delete anything! 2480 2481; CHECK-LABEL: define void @test64( 2482; CHECK: loop: 2483; CHECK: tail call i8* @objc_retain(i8* %x) 2484; CHECK: exit: 2485; CHECK: call void @objc_release(i8* %x) 2486; CHECK: } 2487define void @test64(i8* %x, i1* %p) nounwind { 2488entry: 2489 br label %loop 2490 2491loop: 2492 call i8* @objc_retain(i8* %x) 2493 %q = load i1, i1* %p 2494 br i1 %q, label %loop.more, label %exit 2495 2496loop.more: 2497 br label %loop 2498 2499exit: 2500 call void @objc_release(i8* %x) 2501 ret void 2502} 2503 2504; Move an autorelease past a phi with a null. 2505 2506; CHECK-LABEL: define i8* @test65( 2507; CHECK: if.then: 2508; CHECK: call i8* @objc_autorelease( 2509; CHECK: return: 2510; CHECK-NOT: @objc_autorelease 2511; CHECK: } 2512define i8* @test65(i1 %x) { 2513entry: 2514 br i1 %x, label %return, label %if.then 2515 2516if.then: ; preds = %entry 2517 %c = call i8* @returner() 2518 %s = call i8* @objc_retainAutoreleasedReturnValue(i8* %c) nounwind 2519 br label %return 2520 2521return: ; preds = %if.then, %entry 2522 %retval = phi i8* [ %s, %if.then ], [ null, %entry ] 2523 %q = call i8* @objc_autorelease(i8* %retval) nounwind 2524 ret i8* %retval 2525} 2526 2527; Don't move an autorelease past an autorelease pool boundary. 2528 2529; CHECK-LABEL: define i8* @test65b( 2530; CHECK: if.then: 2531; CHECK-NOT: @objc_autorelease 2532; CHECK: return: 2533; CHECK: call i8* @objc_autorelease( 2534; CHECK: } 2535define i8* @test65b(i1 %x) { 2536entry: 2537 %t = call i8* @objc_autoreleasePoolPush() 2538 br i1 %x, label %return, label %if.then 2539 2540if.then: ; preds = %entry 2541 %c = call i8* @returner() 2542 %s = call i8* @objc_retainAutoreleasedReturnValue(i8* %c) nounwind 2543 br label %return 2544 2545return: ; preds = %if.then, %entry 2546 %retval = phi i8* [ %s, %if.then ], [ null, %entry ] 2547 call void @objc_autoreleasePoolPop(i8* %t) 2548 %q = call i8* @objc_autorelease(i8* %retval) nounwind 2549 ret i8* %retval 2550} 2551 2552; Don't move an autoreleaseReuturnValue, which would break 2553; the RV optimization. 2554 2555; CHECK-LABEL: define i8* @test65c( 2556; CHECK: if.then: 2557; CHECK-NOT: @objc_autorelease 2558; CHECK: return: 2559; CHECK: call i8* @objc_autoreleaseReturnValue( 2560; CHECK: } 2561define i8* @test65c(i1 %x) { 2562entry: 2563 br i1 %x, label %return, label %if.then 2564 2565if.then: ; preds = %entry 2566 %c = call i8* @returner() 2567 %s = call i8* @objc_retainAutoreleasedReturnValue(i8* %c) nounwind 2568 br label %return 2569 2570return: ; preds = %if.then, %entry 2571 %retval = phi i8* [ %s, %if.then ], [ null, %entry ] 2572 %q = call i8* @objc_autoreleaseReturnValue(i8* %retval) nounwind 2573 ret i8* %retval 2574} 2575 2576; An objc_retain can serve as a may-use for a different pointer. 2577; rdar://11931823 2578 2579; CHECK-LABEL: define void @test66a( 2580; CHECK: tail call i8* @objc_retain(i8* %cond) [[NUW]] 2581; CHECK: tail call void @objc_release(i8* %call) [[NUW]] 2582; CHECK: tail call i8* @objc_retain(i8* %tmp8) [[NUW]] 2583; CHECK: tail call void @objc_release(i8* %cond) [[NUW]] 2584; CHECK: } 2585define void @test66a(i8* %tmp5, i8* %bar, i1 %tobool, i1 %tobool1, i8* %call) { 2586entry: 2587 br i1 %tobool, label %cond.true, label %cond.end 2588 2589cond.true: 2590 br label %cond.end 2591 2592cond.end: ; preds = %cond.true, %entry 2593 %cond = phi i8* [ %tmp5, %cond.true ], [ %call, %entry ] 2594 %tmp7 = tail call i8* @objc_retain(i8* %cond) nounwind 2595 tail call void @objc_release(i8* %call) nounwind 2596 %tmp8 = select i1 %tobool1, i8* %cond, i8* %bar 2597 %tmp9 = tail call i8* @objc_retain(i8* %tmp8) nounwind 2598 tail call void @objc_release(i8* %cond) nounwind 2599 ret void 2600} 2601 2602; CHECK-LABEL: define void @test66b( 2603; CHECK: tail call i8* @objc_retain(i8* %cond) [[NUW]] 2604; CHECK: tail call void @objc_release(i8* %call) [[NUW]] 2605; CHECK: tail call i8* @objc_retain(i8* %tmp8) [[NUW]] 2606; CHECK: tail call void @objc_release(i8* %cond) [[NUW]] 2607; CHECK: } 2608define void @test66b(i8* %tmp5, i8* %bar, i1 %tobool, i1 %tobool1, i8* %call) { 2609entry: 2610 br i1 %tobool, label %cond.true, label %cond.end 2611 2612cond.true: 2613 br label %cond.end 2614 2615cond.end: ; preds = %cond.true, %entry 2616 %cond = phi i8* [ %tmp5, %cond.true ], [ %call, %entry ] 2617 %tmp7 = tail call i8* @objc_retain(i8* %cond) nounwind 2618 tail call void @objc_release(i8* %call) nounwind, !clang.imprecise_release !0 2619 %tmp8 = select i1 %tobool1, i8* %cond, i8* %bar 2620 %tmp9 = tail call i8* @objc_retain(i8* %tmp8) nounwind 2621 tail call void @objc_release(i8* %cond) nounwind 2622 ret void 2623} 2624 2625; CHECK-LABEL: define void @test66c( 2626; CHECK: tail call i8* @objc_retain(i8* %cond) [[NUW]] 2627; CHECK: tail call void @objc_release(i8* %call) [[NUW]] 2628; CHECK: tail call i8* @objc_retain(i8* %tmp8) [[NUW]] 2629; CHECK: tail call void @objc_release(i8* %cond) [[NUW]] 2630; CHECK: } 2631define void @test66c(i8* %tmp5, i8* %bar, i1 %tobool, i1 %tobool1, i8* %call) { 2632entry: 2633 br i1 %tobool, label %cond.true, label %cond.end 2634 2635cond.true: 2636 br label %cond.end 2637 2638cond.end: ; preds = %cond.true, %entry 2639 %cond = phi i8* [ %tmp5, %cond.true ], [ %call, %entry ] 2640 %tmp7 = tail call i8* @objc_retain(i8* %cond) nounwind 2641 tail call void @objc_release(i8* %call) nounwind 2642 %tmp8 = select i1 %tobool1, i8* %cond, i8* %bar 2643 %tmp9 = tail call i8* @objc_retain(i8* %tmp8) nounwind, !clang.imprecise_release !0 2644 tail call void @objc_release(i8* %cond) nounwind 2645 ret void 2646} 2647 2648; CHECK-LABEL: define void @test66d( 2649; CHECK: tail call i8* @objc_retain(i8* %cond) [[NUW]] 2650; CHECK: tail call void @objc_release(i8* %call) [[NUW]] 2651; CHECK: tail call i8* @objc_retain(i8* %tmp8) [[NUW]] 2652; CHECK: tail call void @objc_release(i8* %cond) [[NUW]] 2653; CHECK: } 2654define void @test66d(i8* %tmp5, i8* %bar, i1 %tobool, i1 %tobool1, i8* %call) { 2655entry: 2656 br i1 %tobool, label %cond.true, label %cond.end 2657 2658cond.true: 2659 br label %cond.end 2660 2661cond.end: ; preds = %cond.true, %entry 2662 %cond = phi i8* [ %tmp5, %cond.true ], [ %call, %entry ] 2663 %tmp7 = tail call i8* @objc_retain(i8* %cond) nounwind 2664 tail call void @objc_release(i8* %call) nounwind, !clang.imprecise_release !0 2665 %tmp8 = select i1 %tobool1, i8* %cond, i8* %bar 2666 %tmp9 = tail call i8* @objc_retain(i8* %tmp8) nounwind 2667 tail call void @objc_release(i8* %cond) nounwind, !clang.imprecise_release !0 2668 ret void 2669} 2670 2671; A few real-world testcases. 2672 2673@.str4 = private unnamed_addr constant [33 x i8] c"-[A z] = { %f, %f, { %f, %f } }\0A\00" 2674@"OBJC_IVAR_$_A.myZ" = global i64 20, section "__DATA, __objc_const", align 8 2675declare i32 @printf(i8* nocapture, ...) nounwind 2676declare i32 @puts(i8* nocapture) nounwind 2677@str = internal constant [16 x i8] c"-[ Top0 _getX ]\00" 2678 2679; CHECK: define { <2 x float>, <2 x float> } @"\01-[A z]"({}* %self, i8* nocapture %_cmd) [[NUW]] { 2680; CHECK-NOT: @objc_ 2681; CHECK: } 2682 2683define {<2 x float>, <2 x float>} @"\01-[A z]"({}* %self, i8* nocapture %_cmd) nounwind { 2684invoke.cont: 2685 %0 = bitcast {}* %self to i8* 2686 %1 = tail call i8* @objc_retain(i8* %0) nounwind 2687 tail call void @llvm.dbg.value(metadata {}* %self, i64 0, metadata !DILocalVariable(scope: !2), metadata !DIExpression()), !dbg !DILocation(scope: !2) 2688 tail call void @llvm.dbg.value(metadata {}* %self, i64 0, metadata !DILocalVariable(scope: !2), metadata !DIExpression()), !dbg !DILocation(scope: !2) 2689 %ivar = load i64, i64* @"OBJC_IVAR_$_A.myZ", align 8 2690 %add.ptr = getelementptr i8, i8* %0, i64 %ivar 2691 %tmp1 = bitcast i8* %add.ptr to float* 2692 %tmp2 = load float, float* %tmp1, align 4 2693 %conv = fpext float %tmp2 to double 2694 %add.ptr.sum = add i64 %ivar, 4 2695 %tmp6 = getelementptr inbounds i8, i8* %0, i64 %add.ptr.sum 2696 %2 = bitcast i8* %tmp6 to float* 2697 %tmp7 = load float, float* %2, align 4 2698 %conv8 = fpext float %tmp7 to double 2699 %add.ptr.sum36 = add i64 %ivar, 8 2700 %tmp12 = getelementptr inbounds i8, i8* %0, i64 %add.ptr.sum36 2701 %arrayidx = bitcast i8* %tmp12 to float* 2702 %tmp13 = load float, float* %arrayidx, align 4 2703 %conv14 = fpext float %tmp13 to double 2704 %tmp12.sum = add i64 %ivar, 12 2705 %arrayidx19 = getelementptr inbounds i8, i8* %0, i64 %tmp12.sum 2706 %3 = bitcast i8* %arrayidx19 to float* 2707 %tmp20 = load float, float* %3, align 4 2708 %conv21 = fpext float %tmp20 to double 2709 %call = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([33 x i8], [33 x i8]* @.str4, i64 0, i64 0), double %conv, double %conv8, double %conv14, double %conv21) 2710 %ivar23 = load i64, i64* @"OBJC_IVAR_$_A.myZ", align 8 2711 %add.ptr24 = getelementptr i8, i8* %0, i64 %ivar23 2712 %4 = bitcast i8* %add.ptr24 to i128* 2713 %srcval = load i128, i128* %4, align 4 2714 tail call void @objc_release(i8* %0) nounwind 2715 %tmp29 = trunc i128 %srcval to i64 2716 %tmp30 = bitcast i64 %tmp29 to <2 x float> 2717 %tmp31 = insertvalue {<2 x float>, <2 x float>} undef, <2 x float> %tmp30, 0 2718 %tmp32 = lshr i128 %srcval, 64 2719 %tmp33 = trunc i128 %tmp32 to i64 2720 %tmp34 = bitcast i64 %tmp33 to <2 x float> 2721 %tmp35 = insertvalue {<2 x float>, <2 x float>} %tmp31, <2 x float> %tmp34, 1 2722 ret {<2 x float>, <2 x float>} %tmp35 2723} 2724 2725; CHECK: @"\01-[Top0 _getX]"({}* %self, i8* nocapture %_cmd) [[NUW]] { 2726; CHECK-NOT: @objc_ 2727; CHECK: } 2728 2729define i32 @"\01-[Top0 _getX]"({}* %self, i8* nocapture %_cmd) nounwind { 2730invoke.cont: 2731 %0 = bitcast {}* %self to i8* 2732 %1 = tail call i8* @objc_retain(i8* %0) nounwind 2733 %puts = tail call i32 @puts(i8* getelementptr inbounds ([16 x i8], [16 x i8]* @str, i64 0, i64 0)) 2734 tail call void @objc_release(i8* %0) nounwind 2735 ret i32 0 2736} 2737 2738@"\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], [5 x i8]* @"\01L_OBJC_METH_VAR_NAME_", i64 0, i64 0), section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2739@"\01L_OBJC_IMAGE_INFO" = internal constant [2 x i32] [i32 0, i32 16], section "__DATA, __objc_imageinfo, regular, no_dead_strip" 2740@llvm.used = appending global [3 x i8*] [i8* getelementptr inbounds ([5 x i8], [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" 2741 2742; A simple loop. Eliminate the retain and release inside of it! 2743 2744; CHECK: define void @loop(i8* %x, i64 %n) { 2745; CHECK: for.body: 2746; CHECK-NOT: @objc_ 2747; CHECK: @objc_msgSend 2748; CHECK-NOT: @objc_ 2749; CHECK: for.end: 2750; CHECK: } 2751define void @loop(i8* %x, i64 %n) { 2752entry: 2753 %0 = tail call i8* @objc_retain(i8* %x) nounwind 2754 %cmp9 = icmp sgt i64 %n, 0 2755 br i1 %cmp9, label %for.body, label %for.end 2756 2757for.body: ; preds = %entry, %for.body 2758 %i.010 = phi i64 [ %inc, %for.body ], [ 0, %entry ] 2759 %1 = tail call i8* @objc_retain(i8* %x) nounwind 2760 %tmp5 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8 2761 %call = tail call i8* (i8*, i8*, ...) @objc_msgSend(i8* %1, i8* %tmp5) 2762 tail call void @objc_release(i8* %1) nounwind, !clang.imprecise_release !0 2763 %inc = add nsw i64 %i.010, 1 2764 %exitcond = icmp eq i64 %inc, %n 2765 br i1 %exitcond, label %for.end, label %for.body 2766 2767for.end: ; preds = %for.body, %entry 2768 tail call void @objc_release(i8* %x) nounwind, !clang.imprecise_release !0 2769 ret void 2770} 2771 2772; ObjCARCOpt can delete the retain,release on self. 2773 2774; CHECK: define void @TextEditTest(%2* %self, %3* %pboard) { 2775; CHECK-NOT: call i8* @objc_retain(i8* %tmp7) 2776; CHECK: } 2777 2778%0 = type { i8* (i8*, %struct._message_ref_t*, ...)*, i8* } 2779%1 = type opaque 2780%2 = type opaque 2781%3 = type opaque 2782%4 = type opaque 2783%5 = type opaque 2784%struct.NSConstantString = type { i32*, i32, i8*, i64 } 2785%struct._NSRange = type { i64, i64 } 2786%struct.__CFString = type opaque 2787%struct.__method_list_t = type { i32, i32, [0 x %struct._objc_method] } 2788%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* } 2789%struct._class_t = type { %struct._class_t*, %struct._class_t*, %struct._objc_cache*, i8* (i8*, i8*)**, %struct._class_ro_t* } 2790%struct._ivar_list_t = type { i32, i32, [0 x %struct._ivar_t] } 2791%struct._ivar_t = type { i64*, i8*, i8*, i32, i32 } 2792%struct._message_ref_t = type { i8*, i8* } 2793%struct._objc_cache = type opaque 2794%struct._objc_method = type { i8*, i8*, i8* } 2795%struct._objc_protocol_list = type { i64, [0 x %struct._protocol_t*] } 2796%struct._prop_list_t = type { i32, i32, [0 x %struct._message_ref_t] } 2797%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 } 2798 2799@"\01L_OBJC_CLASSLIST_REFERENCES_$_17" = external hidden global %struct._class_t*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8 2800@kUTTypePlainText = external constant %struct.__CFString* 2801@"\01L_OBJC_SELECTOR_REFERENCES_19" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2802@"\01L_OBJC_SELECTOR_REFERENCES_21" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2803@"\01L_OBJC_SELECTOR_REFERENCES_23" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2804@"\01L_OBJC_SELECTOR_REFERENCES_25" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2805@"\01L_OBJC_CLASSLIST_REFERENCES_$_26" = external hidden global %struct._class_t*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8 2806@"\01L_OBJC_SELECTOR_REFERENCES_28" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2807@"\01L_OBJC_CLASSLIST_REFERENCES_$_29" = external hidden global %struct._class_t*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8 2808@"\01L_OBJC_SELECTOR_REFERENCES_31" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2809@"\01L_OBJC_SELECTOR_REFERENCES_33" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2810@"\01L_OBJC_SELECTOR_REFERENCES_35" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2811@"\01L_OBJC_SELECTOR_REFERENCES_37" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2812@"\01L_OBJC_CLASSLIST_REFERENCES_$_38" = external hidden global %struct._class_t*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8 2813@"\01L_OBJC_SELECTOR_REFERENCES_40" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2814@"\01L_OBJC_SELECTOR_REFERENCES_42" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2815@_unnamed_cfstring_44 = external hidden constant %struct.NSConstantString, section "__DATA,__cfstring" 2816@"\01L_OBJC_SELECTOR_REFERENCES_46" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2817@"\01L_OBJC_SELECTOR_REFERENCES_48" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2818@"\01l_objc_msgSend_fixup_isEqual_" = external hidden global %0, section "__DATA, __objc_msgrefs, coalesced", align 16 2819@"\01L_OBJC_CLASSLIST_REFERENCES_$_50" = external hidden global %struct._class_t*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8 2820@NSCocoaErrorDomain = external constant %1* 2821@"\01L_OBJC_CLASSLIST_REFERENCES_$_51" = external hidden global %struct._class_t*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8 2822@NSFilePathErrorKey = external constant %1* 2823@"\01L_OBJC_SELECTOR_REFERENCES_53" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2824@"\01L_OBJC_SELECTOR_REFERENCES_55" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2825@"\01L_OBJC_CLASSLIST_REFERENCES_$_56" = external hidden global %struct._class_t*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8 2826@"\01L_OBJC_SELECTOR_REFERENCES_58" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2827@"\01L_OBJC_SELECTOR_REFERENCES_60" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2828 2829declare %1* @truncatedString(%1*, i64) 2830define void @TextEditTest(%2* %self, %3* %pboard) { 2831entry: 2832 %err = alloca %4*, align 8 2833 %tmp7 = bitcast %2* %self to i8* 2834 %tmp8 = call i8* @objc_retain(i8* %tmp7) nounwind 2835 store %4* null, %4** %err, align 8 2836 %tmp1 = load %struct._class_t*, %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_17", align 8 2837 %tmp2 = load %struct.__CFString*, %struct.__CFString** @kUTTypePlainText, align 8 2838 %tmp3 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_19", align 8 2839 %tmp4 = bitcast %struct._class_t* %tmp1 to i8* 2840 %call5 = call i8* (i8*, i8*, ...) @objc_msgSend(i8* %tmp4, i8* %tmp3, %struct.__CFString* %tmp2) 2841 %tmp5 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_21", align 8 2842 %tmp6 = bitcast %3* %pboard to i8* 2843 %call76 = call i8* (i8*, i8*, ...) @objc_msgSend(i8* %tmp6, i8* %tmp5, i8* %call5) 2844 %tmp9 = call i8* @objc_retain(i8* %call76) nounwind 2845 %tobool = icmp eq i8* %tmp9, null 2846 br i1 %tobool, label %end, label %land.lhs.true 2847 2848land.lhs.true: ; preds = %entry 2849 %tmp11 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_23", align 8 2850 %call137 = call i8* (i8*, i8*, ...) @objc_msgSend(i8* %tmp6, i8* %tmp11, i8* %tmp9) 2851 %tmp = bitcast i8* %call137 to %1* 2852 %tmp10 = call i8* @objc_retain(i8* %call137) nounwind 2853 call void @objc_release(i8* null) nounwind 2854 %tmp12 = call i8* @objc_retain(i8* %call137) nounwind 2855 call void @objc_release(i8* null) nounwind 2856 %tobool16 = icmp eq i8* %call137, null 2857 br i1 %tobool16, label %end, label %if.then 2858 2859if.then: ; preds = %land.lhs.true 2860 %tmp19 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_25", align 8 2861 %call21 = call signext i8 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8 (i8*, i8*)*)(i8* %call137, i8* %tmp19) 2862 %tobool22 = icmp eq i8 %call21, 0 2863 br i1 %tobool22, label %if.then44, label %land.lhs.true23 2864 2865land.lhs.true23: ; preds = %if.then 2866 %tmp24 = load %struct._class_t*, %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_26", align 8 2867 %tmp26 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_28", align 8 2868 %tmp27 = bitcast %struct._class_t* %tmp24 to i8* 2869 %call2822 = call i8* (i8*, i8*, ...) @objc_msgSend(i8* %tmp27, i8* %tmp26, i8* %call137) 2870 %tmp13 = bitcast i8* %call2822 to %5* 2871 %tmp14 = call i8* @objc_retain(i8* %call2822) nounwind 2872 call void @objc_release(i8* null) nounwind 2873 %tobool30 = icmp eq i8* %call2822, null 2874 br i1 %tobool30, label %if.then44, label %if.end 2875 2876if.end: ; preds = %land.lhs.true23 2877 %tmp32 = load %struct._class_t*, %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_29", align 8 2878 %tmp33 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_31", align 8 2879 %tmp34 = bitcast %struct._class_t* %tmp32 to i8* 2880 %call35 = call i8* (i8*, i8*, ...) @objc_msgSend(i8* %tmp34, i8* %tmp33) 2881 %tmp37 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_33", align 8 2882 %call3923 = call i8* (i8*, i8*, ...) @objc_msgSend(i8* %call35, i8* %tmp37, i8* %call2822, i32 signext 1, %4** %err) 2883 %cmp = icmp eq i8* %call3923, null 2884 br i1 %cmp, label %if.then44, label %end 2885 2886if.then44: ; preds = %if.end, %land.lhs.true23, %if.then 2887 %url.025 = phi %5* [ %tmp13, %if.end ], [ %tmp13, %land.lhs.true23 ], [ null, %if.then ] 2888 %tmp49 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_35", align 8 2889 %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) 2890 %call513 = extractvalue %struct._NSRange %call51, 0 2891 %call514 = extractvalue %struct._NSRange %call51, 1 2892 %tmp52 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_37", align 8 2893 %call548 = call i8* (i8*, i8*, ...) @objc_msgSend(i8* %call137, i8* %tmp52, i64 %call513, i64 %call514) 2894 %tmp55 = load %struct._class_t*, %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_38", align 8 2895 %tmp56 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_40", align 8 2896 %tmp57 = bitcast %struct._class_t* %tmp55 to i8* 2897 %call58 = call i8* (i8*, i8*, ...) @objc_msgSend(i8* %tmp57, i8* %tmp56) 2898 %tmp59 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_42", align 8 2899 %call6110 = call i8* (i8*, i8*, ...) @objc_msgSend(i8* %call548, i8* %tmp59, i8* %call58) 2900 %tmp15 = call i8* @objc_retain(i8* %call6110) nounwind 2901 call void @objc_release(i8* %call137) nounwind 2902 %tmp64 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_46", align 8 2903 %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*)) 2904 %tobool67 = icmp eq i8 %call66, 0 2905 br i1 %tobool67, label %if.end74, label %if.then68 2906 2907if.then68: ; preds = %if.then44 2908 %tmp70 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_48", align 8 2909 %call7220 = call i8* (i8*, i8*, ...) @objc_msgSend(i8* %call6110, i8* %tmp70) 2910 %tmp16 = call i8* @objc_retain(i8* %call7220) nounwind 2911 call void @objc_release(i8* %call6110) nounwind 2912 br label %if.end74 2913 2914if.end74: ; preds = %if.then68, %if.then44 2915 %filename.0.in = phi i8* [ %call7220, %if.then68 ], [ %call6110, %if.then44 ] 2916 %filename.0 = bitcast i8* %filename.0.in to %1* 2917 %tmp17 = load i8*, i8** bitcast (%0* @"\01l_objc_msgSend_fixup_isEqual_" to i8**), align 16 2918 %tmp18 = bitcast i8* %tmp17 to i8 (i8*, %struct._message_ref_t*, i8*, ...)* 2919 %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) 2920 %tobool79 = icmp eq i8 %call78, 0 2921 br i1 %tobool79, label %land.lhs.true80, label %if.then109 2922 2923land.lhs.true80: ; preds = %if.end74 2924 %tmp82 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_25", align 8 2925 %call84 = call signext i8 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8 (i8*, i8*)*)(i8* %filename.0.in, i8* %tmp82) 2926 %tobool86 = icmp eq i8 %call84, 0 2927 br i1 %tobool86, label %if.then109, label %if.end106 2928 2929if.end106: ; preds = %land.lhs.true80 2930 %tmp88 = load %struct._class_t*, %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_26", align 8 2931 %tmp90 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_28", align 8 2932 %tmp91 = bitcast %struct._class_t* %tmp88 to i8* 2933 %call9218 = call i8* (i8*, i8*, ...) @objc_msgSend(i8* %tmp91, i8* %tmp90, i8* %filename.0.in) 2934 %tmp20 = bitcast i8* %call9218 to %5* 2935 %tmp21 = call i8* @objc_retain(i8* %call9218) nounwind 2936 %tmp22 = bitcast %5* %url.025 to i8* 2937 call void @objc_release(i8* %tmp22) nounwind 2938 %tmp94 = load %struct._class_t*, %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_29", align 8 2939 %tmp95 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_31", align 8 2940 %tmp96 = bitcast %struct._class_t* %tmp94 to i8* 2941 %call97 = call i8* (i8*, i8*, ...) @objc_msgSend(i8* %tmp96, i8* %tmp95) 2942 %tmp99 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_33", align 8 2943 %call10119 = call i8* (i8*, i8*, ...) @objc_msgSend(i8* %call97, i8* %tmp99, i8* %call9218, i32 signext 1, %4** %err) 2944 %phitmp = icmp eq i8* %call10119, null 2945 br i1 %phitmp, label %if.then109, label %end 2946 2947if.then109: ; preds = %if.end106, %land.lhs.true80, %if.end74 2948 %url.129 = phi %5* [ %tmp20, %if.end106 ], [ %url.025, %if.end74 ], [ %url.025, %land.lhs.true80 ] 2949 %tmp110 = load %4*, %4** %err, align 8 2950 %tobool111 = icmp eq %4* %tmp110, null 2951 br i1 %tobool111, label %if.then112, label %if.end125 2952 2953if.then112: ; preds = %if.then109 2954 %tmp113 = load %struct._class_t*, %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_50", align 8 2955 %tmp114 = load %1*, %1** @NSCocoaErrorDomain, align 8 2956 %tmp115 = load %struct._class_t*, %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_51", align 8 2957 %call117 = call %1* @truncatedString(%1* %filename.0, i64 1034) 2958 %tmp118 = load %1*, %1** @NSFilePathErrorKey, align 8 2959 %tmp119 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_53", align 8 2960 %tmp120 = bitcast %struct._class_t* %tmp115 to i8* 2961 %call12113 = call i8* (i8*, i8*, ...) @objc_msgSend(i8* %tmp120, i8* %tmp119, %1* %call117, %1* %tmp118, i8* null) 2962 %tmp122 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_55", align 8 2963 %tmp123 = bitcast %struct._class_t* %tmp113 to i8* 2964 %call12414 = call i8* (i8*, i8*, ...) @objc_msgSend(i8* %tmp123, i8* %tmp122, %1* %tmp114, i64 258, i8* %call12113) 2965 %tmp23 = call i8* @objc_retain(i8* %call12414) nounwind 2966 %tmp25 = call i8* @objc_autorelease(i8* %tmp23) nounwind 2967 %tmp28 = bitcast i8* %tmp25 to %4* 2968 store %4* %tmp28, %4** %err, align 8 2969 br label %if.end125 2970 2971if.end125: ; preds = %if.then112, %if.then109 2972 %tmp127 = phi %4* [ %tmp110, %if.then109 ], [ %tmp28, %if.then112 ] 2973 %tmp126 = load %struct._class_t*, %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_56", align 8 2974 %tmp128 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_58", align 8 2975 %tmp129 = bitcast %struct._class_t* %tmp126 to i8* 2976 %call13015 = call i8* (i8*, i8*, ...) @objc_msgSend(i8* %tmp129, i8* %tmp128, %4* %tmp127) 2977 %tmp131 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_60", align 8 2978 %call13317 = call i8* (i8*, i8*, ...) @objc_msgSend(i8* %call13015, i8* %tmp131) 2979 br label %end 2980 2981end: ; preds = %if.end125, %if.end106, %if.end, %land.lhs.true, %entry 2982 %filename.2 = phi %1* [ %filename.0, %if.end106 ], [ %filename.0, %if.end125 ], [ %tmp, %land.lhs.true ], [ null, %entry ], [ %tmp, %if.end ] 2983 %origFilename.0 = phi %1* [ %tmp, %if.end106 ], [ %tmp, %if.end125 ], [ %tmp, %land.lhs.true ], [ null, %entry ], [ %tmp, %if.end ] 2984 %url.2 = phi %5* [ %tmp20, %if.end106 ], [ %url.129, %if.end125 ], [ null, %land.lhs.true ], [ null, %entry ], [ %tmp13, %if.end ] 2985 call void @objc_release(i8* %tmp9) nounwind, !clang.imprecise_release !0 2986 %tmp29 = bitcast %5* %url.2 to i8* 2987 call void @objc_release(i8* %tmp29) nounwind, !clang.imprecise_release !0 2988 %tmp30 = bitcast %1* %origFilename.0 to i8* 2989 call void @objc_release(i8* %tmp30) nounwind, !clang.imprecise_release !0 2990 %tmp31 = bitcast %1* %filename.2 to i8* 2991 call void @objc_release(i8* %tmp31) nounwind, !clang.imprecise_release !0 2992 call void @objc_release(i8* %tmp7) nounwind, !clang.imprecise_release !0 2993 ret void 2994} 2995 2996declare i32 @__gxx_personality_v0(...) 2997 2998declare i32 @objc_sync_enter(i8*) 2999declare i32 @objc_sync_exit(i8*) 3000 3001; Make sure that we understand that objc_sync_{enter,exit} are IC_User not 3002; IC_Call/IC_CallOrUser. 3003 3004; CHECK-LABEL: define void @test67( 3005; CHECK-NEXT: call i32 @objc_sync_enter(i8* %x) 3006; CHECK-NEXT: call i32 @objc_sync_exit(i8* %x) 3007; CHECK-NEXT: ret void 3008; CHECK-NEXT: } 3009define void @test67(i8* %x) { 3010 call i8* @objc_retain(i8* %x) 3011 call i32 @objc_sync_enter(i8* %x) 3012 call i32 @objc_sync_exit(i8* %x) 3013 call void @objc_release(i8* %x), !clang.imprecise_release !0 3014 ret void 3015} 3016 3017!llvm.module.flags = !{!1} 3018 3019!0 = !{} 3020!1 = !{i32 1, !"Debug Info Version", i32 3} 3021!2 = distinct !DISubprogram() 3022 3023; CHECK: attributes #0 = { nounwind readnone } 3024; CHECK: attributes [[NUW]] = { nounwind } 3025; CHECK: ![[RELEASE]] = !{} 3026