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