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