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