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