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