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