1; RUN: opt -objc-arc -S < %s | FileCheck %s 2 3target datalayout = "e-p:64:64:64" 4 5declare i8* @objc_retain(i8*) 6declare void @objc_release(i8*) 7declare i8* @objc_autorelease(i8*) 8declare void @objc_autoreleasePoolPop(i8*) 9declare void @objc_autoreleasePoolPush() 10declare i8* @objc_retainBlock(i8*) 11 12declare i8* @objc_retainedObject(i8*) 13declare i8* @objc_unretainedObject(i8*) 14declare i8* @objc_unretainedPointer(i8*) 15 16declare void @use_pointer(i8*) 17declare void @callee() 18declare void @callee_fnptr(void ()*) 19declare void @invokee() 20declare i8* @returner() 21 22declare void @llvm.dbg.value(metadata, i64, metadata) 23 24declare i8* @objc_msgSend(i8*, i8*, ...) 25 26; Simple retain+release pair deletion, with some intervening control 27; flow and harmless instructions. 28 29; CHECK: define void @test0( 30; CHECK-NOT: @objc_ 31; CHECK: } 32define void @test0(i32* %x, i1 %p) nounwind { 33entry: 34 %a = bitcast i32* %x to i8* 35 %0 = call i8* @objc_retain(i8* %a) nounwind 36 br i1 %p, label %t, label %f 37 38t: 39 store i8 3, i8* %a 40 %b = bitcast i32* %x to float* 41 store float 2.0, float* %b 42 br label %return 43 44f: 45 store i32 7, i32* %x 46 br label %return 47 48return: 49 %c = bitcast i32* %x to i8* 50 call void @objc_release(i8* %c) nounwind 51 ret void 52} 53 54; Like test0 but the release isn't always executed when the retain is, 55; so the optimization is not safe. 56 57; TODO: Make the objc_release's argument be %0. 58 59; CHECK: define void @test1( 60; CHECK: @objc_retain(i8* %a) 61; CHECK: @objc_release 62; CHECK: } 63define void @test1(i32* %x, i1 %p, i1 %q) nounwind { 64entry: 65 %a = bitcast i32* %x to i8* 66 %0 = call i8* @objc_retain(i8* %a) nounwind 67 br i1 %p, label %t, label %f 68 69t: 70 store i8 3, i8* %a 71 %b = bitcast i32* %x to float* 72 store float 2.0, float* %b 73 br label %return 74 75f: 76 store i32 7, i32* %x 77 call void @callee() 78 br i1 %q, label %return, label %alt_return 79 80return: 81 %c = bitcast i32* %x to i8* 82 call void @objc_release(i8* %c) nounwind 83 ret void 84 85alt_return: 86 ret void 87} 88 89; Don't do partial elimination into two different CFG diamonds. 90 91; CHECK: define void @test1b( 92; CHECK: entry: 93; CHECK: tail call i8* @objc_retain(i8* %x) nounwind 94; CHECK-NOT: @objc_ 95; CHECK: if.end5: 96; CHECK: tail call void @objc_release(i8* %x) nounwind, !clang.imprecise_release !0 97; CHECK-NOT: @objc_ 98; CHECK: } 99define void @test1b(i8* %x, i1 %p, i1 %q) { 100entry: 101 tail call i8* @objc_retain(i8* %x) nounwind 102 br i1 %p, label %if.then, label %if.end 103 104if.then: ; preds = %entry 105 tail call void @callee() 106 br label %if.end 107 108if.end: ; preds = %if.then, %entry 109 br i1 %q, label %if.then3, label %if.end5 110 111if.then3: ; preds = %if.end 112 tail call void @use_pointer(i8* %x) 113 br label %if.end5 114 115if.end5: ; preds = %if.then3, %if.end 116 tail call void @objc_release(i8* %x) nounwind, !clang.imprecise_release !0 117 ret void 118} 119 120; Like test0 but the pointer is passed to an intervening call, 121; so the optimization is not safe. 122 123; CHECK: define void @test2( 124; CHECK: @objc_retain(i8* %a) 125; CHECK: @objc_release 126; CHECK: } 127define void @test2(i32* %x, i1 %p) nounwind { 128entry: 129 %a = bitcast i32* %x to i8* 130 %0 = call i8* @objc_retain(i8* %a) nounwind 131 br i1 %p, label %t, label %f 132 133t: 134 store i8 3, i8* %a 135 %b = bitcast i32* %x to float* 136 store float 2.0, float* %b 137 br label %return 138 139f: 140 store i32 7, i32* %x 141 call void @use_pointer(i8* %0) 142 %d = bitcast i32* %x to float* 143 store float 3.0, float* %d 144 br label %return 145 146return: 147 %c = bitcast i32* %x to i8* 148 call void @objc_release(i8* %c) nounwind 149 ret void 150} 151 152; Like test0 but the release is in a loop, 153; so the optimization is not safe. 154 155; TODO: For now, assume this can't happen. 156 157; CHECK: define void @test3( 158; TODO: @objc_retain(i8* %a) 159; TODO: @objc_release 160; CHECK: } 161define void @test3(i32* %x, i1* %q) nounwind { 162entry: 163 %a = bitcast i32* %x to i8* 164 %0 = call i8* @objc_retain(i8* %a) nounwind 165 br label %loop 166 167loop: 168 %c = bitcast i32* %x to i8* 169 call void @objc_release(i8* %c) nounwind 170 %j = load volatile i1* %q 171 br i1 %j, label %loop, label %return 172 173return: 174 ret void 175} 176 177; TODO: For now, assume this can't happen. 178 179; Like test0 but the retain is in a loop, 180; so the optimization is not safe. 181 182; CHECK: define void @test4( 183; TODO: @objc_retain(i8* %a) 184; TODO: @objc_release 185; CHECK: } 186define void @test4(i32* %x, i1* %q) nounwind { 187entry: 188 br label %loop 189 190loop: 191 %a = bitcast i32* %x to i8* 192 %0 = call i8* @objc_retain(i8* %a) nounwind 193 %j = load volatile i1* %q 194 br i1 %j, label %loop, label %return 195 196return: 197 %c = bitcast i32* %x to i8* 198 call void @objc_release(i8* %c) nounwind 199 ret void 200} 201 202; Like test0 but the pointer is conditionally passed to an intervening call, 203; so the optimization is not safe. 204 205; CHECK: define void @test5( 206; CHECK: @objc_retain(i8* 207; CHECK: @objc_release 208; CHECK: } 209define void @test5(i32* %x, i1 %q, i8* %y) nounwind { 210entry: 211 %a = bitcast i32* %x to i8* 212 %0 = call i8* @objc_retain(i8* %a) nounwind 213 %s = select i1 %q, i8* %y, i8* %0 214 call void @use_pointer(i8* %s) 215 store i32 7, i32* %x 216 %c = bitcast i32* %x to i8* 217 call void @objc_release(i8* %c) nounwind 218 ret void 219} 220 221; retain+release pair deletion, where the release happens on two different 222; flow paths. 223 224; CHECK: define void @test6( 225; CHECK-NOT: @objc_ 226; CHECK: } 227define void @test6(i32* %x, i1 %p) nounwind { 228entry: 229 %a = bitcast i32* %x to i8* 230 %0 = call i8* @objc_retain(i8* %a) nounwind 231 br i1 %p, label %t, label %f 232 233t: 234 store i8 3, i8* %a 235 %b = bitcast i32* %x to float* 236 store float 2.0, float* %b 237 %ct = bitcast i32* %x to i8* 238 call void @objc_release(i8* %ct) nounwind 239 br label %return 240 241f: 242 store i32 7, i32* %x 243 call void @callee() 244 %cf = bitcast i32* %x to i8* 245 call void @objc_release(i8* %cf) nounwind 246 br label %return 247 248return: 249 ret void 250} 251 252; retain+release pair deletion, where the retain happens on two different 253; flow paths. 254 255; CHECK: define void @test7( 256; CHECK-NOT: @objc_ 257; CHECK: } 258define void @test7(i32* %x, i1 %p) nounwind { 259entry: 260 %a = bitcast i32* %x to i8* 261 br i1 %p, label %t, label %f 262 263t: 264 %0 = call i8* @objc_retain(i8* %a) nounwind 265 store i8 3, i8* %a 266 %b = bitcast i32* %x to float* 267 store float 2.0, float* %b 268 br label %return 269 270f: 271 %1 = call i8* @objc_retain(i8* %a) nounwind 272 store i32 7, i32* %x 273 call void @callee() 274 br label %return 275 276return: 277 %c = bitcast i32* %x to i8* 278 call void @objc_release(i8* %c) nounwind 279 ret void 280} 281 282; Like test7, but there's a retain/retainBlock mismatch. Don't delete! 283 284; CHECK: define void @test7b 285; CHECK: t: 286; CHECK: call i8* @objc_retainBlock 287; CHECK: f: 288; CHECK: call i8* @objc_retain 289; CHECK: return: 290; CHECK: call void @objc_release 291; CHECK: } 292define void @test7b(i32* %x, i1 %p) nounwind { 293entry: 294 %a = bitcast i32* %x to i8* 295 br i1 %p, label %t, label %f 296 297t: 298 %0 = call i8* @objc_retainBlock(i8* %a) nounwind 299 store i8 3, i8* %a 300 %b = bitcast i32* %x to float* 301 store float 2.0, float* %b 302 br label %return 303 304f: 305 %1 = call i8* @objc_retain(i8* %a) nounwind 306 store i32 7, i32* %x 307 call void @callee() 308 br label %return 309 310return: 311 %c = bitcast i32* %x to i8* 312 call void @objc_release(i8* %c) nounwind 313 ret void 314} 315 316; retain+release pair deletion, where the retain and release both happen on 317; different flow paths. Wild! 318 319; CHECK: define void @test8( 320; CHECK-NOT: @objc_ 321; CHECK: } 322define void @test8(i32* %x, i1 %p, i1 %q) nounwind { 323entry: 324 %a = bitcast i32* %x to i8* 325 br i1 %p, label %t, label %f 326 327t: 328 %0 = call i8* @objc_retain(i8* %a) nounwind 329 store i8 3, i8* %a 330 %b = bitcast i32* %x to float* 331 store float 2.0, float* %b 332 br label %mid 333 334f: 335 %1 = call i8* @objc_retain(i8* %a) nounwind 336 store i32 7, i32* %x 337 br label %mid 338 339mid: 340 br i1 %q, label %u, label %g 341 342u: 343 call void @callee() 344 %cu = bitcast i32* %x to i8* 345 call void @objc_release(i8* %cu) nounwind 346 br label %return 347 348g: 349 %cg = bitcast i32* %x to i8* 350 call void @objc_release(i8* %cg) nounwind 351 br label %return 352 353return: 354 ret void 355} 356 357; Trivial retain+release pair deletion. 358 359; CHECK: define void @test9( 360; CHECK-NOT: @objc_ 361; CHECK: } 362define void @test9(i8* %x) nounwind { 363entry: 364 %0 = call i8* @objc_retain(i8* %x) nounwind 365 call void @objc_release(i8* %0) nounwind 366 ret void 367} 368 369; Retain+release pair, but on an unknown pointer relationship. Don't delete! 370 371; CHECK: define void @test9b 372; CHECK: @objc_retain(i8* %x) 373; CHECK: @objc_release(i8* %s) 374; CHECK: } 375define void @test9b(i8* %x, i1 %j, i8* %p) nounwind { 376entry: 377 %0 = call i8* @objc_retain(i8* %x) nounwind 378 %s = select i1 %j, i8* %x, i8* %p 379 call void @objc_release(i8* %s) nounwind 380 ret void 381} 382 383; Trivial retain+release pair with intervening calls - don't delete! 384 385; CHECK: define void @test10( 386; CHECK: @objc_retain(i8* %x) 387; CHECK: @callee 388; CHECK: @use_pointer 389; CHECK: @objc_release 390; CHECK: } 391define void @test10(i8* %x) nounwind { 392entry: 393 %0 = call i8* @objc_retain(i8* %x) nounwind 394 call void @callee() 395 call void @use_pointer(i8* %x) 396 call void @objc_release(i8* %0) nounwind 397 ret void 398} 399 400; Trivial retain+autoreleaserelease pair. Don't delete! 401; Also, add a tail keyword, since objc_retain can never be passed 402; a stack argument. 403 404; CHECK: define void @test11( 405; CHECK: tail call i8* @objc_retain(i8* %x) nounwind 406; CHECK: tail call i8* @objc_autorelease(i8* %0) nounwind 407; CHECK: } 408define void @test11(i8* %x) nounwind { 409entry: 410 %0 = call i8* @objc_retain(i8* %x) nounwind 411 call i8* @objc_autorelease(i8* %0) nounwind 412 call void @use_pointer(i8* %x) 413 ret void 414} 415 416; Same as test11 but with no use_pointer call. Delete the pair! 417 418; CHECK: define void @test11a( 419; CHECK: entry: 420; CHECK-NEXT: ret void 421; CHECK: } 422define void @test11a(i8* %x) nounwind { 423entry: 424 %0 = call i8* @objc_retain(i8* %x) nounwind 425 call i8* @objc_autorelease(i8* %0) nounwind 426 ret void 427} 428 429; Same as test11 but the value is returned. Do an RV optimization. 430 431; CHECK: define i8* @test11b( 432; CHECK: tail call i8* @objc_retain(i8* %x) nounwind 433; CHECK: tail call i8* @objc_autoreleaseReturnValue(i8* %0) nounwind 434; CHECK: } 435define i8* @test11b(i8* %x) nounwind { 436entry: 437 %0 = call i8* @objc_retain(i8* %x) nounwind 438 call i8* @objc_autorelease(i8* %0) nounwind 439 ret i8* %x 440} 441 442; Trivial retain,release pair with intervening call, but it's dominated 443; by another retain - delete! 444 445; CHECK: define void @test12( 446; CHECK-NEXT: entry: 447; CHECK-NEXT: @objc_retain(i8* %x) 448; CHECK-NOT: @objc_ 449; CHECK: } 450define void @test12(i8* %x, i64 %n) { 451entry: 452 call i8* @objc_retain(i8* %x) nounwind 453 call i8* @objc_retain(i8* %x) nounwind 454 call void @use_pointer(i8* %x) 455 call void @use_pointer(i8* %x) 456 call void @objc_release(i8* %x) nounwind 457 ret void 458} 459 460; Trivial retain,autorelease pair. Don't delete! 461 462; CHECK: define void @test13( 463; CHECK: tail call i8* @objc_retain(i8* %x) nounwind 464; CHECK: tail call i8* @objc_retain(i8* %x) nounwind 465; CHECK: @use_pointer(i8* %x) 466; CHECK: tail call i8* @objc_autorelease(i8* %x) nounwind 467; CHECK: } 468define void @test13(i8* %x, i64 %n) { 469entry: 470 call i8* @objc_retain(i8* %x) nounwind 471 call i8* @objc_retain(i8* %x) nounwind 472 call void @use_pointer(i8* %x) 473 call i8* @objc_autorelease(i8* %x) nounwind 474 ret void 475} 476 477; Delete the retain+release pair. 478 479; CHECK: define void @test13b 480; CHECK-NEXT: entry: 481; CHECK-NEXT: @objc_retain(i8* %x) 482; CHECK-NEXT: @use_pointer 483; CHECK-NEXT: @use_pointer 484; CHECK-NEXT: ret void 485define void @test13b(i8* %x, i64 %n) { 486entry: 487 call i8* @objc_retain(i8* %x) nounwind 488 call i8* @objc_retain(i8* %x) nounwind 489 call void @use_pointer(i8* %x) 490 call void @use_pointer(i8* %x) 491 call void @objc_release(i8* %x) nounwind 492 ret void 493} 494 495; Don't delete the retain+release pair because there's an 496; autoreleasePoolPop in the way. 497 498; CHECK: define void @test13c 499; CHECK: @objc_retain(i8* %x) 500; CHECK: @objc_autoreleasePoolPop 501; CHECK: @objc_retain(i8* %x) 502; CHECK: @use_pointer 503; CHECK: @objc_release 504; CHECK: } 505define void @test13c(i8* %x, i64 %n) { 506entry: 507 call i8* @objc_retain(i8* %x) nounwind 508 call void @objc_autoreleasePoolPop(i8* undef) 509 call i8* @objc_retain(i8* %x) nounwind 510 call void @use_pointer(i8* %x) 511 call void @use_pointer(i8* %x) 512 call void @objc_release(i8* %x) nounwind 513 ret void 514} 515 516; Like test13c, but there's an autoreleasePoolPush in the way, but that 517; doesn't matter. 518 519; CHECK: define void @test13d 520; CHECK-NEXT: entry: 521; CHECK-NEXT: @objc_retain(i8* %x) 522; CHECK-NEXT: @objc_autoreleasePoolPush 523; CHECK-NEXT: @use_pointer 524; CHECK-NEXT: @use_pointer 525; CHECK-NEXT: ret void 526define void @test13d(i8* %x, i64 %n) { 527entry: 528 call i8* @objc_retain(i8* %x) nounwind 529 call void @objc_autoreleasePoolPush() 530 call i8* @objc_retain(i8* %x) nounwind 531 call void @use_pointer(i8* %x) 532 call void @use_pointer(i8* %x) 533 call void @objc_release(i8* %x) nounwind 534 ret void 535} 536 537; Trivial retain,release pair with intervening call, but it's post-dominated 538; by another release - delete! 539 540; CHECK: define void @test14( 541; CHECK-NEXT: entry: 542; CHECK-NEXT: @use_pointer 543; CHECK-NEXT: @use_pointer 544; CHECK-NEXT: @objc_release 545; CHECK-NEXT: ret void 546; CHECK-NEXT: } 547define void @test14(i8* %x, i64 %n) { 548entry: 549 call i8* @objc_retain(i8* %x) nounwind 550 call void @use_pointer(i8* %x) 551 call void @use_pointer(i8* %x) 552 call void @objc_release(i8* %x) nounwind 553 call void @objc_release(i8* %x) nounwind 554 ret void 555} 556 557; Trivial retain,autorelease pair with intervening call, but it's post-dominated 558; by another release. Don't delete anything. 559 560; CHECK: define void @test15( 561; CHECK-NEXT: entry: 562; CHECK-NEXT: @objc_retain(i8* %x) 563; CHECK-NEXT: @use_pointer 564; CHECK-NEXT: @objc_autorelease(i8* %x) 565; CHECK-NEXT: @objc_release 566; CHECK-NEXT: ret void 567; CHECK-NEXT: } 568define void @test15(i8* %x, i64 %n) { 569entry: 570 call i8* @objc_retain(i8* %x) nounwind 571 call void @use_pointer(i8* %x) 572 call i8* @objc_autorelease(i8* %x) nounwind 573 call void @objc_release(i8* %x) nounwind 574 ret void 575} 576 577; Trivial retain,autorelease pair, post-dominated 578; by another release. Delete the retain and release. 579 580; CHECK: define void @test15b 581; CHECK-NEXT: entry: 582; CHECK-NEXT: @objc_autorelease 583; CHECK-NEXT: ret void 584; CHECK-NEXT: } 585define void @test15b(i8* %x, i64 %n) { 586entry: 587 call i8* @objc_retain(i8* %x) nounwind 588 call i8* @objc_autorelease(i8* %x) nounwind 589 call void @objc_release(i8* %x) nounwind 590 ret void 591} 592 593; Retain+release pairs in diamonds, all dominated by a retain. 594 595; CHECK: define void @test16( 596; CHECK: @objc_retain(i8* %x) 597; CHECK-NOT: @objc 598; CHECK: } 599define void @test16(i1 %a, i1 %b, i8* %x) { 600entry: 601 call i8* @objc_retain(i8* %x) nounwind 602 br i1 %a, label %red, label %orange 603 604red: 605 call i8* @objc_retain(i8* %x) nounwind 606 br label %yellow 607 608orange: 609 call i8* @objc_retain(i8* %x) nounwind 610 br label %yellow 611 612yellow: 613 call void @use_pointer(i8* %x) 614 call void @use_pointer(i8* %x) 615 br i1 %b, label %green, label %blue 616 617green: 618 call void @objc_release(i8* %x) nounwind 619 br label %purple 620 621blue: 622 call void @objc_release(i8* %x) nounwind 623 br label %purple 624 625purple: 626 ret void 627} 628 629; Retain+release pairs in diamonds, all post-dominated by a release. 630 631; CHECK: define void @test17( 632; CHECK-NOT: @objc_ 633; CHECK: purple: 634; CHECK: @objc_release 635; CHECK: } 636define void @test17(i1 %a, i1 %b, i8* %x) { 637entry: 638 br i1 %a, label %red, label %orange 639 640red: 641 call i8* @objc_retain(i8* %x) nounwind 642 br label %yellow 643 644orange: 645 call i8* @objc_retain(i8* %x) nounwind 646 br label %yellow 647 648yellow: 649 call void @use_pointer(i8* %x) 650 call void @use_pointer(i8* %x) 651 br i1 %b, label %green, label %blue 652 653green: 654 call void @objc_release(i8* %x) nounwind 655 br label %purple 656 657blue: 658 call void @objc_release(i8* %x) nounwind 659 br label %purple 660 661purple: 662 call void @objc_release(i8* %x) nounwind 663 ret void 664} 665 666; Delete no-ops. 667 668; CHECK: define void @test18( 669; CHECK-NOT: @objc_ 670; CHECK: } 671define void @test18() { 672 call i8* @objc_retain(i8* null) 673 call void @objc_release(i8* null) 674 call i8* @objc_autorelease(i8* null) 675 ret void 676} 677 678; Delete no-ops where undef can be assumed to be null. 679 680; CHECK: define void @test18b 681; CHECK-NOT: @objc_ 682; CHECK: } 683define void @test18b() { 684 call i8* @objc_retain(i8* undef) 685 call void @objc_release(i8* undef) 686 call i8* @objc_autorelease(i8* undef) 687 ret void 688} 689 690; Replace uses of arguments with uses of return values, to reduce 691; register pressure. 692 693; CHECK: define void @test19(i32* %y) { 694; CHECK: %z = bitcast i32* %y to i8* 695; CHECK: %0 = bitcast i32* %y to i8* 696; CHECK: %1 = tail call i8* @objc_retain(i8* %0) 697; CHECK: call void @use_pointer(i8* %z) 698; CHECK: call void @use_pointer(i8* %z) 699; CHECK: %2 = bitcast i32* %y to i8* 700; CHECK: call void @objc_release(i8* %2) 701; CHECK: ret void 702; CHECK: } 703define void @test19(i32* %y) { 704entry: 705 %x = bitcast i32* %y to i8* 706 %0 = call i8* @objc_retain(i8* %x) nounwind 707 %z = bitcast i32* %y to i8* 708 call void @use_pointer(i8* %z) 709 call void @use_pointer(i8* %z) 710 call void @objc_release(i8* %x) 711 ret void 712} 713 714; Bitcast insertion 715 716; CHECK: define void @test20( 717; CHECK: %tmp1 = tail call i8* @objc_retain(i8* %tmp) nounwind 718; CHECK-NEXT: invoke 719define void @test20(double* %self) { 720if.then12: 721 %tmp = bitcast double* %self to i8* 722 %tmp1 = call i8* @objc_retain(i8* %tmp) nounwind 723 invoke void @invokee() 724 to label %invoke.cont23 unwind label %lpad20 725 726invoke.cont23: ; preds = %if.then12 727 invoke void @invokee() 728 to label %if.end unwind label %lpad20 729 730lpad20: ; preds = %invoke.cont23, %if.then12 731 %tmp502 = phi double* [ undef, %invoke.cont23 ], [ %self, %if.then12 ] 732 %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 733 cleanup 734 unreachable 735 736if.end: ; preds = %invoke.cont23 737 ret void 738} 739 740; Delete a redundant retain,autorelease when forwaring a call result 741; directly to a return value. 742 743; CHECK: define i8* @test21( 744; CHECK: call i8* @returner() 745; CHECK-NEXT: ret i8* %call 746define i8* @test21() { 747entry: 748 %call = call i8* @returner() 749 %0 = call i8* @objc_retain(i8* %call) nounwind 750 %1 = call i8* @objc_autorelease(i8* %0) nounwind 751 ret i8* %1 752} 753 754; Move an objc call up through a phi that has null operands. 755 756; CHECK: define void @test22( 757; CHECK: B: 758; CHECK: %1 = bitcast double* %p to i8* 759; CHECK: call void @objc_release(i8* %1) 760; CHECK: br label %C 761; CHECK: C: ; preds = %B, %A 762; CHECK-NOT: @objc_release 763; CHECK: } 764define void @test22(double* %p, i1 %a) { 765 br i1 %a, label %A, label %B 766A: 767 br label %C 768B: 769 br label %C 770C: 771 %h = phi double* [ null, %A ], [ %p, %B ] 772 %c = bitcast double* %h to i8* 773 call void @objc_release(i8* %c) 774 ret void 775} 776 777; Optimize objc_retainBlock. 778 779; CHECK: define void @test23( 780; CHECK-NOT: @objc_ 781; CHECK: } 782%block0 = type { i64, i64, i8*, i8* } 783%block1 = type { i8**, i32, i32, i32 (%struct.__block_literal_1*)*, %block0* } 784%struct.__block_descriptor = type { i64, i64 } 785%struct.__block_literal_1 = type { i8**, i32, i32, i8**, %struct.__block_descriptor* } 786@__block_holder_tmp_1 = external constant %block1 787define void @test23() { 788entry: 789 %0 = call i8* @objc_retainBlock(i8* bitcast (%block1* @__block_holder_tmp_1 to i8*)) nounwind 790 call void @bar(i32 ()* bitcast (%block1* @__block_holder_tmp_1 to i32 ()*)) 791 call void @bar(i32 ()* bitcast (%block1* @__block_holder_tmp_1 to i32 ()*)) 792 call void @objc_release(i8* bitcast (%block1* @__block_holder_tmp_1 to i8*)) nounwind 793 ret void 794} 795 796; Don't optimize objc_retainBlock. 797 798; CHECK: define void @test23b 799; CHECK: @objc_retainBlock 800; CHECK: @objc_release 801; CHECK: } 802define void @test23b(i8* %p) { 803entry: 804 %0 = call i8* @objc_retainBlock(i8* %p) nounwind 805 call void @callee() 806 call void @use_pointer(i8* %p) 807 call void @objc_release(i8* %p) nounwind 808 ret void 809} 810 811; Any call can decrement a retain count. 812 813; CHECK: define void @test24( 814; CHECK: @objc_retain(i8* %a) 815; CHECK: @objc_release 816; CHECK: } 817define void @test24(i8* %r, i8* %a) { 818 call i8* @objc_retain(i8* %a) 819 call void @use_pointer(i8* %r) 820 %q = load i8* %a 821 call void @objc_release(i8* %a) 822 ret void 823} 824 825; Don't move a retain/release pair if the release can be moved 826; but the retain can't be moved to balance it. 827 828; CHECK: define void @test25( 829; CHECK: entry: 830; CHECK: call i8* @objc_retain(i8* %p) 831; CHECK: true: 832; CHECK: done: 833; CHECK: call void @objc_release(i8* %p) 834; CHECK: } 835define void @test25(i8* %p, i1 %x) { 836entry: 837 %f0 = call i8* @objc_retain(i8* %p) 838 call void @callee() 839 br i1 %x, label %true, label %done 840 841true: 842 store i8 0, i8* %p 843 br label %done 844 845done: 846 call void @objc_release(i8* %p) 847 ret void 848} 849 850; Don't move a retain/release pair if the retain can be moved 851; but the release can't be moved to balance it. 852 853; CHECK: define void @test26( 854; CHECK: entry: 855; CHECK: call i8* @objc_retain(i8* %p) 856; CHECK: true: 857; CHECK: done: 858; CHECK: call void @objc_release(i8* %p) 859; CHECK: } 860define void @test26(i8* %p, i1 %x) { 861entry: 862 %f0 = call i8* @objc_retain(i8* %p) 863 br i1 %x, label %true, label %done 864 865true: 866 call void @callee() 867 br label %done 868 869done: 870 store i8 0, i8* %p 871 call void @objc_release(i8* %p) 872 ret void 873} 874 875; Don't sink the retain,release into the loop. 876 877; CHECK: define void @test27( 878; CHECK: entry: 879; CHECK: call i8* @objc_retain(i8* %p) 880; CHECK: loop: 881; CHECK-NOT: @objc_ 882; CHECK: done: 883; CHECK: call void @objc_release 884; CHECK: } 885define void @test27(i8* %p, i1 %x, i1 %y) { 886entry: 887 %f0 = call i8* @objc_retain(i8* %p) 888 br i1 %x, label %loop, label %done 889 890loop: 891 call void @callee() 892 store i8 0, i8* %p 893 br i1 %y, label %done, label %loop 894 895done: 896 call void @objc_release(i8* %p) 897 ret void 898} 899 900; Trivial code motion case: Triangle. 901 902; CHECK: define void @test28( 903; CHECK-NOT: @objc_ 904; CHECK: true: 905; CHECK: call i8* @objc_retain( 906; CHECK: call void @callee() 907; CHECK: store 908; CHECK: call void @objc_release 909; CHECK: done: 910; CHECK-NOT: @objc_ 911; CHECK: } 912define void @test28(i8* %p, i1 %x) { 913entry: 914 %f0 = call i8* @objc_retain(i8* %p) 915 br i1 %x, label %true, label %done 916 917true: 918 call void @callee() 919 store i8 0, i8* %p 920 br label %done 921 922done: 923 call void @objc_release(i8* %p), !clang.imprecise_release !0 924 ret void 925} 926 927; Trivial code motion case: Triangle, but no metadata. Don't move past 928; unrelated memory references! 929 930; CHECK: define void @test28b 931; CHECK: call i8* @objc_retain( 932; CHECK: true: 933; CHECK-NOT: @objc_ 934; CHECK: call void @callee() 935; CHECK-NOT: @objc_ 936; CHECK: store 937; CHECK-NOT: @objc_ 938; CHECK: done: 939; CHECK: @objc_release 940; CHECK: } 941define void @test28b(i8* %p, i1 %x, i8* noalias %t) { 942entry: 943 %f0 = call i8* @objc_retain(i8* %p) 944 br i1 %x, label %true, label %done 945 946true: 947 call void @callee() 948 store i8 0, i8* %p 949 br label %done 950 951done: 952 store i8 0, i8* %t 953 call void @objc_release(i8* %p) 954 ret void 955} 956 957; Trivial code motion case: Triangle, with metadata. Do move past 958; unrelated memory references! And preserve the metadata. 959 960; CHECK: define void @test28c 961; CHECK-NOT: @objc_ 962; CHECK: true: 963; CHECK: call i8* @objc_retain( 964; CHECK: call void @callee() 965; CHECK: store 966; CHECK: call void @objc_release(i8* %p) nounwind, !clang.imprecise_release 967; CHECK: done: 968; CHECK-NOT: @objc_ 969; CHECK: } 970define void @test28c(i8* %p, i1 %x, i8* noalias %t) { 971entry: 972 %f0 = call i8* @objc_retain(i8* %p) 973 br i1 %x, label %true, label %done 974 975true: 976 call void @callee() 977 store i8 0, i8* %p 978 br label %done 979 980done: 981 store i8 0, i8* %t 982 call void @objc_release(i8* %p), !clang.imprecise_release !0 983 ret void 984} 985 986; Like test28. but with two releases. 987 988; CHECK: define void @test29( 989; CHECK-NOT: @objc_ 990; CHECK: true: 991; CHECK: call i8* @objc_retain( 992; CHECK: call void @callee() 993; CHECK: store 994; CHECK: call void @objc_release 995; CHECK-NOT: @objc_release 996; CHECK: done: 997; CHECK-NOT: @objc_ 998; CHECK: ohno: 999; CHECK-NOT: @objc_ 1000; CHECK: } 1001define void @test29(i8* %p, i1 %x, i1 %y) { 1002entry: 1003 %f0 = call i8* @objc_retain(i8* %p) 1004 br i1 %x, label %true, label %done 1005 1006true: 1007 call void @callee() 1008 store i8 0, i8* %p 1009 br i1 %y, label %done, label %ohno 1010 1011done: 1012 call void @objc_release(i8* %p) 1013 ret void 1014 1015ohno: 1016 call void @objc_release(i8* %p) 1017 ret void 1018} 1019 1020; Basic case with the use and call in a diamond 1021; with an extra release. 1022 1023; CHECK: define void @test30( 1024; CHECK-NOT: @objc_ 1025; CHECK: true: 1026; CHECK: call i8* @objc_retain( 1027; CHECK: call void @callee() 1028; CHECK: store 1029; CHECK: call void @objc_release 1030; CHECK-NOT: @objc_release 1031; CHECK: false: 1032; CHECK-NOT: @objc_ 1033; CHECK: done: 1034; CHECK-NOT: @objc_ 1035; CHECK: ohno: 1036; CHECK-NOT: @objc_ 1037; CHECK: } 1038define void @test30(i8* %p, i1 %x, i1 %y, i1 %z) { 1039entry: 1040 %f0 = call i8* @objc_retain(i8* %p) 1041 br i1 %x, label %true, label %false 1042 1043true: 1044 call void @callee() 1045 store i8 0, i8* %p 1046 br i1 %y, label %done, label %ohno 1047 1048false: 1049 br i1 %z, label %done, label %ohno 1050 1051done: 1052 call void @objc_release(i8* %p) 1053 ret void 1054 1055ohno: 1056 call void @objc_release(i8* %p) 1057 ret void 1058} 1059 1060; Basic case with a mergeable release. 1061 1062; CHECK: define void @test31( 1063; CHECK: call i8* @objc_retain(i8* %p) 1064; CHECK: call void @callee() 1065; CHECK: store 1066; CHECK: call void @objc_release 1067; CHECK-NOT: @objc_release 1068; CHECK: true: 1069; CHECK-NOT: @objc_release 1070; CHECK: false: 1071; CHECK-NOT: @objc_release 1072; CHECK: ret void 1073; CHECK-NOT: @objc_release 1074; CHECK: } 1075define void @test31(i8* %p, i1 %x) { 1076entry: 1077 %f0 = call i8* @objc_retain(i8* %p) 1078 call void @callee() 1079 store i8 0, i8* %p 1080 br i1 %x, label %true, label %false 1081true: 1082 call void @objc_release(i8* %p) 1083 ret void 1084false: 1085 call void @objc_release(i8* %p) 1086 ret void 1087} 1088 1089; Don't consider bitcasts or getelementptrs direct uses. 1090 1091; CHECK: define void @test32( 1092; CHECK-NOT: @objc_ 1093; CHECK: true: 1094; CHECK: call i8* @objc_retain( 1095; CHECK: call void @callee() 1096; CHECK: store 1097; CHECK: call void @objc_release 1098; CHECK: done: 1099; CHECK-NOT: @objc_ 1100; CHECK: } 1101define void @test32(i8* %p, i1 %x) { 1102entry: 1103 %f0 = call i8* @objc_retain(i8* %p) 1104 br i1 %x, label %true, label %done 1105 1106true: 1107 call void @callee() 1108 store i8 0, i8* %p 1109 br label %done 1110 1111done: 1112 %g = bitcast i8* %p to i8* 1113 %h = getelementptr i8* %g, i64 0 1114 call void @objc_release(i8* %g) 1115 ret void 1116} 1117 1118; Do consider icmps to be direct uses. 1119 1120; CHECK: define void @test33( 1121; CHECK-NOT: @objc_ 1122; CHECK: true: 1123; CHECK: call i8* @objc_retain( 1124; CHECK: call void @callee() 1125; CHECK: icmp 1126; CHECK: call void @objc_release 1127; CHECK: done: 1128; CHECK-NOT: @objc_ 1129; CHECK: } 1130define void @test33(i8* %p, i1 %x, i8* %y) { 1131entry: 1132 %f0 = call i8* @objc_retain(i8* %p) 1133 br i1 %x, label %true, label %done 1134 1135true: 1136 call void @callee() 1137 %v = icmp eq i8* %p, %y 1138 br label %done 1139 1140done: 1141 %g = bitcast i8* %p to i8* 1142 %h = getelementptr i8* %g, i64 0 1143 call void @objc_release(i8* %g) 1144 ret void 1145} 1146 1147; Delete retain,release if there's just a possible dec. 1148 1149; CHECK: define void @test34( 1150; CHECK-NOT: @objc_ 1151; CHECK: } 1152define void @test34(i8* %p, i1 %x, i8* %y) { 1153entry: 1154 %f0 = call i8* @objc_retain(i8* %p) 1155 br i1 %x, label %true, label %done 1156 1157true: 1158 call void @callee() 1159 br label %done 1160 1161done: 1162 %g = bitcast i8* %p to i8* 1163 %h = getelementptr i8* %g, i64 0 1164 call void @objc_release(i8* %g) 1165 ret void 1166} 1167 1168; Delete retain,release if there's just a use. 1169 1170; CHECK: define void @test35( 1171; CHECK-NOT: @objc_ 1172; CHECK: } 1173define void @test35(i8* %p, i1 %x, i8* %y) { 1174entry: 1175 %f0 = call i8* @objc_retain(i8* %p) 1176 br i1 %x, label %true, label %done 1177 1178true: 1179 %v = icmp eq i8* %p, %y 1180 br label %done 1181 1182done: 1183 %g = bitcast i8* %p to i8* 1184 %h = getelementptr i8* %g, i64 0 1185 call void @objc_release(i8* %g) 1186 ret void 1187} 1188 1189; Delete a retain,release if there's no actual use. 1190 1191; CHECK: define void @test36( 1192; CHECK-NOT: @objc_ 1193; CHECK: call void @callee() 1194; CHECK-NOT: @objc_ 1195; CHECK: call void @callee() 1196; CHECK-NOT: @objc_ 1197; CHECK: } 1198define void @test36(i8* %p) { 1199entry: 1200 call i8* @objc_retain(i8* %p) 1201 call void @callee() 1202 call void @callee() 1203 call void @objc_release(i8* %p) 1204 ret void 1205} 1206 1207; Like test36, but with metadata. 1208 1209; CHECK: define void @test37( 1210; CHECK-NOT: @objc_ 1211; CHECK: } 1212define void @test37(i8* %p) { 1213entry: 1214 call i8* @objc_retain(i8* %p) 1215 call void @callee() 1216 call void @callee() 1217 call void @objc_release(i8* %p), !clang.imprecise_release !0 1218 ret void 1219} 1220 1221; Be aggressive about analyzing phis to eliminate possible uses. 1222 1223; CHECK: define void @test38( 1224; CHECK-NOT: @objc_ 1225; CHECK: } 1226define void @test38(i8* %p, i1 %u, i1 %m, i8* %z, i8* %y, i8* %x, i8* %w) { 1227entry: 1228 call i8* @objc_retain(i8* %p) 1229 br i1 %u, label %true, label %false 1230true: 1231 br i1 %m, label %a, label %b 1232false: 1233 br i1 %m, label %c, label %d 1234a: 1235 br label %e 1236b: 1237 br label %e 1238c: 1239 br label %f 1240d: 1241 br label %f 1242e: 1243 %j = phi i8* [ %z, %a ], [ %y, %b ] 1244 br label %g 1245f: 1246 %k = phi i8* [ %w, %c ], [ %x, %d ] 1247 br label %g 1248g: 1249 %h = phi i8* [ %j, %e ], [ %k, %f ] 1250 call void @use_pointer(i8* %h) 1251 call void @objc_release(i8* %p), !clang.imprecise_release !0 1252 ret void 1253} 1254 1255; Delete retain,release pairs around loops. 1256 1257; CHECK: define void @test39( 1258; CHECK_NOT: @objc_ 1259; CHECK: } 1260define void @test39(i8* %p) { 1261entry: 1262 %0 = call i8* @objc_retain(i8* %p) 1263 br label %loop 1264 1265loop: ; preds = %loop, %entry 1266 br i1 undef, label %loop, label %exit 1267 1268exit: ; preds = %loop 1269 call void @objc_release(i8* %0), !clang.imprecise_release !0 1270 ret void 1271} 1272 1273; Delete retain,release pairs around loops containing uses. 1274 1275; CHECK: define void @test39b( 1276; CHECK_NOT: @objc_ 1277; CHECK: } 1278define void @test39b(i8* %p) { 1279entry: 1280 %0 = call i8* @objc_retain(i8* %p) 1281 br label %loop 1282 1283loop: ; preds = %loop, %entry 1284 store i8 0, i8* %0 1285 br i1 undef, label %loop, label %exit 1286 1287exit: ; preds = %loop 1288 call void @objc_release(i8* %0), !clang.imprecise_release !0 1289 ret void 1290} 1291 1292; Delete retain,release pairs around loops containing potential decrements. 1293 1294; CHECK: define void @test39c( 1295; CHECK_NOT: @objc_ 1296; CHECK: } 1297define void @test39c(i8* %p) { 1298entry: 1299 %0 = call i8* @objc_retain(i8* %p) 1300 br label %loop 1301 1302loop: ; preds = %loop, %entry 1303 call void @use_pointer(i8* %0) 1304 br i1 undef, label %loop, label %exit 1305 1306exit: ; preds = %loop 1307 call void @objc_release(i8* %0), !clang.imprecise_release !0 1308 ret void 1309} 1310 1311; Delete retain,release pairs around loops even if 1312; the successors are in a different order. 1313 1314; CHECK: define void @test40( 1315; CHECK_NOT: @objc_ 1316; CHECK: } 1317define void @test40(i8* %p) { 1318entry: 1319 %0 = call i8* @objc_retain(i8* %p) 1320 br label %loop 1321 1322loop: ; preds = %loop, %entry 1323 call void @use_pointer(i8* %0) 1324 br i1 undef, label %exit, label %loop 1325 1326exit: ; preds = %loop 1327 call void @objc_release(i8* %0), !clang.imprecise_release !0 1328 ret void 1329} 1330 1331; Do the known-incremented retain+release elimination even if the pointer 1332; is also autoreleased. 1333 1334; CHECK: define void @test42( 1335; CHECK-NEXT: entry: 1336; CHECK-NEXT: call i8* @objc_retain(i8* %p) 1337; CHECK-NEXT: call i8* @objc_autorelease(i8* %p) 1338; CHECK-NEXT: call void @use_pointer(i8* %p) 1339; CHECK-NEXT: call void @use_pointer(i8* %p) 1340; CHECK-NEXT: ret void 1341; CHECK-NEXT: } 1342define void @test42(i8* %p) { 1343entry: 1344 call i8* @objc_retain(i8* %p) 1345 call i8* @objc_autorelease(i8* %p) 1346 call i8* @objc_retain(i8* %p) 1347 call void @use_pointer(i8* %p) 1348 call void @use_pointer(i8* %p) 1349 call void @objc_release(i8* %p) 1350 ret void 1351} 1352 1353; Don't the known-incremented retain+release elimination if the pointer is 1354; autoreleased and there's an autoreleasePoolPop. 1355 1356; CHECK: define void @test43( 1357; CHECK-NEXT: entry: 1358; CHECK-NEXT: call i8* @objc_retain(i8* %p) 1359; CHECK-NEXT: call i8* @objc_autorelease(i8* %p) 1360; CHECK-NEXT: call i8* @objc_retain 1361; CHECK-NEXT: call void @use_pointer(i8* %p) 1362; CHECK-NEXT: call void @use_pointer(i8* %p) 1363; CHECK-NEXT: call void @objc_autoreleasePoolPop(i8* undef) 1364; CHECK-NEXT: call void @objc_release 1365; CHECK-NEXT: ret void 1366; CHECK-NEXT: } 1367define void @test43(i8* %p) { 1368entry: 1369 call i8* @objc_retain(i8* %p) 1370 call i8* @objc_autorelease(i8* %p) 1371 call i8* @objc_retain(i8* %p) 1372 call void @use_pointer(i8* %p) 1373 call void @use_pointer(i8* %p) 1374 call void @objc_autoreleasePoolPop(i8* undef) 1375 call void @objc_release(i8* %p) 1376 ret void 1377} 1378 1379; Do the known-incremented retain+release elimination if the pointer is 1380; autoreleased and there's an autoreleasePoolPush. 1381 1382; CHECK: define void @test43b 1383; CHECK-NEXT: entry: 1384; CHECK-NEXT: call i8* @objc_retain(i8* %p) 1385; CHECK-NEXT: call i8* @objc_autorelease(i8* %p) 1386; CHECK-NEXT: call void @use_pointer(i8* %p) 1387; CHECK-NEXT: call void @use_pointer(i8* %p) 1388; CHECK-NEXT: call void @objc_autoreleasePoolPush() 1389; CHECK-NEXT: ret void 1390; CHECK-NEXT: } 1391define void @test43b(i8* %p) { 1392entry: 1393 call i8* @objc_retain(i8* %p) 1394 call i8* @objc_autorelease(i8* %p) 1395 call i8* @objc_retain(i8* %p) 1396 call void @use_pointer(i8* %p) 1397 call void @use_pointer(i8* %p) 1398 call void @objc_autoreleasePoolPush() 1399 call void @objc_release(i8* %p) 1400 ret void 1401} 1402 1403; Do retain+release elimination for non-provenance pointers. 1404 1405; CHECK: define void @test44( 1406; CHECK-NOT: objc_ 1407; CHECK: } 1408define void @test44(i8** %pp) { 1409 %p = load i8** %pp 1410 %q = call i8* @objc_retain(i8* %p) 1411 call void @objc_release(i8* %q) 1412 ret void 1413} 1414 1415; Don't delete retain+release with an unknown-provenance 1416; may-alias objc_release between them. 1417 1418; CHECK: define void @test45( 1419; CHECK: call i8* @objc_retain(i8* %p) 1420; CHECK: call void @objc_release(i8* %q) 1421; CHECK: call void @use_pointer(i8* %p) 1422; CHECK: call void @objc_release(i8* %p) 1423define void @test45(i8** %pp, i8** %qq) { 1424 %p = load i8** %pp 1425 %q = load i8** %qq 1426 call i8* @objc_retain(i8* %p) 1427 call void @objc_release(i8* %q) 1428 call void @use_pointer(i8* %p) 1429 call void @objc_release(i8* %p) 1430 ret void 1431} 1432 1433; Don't delete retain and autorelease here. 1434 1435; CHECK: define void @test46( 1436; CHECK: tail call i8* @objc_retain(i8* %p) nounwind 1437; CHECK: true: 1438; CHECK: tail call i8* @objc_autorelease(i8* %p) nounwind 1439define void @test46(i8* %p, i1 %a) { 1440entry: 1441 call i8* @objc_retain(i8* %p) 1442 br i1 %a, label %true, label %false 1443 1444true: 1445 call i8* @objc_autorelease(i8* %p) 1446 call void @use_pointer(i8* %p) 1447 ret void 1448 1449false: 1450 ret void 1451} 1452 1453; Delete no-op cast calls. 1454 1455; CHECK: define i8* @test47( 1456; CHECK-NOT: call 1457; CHECK: ret i8* %p 1458define i8* @test47(i8* %p) nounwind { 1459 %x = call i8* @objc_retainedObject(i8* %p) 1460 ret i8* %x 1461} 1462 1463; Delete no-op cast calls. 1464 1465; CHECK: define i8* @test48( 1466; CHECK-NOT: call 1467; CHECK: ret i8* %p 1468define i8* @test48(i8* %p) nounwind { 1469 %x = call i8* @objc_unretainedObject(i8* %p) 1470 ret i8* %x 1471} 1472 1473; Delete no-op cast calls. 1474 1475; CHECK: define i8* @test49( 1476; CHECK-NOT: call 1477; CHECK: ret i8* %p 1478define i8* @test49(i8* %p) nounwind { 1479 %x = call i8* @objc_unretainedPointer(i8* %p) 1480 ret i8* %x 1481} 1482 1483; Do delete retain+release with intervening stores of the 1484; address value; 1485 1486; CHECK: define void @test50( 1487; CHECK-NOT: @objc_ 1488; CHECK: } 1489define void @test50(i8* %p, i8** %pp) { 1490 call i8* @objc_retain(i8* %p) 1491 call void @callee() 1492 store i8* %p, i8** %pp 1493 call void @objc_release(i8* %p) 1494 ret void 1495} 1496 1497; Don't delete retain+release with intervening stores through the 1498; address value. 1499 1500; CHECK: define void @test51( 1501; CHECK: call i8* @objc_retain(i8* %p) 1502; CHECK: call void @objc_release(i8* %p) 1503define void @test51(i8* %p) { 1504 call i8* @objc_retain(i8* %p) 1505 call void @callee() 1506 store i8 0, i8* %p 1507 call void @objc_release(i8* %p) 1508 ret void 1509} 1510 1511; Don't delete retain+release with intervening use of a pointer of 1512; unknown provenance. 1513 1514; CHECK: define void @test52( 1515; CHECK: call i8* @objc_retain 1516; CHECK: call void @callee() 1517; CHECK: call void @use_pointer(i8* %z) 1518; CHECK: call void @objc_release 1519define void @test52(i8** %zz, i8** %pp) { 1520 %p = load i8** %pp 1521 %1 = call i8* @objc_retain(i8* %p) 1522 call void @callee() 1523 %z = load i8** %zz 1524 call void @use_pointer(i8* %z) 1525 call void @objc_release(i8* %p) 1526 ret void 1527} 1528 1529; Like test52, but the pointer has function type, so it's assumed to 1530; be not reference counted. 1531 1532; CHECK: define void @test53( 1533; CHECK-NOT: @objc_ 1534; CHECK: } 1535define void @test53(void ()** %zz, i8** %pp) { 1536 %p = load i8** %pp 1537 %1 = call i8* @objc_retain(i8* %p) 1538 call void @callee() 1539 %z = load void ()** %zz 1540 call void @callee_fnptr(void ()* %z) 1541 call void @objc_release(i8* %p) 1542 ret void 1543} 1544 1545; Convert autorelease to release if the value is unused. 1546 1547; CHECK: define void @test54( 1548; CHECK: call i8* @returner() 1549; CHECK-NEXT: call void @objc_release(i8* %t) nounwind, !clang.imprecise_release !0 1550; CHECK-NEXT: ret void 1551define void @test54() { 1552 %t = call i8* @returner() 1553 call i8* @objc_autorelease(i8* %t) 1554 ret void 1555} 1556 1557; Nested retain+release pairs. Delete them both. 1558 1559; CHECK: define void @test55( 1560; CHECK-NOT: @objc 1561; CHECK: } 1562define void @test55(i8* %x) { 1563entry: 1564 %0 = call i8* @objc_retain(i8* %x) nounwind 1565 %1 = call i8* @objc_retain(i8* %x) nounwind 1566 call void @objc_release(i8* %x) nounwind 1567 call void @objc_release(i8* %x) nounwind 1568 ret void 1569} 1570 1571; Nested retain+release pairs where the inner pair depends 1572; on the outer pair to be removed, and then the outer pair 1573; can be partially eliminated. Plus an extra outer pair to 1574; eliminate, for fun. 1575 1576; CHECK: define void @test56( 1577; CHECK-NOT: @objc 1578; CHECK: if.then: 1579; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %x) nounwind 1580; CHECK-NEXT: tail call void @use_pointer(i8* %x) 1581; CHECK-NEXT: tail call void @use_pointer(i8* %x) 1582; CHECK-NEXT: tail call void @objc_release(i8* %x) nounwind, !clang.imprecise_release !0 1583; CHECK-NEXT: br label %if.end 1584; CHECK-NOT: @objc 1585; CHECK: } 1586define void @test56(i8* %x, i32 %n) { 1587entry: 1588 %0 = tail call i8* @objc_retain(i8* %x) nounwind 1589 %1 = tail call i8* @objc_retain(i8* %0) nounwind 1590 %tobool = icmp eq i32 %n, 0 1591 br i1 %tobool, label %if.end, label %if.then 1592 1593if.then: ; preds = %entry 1594 %2 = tail call i8* @objc_retain(i8* %1) nounwind 1595 tail call void @use_pointer(i8* %2) 1596 tail call void @use_pointer(i8* %2) 1597 tail call void @objc_release(i8* %2) nounwind, !clang.imprecise_release !0 1598 br label %if.end 1599 1600if.end: ; preds = %entry, %if.then 1601 tail call void @objc_release(i8* %1) nounwind, !clang.imprecise_release !0 1602 tail call void @objc_release(i8* %0) nounwind, !clang.imprecise_release !0 1603 ret void 1604} 1605 1606; When there are adjacent retain+release pairs, the first one is 1607; known unnecessary because the presence of the second one means that 1608; the first one won't be deleting the object. 1609 1610; CHECK: define void @test57( 1611; CHECK-NEXT: entry: 1612; CHECK-NEXT: call void @use_pointer(i8* %x) 1613; CHECK-NEXT: call void @use_pointer(i8* %x) 1614; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %x) nounwind 1615; CHECK-NEXT: call void @use_pointer(i8* %x) 1616; CHECK-NEXT: call void @use_pointer(i8* %x) 1617; CHECK-NEXT: call void @objc_release(i8* %x) nounwind 1618; CHECK-NEXT: ret void 1619; CHECK-NEXT: } 1620define void @test57(i8* %x) nounwind { 1621entry: 1622 call i8* @objc_retain(i8* %x) nounwind 1623 call void @use_pointer(i8* %x) 1624 call void @use_pointer(i8* %x) 1625 call void @objc_release(i8* %x) nounwind 1626 call i8* @objc_retain(i8* %x) nounwind 1627 call void @use_pointer(i8* %x) 1628 call void @use_pointer(i8* %x) 1629 call void @objc_release(i8* %x) nounwind 1630 ret void 1631} 1632 1633; An adjacent retain+release pair is sufficient even if it will be 1634; removed itself. 1635 1636; CHECK: define void @test58( 1637; CHECK-NEXT: entry: 1638; CHECK-NEXT: call void @use_pointer(i8* %x) 1639; CHECK-NEXT: call void @use_pointer(i8* %x) 1640; CHECK-NEXT: ret void 1641; CHECK-NEXT: } 1642define void @test58(i8* %x) nounwind { 1643entry: 1644 call i8* @objc_retain(i8* %x) nounwind 1645 call void @use_pointer(i8* %x) 1646 call void @use_pointer(i8* %x) 1647 call void @objc_release(i8* %x) nounwind 1648 call i8* @objc_retain(i8* %x) nounwind 1649 call void @objc_release(i8* %x) nounwind 1650 ret void 1651} 1652 1653; Don't delete the second retain+release pair in an adjacent set. 1654 1655; CHECK: define void @test59( 1656; CHECK-NEXT: entry: 1657; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %x) nounwind 1658; CHECK-NEXT: call void @use_pointer(i8* %x) 1659; CHECK-NEXT: call void @use_pointer(i8* %x) 1660; CHECK-NEXT: call void @objc_release(i8* %x) nounwind 1661; CHECK-NEXT: ret void 1662; CHECK-NEXT: } 1663define void @test59(i8* %x) nounwind { 1664entry: 1665 %a = call i8* @objc_retain(i8* %x) nounwind 1666 call void @objc_release(i8* %x) nounwind 1667 %b = call i8* @objc_retain(i8* %x) nounwind 1668 call void @use_pointer(i8* %x) 1669 call void @use_pointer(i8* %x) 1670 call void @objc_release(i8* %x) nounwind 1671 ret void 1672} 1673 1674; Constant pointers to objects don't need reference counting. 1675 1676@constptr = external constant i8* 1677@something = external global i8* 1678 1679; CHECK: define void @test60( 1680; CHECK-NOT: @objc_ 1681; CHECK: } 1682define void @test60() { 1683 %t = load i8** @constptr 1684 %s = load i8** @something 1685 call i8* @objc_retain(i8* %s) 1686 call void @callee() 1687 call void @use_pointer(i8* %t) 1688 call void @objc_release(i8* %s) 1689 ret void 1690} 1691 1692; Constant pointers to objects don't need to be considered related to other 1693; pointers. 1694 1695; CHECK: define void @test61( 1696; CHECK-NOT: @objc_ 1697; CHECK: } 1698define void @test61() { 1699 %t = load i8** @constptr 1700 call i8* @objc_retain(i8* %t) 1701 call void @callee() 1702 call void @use_pointer(i8* %t) 1703 call void @objc_release(i8* %t) 1704 ret void 1705} 1706 1707declare void @bar(i32 ()*) 1708 1709; A few real-world testcases. 1710 1711@.str4 = private unnamed_addr constant [33 x i8] c"-[A z] = { %f, %f, { %f, %f } }\0A\00" 1712@"OBJC_IVAR_$_A.myZ" = global i64 20, section "__DATA, __objc_const", align 8 1713declare i32 @printf(i8* nocapture, ...) nounwind 1714declare i32 @puts(i8* nocapture) nounwind 1715@str = internal constant [16 x i8] c"-[ Top0 _getX ]\00" 1716 1717; CHECK: @"\01-[A z]" 1718; CHECK-NOT: @objc_ 1719; CHECK: } 1720 1721define {<2 x float>, <2 x float>} @"\01-[A z]"({}* %self, i8* nocapture %_cmd) nounwind { 1722invoke.cont: 1723 %0 = bitcast {}* %self to i8* 1724 %1 = tail call i8* @objc_retain(i8* %0) nounwind 1725 tail call void @llvm.dbg.value(metadata !{{}* %self}, i64 0, metadata !0) 1726 tail call void @llvm.dbg.value(metadata !{{}* %self}, i64 0, metadata !0) 1727 %ivar = load i64* @"OBJC_IVAR_$_A.myZ", align 8 1728 %add.ptr = getelementptr i8* %0, i64 %ivar 1729 %tmp1 = bitcast i8* %add.ptr to float* 1730 %tmp2 = load float* %tmp1, align 4 1731 %conv = fpext float %tmp2 to double 1732 %add.ptr.sum = add i64 %ivar, 4 1733 %tmp6 = getelementptr inbounds i8* %0, i64 %add.ptr.sum 1734 %2 = bitcast i8* %tmp6 to float* 1735 %tmp7 = load float* %2, align 4 1736 %conv8 = fpext float %tmp7 to double 1737 %add.ptr.sum36 = add i64 %ivar, 8 1738 %tmp12 = getelementptr inbounds i8* %0, i64 %add.ptr.sum36 1739 %arrayidx = bitcast i8* %tmp12 to float* 1740 %tmp13 = load float* %arrayidx, align 4 1741 %conv14 = fpext float %tmp13 to double 1742 %tmp12.sum = add i64 %ivar, 12 1743 %arrayidx19 = getelementptr inbounds i8* %0, i64 %tmp12.sum 1744 %3 = bitcast i8* %arrayidx19 to float* 1745 %tmp20 = load float* %3, align 4 1746 %conv21 = fpext float %tmp20 to double 1747 %call = tail call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([33 x i8]* @.str4, i64 0, i64 0), double %conv, double %conv8, double %conv14, double %conv21) 1748 %ivar23 = load i64* @"OBJC_IVAR_$_A.myZ", align 8 1749 %add.ptr24 = getelementptr i8* %0, i64 %ivar23 1750 %4 = bitcast i8* %add.ptr24 to i128* 1751 %srcval = load i128* %4, align 4 1752 tail call void @objc_release(i8* %0) nounwind 1753 %tmp29 = trunc i128 %srcval to i64 1754 %tmp30 = bitcast i64 %tmp29 to <2 x float> 1755 %tmp31 = insertvalue {<2 x float>, <2 x float>} undef, <2 x float> %tmp30, 0 1756 %tmp32 = lshr i128 %srcval, 64 1757 %tmp33 = trunc i128 %tmp32 to i64 1758 %tmp34 = bitcast i64 %tmp33 to <2 x float> 1759 %tmp35 = insertvalue {<2 x float>, <2 x float>} %tmp31, <2 x float> %tmp34, 1 1760 ret {<2 x float>, <2 x float>} %tmp35 1761} 1762 1763; CHECK: @"\01-[Top0 _getX]" 1764; CHECK-NOT: @objc_ 1765; CHECK: } 1766 1767define i32 @"\01-[Top0 _getX]"({}* %self, i8* nocapture %_cmd) nounwind { 1768invoke.cont: 1769 %0 = bitcast {}* %self to i8* 1770 %1 = tail call i8* @objc_retain(i8* %0) nounwind 1771 %puts = tail call i32 @puts(i8* getelementptr inbounds ([16 x i8]* @str, i64 0, i64 0)) 1772 tail call void @objc_release(i8* %0) nounwind 1773 ret i32 0 1774} 1775 1776@"\01L_OBJC_METH_VAR_NAME_" = internal global [5 x i8] c"frob\00", section "__TEXT,__cstring,cstring_literals", align 1@"\01L_OBJC_SELECTOR_REFERENCES_" = internal global i8* getelementptr inbounds ([5 x i8]* @"\01L_OBJC_METH_VAR_NAME_", i64 0, i64 0), section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 1777@"\01L_OBJC_IMAGE_INFO" = internal constant [2 x i32] [i32 0, i32 16], section "__DATA, __objc_imageinfo, regular, no_dead_strip" 1778@llvm.used = appending global [3 x i8*] [i8* getelementptr inbounds ([5 x i8]* @"\01L_OBJC_METH_VAR_NAME_", i32 0, i32 0), i8* bitcast (i8** @"\01L_OBJC_SELECTOR_REFERENCES_" to i8*), i8* bitcast ([2 x i32]* @"\01L_OBJC_IMAGE_INFO" to i8*)], section "llvm.metadata" 1779 1780; A simple loop. Eliminate the retain and release inside of it! 1781 1782; CHECK: define void @loop 1783; CHECK: for.body: 1784; CHECK-NOT: @objc_ 1785; CHECK: @objc_msgSend 1786; CHECK-NOT: @objc_ 1787; CHECK: for.end: 1788define void @loop(i8* %x, i64 %n) { 1789entry: 1790 %0 = tail call i8* @objc_retain(i8* %x) nounwind 1791 %cmp9 = icmp sgt i64 %n, 0 1792 br i1 %cmp9, label %for.body, label %for.end 1793 1794for.body: ; preds = %entry, %for.body 1795 %i.010 = phi i64 [ %inc, %for.body ], [ 0, %entry ] 1796 %1 = tail call i8* @objc_retain(i8* %x) nounwind 1797 %tmp5 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8 1798 %call = tail call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %1, i8* %tmp5) 1799 tail call void @objc_release(i8* %1) nounwind, !clang.imprecise_release !0 1800 %inc = add nsw i64 %i.010, 1 1801 %exitcond = icmp eq i64 %inc, %n 1802 br i1 %exitcond, label %for.end, label %for.body 1803 1804for.end: ; preds = %for.body, %entry 1805 tail call void @objc_release(i8* %x) nounwind, !clang.imprecise_release !0 1806 ret void 1807} 1808 1809; ObjCARCOpt can delete the retain,release on self. 1810 1811; CHECK: define void @TextEditTest 1812; CHECK-NOT: call i8* @objc_retain(i8* %tmp7) 1813; CHECK: } 1814 1815%0 = type { i8* (i8*, %struct._message_ref_t*, ...)*, i8* } 1816%1 = type opaque 1817%2 = type opaque 1818%3 = type opaque 1819%4 = type opaque 1820%5 = type opaque 1821%struct.NSConstantString = type { i32*, i32, i8*, i64 } 1822%struct._NSRange = type { i64, i64 } 1823%struct.__CFString = type opaque 1824%struct.__method_list_t = type { i32, i32, [0 x %struct._objc_method] } 1825%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* } 1826%struct._class_t = type { %struct._class_t*, %struct._class_t*, %struct._objc_cache*, i8* (i8*, i8*)**, %struct._class_ro_t* } 1827%struct._ivar_list_t = type { i32, i32, [0 x %struct._ivar_t] } 1828%struct._ivar_t = type { i64*, i8*, i8*, i32, i32 } 1829%struct._message_ref_t = type { i8*, i8* } 1830%struct._objc_cache = type opaque 1831%struct._objc_method = type { i8*, i8*, i8* } 1832%struct._objc_protocol_list = type { i64, [0 x %struct._protocol_t*] } 1833%struct._prop_list_t = type { i32, i32, [0 x %struct._message_ref_t] } 1834%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 } 1835 1836@"\01L_OBJC_CLASSLIST_REFERENCES_$_17" = external hidden global %struct._class_t*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8 1837@kUTTypePlainText = external constant %struct.__CFString* 1838@"\01L_OBJC_SELECTOR_REFERENCES_19" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 1839@"\01L_OBJC_SELECTOR_REFERENCES_21" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 1840@"\01L_OBJC_SELECTOR_REFERENCES_23" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 1841@"\01L_OBJC_SELECTOR_REFERENCES_25" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 1842@"\01L_OBJC_CLASSLIST_REFERENCES_$_26" = external hidden global %struct._class_t*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8 1843@"\01L_OBJC_SELECTOR_REFERENCES_28" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 1844@"\01L_OBJC_CLASSLIST_REFERENCES_$_29" = external hidden global %struct._class_t*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8 1845@"\01L_OBJC_SELECTOR_REFERENCES_31" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 1846@"\01L_OBJC_SELECTOR_REFERENCES_33" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 1847@"\01L_OBJC_SELECTOR_REFERENCES_35" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 1848@"\01L_OBJC_SELECTOR_REFERENCES_37" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 1849@"\01L_OBJC_CLASSLIST_REFERENCES_$_38" = external hidden global %struct._class_t*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8 1850@"\01L_OBJC_SELECTOR_REFERENCES_40" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 1851@"\01L_OBJC_SELECTOR_REFERENCES_42" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 1852@_unnamed_cfstring_44 = external hidden constant %struct.NSConstantString, section "__DATA,__cfstring" 1853@"\01L_OBJC_SELECTOR_REFERENCES_46" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 1854@"\01L_OBJC_SELECTOR_REFERENCES_48" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 1855@"\01l_objc_msgSend_fixup_isEqual_" = external hidden global %0, section "__DATA, __objc_msgrefs, coalesced", align 16 1856@"\01L_OBJC_CLASSLIST_REFERENCES_$_50" = external hidden global %struct._class_t*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8 1857@NSCocoaErrorDomain = external constant %1* 1858@"\01L_OBJC_CLASSLIST_REFERENCES_$_51" = external hidden global %struct._class_t*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8 1859@NSFilePathErrorKey = external constant %1* 1860@"\01L_OBJC_SELECTOR_REFERENCES_53" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 1861@"\01L_OBJC_SELECTOR_REFERENCES_55" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 1862@"\01L_OBJC_CLASSLIST_REFERENCES_$_56" = external hidden global %struct._class_t*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8 1863@"\01L_OBJC_SELECTOR_REFERENCES_58" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 1864@"\01L_OBJC_SELECTOR_REFERENCES_60" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 1865 1866declare %1* @truncatedString(%1*, i64) 1867define void @TextEditTest(%2* %self, %3* %pboard) { 1868entry: 1869 %err = alloca %4*, align 8 1870 %tmp7 = bitcast %2* %self to i8* 1871 %tmp8 = call i8* @objc_retain(i8* %tmp7) nounwind 1872 store %4* null, %4** %err, align 8 1873 %tmp1 = load %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_17", align 8 1874 %tmp2 = load %struct.__CFString** @kUTTypePlainText, align 8 1875 %tmp3 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_19", align 8 1876 %tmp4 = bitcast %struct._class_t* %tmp1 to i8* 1877 %call5 = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %tmp4, i8* %tmp3, %struct.__CFString* %tmp2) 1878 %tmp5 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_21", align 8 1879 %tmp6 = bitcast %3* %pboard to i8* 1880 %call76 = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %tmp6, i8* %tmp5, i8* %call5) 1881 %tmp9 = call i8* @objc_retain(i8* %call76) nounwind 1882 %tobool = icmp eq i8* %tmp9, null 1883 br i1 %tobool, label %end, label %land.lhs.true 1884 1885land.lhs.true: ; preds = %entry 1886 %tmp11 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_23", align 8 1887 %call137 = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %tmp6, i8* %tmp11, i8* %tmp9) 1888 %tmp = bitcast i8* %call137 to %1* 1889 %tmp10 = call i8* @objc_retain(i8* %call137) nounwind 1890 call void @objc_release(i8* null) nounwind 1891 %tmp12 = call i8* @objc_retain(i8* %call137) nounwind 1892 call void @objc_release(i8* null) nounwind 1893 %tobool16 = icmp eq i8* %call137, null 1894 br i1 %tobool16, label %end, label %if.then 1895 1896if.then: ; preds = %land.lhs.true 1897 %tmp19 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_25", align 8 1898 %call21 = call signext i8 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8 (i8*, i8*)*)(i8* %call137, i8* %tmp19) 1899 %tobool22 = icmp eq i8 %call21, 0 1900 br i1 %tobool22, label %if.then44, label %land.lhs.true23 1901 1902land.lhs.true23: ; preds = %if.then 1903 %tmp24 = load %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_26", align 8 1904 %tmp26 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_28", align 8 1905 %tmp27 = bitcast %struct._class_t* %tmp24 to i8* 1906 %call2822 = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %tmp27, i8* %tmp26, i8* %call137) 1907 %tmp13 = bitcast i8* %call2822 to %5* 1908 %tmp14 = call i8* @objc_retain(i8* %call2822) nounwind 1909 call void @objc_release(i8* null) nounwind 1910 %tobool30 = icmp eq i8* %call2822, null 1911 br i1 %tobool30, label %if.then44, label %if.end 1912 1913if.end: ; preds = %land.lhs.true23 1914 %tmp32 = load %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_29", align 8 1915 %tmp33 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_31", align 8 1916 %tmp34 = bitcast %struct._class_t* %tmp32 to i8* 1917 %call35 = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %tmp34, i8* %tmp33) 1918 %tmp37 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_33", align 8 1919 %call3923 = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %call35, i8* %tmp37, i8* %call2822, i32 signext 1, %4** %err) 1920 %cmp = icmp eq i8* %call3923, null 1921 br i1 %cmp, label %if.then44, label %end 1922 1923if.then44: ; preds = %if.end, %land.lhs.true23, %if.then 1924 %url.025 = phi %5* [ %tmp13, %if.end ], [ %tmp13, %land.lhs.true23 ], [ null, %if.then ] 1925 %tmp49 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_35", align 8 1926 %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) 1927 %call513 = extractvalue %struct._NSRange %call51, 0 1928 %call514 = extractvalue %struct._NSRange %call51, 1 1929 %tmp52 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_37", align 8 1930 %call548 = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %call137, i8* %tmp52, i64 %call513, i64 %call514) 1931 %tmp55 = load %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_38", align 8 1932 %tmp56 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_40", align 8 1933 %tmp57 = bitcast %struct._class_t* %tmp55 to i8* 1934 %call58 = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %tmp57, i8* %tmp56) 1935 %tmp59 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_42", align 8 1936 %call6110 = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %call548, i8* %tmp59, i8* %call58) 1937 %tmp15 = call i8* @objc_retain(i8* %call6110) nounwind 1938 call void @objc_release(i8* %call137) nounwind 1939 %tmp64 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_46", align 8 1940 %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*)) 1941 %tobool67 = icmp eq i8 %call66, 0 1942 br i1 %tobool67, label %if.end74, label %if.then68 1943 1944if.then68: ; preds = %if.then44 1945 %tmp70 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_48", align 8 1946 %call7220 = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %call6110, i8* %tmp70) 1947 %tmp16 = call i8* @objc_retain(i8* %call7220) nounwind 1948 call void @objc_release(i8* %call6110) nounwind 1949 br label %if.end74 1950 1951if.end74: ; preds = %if.then68, %if.then44 1952 %filename.0.in = phi i8* [ %call7220, %if.then68 ], [ %call6110, %if.then44 ] 1953 %filename.0 = bitcast i8* %filename.0.in to %1* 1954 %tmp17 = load i8** bitcast (%0* @"\01l_objc_msgSend_fixup_isEqual_" to i8**), align 16 1955 %tmp18 = bitcast i8* %tmp17 to i8 (i8*, %struct._message_ref_t*, i8*, ...)* 1956 %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) 1957 %tobool79 = icmp eq i8 %call78, 0 1958 br i1 %tobool79, label %land.lhs.true80, label %if.then109 1959 1960land.lhs.true80: ; preds = %if.end74 1961 %tmp82 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_25", align 8 1962 %call84 = call signext i8 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8 (i8*, i8*)*)(i8* %filename.0.in, i8* %tmp82) 1963 %tobool86 = icmp eq i8 %call84, 0 1964 br i1 %tobool86, label %if.then109, label %if.end106 1965 1966if.end106: ; preds = %land.lhs.true80 1967 %tmp88 = load %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_26", align 8 1968 %tmp90 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_28", align 8 1969 %tmp91 = bitcast %struct._class_t* %tmp88 to i8* 1970 %call9218 = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %tmp91, i8* %tmp90, i8* %filename.0.in) 1971 %tmp20 = bitcast i8* %call9218 to %5* 1972 %tmp21 = call i8* @objc_retain(i8* %call9218) nounwind 1973 %tmp22 = bitcast %5* %url.025 to i8* 1974 call void @objc_release(i8* %tmp22) nounwind 1975 %tmp94 = load %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_29", align 8 1976 %tmp95 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_31", align 8 1977 %tmp96 = bitcast %struct._class_t* %tmp94 to i8* 1978 %call97 = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %tmp96, i8* %tmp95) 1979 %tmp99 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_33", align 8 1980 %call10119 = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %call97, i8* %tmp99, i8* %call9218, i32 signext 1, %4** %err) 1981 %phitmp = icmp eq i8* %call10119, null 1982 br i1 %phitmp, label %if.then109, label %end 1983 1984if.then109: ; preds = %if.end106, %land.lhs.true80, %if.end74 1985 %url.129 = phi %5* [ %tmp20, %if.end106 ], [ %url.025, %if.end74 ], [ %url.025, %land.lhs.true80 ] 1986 %tmp110 = load %4** %err, align 8 1987 %tobool111 = icmp eq %4* %tmp110, null 1988 br i1 %tobool111, label %if.then112, label %if.end125 1989 1990if.then112: ; preds = %if.then109 1991 %tmp113 = load %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_50", align 8 1992 %tmp114 = load %1** @NSCocoaErrorDomain, align 8 1993 %tmp115 = load %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_51", align 8 1994 %call117 = call %1* @truncatedString(%1* %filename.0, i64 1034) 1995 %tmp118 = load %1** @NSFilePathErrorKey, align 8 1996 %tmp119 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_53", align 8 1997 %tmp120 = bitcast %struct._class_t* %tmp115 to i8* 1998 %call12113 = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %tmp120, i8* %tmp119, %1* %call117, %1* %tmp118, i8* null) 1999 %tmp122 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_55", align 8 2000 %tmp123 = bitcast %struct._class_t* %tmp113 to i8* 2001 %call12414 = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %tmp123, i8* %tmp122, %1* %tmp114, i64 258, i8* %call12113) 2002 %tmp23 = call i8* @objc_retain(i8* %call12414) nounwind 2003 %tmp25 = call i8* @objc_autorelease(i8* %tmp23) nounwind 2004 %tmp28 = bitcast i8* %tmp25 to %4* 2005 store %4* %tmp28, %4** %err, align 8 2006 br label %if.end125 2007 2008if.end125: ; preds = %if.then112, %if.then109 2009 %tmp127 = phi %4* [ %tmp110, %if.then109 ], [ %tmp28, %if.then112 ] 2010 %tmp126 = load %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_56", align 8 2011 %tmp128 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_58", align 8 2012 %tmp129 = bitcast %struct._class_t* %tmp126 to i8* 2013 %call13015 = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %tmp129, i8* %tmp128, %4* %tmp127) 2014 %tmp131 = load i8** @"\01L_OBJC_SELECTOR_REFERENCES_60", align 8 2015 %call13317 = call i8* (i8*, i8*, ...)* @objc_msgSend(i8* %call13015, i8* %tmp131) 2016 br label %end 2017 2018end: ; preds = %if.end125, %if.end106, %if.end, %land.lhs.true, %entry 2019 %filename.2 = phi %1* [ %filename.0, %if.end106 ], [ %filename.0, %if.end125 ], [ %tmp, %land.lhs.true ], [ null, %entry ], [ %tmp, %if.end ] 2020 %origFilename.0 = phi %1* [ %tmp, %if.end106 ], [ %tmp, %if.end125 ], [ %tmp, %land.lhs.true ], [ null, %entry ], [ %tmp, %if.end ] 2021 %url.2 = phi %5* [ %tmp20, %if.end106 ], [ %url.129, %if.end125 ], [ null, %land.lhs.true ], [ null, %entry ], [ %tmp13, %if.end ] 2022 call void @objc_release(i8* %tmp9) nounwind, !clang.imprecise_release !0 2023 %tmp29 = bitcast %5* %url.2 to i8* 2024 call void @objc_release(i8* %tmp29) nounwind, !clang.imprecise_release !0 2025 %tmp30 = bitcast %1* %origFilename.0 to i8* 2026 call void @objc_release(i8* %tmp30) nounwind, !clang.imprecise_release !0 2027 %tmp31 = bitcast %1* %filename.2 to i8* 2028 call void @objc_release(i8* %tmp31) nounwind, !clang.imprecise_release !0 2029 call void @objc_release(i8* %tmp7) nounwind, !clang.imprecise_release !0 2030 ret void 2031} 2032 2033!0 = metadata !{} 2034 2035declare i32 @__gxx_personality_v0(...) 2036