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, i64, 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) 1349 ret void 1350 } 1351 1352 ; Any call can decrement a retain count. 1353 1354 ; CHECK-LABEL: define void @test24( 1355 ; CHECK: @objc_retain(i8* %a) 1356 ; CHECK: @objc_release 1357 ; CHECK: } 1358 define void @test24(i8* %r, i8* %a) { 1359 call i8* @objc_retain(i8* %a) 1360 call void @use_pointer(i8* %r) 1361 %q = load i8, i8* %a 1362 call void @objc_release(i8* %a) 1363 ret void 1364 } 1365 1366 ; Don't move a retain/release pair if the release can be moved 1367 ; but the retain can't be moved to balance it. 1368 1369 ; CHECK-LABEL: define void @test25( 1370 ; CHECK: entry: 1371 ; CHECK: call i8* @objc_retain(i8* %p) 1372 ; CHECK: true: 1373 ; CHECK: done: 1374 ; CHECK: call void @objc_release(i8* %p) 1375 ; CHECK: } 1376 define void @test25(i8* %p, i1 %x) { 1377 entry: 1378 %f0 = call i8* @objc_retain(i8* %p) 1379 call void @callee() 1380 br i1 %x, label %true, label %done 1381 1382 true: 1383 store i8 0, i8* %p 1384 br label %done 1385 1386 done: 1387 call void @objc_release(i8* %p) 1388 ret void 1389 } 1390 1391 ; Don't move a retain/release pair if the retain can be moved 1392 ; but the release can't be moved to balance it. 1393 1394 ; CHECK-LABEL: define void @test26( 1395 ; CHECK: entry: 1396 ; CHECK: call i8* @objc_retain(i8* %p) 1397 ; CHECK: true: 1398 ; CHECK: done: 1399 ; CHECK: call void @objc_release(i8* %p) 1400 ; CHECK: } 1401 define void @test26(i8* %p, i1 %x) { 1402 entry: 1403 %f0 = call i8* @objc_retain(i8* %p) 1404 br i1 %x, label %true, label %done 1405 1406 true: 1407 call void @callee() 1408 br label %done 1409 1410 done: 1411 store i8 0, i8* %p 1412 call void @objc_release(i8* %p) 1413 ret void 1414 } 1415 1416 ; Don't sink the retain,release into the loop. 1417 1418 ; CHECK-LABEL: define void @test27( 1419 ; CHECK: entry: 1420 ; CHECK: call i8* @objc_retain(i8* %p) 1421 ; CHECK: loop: 1422 ; CHECK-NOT: @objc_ 1423 ; CHECK: done: 1424 ; CHECK: call void @objc_release 1425 ; CHECK: } 1426 define void @test27(i8* %p, i1 %x, i1 %y) { 1427 entry: 1428 %f0 = call i8* @objc_retain(i8* %p) 1429 br i1 %x, label %loop, label %done 1430 1431 loop: 1432 call void @callee() 1433 store i8 0, i8* %p 1434 br i1 %y, label %done, label %loop 1435 1436 done: 1437 call void @objc_release(i8* %p) 1438 ret void 1439 } 1440 1441 ; Trivial code motion case: Triangle. 1442 1443 ; CHECK-LABEL: define void @test28( 1444 ; CHECK-NOT: @objc_ 1445 ; CHECK: true: 1446 ; CHECK: call i8* @objc_retain( 1447 ; CHECK: call void @callee() 1448 ; CHECK: store 1449 ; CHECK: call void @objc_release 1450 ; CHECK: done: 1451 ; CHECK-NOT: @objc_ 1452 ; CHECK: } 1453 define void @test28(i8* %p, i1 %x) { 1454 entry: 1455 %f0 = call i8* @objc_retain(i8* %p) 1456 br i1 %x, label %true, label %done 1457 1458 true: 1459 call void @callee() 1460 store i8 0, i8* %p 1461 br label %done 1462 1463 done: 1464 call void @objc_release(i8* %p), !clang.imprecise_release !0 1465 ret void 1466 } 1467 1468 ; Trivial code motion case: Triangle, but no metadata. Don't move past 1469 ; unrelated memory references! 1470 1471 ; CHECK-LABEL: define void @test28b( 1472 ; CHECK: call i8* @objc_retain( 1473 ; CHECK: true: 1474 ; CHECK-NOT: @objc_ 1475 ; CHECK: call void @callee() 1476 ; CHECK-NOT: @objc_ 1477 ; CHECK: store 1478 ; CHECK-NOT: @objc_ 1479 ; CHECK: done: 1480 ; CHECK: @objc_release 1481 ; CHECK: } 1482 define void @test28b(i8* %p, i1 %x, i8* noalias %t) { 1483 entry: 1484 %f0 = call i8* @objc_retain(i8* %p) 1485 br i1 %x, label %true, label %done 1486 1487 true: 1488 call void @callee() 1489 store i8 0, i8* %p 1490 br label %done 1491 1492 done: 1493 store i8 0, i8* %t 1494 call void @objc_release(i8* %p) 1495 ret void 1496 } 1497 1498 ; Trivial code motion case: Triangle, with metadata. Do move past 1499 ; unrelated memory references! And preserve the metadata. 1500 1501 ; CHECK-LABEL: define void @test28c( 1502 ; CHECK-NOT: @objc_ 1503 ; CHECK: true: 1504 ; CHECK: call i8* @objc_retain( 1505 ; CHECK: call void @callee() 1506 ; CHECK: store 1507 ; CHECK: call void @objc_release(i8* %p) [[NUW]], !clang.imprecise_release 1508 ; CHECK: done: 1509 ; CHECK-NOT: @objc_ 1510 ; CHECK: } 1511 define void @test28c(i8* %p, i1 %x, i8* noalias %t) { 1512 entry: 1513 %f0 = call i8* @objc_retain(i8* %p) 1514 br i1 %x, label %true, label %done 1515 1516 true: 1517 call void @callee() 1518 store i8 0, i8* %p 1519 br label %done 1520 1521 done: 1522 store i8 0, i8* %t 1523 call void @objc_release(i8* %p), !clang.imprecise_release !0 1524 ret void 1525 } 1526 1527 ; Like test28. but with two releases. 1528 1529 ; CHECK-LABEL: define void @test29( 1530 ; CHECK-NOT: @objc_ 1531 ; CHECK: true: 1532 ; CHECK: call i8* @objc_retain( 1533 ; CHECK: call void @callee() 1534 ; CHECK: store 1535 ; CHECK: call void @objc_release 1536 ; CHECK-NOT: @objc_release 1537 ; CHECK: done: 1538 ; CHECK-NOT: @objc_ 1539 ; CHECK: ohno: 1540 ; CHECK-NOT: @objc_ 1541 ; CHECK: } 1542 define void @test29(i8* %p, i1 %x, i1 %y) { 1543 entry: 1544 %f0 = call i8* @objc_retain(i8* %p) 1545 br i1 %x, label %true, label %done 1546 1547 true: 1548 call void @callee() 1549 store i8 0, i8* %p 1550 br i1 %y, label %done, label %ohno 1551 1552 done: 1553 call void @objc_release(i8* %p) 1554 ret void 1555 1556 ohno: 1557 call void @objc_release(i8* %p) 1558 ret void 1559 } 1560 1561 ; Basic case with the use and call in a diamond 1562 ; with an extra release. 1563 1564 ; CHECK-LABEL: define void @test30( 1565 ; CHECK-NOT: @objc_ 1566 ; CHECK: true: 1567 ; CHECK: call i8* @objc_retain( 1568 ; CHECK: call void @callee() 1569 ; CHECK: store 1570 ; CHECK: call void @objc_release 1571 ; CHECK-NOT: @objc_release 1572 ; CHECK: false: 1573 ; CHECK-NOT: @objc_ 1574 ; CHECK: done: 1575 ; CHECK-NOT: @objc_ 1576 ; CHECK: ohno: 1577 ; CHECK-NOT: @objc_ 1578 ; CHECK: } 1579 define void @test30(i8* %p, i1 %x, i1 %y, i1 %z) { 1580 entry: 1581 %f0 = call i8* @objc_retain(i8* %p) 1582 br i1 %x, label %true, label %false 1583 1584 true: 1585 call void @callee() 1586 store i8 0, i8* %p 1587 br i1 %y, label %done, label %ohno 1588 1589 false: 1590 br i1 %z, label %done, label %ohno 1591 1592 done: 1593 call void @objc_release(i8* %p) 1594 ret void 1595 1596 ohno: 1597 call void @objc_release(i8* %p) 1598 ret void 1599 } 1600 1601 ; Basic case with a mergeable release. 1602 1603 ; CHECK-LABEL: define void @test31( 1604 ; CHECK: call i8* @objc_retain(i8* %p) 1605 ; CHECK: call void @callee() 1606 ; CHECK: store 1607 ; CHECK: call void @objc_release 1608 ; CHECK-NOT: @objc_release 1609 ; CHECK: true: 1610 ; CHECK-NOT: @objc_release 1611 ; CHECK: false: 1612 ; CHECK-NOT: @objc_release 1613 ; CHECK: ret void 1614 ; CHECK-NOT: @objc_release 1615 ; CHECK: } 1616 define void @test31(i8* %p, i1 %x) { 1617 entry: 1618 %f0 = call i8* @objc_retain(i8* %p) 1619 call void @callee() 1620 store i8 0, i8* %p 1621 br i1 %x, label %true, label %false 1622 true: 1623 call void @objc_release(i8* %p) 1624 ret void 1625 false: 1626 call void @objc_release(i8* %p) 1627 ret void 1628 } 1629 1630 ; Don't consider bitcasts or getelementptrs direct uses. 1631 1632 ; CHECK-LABEL: define void @test32( 1633 ; CHECK-NOT: @objc_ 1634 ; CHECK: true: 1635 ; CHECK: call i8* @objc_retain( 1636 ; CHECK: call void @callee() 1637 ; CHECK: store 1638 ; CHECK: call void @objc_release 1639 ; CHECK: done: 1640 ; CHECK-NOT: @objc_ 1641 ; CHECK: } 1642 define void @test32(i8* %p, i1 %x) { 1643 entry: 1644 %f0 = call i8* @objc_retain(i8* %p) 1645 br i1 %x, label %true, label %done 1646 1647 true: 1648 call void @callee() 1649 store i8 0, i8* %p 1650 br label %done 1651 1652 done: 1653 %g = bitcast i8* %p to i8* 1654 %h = getelementptr i8, i8* %g, i64 0 1655 call void @objc_release(i8* %g) 1656 ret void 1657 } 1658 1659 ; Do consider icmps to be direct uses. 1660 1661 ; CHECK-LABEL: define void @test33( 1662 ; CHECK-NOT: @objc_ 1663 ; CHECK: true: 1664 ; CHECK: call i8* @objc_retain( 1665 ; CHECK: call void @callee() 1666 ; CHECK: icmp 1667 ; CHECK: call void @objc_release 1668 ; CHECK: done: 1669 ; CHECK-NOT: @objc_ 1670 ; CHECK: } 1671 define void @test33(i8* %p, i1 %x, i8* %y) { 1672 entry: 1673 %f0 = call i8* @objc_retain(i8* %p) 1674 br i1 %x, label %true, label %done 1675 1676 true: 1677 call void @callee() 1678 %v = icmp eq i8* %p, %y 1679 br label %done 1680 1681 done: 1682 %g = bitcast i8* %p to i8* 1683 %h = getelementptr i8, i8* %g, i64 0 1684 call void @objc_release(i8* %g) 1685 ret void 1686 } 1687 1688 ; Delete retain,release if there's just a possible dec and we have imprecise 1689 ; releases. 1690 1691 ; CHECK-LABEL: define void @test34a( 1692 ; CHECK: call i8* @objc_retain 1693 ; CHECK: true: 1694 ; CHECK: done: 1695 ; CHECK: call void @objc_release 1696 ; CHECK: } 1697 define void @test34a(i8* %p, i1 %x, i8* %y) { 1698 entry: 1699 %f0 = call i8* @objc_retain(i8* %p) 1700 br i1 %x, label %true, label %done 1701 1702 true: 1703 call void @callee() 1704 br label %done 1705 1706 done: 1707 %g = bitcast i8* %p to i8* 1708 %h = getelementptr i8, i8* %g, i64 0 1709 call void @objc_release(i8* %g) 1710 ret void 1711 } 1712 1713 ; CHECK-LABEL: define void @test34b( 1714 ; CHECK-NOT: @objc_ 1715 ; CHECK: } 1716 define void @test34b(i8* %p, i1 %x, i8* %y) { 1717 entry: 1718 %f0 = call i8* @objc_retain(i8* %p) 1719 br i1 %x, label %true, label %done 1720 1721 true: 1722 call void @callee() 1723 br label %done 1724 1725 done: 1726 %g = bitcast i8* %p to i8* 1727 %h = getelementptr i8, i8* %g, i64 0 1728 call void @objc_release(i8* %g), !clang.imprecise_release !0 1729 ret void 1730 } 1731 1732 1733 ; Delete retain,release if there's just a use and we do not have a precise 1734 ; release. 1735 1736 ; Precise. 1737 ; CHECK-LABEL: define void @test35a( 1738 ; CHECK: entry: 1739 ; CHECK: call i8* @objc_retain 1740 ; CHECK: true: 1741 ; CHECK: done: 1742 ; CHECK: call void @objc_release 1743 ; CHECK: } 1744 define void @test35a(i8* %p, i1 %x, i8* %y) { 1745 entry: 1746 %f0 = call i8* @objc_retain(i8* %p) 1747 br i1 %x, label %true, label %done 1748 1749 true: 1750 %v = icmp eq i8* %p, %y 1751 br label %done 1752 1753 done: 1754 %g = bitcast i8* %p to i8* 1755 %h = getelementptr i8, i8* %g, i64 0 1756 call void @objc_release(i8* %g) 1757 ret void 1758 } 1759 1760 ; Imprecise. 1761 ; CHECK-LABEL: define void @test35b( 1762 ; CHECK-NOT: @objc_ 1763 ; CHECK: } 1764 define void @test35b(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), !clang.imprecise_release !0 1777 ret void 1778 } 1779 1780 ; Delete a retain,release if there's no actual use and we have precise release. 1781 1782 ; CHECK-LABEL: define void @test36a( 1783 ; CHECK: @objc_retain 1784 ; CHECK: call void @callee() 1785 ; CHECK-NOT: @objc_ 1786 ; CHECK: call void @callee() 1787 ; CHECK: @objc_release 1788 ; CHECK: } 1789 define void @test36a(i8* %p) { 1790 entry: 1791 call i8* @objc_retain(i8* %p) 1792 call void @callee() 1793 call void @callee() 1794 call void @objc_release(i8* %p) 1795 ret void 1796 } 1797 1798 ; Like test36, but with metadata. 1799 1800 ; CHECK-LABEL: define void @test36b( 1801 ; CHECK-NOT: @objc_ 1802 ; CHECK: } 1803 define void @test36b(i8* %p) { 1804 entry: 1805 call i8* @objc_retain(i8* %p) 1806 call void @callee() 1807 call void @callee() 1808 call void @objc_release(i8* %p), !clang.imprecise_release !0 1809 ret void 1810 } 1811 1812 ; Be aggressive about analyzing phis to eliminate possible uses. 1813 1814 ; CHECK-LABEL: define void @test38( 1815 ; CHECK-NOT: @objc_ 1816 ; CHECK: } 1817 define void @test38(i8* %p, i1 %u, i1 %m, i8* %z, i8* %y, i8* %x, i8* %w) { 1818 entry: 1819 call i8* @objc_retain(i8* %p) 1820 br i1 %u, label %true, label %false 1821 true: 1822 br i1 %m, label %a, label %b 1823 false: 1824 br i1 %m, label %c, label %d 1825 a: 1826 br label %e 1827 b: 1828 br label %e 1829 c: 1830 br label %f 1831 d: 1832 br label %f 1833 e: 1834 %j = phi i8* [ %z, %a ], [ %y, %b ] 1835 br label %g 1836 f: 1837 %k = phi i8* [ %w, %c ], [ %x, %d ] 1838 br label %g 1839 g: 1840 %h = phi i8* [ %j, %e ], [ %k, %f ] 1841 call void @use_pointer(i8* %h) 1842 call void @objc_release(i8* %p), !clang.imprecise_release !0 1843 ret void 1844 } 1845 1846 ; Delete retain,release pairs around loops. 1847 1848 ; CHECK-LABEL: define void @test39( 1849 ; CHECK-NOT: @objc_ 1850 ; CHECK: } 1851 define void @test39(i8* %p) { 1852 entry: 1853 %0 = call i8* @objc_retain(i8* %p) 1854 br label %loop 1855 1856 loop: ; preds = %loop, %entry 1857 br i1 undef, label %loop, label %exit 1858 1859 exit: ; preds = %loop 1860 call void @objc_release(i8* %0), !clang.imprecise_release !0 1861 ret void 1862 } 1863 1864 ; Delete retain,release pairs around loops containing uses. 1865 1866 ; CHECK-LABEL: define void @test39b( 1867 ; CHECK-NOT: @objc_ 1868 ; CHECK: } 1869 define void @test39b(i8* %p) { 1870 entry: 1871 %0 = call i8* @objc_retain(i8* %p) 1872 br label %loop 1873 1874 loop: ; preds = %loop, %entry 1875 store i8 0, i8* %0 1876 br i1 undef, label %loop, label %exit 1877 1878 exit: ; preds = %loop 1879 call void @objc_release(i8* %0), !clang.imprecise_release !0 1880 ret void 1881 } 1882 1883 ; Delete retain,release pairs around loops containing potential decrements. 1884 1885 ; CHECK-LABEL: define void @test39c( 1886 ; CHECK-NOT: @objc_ 1887 ; CHECK: } 1888 define void @test39c(i8* %p) { 1889 entry: 1890 %0 = call i8* @objc_retain(i8* %p) 1891 br label %loop 1892 1893 loop: ; preds = %loop, %entry 1894 call void @use_pointer(i8* %0) 1895 br i1 undef, label %loop, label %exit 1896 1897 exit: ; preds = %loop 1898 call void @objc_release(i8* %0), !clang.imprecise_release !0 1899 ret void 1900 } 1901 1902 ; Delete retain,release pairs around loops even if 1903 ; the successors are in a different order. 1904 1905 ; CHECK-LABEL: define void @test40( 1906 ; CHECK-NOT: @objc_ 1907 ; CHECK: } 1908 define void @test40(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 %exit, label %loop 1916 1917 exit: ; preds = %loop 1918 call void @objc_release(i8* %0), !clang.imprecise_release !0 1919 ret void 1920 } 1921 1922 ; Do the known-incremented retain+release elimination even if the pointer 1923 ; is also autoreleased. 1924 1925 ; CHECK-LABEL: define void @test42( 1926 ; CHECK-NEXT: entry: 1927 ; CHECK-NEXT: call i8* @objc_retain(i8* %p) 1928 ; CHECK-NEXT: call i8* @objc_autorelease(i8* %p) 1929 ; CHECK-NEXT: call void @use_pointer(i8* %p) 1930 ; CHECK-NEXT: call void @use_pointer(i8* %p) 1931 ; CHECK-NEXT: call void @use_pointer(i8* %p) 1932 ; CHECK-NEXT: call void @use_pointer(i8* %p) 1933 ; CHECK-NEXT: call void @objc_release(i8* %p) 1934 ; CHECK-NEXT: ret void 1935 ; CHECK-NEXT: } 1936 define void @test42(i8* %p) { 1937 entry: 1938 call i8* @objc_retain(i8* %p) 1939 call i8* @objc_autorelease(i8* %p) 1940 call i8* @objc_retain(i8* %p) 1941 call void @use_pointer(i8* %p) 1942 call void @use_pointer(i8* %p) 1943 call void @objc_release(i8* %p) 1944 call void @use_pointer(i8* %p) 1945 call void @use_pointer(i8* %p) 1946 call void @objc_release(i8* %p) 1947 ret void 1948 } 1949 1950 ; Don't the known-incremented retain+release elimination if the pointer is 1951 ; autoreleased and there's an autoreleasePoolPop. 1952 1953 ; CHECK-LABEL: define void @test43( 1954 ; CHECK-NEXT: entry: 1955 ; CHECK-NEXT: call i8* @objc_retain(i8* %p) 1956 ; CHECK-NEXT: call i8* @objc_autorelease(i8* %p) 1957 ; CHECK-NEXT: call i8* @objc_retain 1958 ; CHECK-NEXT: call void @use_pointer(i8* %p) 1959 ; CHECK-NEXT: call void @use_pointer(i8* %p) 1960 ; CHECK-NEXT: call void @objc_autoreleasePoolPop(i8* undef) 1961 ; CHECK-NEXT: call void @objc_release 1962 ; CHECK-NEXT: ret void 1963 ; CHECK-NEXT: } 1964 define void @test43(i8* %p) { 1965 entry: 1966 call i8* @objc_retain(i8* %p) 1967 call i8* @objc_autorelease(i8* %p) 1968 call i8* @objc_retain(i8* %p) 1969 call void @use_pointer(i8* %p) 1970 call void @use_pointer(i8* %p) 1971 call void @objc_autoreleasePoolPop(i8* undef) 1972 call void @objc_release(i8* %p) 1973 ret void 1974 } 1975 1976 ; Do the known-incremented retain+release elimination if the pointer is 1977 ; autoreleased and there's an autoreleasePoolPush. 1978 1979 ; CHECK-LABEL: define void @test43b( 1980 ; CHECK-NEXT: entry: 1981 ; CHECK-NEXT: call i8* @objc_retain(i8* %p) 1982 ; CHECK-NEXT: call i8* @objc_autorelease(i8* %p) 1983 ; CHECK-NEXT: call void @use_pointer(i8* %p) 1984 ; CHECK-NEXT: call void @use_pointer(i8* %p) 1985 ; CHECK-NEXT: call i8* @objc_autoreleasePoolPush() 1986 ; CHECK-NEXT: call void @use_pointer(i8* %p) 1987 ; CHECK-NEXT: call void @objc_release 1988 ; CHECK-NEXT: ret void 1989 ; CHECK-NEXT: } 1990 define void @test43b(i8* %p) { 1991 entry: 1992 call i8* @objc_retain(i8* %p) 1993 call i8* @objc_autorelease(i8* %p) 1994 call i8* @objc_retain(i8* %p) 1995 call void @use_pointer(i8* %p) 1996 call void @use_pointer(i8* %p) 1997 call i8* @objc_autoreleasePoolPush() 1998 call void @objc_release(i8* %p) 1999 call void @use_pointer(i8* %p) 2000 call void @objc_release(i8* %p) 2001 ret void 2002 } 2003 2004 ; Do retain+release elimination for non-provenance pointers. 2005 2006 ; CHECK-LABEL: define void @test44( 2007 ; CHECK-NOT: objc_ 2008 ; CHECK: } 2009 define void @test44(i8** %pp) { 2010 %p = load i8*, i8** %pp 2011 %q = call i8* @objc_retain(i8* %p) 2012 call void @objc_release(i8* %q) 2013 ret void 2014 } 2015 2016 ; Don't delete retain+release with an unknown-provenance 2017 ; may-alias objc_release between them. 2018 2019 ; CHECK-LABEL: define void @test45( 2020 ; CHECK: call i8* @objc_retain(i8* %p) 2021 ; CHECK: call void @objc_release(i8* %q) 2022 ; CHECK: call void @use_pointer(i8* %p) 2023 ; CHECK: call void @objc_release(i8* %p) 2024 ; CHECK: } 2025 define void @test45(i8** %pp, i8** %qq) { 2026 %p = load i8*, i8** %pp 2027 %q = load i8*, i8** %qq 2028 call i8* @objc_retain(i8* %p) 2029 call void @objc_release(i8* %q) 2030 call void @use_pointer(i8* %p) 2031 call void @objc_release(i8* %p) 2032 ret void 2033 } 2034 2035 ; Don't delete retain and autorelease here. 2036 2037 ; CHECK-LABEL: define void @test46( 2038 ; CHECK: tail call i8* @objc_retain(i8* %p) [[NUW]] 2039 ; CHECK: true: 2040 ; CHECK: call i8* @objc_autorelease(i8* %p) [[NUW]] 2041 ; CHECK: } 2042 define void @test46(i8* %p, i1 %a) { 2043 entry: 2044 call i8* @objc_retain(i8* %p) 2045 br i1 %a, label %true, label %false 2046 2047 true: 2048 call i8* @objc_autorelease(i8* %p) 2049 call void @use_pointer(i8* %p) 2050 ret void 2051 2052 false: 2053 ret void 2054 } 2055 2056 ; Delete no-op cast calls. 2057 2058 ; CHECK-LABEL: define i8* @test47( 2059 ; CHECK-NOT: call 2060 ; CHECK: ret i8* %p 2061 ; CHECK: } 2062 define i8* @test47(i8* %p) nounwind { 2063 %x = call i8* @objc_retainedObject(i8* %p) 2064 ret i8* %x 2065 } 2066 2067 ; Delete no-op cast calls. 2068 2069 ; CHECK-LABEL: define i8* @test48( 2070 ; CHECK-NOT: call 2071 ; CHECK: ret i8* %p 2072 ; CHECK: } 2073 define i8* @test48(i8* %p) nounwind { 2074 %x = call i8* @objc_unretainedObject(i8* %p) 2075 ret i8* %x 2076 } 2077 2078 ; Delete no-op cast calls. 2079 2080 ; CHECK-LABEL: define i8* @test49( 2081 ; CHECK-NOT: call 2082 ; CHECK: ret i8* %p 2083 ; CHECK: } 2084 define i8* @test49(i8* %p) nounwind { 2085 %x = call i8* @objc_unretainedPointer(i8* %p) 2086 ret i8* %x 2087 } 2088 2089 ; Do delete retain+release with intervening stores of the address value if we 2090 ; have imprecise release attached to objc_release. 2091 2092 ; CHECK-LABEL: define void @test50a( 2093 ; CHECK-NEXT: call i8* @objc_retain 2094 ; CHECK-NEXT: call void @callee 2095 ; CHECK-NEXT: store 2096 ; CHECK-NEXT: call void @objc_release 2097 ; CHECK-NEXT: ret void 2098 ; CHECK-NEXT: } 2099 define void @test50a(i8* %p, i8** %pp) { 2100 call i8* @objc_retain(i8* %p) 2101 call void @callee() 2102 store i8* %p, i8** %pp 2103 call void @objc_release(i8* %p) 2104 ret void 2105 } 2106 2107 ; CHECK-LABEL: define void @test50b( 2108 ; CHECK-NOT: @objc_ 2109 ; CHECK: } 2110 define void @test50b(i8* %p, i8** %pp) { 2111 call i8* @objc_retain(i8* %p) 2112 call void @callee() 2113 store i8* %p, i8** %pp 2114 call void @objc_release(i8* %p), !clang.imprecise_release !0 2115 ret void 2116 } 2117 2118 2119 ; Don't delete retain+release with intervening stores through the 2120 ; address value. 2121 2122 ; CHECK-LABEL: define void @test51a( 2123 ; CHECK: call i8* @objc_retain(i8* %p) 2124 ; CHECK: call void @objc_release(i8* %p) 2125 ; CHECK: ret void 2126 ; CHECK: } 2127 define void @test51a(i8* %p) { 2128 call i8* @objc_retain(i8* %p) 2129 call void @callee() 2130 store i8 0, i8* %p 2131 call void @objc_release(i8* %p) 2132 ret void 2133 } 2134 2135 ; CHECK-LABEL: define void @test51b( 2136 ; CHECK: call i8* @objc_retain(i8* %p) 2137 ; CHECK: call void @objc_release(i8* %p) 2138 ; CHECK: ret void 2139 ; CHECK: } 2140 define void @test51b(i8* %p) { 2141 call i8* @objc_retain(i8* %p) 2142 call void @callee() 2143 store i8 0, i8* %p 2144 call void @objc_release(i8* %p), !clang.imprecise_release !0 2145 ret void 2146 } 2147 2148 ; Don't delete retain+release with intervening use of a pointer of 2149 ; unknown provenance. 2150 2151 ; CHECK-LABEL: define void @test52a( 2152 ; CHECK: call i8* @objc_retain 2153 ; CHECK: call void @callee() 2154 ; CHECK: call void @use_pointer(i8* %z) 2155 ; CHECK: call void @objc_release 2156 ; CHECK: ret void 2157 ; CHECK: } 2158 define void @test52a(i8** %zz, i8** %pp) { 2159 %p = load i8*, i8** %pp 2160 %1 = call i8* @objc_retain(i8* %p) 2161 call void @callee() 2162 %z = load i8*, i8** %zz 2163 call void @use_pointer(i8* %z) 2164 call void @objc_release(i8* %p) 2165 ret void 2166 } 2167 2168 ; CHECK-LABEL: define void @test52b( 2169 ; CHECK: call i8* @objc_retain 2170 ; CHECK: call void @callee() 2171 ; CHECK: call void @use_pointer(i8* %z) 2172 ; CHECK: call void @objc_release 2173 ; CHECK: ret void 2174 ; CHECK: } 2175 define void @test52b(i8** %zz, i8** %pp) { 2176 %p = load i8*, i8** %pp 2177 %1 = call i8* @objc_retain(i8* %p) 2178 call void @callee() 2179 %z = load i8*, i8** %zz 2180 call void @use_pointer(i8* %z) 2181 call void @objc_release(i8* %p), !clang.imprecise_release !0 2182 ret void 2183 } 2184 2185 ; Like test52, but the pointer has function type, so it's assumed to 2186 ; be not reference counted. 2187 ; Oops. That's wrong. Clang sometimes uses function types gratuitously. 2188 ; See rdar://10551239. 2189 2190 ; CHECK-LABEL: define void @test53( 2191 ; CHECK: @objc_ 2192 ; CHECK: } 2193 define void @test53(void ()** %zz, i8** %pp) { 2194 %p = load i8*, i8** %pp 2195 %1 = call i8* @objc_retain(i8* %p) 2196 call void @callee() 2197 %z = load void ()*, void ()** %zz 2198 call void @callee_fnptr(void ()* %z) 2199 call void @objc_release(i8* %p) 2200 ret void 2201 } 2202 2203 ; Convert autorelease to release if the value is unused. 2204 2205 ; CHECK-LABEL: define void @test54( 2206 ; CHECK: call i8* @returner() 2207 ; CHECK-NEXT: call void @objc_release(i8* %t) [[NUW]], !clang.imprecise_release ![[RELEASE]] 2208 ; CHECK-NEXT: ret void 2209 ; CHECK: } 2210 define void @test54() { 2211 %t = call i8* @returner() 2212 call i8* @objc_autorelease(i8* %t) 2213 ret void 2214 } 2215 2216 ; Nested retain+release pairs. Delete them both. 2217 2218 ; CHECK-LABEL: define void @test55( 2219 ; CHECK-NOT: @objc 2220 ; CHECK: } 2221 define void @test55(i8* %x) { 2222 entry: 2223 %0 = call i8* @objc_retain(i8* %x) nounwind 2224 %1 = call i8* @objc_retain(i8* %x) nounwind 2225 call void @objc_release(i8* %x) nounwind 2226 call void @objc_release(i8* %x) nounwind 2227 ret void 2228 } 2229 2230 ; Nested retain+release pairs where the inner pair depends 2231 ; on the outer pair to be removed, and then the outer pair 2232 ; can be partially eliminated. Plus an extra outer pair to 2233 ; eliminate, for fun. 2234 2235 ; CHECK-LABEL: define void @test56( 2236 ; CHECK-NOT: @objc 2237 ; CHECK: if.then: 2238 ; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %x) [[NUW]] 2239 ; CHECK-NEXT: tail call void @use_pointer(i8* %x) 2240 ; CHECK-NEXT: tail call void @use_pointer(i8* %x) 2241 ; CHECK-NEXT: tail call void @objc_release(i8* %x) [[NUW]], !clang.imprecise_release ![[RELEASE]] 2242 ; CHECK-NEXT: br label %if.end 2243 ; CHECK-NOT: @objc 2244 ; CHECK: } 2245 define void @test56(i8* %x, i32 %n) { 2246 entry: 2247 %0 = tail call i8* @objc_retain(i8* %x) nounwind 2248 %1 = tail call i8* @objc_retain(i8* %0) nounwind 2249 %tobool = icmp eq i32 %n, 0 2250 br i1 %tobool, label %if.end, label %if.then 2251 2252 if.then: ; preds = %entry 2253 %2 = tail call i8* @objc_retain(i8* %1) nounwind 2254 tail call void @use_pointer(i8* %2) 2255 tail call void @use_pointer(i8* %2) 2256 tail call void @objc_release(i8* %2) nounwind, !clang.imprecise_release !0 2257 br label %if.end 2258 2259 if.end: ; preds = %entry, %if.then 2260 tail call void @objc_release(i8* %1) nounwind, !clang.imprecise_release !0 2261 tail call void @objc_release(i8* %0) nounwind, !clang.imprecise_release !0 2262 ret void 2263 } 2264 2265 ; When there are adjacent retain+release pairs, the first one is known 2266 ; unnecessary because the presence of the second one means that the first one 2267 ; won't be deleting the object. 2268 2269 ; CHECK-LABEL: define void @test57( 2270 ; CHECK-NEXT: entry: 2271 ; CHECK-NEXT: tail call i8* @objc_retain(i8* %x) [[NUW]] 2272 ; CHECK-NEXT: call void @use_pointer(i8* %x) 2273 ; CHECK-NEXT: call void @use_pointer(i8* %x) 2274 ; CHECK-NEXT: tail call i8* @objc_retain(i8* %x) [[NUW]] 2275 ; CHECK-NEXT: call void @use_pointer(i8* %x) 2276 ; CHECK-NEXT: call void @use_pointer(i8* %x) 2277 ; CHECK-NEXT: call void @objc_release(i8* %x) [[NUW]] 2278 ; CHECK-NEXT: ret void 2279 ; CHECK-NEXT: } 2280 define void @test57(i8* %x) nounwind { 2281 entry: 2282 call i8* @objc_retain(i8* %x) nounwind 2283 call i8* @objc_retain(i8* %x) nounwind 2284 call void @use_pointer(i8* %x) 2285 call void @use_pointer(i8* %x) 2286 call void @objc_release(i8* %x) nounwind 2287 call i8* @objc_retain(i8* %x) nounwind 2288 call void @use_pointer(i8* %x) 2289 call void @use_pointer(i8* %x) 2290 call void @objc_release(i8* %x) nounwind 2291 ret void 2292 } 2293 2294 ; An adjacent retain+release pair is sufficient even if it will be 2295 ; removed itself. 2296 2297 ; CHECK-LABEL: define void @test58( 2298 ; CHECK-NEXT: entry: 2299 ; CHECK-NEXT: @objc_retain 2300 ; CHECK-NEXT: call void @use_pointer(i8* %x) 2301 ; CHECK-NEXT: call void @use_pointer(i8* %x) 2302 ; CHECK-NEXT: ret void 2303 ; CHECK-NEXT: } 2304 define void @test58(i8* %x) nounwind { 2305 entry: 2306 call i8* @objc_retain(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 call i8* @objc_retain(i8* %x) nounwind 2312 call void @objc_release(i8* %x) nounwind 2313 ret void 2314 } 2315 2316 ; Don't delete the second retain+release pair in an adjacent set. 2317 2318 ; CHECK-LABEL: define void @test59( 2319 ; CHECK-NEXT: entry: 2320 ; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %x) [[NUW]] 2321 ; CHECK-NEXT: call void @use_pointer(i8* %x) 2322 ; CHECK-NEXT: call void @use_pointer(i8* %x) 2323 ; CHECK-NEXT: call void @objc_release(i8* %x) [[NUW]] 2324 ; CHECK-NEXT: ret void 2325 ; CHECK-NEXT: } 2326 define void @test59(i8* %x) nounwind { 2327 entry: 2328 %a = call i8* @objc_retain(i8* %x) nounwind 2329 call void @objc_release(i8* %x) nounwind 2330 %b = call i8* @objc_retain(i8* %x) nounwind 2331 call void @use_pointer(i8* %x) 2332 call void @use_pointer(i8* %x) 2333 call void @objc_release(i8* %x) nounwind 2334 ret void 2335 } 2336 2337 ; Constant pointers to objects don't need reference counting. 2338 2339 @constptr = external constant i8* 2340 @something = external global i8* 2341 2342 ; We have a precise lifetime retain/release here. We can not remove them since 2343 ; @something is not constant. 2344 2345 ; CHECK-LABEL: define void @test60a( 2346 ; CHECK: call i8* @objc_retain 2347 ; CHECK: call void @objc_release 2348 ; CHECK: } 2349 define void @test60a() { 2350 %t = load i8*, i8** @constptr 2351 %s = load i8*, i8** @something 2352 call i8* @objc_retain(i8* %s) 2353 call void @callee() 2354 call void @use_pointer(i8* %t) 2355 call void @objc_release(i8* %s) 2356 ret void 2357 } 2358 2359 ; CHECK-LABEL: define void @test60b( 2360 ; CHECK: call i8* @objc_retain 2361 ; CHECK-NOT: call i8* @objc_retain 2362 ; CHECK-NOT: call i8* @objc_release 2363 ; CHECK: } 2364 define void @test60b() { 2365 %t = load i8*, i8** @constptr 2366 %s = load i8*, i8** @something 2367 call i8* @objc_retain(i8* %t) 2368 call i8* @objc_retain(i8* %t) 2369 call void @callee() 2370 call void @use_pointer(i8* %s) 2371 call void @objc_release(i8* %t) 2372 ret void 2373 } 2374 2375 ; CHECK-LABEL: define void @test60c( 2376 ; CHECK-NOT: @objc_ 2377 ; CHECK: } 2378 define void @test60c() { 2379 %t = load i8*, i8** @constptr 2380 %s = load i8*, i8** @something 2381 call i8* @objc_retain(i8* %t) 2382 call void @callee() 2383 call void @use_pointer(i8* %s) 2384 call void @objc_release(i8* %t), !clang.imprecise_release !0 2385 ret void 2386 } 2387 2388 ; CHECK-LABEL: define void @test60d( 2389 ; CHECK-NOT: @objc_ 2390 ; CHECK: } 2391 define void @test60d() { 2392 %t = load i8*, i8** @constptr 2393 %s = load i8*, i8** @something 2394 call i8* @objc_retain(i8* %t) 2395 call void @callee() 2396 call void @use_pointer(i8* %s) 2397 call void @objc_release(i8* %t) 2398 ret void 2399 } 2400 2401 ; CHECK-LABEL: define void @test60e( 2402 ; CHECK-NOT: @objc_ 2403 ; CHECK: } 2404 define void @test60e() { 2405 %t = load i8*, i8** @constptr 2406 %s = load i8*, i8** @something 2407 call i8* @objc_retain(i8* %t) 2408 call void @callee() 2409 call void @use_pointer(i8* %s) 2410 call void @objc_release(i8* %t), !clang.imprecise_release !0 2411 ret void 2412 } 2413 2414 ; Constant pointers to objects don't need to be considered related to other 2415 ; pointers. 2416 2417 ; CHECK-LABEL: define void @test61( 2418 ; CHECK-NOT: @objc_ 2419 ; CHECK: } 2420 define void @test61() { 2421 %t = load i8*, i8** @constptr 2422 call i8* @objc_retain(i8* %t) 2423 call void @callee() 2424 call void @use_pointer(i8* %t) 2425 call void @objc_release(i8* %t) 2426 ret void 2427 } 2428 2429 ; Delete a retain matched by releases when one is inside the loop and the 2430 ; other is outside the loop. 2431 2432 ; CHECK-LABEL: define void @test62( 2433 ; CHECK-NOT: @objc_ 2434 ; CHECK: } 2435 define void @test62(i8* %x, i1* %p) nounwind { 2436 entry: 2437 br label %loop 2438 2439 loop: 2440 call i8* @objc_retain(i8* %x) 2441 %q = load i1, i1* %p 2442 br i1 %q, label %loop.more, label %exit 2443 2444 loop.more: 2445 call void @objc_release(i8* %x) 2446 br label %loop 2447 2448 exit: 2449 call void @objc_release(i8* %x) 2450 ret void 2451 } 2452 2453 ; Like test62 but with no release in exit. 2454 ; Don't delete anything! 2455 2456 ; CHECK-LABEL: define void @test63( 2457 ; CHECK: loop: 2458 ; CHECK: tail call i8* @objc_retain(i8* %x) 2459 ; CHECK: loop.more: 2460 ; CHECK: call void @objc_release(i8* %x) 2461 ; CHECK: } 2462 define void @test63(i8* %x, i1* %p) nounwind { 2463 entry: 2464 br label %loop 2465 2466 loop: 2467 call i8* @objc_retain(i8* %x) 2468 %q = load i1, i1* %p 2469 br i1 %q, label %loop.more, label %exit 2470 2471 loop.more: 2472 call void @objc_release(i8* %x) 2473 br label %loop 2474 2475 exit: 2476 ret void 2477 } 2478 2479 ; Like test62 but with no release in loop.more. 2480 ; Don't delete anything! 2481 2482 ; CHECK-LABEL: define void @test64( 2483 ; CHECK: loop: 2484 ; CHECK: tail call i8* @objc_retain(i8* %x) 2485 ; CHECK: exit: 2486 ; CHECK: call void @objc_release(i8* %x) 2487 ; CHECK: } 2488 define void @test64(i8* %x, i1* %p) nounwind { 2489 entry: 2490 br label %loop 2491 2492 loop: 2493 call i8* @objc_retain(i8* %x) 2494 %q = load i1, i1* %p 2495 br i1 %q, label %loop.more, label %exit 2496 2497 loop.more: 2498 br label %loop 2499 2500 exit: 2501 call void @objc_release(i8* %x) 2502 ret void 2503 } 2504 2505 ; Move an autorelease past a phi with a null. 2506 2507 ; CHECK-LABEL: define i8* @test65( 2508 ; CHECK: if.then: 2509 ; CHECK: call i8* @objc_autorelease( 2510 ; CHECK: return: 2511 ; CHECK-NOT: @objc_autorelease 2512 ; CHECK: } 2513 define i8* @test65(i1 %x) { 2514 entry: 2515 br i1 %x, label %return, label %if.then 2516 2517 if.then: ; preds = %entry 2518 %c = call i8* @returner() 2519 %s = call i8* @objc_retainAutoreleasedReturnValue(i8* %c) nounwind 2520 br label %return 2521 2522 return: ; preds = %if.then, %entry 2523 %retval = phi i8* [ %s, %if.then ], [ null, %entry ] 2524 %q = call i8* @objc_autorelease(i8* %retval) nounwind 2525 ret i8* %retval 2526 } 2527 2528 ; Don't move an autorelease past an autorelease pool boundary. 2529 2530 ; CHECK-LABEL: define i8* @test65b( 2531 ; CHECK: if.then: 2532 ; CHECK-NOT: @objc_autorelease 2533 ; CHECK: return: 2534 ; CHECK: call i8* @objc_autorelease( 2535 ; CHECK: } 2536 define i8* @test65b(i1 %x) { 2537 entry: 2538 %t = call i8* @objc_autoreleasePoolPush() 2539 br i1 %x, label %return, label %if.then 2540 2541 if.then: ; preds = %entry 2542 %c = call i8* @returner() 2543 %s = call i8* @objc_retainAutoreleasedReturnValue(i8* %c) nounwind 2544 br label %return 2545 2546 return: ; preds = %if.then, %entry 2547 %retval = phi i8* [ %s, %if.then ], [ null, %entry ] 2548 call void @objc_autoreleasePoolPop(i8* %t) 2549 %q = call i8* @objc_autorelease(i8* %retval) nounwind 2550 ret i8* %retval 2551 } 2552 2553 ; Don't move an autoreleaseReuturnValue, which would break 2554 ; the RV optimization. 2555 2556 ; CHECK-LABEL: define i8* @test65c( 2557 ; CHECK: if.then: 2558 ; CHECK-NOT: @objc_autorelease 2559 ; CHECK: return: 2560 ; CHECK: call i8* @objc_autoreleaseReturnValue( 2561 ; CHECK: } 2562 define i8* @test65c(i1 %x) { 2563 entry: 2564 br i1 %x, label %return, label %if.then 2565 2566 if.then: ; preds = %entry 2567 %c = call i8* @returner() 2568 %s = call i8* @objc_retainAutoreleasedReturnValue(i8* %c) nounwind 2569 br label %return 2570 2571 return: ; preds = %if.then, %entry 2572 %retval = phi i8* [ %s, %if.then ], [ null, %entry ] 2573 %q = call i8* @objc_autoreleaseReturnValue(i8* %retval) nounwind 2574 ret i8* %retval 2575 } 2576 2577 ; CHECK-LABEL: define i8* @test65d( 2578 ; CHECK: if.then: 2579 ; CHECK-NOT: @objc_autorelease 2580 ; CHECK: return: 2581 ; CHECK: call i8* @objc_autoreleaseReturnValue( 2582 ; CHECK: } 2583 define i8* @test65d(i1 %x) { 2584 entry: 2585 br i1 %x, label %return, label %if.then 2586 2587 if.then: ; preds = %entry 2588 %c = call i8* @returner() 2589 %s = call i8* @objc_unsafeClaimAutoreleasedReturnValue(i8* %c) nounwind 2590 br label %return 2591 2592 return: ; preds = %if.then, %entry 2593 %retval = phi i8* [ %s, %if.then ], [ null, %entry ] 2594 %q = call i8* @objc_autoreleaseReturnValue(i8* %retval) nounwind 2595 ret i8* %retval 2596 } 2597 2598 ; An objc_retain can serve as a may-use for a different pointer. 2599 ; rdar://11931823 2600 2601 ; CHECK-LABEL: define void @test66a( 2602 ; CHECK: tail call i8* @objc_retain(i8* %cond) [[NUW]] 2603 ; CHECK: tail call void @objc_release(i8* %call) [[NUW]] 2604 ; CHECK: tail call i8* @objc_retain(i8* %tmp8) [[NUW]] 2605 ; CHECK: tail call void @objc_release(i8* %cond) [[NUW]] 2606 ; CHECK: } 2607 define void @test66a(i8* %tmp5, i8* %bar, i1 %tobool, i1 %tobool1, i8* %call) { 2608 entry: 2609 br i1 %tobool, label %cond.true, label %cond.end 2610 2611 cond.true: 2612 br label %cond.end 2613 2614 cond.end: ; preds = %cond.true, %entry 2615 %cond = phi i8* [ %tmp5, %cond.true ], [ %call, %entry ] 2616 %tmp7 = tail call i8* @objc_retain(i8* %cond) nounwind 2617 tail call void @objc_release(i8* %call) nounwind 2618 %tmp8 = select i1 %tobool1, i8* %cond, i8* %bar 2619 %tmp9 = tail call i8* @objc_retain(i8* %tmp8) nounwind 2620 tail call void @objc_release(i8* %cond) nounwind 2621 ret void 2622 } 2623 2624 ; CHECK-LABEL: define void @test66b( 2625 ; CHECK: tail call i8* @objc_retain(i8* %cond) [[NUW]] 2626 ; CHECK: tail call void @objc_release(i8* %call) [[NUW]] 2627 ; CHECK: tail call i8* @objc_retain(i8* %tmp8) [[NUW]] 2628 ; CHECK: tail call void @objc_release(i8* %cond) [[NUW]] 2629 ; CHECK: } 2630 define void @test66b(i8* %tmp5, i8* %bar, i1 %tobool, i1 %tobool1, i8* %call) { 2631 entry: 2632 br i1 %tobool, label %cond.true, label %cond.end 2633 2634 cond.true: 2635 br label %cond.end 2636 2637 cond.end: ; preds = %cond.true, %entry 2638 %cond = phi i8* [ %tmp5, %cond.true ], [ %call, %entry ] 2639 %tmp7 = tail call i8* @objc_retain(i8* %cond) nounwind 2640 tail call void @objc_release(i8* %call) nounwind, !clang.imprecise_release !0 2641 %tmp8 = select i1 %tobool1, i8* %cond, i8* %bar 2642 %tmp9 = tail call i8* @objc_retain(i8* %tmp8) nounwind 2643 tail call void @objc_release(i8* %cond) nounwind 2644 ret void 2645 } 2646 2647 ; CHECK-LABEL: define void @test66c( 2648 ; CHECK: tail call i8* @objc_retain(i8* %cond) [[NUW]] 2649 ; CHECK: tail call void @objc_release(i8* %call) [[NUW]] 2650 ; CHECK: tail call i8* @objc_retain(i8* %tmp8) [[NUW]] 2651 ; CHECK: tail call void @objc_release(i8* %cond) [[NUW]] 2652 ; CHECK: } 2653 define void @test66c(i8* %tmp5, i8* %bar, i1 %tobool, i1 %tobool1, i8* %call) { 2654 entry: 2655 br i1 %tobool, label %cond.true, label %cond.end 2656 2657 cond.true: 2658 br label %cond.end 2659 2660 cond.end: ; preds = %cond.true, %entry 2661 %cond = phi i8* [ %tmp5, %cond.true ], [ %call, %entry ] 2662 %tmp7 = tail call i8* @objc_retain(i8* %cond) nounwind 2663 tail call void @objc_release(i8* %call) nounwind 2664 %tmp8 = select i1 %tobool1, i8* %cond, i8* %bar 2665 %tmp9 = tail call i8* @objc_retain(i8* %tmp8) nounwind, !clang.imprecise_release !0 2666 tail call void @objc_release(i8* %cond) nounwind 2667 ret void 2668 } 2669 2670 ; CHECK-LABEL: define void @test66d( 2671 ; CHECK: tail call i8* @objc_retain(i8* %cond) [[NUW]] 2672 ; CHECK: tail call void @objc_release(i8* %call) [[NUW]] 2673 ; CHECK: tail call i8* @objc_retain(i8* %tmp8) [[NUW]] 2674 ; CHECK: tail call void @objc_release(i8* %cond) [[NUW]] 2675 ; CHECK: } 2676 define void @test66d(i8* %tmp5, i8* %bar, i1 %tobool, i1 %tobool1, i8* %call) { 2677 entry: 2678 br i1 %tobool, label %cond.true, label %cond.end 2679 2680 cond.true: 2681 br label %cond.end 2682 2683 cond.end: ; preds = %cond.true, %entry 2684 %cond = phi i8* [ %tmp5, %cond.true ], [ %call, %entry ] 2685 %tmp7 = tail call i8* @objc_retain(i8* %cond) nounwind 2686 tail call void @objc_release(i8* %call) nounwind, !clang.imprecise_release !0 2687 %tmp8 = select i1 %tobool1, i8* %cond, i8* %bar 2688 %tmp9 = tail call i8* @objc_retain(i8* %tmp8) nounwind 2689 tail call void @objc_release(i8* %cond) nounwind, !clang.imprecise_release !0 2690 ret void 2691 } 2692 2693 ; A few real-world testcases. 2694 2695 @.str4 = private unnamed_addr constant [33 x i8] c"-[A z] = { %f, %f, { %f, %f } }\0A\00" 2696 @"OBJC_IVAR_$_A.myZ" = global i64 20, section "__DATA, __objc_const", align 8 2697 declare i32 @printf(i8* nocapture, ...) nounwind 2698 declare i32 @puts(i8* nocapture) nounwind 2699 @str = internal constant [16 x i8] c"-[ Top0 _getX ]\00" 2700 2701 ; CHECK: define { <2 x float>, <2 x float> } @"\01-[A z]"({}* %self, i8* nocapture %_cmd) [[NUW]] { 2702 ; CHECK-NOT: @objc_ 2703 ; CHECK: } 2704 2705 define {<2 x float>, <2 x float>} @"\01-[A z]"({}* %self, i8* nocapture %_cmd) nounwind { 2706 invoke.cont: 2707 %0 = bitcast {}* %self to i8* 2708 %1 = tail call i8* @objc_retain(i8* %0) nounwind 2709 tail call void @llvm.dbg.value(metadata {}* %self, i64 0, metadata !DILocalVariable(scope: !2), metadata !DIExpression()), !dbg !DILocation(scope: !2) 2710 tail call void @llvm.dbg.value(metadata {}* %self, i64 0, metadata !DILocalVariable(scope: !2), metadata !DIExpression()), !dbg !DILocation(scope: !2) 2711 %ivar = load i64, i64* @"OBJC_IVAR_$_A.myZ", align 8 2712 %add.ptr = getelementptr i8, i8* %0, i64 %ivar 2713 %tmp1 = bitcast i8* %add.ptr to float* 2714 %tmp2 = load float, float* %tmp1, align 4 2715 %conv = fpext float %tmp2 to double 2716 %add.ptr.sum = add i64 %ivar, 4 2717 %tmp6 = getelementptr inbounds i8, i8* %0, i64 %add.ptr.sum 2718 %2 = bitcast i8* %tmp6 to float* 2719 %tmp7 = load float, float* %2, align 4 2720 %conv8 = fpext float %tmp7 to double 2721 %add.ptr.sum36 = add i64 %ivar, 8 2722 %tmp12 = getelementptr inbounds i8, i8* %0, i64 %add.ptr.sum36 2723 %arrayidx = bitcast i8* %tmp12 to float* 2724 %tmp13 = load float, float* %arrayidx, align 4 2725 %conv14 = fpext float %tmp13 to double 2726 %tmp12.sum = add i64 %ivar, 12 2727 %arrayidx19 = getelementptr inbounds i8, i8* %0, i64 %tmp12.sum 2728 %3 = bitcast i8* %arrayidx19 to float* 2729 %tmp20 = load float, float* %3, align 4 2730 %conv21 = fpext float %tmp20 to double 2731 %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) 2732 %ivar23 = load i64, i64* @"OBJC_IVAR_$_A.myZ", align 8 2733 %add.ptr24 = getelementptr i8, i8* %0, i64 %ivar23 2734 %4 = bitcast i8* %add.ptr24 to i128* 2735 %srcval = load i128, i128* %4, align 4 2736 tail call void @objc_release(i8* %0) nounwind 2737 %tmp29 = trunc i128 %srcval to i64 2738 %tmp30 = bitcast i64 %tmp29 to <2 x float> 2739 %tmp31 = insertvalue {<2 x float>, <2 x float>} undef, <2 x float> %tmp30, 0 2740 %tmp32 = lshr i128 %srcval, 64 2741 %tmp33 = trunc i128 %tmp32 to i64 2742 %tmp34 = bitcast i64 %tmp33 to <2 x float> 2743 %tmp35 = insertvalue {<2 x float>, <2 x float>} %tmp31, <2 x float> %tmp34, 1 2744 ret {<2 x float>, <2 x float>} %tmp35 2745 } 2746 2747 ; CHECK: @"\01-[Top0 _getX]"({}* %self, i8* nocapture %_cmd) [[NUW]] { 2748 ; CHECK-NOT: @objc_ 2749 ; CHECK: } 2750 2751 define i32 @"\01-[Top0 _getX]"({}* %self, i8* nocapture %_cmd) nounwind { 2752 invoke.cont: 2753 %0 = bitcast {}* %self to i8* 2754 %1 = tail call i8* @objc_retain(i8* %0) nounwind 2755 %puts = tail call i32 @puts(i8* getelementptr inbounds ([16 x i8], [16 x i8]* @str, i64 0, i64 0)) 2756 tail call void @objc_release(i8* %0) nounwind 2757 ret i32 0 2758 } 2759 2760 @"\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" 2761 @"\01L_OBJC_IMAGE_INFO" = internal constant [2 x i32] [i32 0, i32 16], section "__DATA, __objc_imageinfo, regular, no_dead_strip" 2762 @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" 2763 2764 ; A simple loop. Eliminate the retain and release inside of it! 2765 2766 ; CHECK: define void @loop(i8* %x, i64 %n) { 2767 ; CHECK: for.body: 2768 ; CHECK-NOT: @objc_ 2769 ; CHECK: @objc_msgSend 2770 ; CHECK-NOT: @objc_ 2771 ; CHECK: for.end: 2772 ; CHECK: } 2773 define void @loop(i8* %x, i64 %n) { 2774 entry: 2775 %0 = tail call i8* @objc_retain(i8* %x) nounwind 2776 %cmp9 = icmp sgt i64 %n, 0 2777 br i1 %cmp9, label %for.body, label %for.end 2778 2779 for.body: ; preds = %entry, %for.body 2780 %i.010 = phi i64 [ %inc, %for.body ], [ 0, %entry ] 2781 %1 = tail call i8* @objc_retain(i8* %x) nounwind 2782 %tmp5 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_", align 8 2783 %call = tail call i8* (i8*, i8*, ...) @objc_msgSend(i8* %1, i8* %tmp5) 2784 tail call void @objc_release(i8* %1) nounwind, !clang.imprecise_release !0 2785 %inc = add nsw i64 %i.010, 1 2786 %exitcond = icmp eq i64 %inc, %n 2787 br i1 %exitcond, label %for.end, label %for.body 2788 2789 for.end: ; preds = %for.body, %entry 2790 tail call void @objc_release(i8* %x) nounwind, !clang.imprecise_release !0 2791 ret void 2792 } 2793 2794 ; ObjCARCOpt can delete the retain,release on self. 2795 2796 ; CHECK: define void @TextEditTest(%2* %self, %3* %pboard) { 2797 ; CHECK-NOT: call i8* @objc_retain(i8* %tmp7) 2798 ; CHECK: } 2799 2800 %0 = type { i8* (i8*, %struct._message_ref_t*, ...)*, i8* } 2801 %1 = type opaque 2802 %2 = type opaque 2803 %3 = type opaque 2804 %4 = type opaque 2805 %5 = type opaque 2806 %struct.NSConstantString = type { i32*, i32, i8*, i64 } 2807 %struct._NSRange = type { i64, i64 } 2808 %struct.__CFString = type opaque 2809 %struct.__method_list_t = type { i32, i32, [0 x %struct._objc_method] } 2810 %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* } 2811 %struct._class_t = type { %struct._class_t*, %struct._class_t*, %struct._objc_cache*, i8* (i8*, i8*)**, %struct._class_ro_t* } 2812 %struct._ivar_list_t = type { i32, i32, [0 x %struct._ivar_t] } 2813 %struct._ivar_t = type { i64*, i8*, i8*, i32, i32 } 2814 %struct._message_ref_t = type { i8*, i8* } 2815 %struct._objc_cache = type opaque 2816 %struct._objc_method = type { i8*, i8*, i8* } 2817 %struct._objc_protocol_list = type { i64, [0 x %struct._protocol_t*] } 2818 %struct._prop_list_t = type { i32, i32, [0 x %struct._message_ref_t] } 2819 %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 } 2820 2821 @"\01L_OBJC_CLASSLIST_REFERENCES_$_17" = external hidden global %struct._class_t*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8 2822 @kUTTypePlainText = external constant %struct.__CFString* 2823 @"\01L_OBJC_SELECTOR_REFERENCES_19" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2824 @"\01L_OBJC_SELECTOR_REFERENCES_21" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2825 @"\01L_OBJC_SELECTOR_REFERENCES_23" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2826 @"\01L_OBJC_SELECTOR_REFERENCES_25" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2827 @"\01L_OBJC_CLASSLIST_REFERENCES_$_26" = external hidden global %struct._class_t*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8 2828 @"\01L_OBJC_SELECTOR_REFERENCES_28" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2829 @"\01L_OBJC_CLASSLIST_REFERENCES_$_29" = external hidden global %struct._class_t*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8 2830 @"\01L_OBJC_SELECTOR_REFERENCES_31" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2831 @"\01L_OBJC_SELECTOR_REFERENCES_33" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2832 @"\01L_OBJC_SELECTOR_REFERENCES_35" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2833 @"\01L_OBJC_SELECTOR_REFERENCES_37" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2834 @"\01L_OBJC_CLASSLIST_REFERENCES_$_38" = external hidden global %struct._class_t*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8 2835 @"\01L_OBJC_SELECTOR_REFERENCES_40" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2836 @"\01L_OBJC_SELECTOR_REFERENCES_42" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2837 @_unnamed_cfstring_44 = external hidden constant %struct.NSConstantString, section "__DATA,__cfstring" 2838 @"\01L_OBJC_SELECTOR_REFERENCES_46" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2839 @"\01L_OBJC_SELECTOR_REFERENCES_48" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2840 @"\01l_objc_msgSend_fixup_isEqual_" = external hidden global %0, section "__DATA, __objc_msgrefs, coalesced", align 16 2841 @"\01L_OBJC_CLASSLIST_REFERENCES_$_50" = external hidden global %struct._class_t*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8 2842 @NSCocoaErrorDomain = external constant %1* 2843 @"\01L_OBJC_CLASSLIST_REFERENCES_$_51" = external hidden global %struct._class_t*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8 2844 @NSFilePathErrorKey = external constant %1* 2845 @"\01L_OBJC_SELECTOR_REFERENCES_53" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2846 @"\01L_OBJC_SELECTOR_REFERENCES_55" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2847 @"\01L_OBJC_CLASSLIST_REFERENCES_$_56" = external hidden global %struct._class_t*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8 2848 @"\01L_OBJC_SELECTOR_REFERENCES_58" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2849 @"\01L_OBJC_SELECTOR_REFERENCES_60" = external hidden global i8*, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip" 2850 2851 declare %1* @truncatedString(%1*, i64) 2852 define void @TextEditTest(%2* %self, %3* %pboard) { 2853 entry: 2854 %err = alloca %4*, align 8 2855 %tmp7 = bitcast %2* %self to i8* 2856 %tmp8 = call i8* @objc_retain(i8* %tmp7) nounwind 2857 store %4* null, %4** %err, align 8 2858 %tmp1 = load %struct._class_t*, %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_17", align 8 2859 %tmp2 = load %struct.__CFString*, %struct.__CFString** @kUTTypePlainText, align 8 2860 %tmp3 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_19", align 8 2861 %tmp4 = bitcast %struct._class_t* %tmp1 to i8* 2862 %call5 = call i8* (i8*, i8*, ...) @objc_msgSend(i8* %tmp4, i8* %tmp3, %struct.__CFString* %tmp2) 2863 %tmp5 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_21", align 8 2864 %tmp6 = bitcast %3* %pboard to i8* 2865 %call76 = call i8* (i8*, i8*, ...) @objc_msgSend(i8* %tmp6, i8* %tmp5, i8* %call5) 2866 %tmp9 = call i8* @objc_retain(i8* %call76) nounwind 2867 %tobool = icmp eq i8* %tmp9, null 2868 br i1 %tobool, label %end, label %land.lhs.true 2869 2870 land.lhs.true: ; preds = %entry 2871 %tmp11 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_23", align 8 2872 %call137 = call i8* (i8*, i8*, ...) @objc_msgSend(i8* %tmp6, i8* %tmp11, i8* %tmp9) 2873 %tmp = bitcast i8* %call137 to %1* 2874 %tmp10 = call i8* @objc_retain(i8* %call137) nounwind 2875 call void @objc_release(i8* null) nounwind 2876 %tmp12 = call i8* @objc_retain(i8* %call137) nounwind 2877 call void @objc_release(i8* null) nounwind 2878 %tobool16 = icmp eq i8* %call137, null 2879 br i1 %tobool16, label %end, label %if.then 2880 2881 if.then: ; preds = %land.lhs.true 2882 %tmp19 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_25", align 8 2883 %call21 = call signext i8 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8 (i8*, i8*)*)(i8* %call137, i8* %tmp19) 2884 %tobool22 = icmp eq i8 %call21, 0 2885 br i1 %tobool22, label %if.then44, label %land.lhs.true23 2886 2887 land.lhs.true23: ; preds = %if.then 2888 %tmp24 = load %struct._class_t*, %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_26", align 8 2889 %tmp26 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_28", align 8 2890 %tmp27 = bitcast %struct._class_t* %tmp24 to i8* 2891 %call2822 = call i8* (i8*, i8*, ...) @objc_msgSend(i8* %tmp27, i8* %tmp26, i8* %call137) 2892 %tmp13 = bitcast i8* %call2822 to %5* 2893 %tmp14 = call i8* @objc_retain(i8* %call2822) nounwind 2894 call void @objc_release(i8* null) nounwind 2895 %tobool30 = icmp eq i8* %call2822, null 2896 br i1 %tobool30, label %if.then44, label %if.end 2897 2898 if.end: ; preds = %land.lhs.true23 2899 %tmp32 = load %struct._class_t*, %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_29", align 8 2900 %tmp33 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_31", align 8 2901 %tmp34 = bitcast %struct._class_t* %tmp32 to i8* 2902 %call35 = call i8* (i8*, i8*, ...) @objc_msgSend(i8* %tmp34, i8* %tmp33) 2903 %tmp37 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_33", align 8 2904 %call3923 = call i8* (i8*, i8*, ...) @objc_msgSend(i8* %call35, i8* %tmp37, i8* %call2822, i32 signext 1, %4** %err) 2905 %cmp = icmp eq i8* %call3923, null 2906 br i1 %cmp, label %if.then44, label %end 2907 2908 if.then44: ; preds = %if.end, %land.lhs.true23, %if.then 2909 %url.025 = phi %5* [ %tmp13, %if.end ], [ %tmp13, %land.lhs.true23 ], [ null, %if.then ] 2910 %tmp49 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_35", align 8 2911 %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) 2912 %call513 = extractvalue %struct._NSRange %call51, 0 2913 %call514 = extractvalue %struct._NSRange %call51, 1 2914 %tmp52 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_37", align 8 2915 %call548 = call i8* (i8*, i8*, ...) @objc_msgSend(i8* %call137, i8* %tmp52, i64 %call513, i64 %call514) 2916 %tmp55 = load %struct._class_t*, %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_38", align 8 2917 %tmp56 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_40", align 8 2918 %tmp57 = bitcast %struct._class_t* %tmp55 to i8* 2919 %call58 = call i8* (i8*, i8*, ...) @objc_msgSend(i8* %tmp57, i8* %tmp56) 2920 %tmp59 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_42", align 8 2921 %call6110 = call i8* (i8*, i8*, ...) @objc_msgSend(i8* %call548, i8* %tmp59, i8* %call58) 2922 %tmp15 = call i8* @objc_retain(i8* %call6110) nounwind 2923 call void @objc_release(i8* %call137) nounwind 2924 %tmp64 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_46", align 8 2925 %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*)) 2926 %tobool67 = icmp eq i8 %call66, 0 2927 br i1 %tobool67, label %if.end74, label %if.then68 2928 2929 if.then68: ; preds = %if.then44 2930 %tmp70 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_48", align 8 2931 %call7220 = call i8* (i8*, i8*, ...) @objc_msgSend(i8* %call6110, i8* %tmp70) 2932 %tmp16 = call i8* @objc_retain(i8* %call7220) nounwind 2933 call void @objc_release(i8* %call6110) nounwind 2934 br label %if.end74 2935 2936 if.end74: ; preds = %if.then68, %if.then44 2937 %filename.0.in = phi i8* [ %call7220, %if.then68 ], [ %call6110, %if.then44 ] 2938 %filename.0 = bitcast i8* %filename.0.in to %1* 2939 %tmp17 = load i8*, i8** bitcast (%0* @"\01l_objc_msgSend_fixup_isEqual_" to i8**), align 16 2940 %tmp18 = bitcast i8* %tmp17 to i8 (i8*, %struct._message_ref_t*, i8*, ...)* 2941 %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) 2942 %tobool79 = icmp eq i8 %call78, 0 2943 br i1 %tobool79, label %land.lhs.true80, label %if.then109 2944 2945 land.lhs.true80: ; preds = %if.end74 2946 %tmp82 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_25", align 8 2947 %call84 = call signext i8 bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8 (i8*, i8*)*)(i8* %filename.0.in, i8* %tmp82) 2948 %tobool86 = icmp eq i8 %call84, 0 2949 br i1 %tobool86, label %if.then109, label %if.end106 2950 2951 if.end106: ; preds = %land.lhs.true80 2952 %tmp88 = load %struct._class_t*, %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_26", align 8 2953 %tmp90 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_28", align 8 2954 %tmp91 = bitcast %struct._class_t* %tmp88 to i8* 2955 %call9218 = call i8* (i8*, i8*, ...) @objc_msgSend(i8* %tmp91, i8* %tmp90, i8* %filename.0.in) 2956 %tmp20 = bitcast i8* %call9218 to %5* 2957 %tmp21 = call i8* @objc_retain(i8* %call9218) nounwind 2958 %tmp22 = bitcast %5* %url.025 to i8* 2959 call void @objc_release(i8* %tmp22) nounwind 2960 %tmp94 = load %struct._class_t*, %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_29", align 8 2961 %tmp95 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_31", align 8 2962 %tmp96 = bitcast %struct._class_t* %tmp94 to i8* 2963 %call97 = call i8* (i8*, i8*, ...) @objc_msgSend(i8* %tmp96, i8* %tmp95) 2964 %tmp99 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_33", align 8 2965 %call10119 = call i8* (i8*, i8*, ...) @objc_msgSend(i8* %call97, i8* %tmp99, i8* %call9218, i32 signext 1, %4** %err) 2966 %phitmp = icmp eq i8* %call10119, null 2967 br i1 %phitmp, label %if.then109, label %end 2968 2969 if.then109: ; preds = %if.end106, %land.lhs.true80, %if.end74 2970 %url.129 = phi %5* [ %tmp20, %if.end106 ], [ %url.025, %if.end74 ], [ %url.025, %land.lhs.true80 ] 2971 %tmp110 = load %4*, %4** %err, align 8 2972 %tobool111 = icmp eq %4* %tmp110, null 2973 br i1 %tobool111, label %if.then112, label %if.end125 2974 2975 if.then112: ; preds = %if.then109 2976 %tmp113 = load %struct._class_t*, %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_50", align 8 2977 %tmp114 = load %1*, %1** @NSCocoaErrorDomain, align 8 2978 %tmp115 = load %struct._class_t*, %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_51", align 8 2979 %call117 = call %1* @truncatedString(%1* %filename.0, i64 1034) 2980 %tmp118 = load %1*, %1** @NSFilePathErrorKey, align 8 2981 %tmp119 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_53", align 8 2982 %tmp120 = bitcast %struct._class_t* %tmp115 to i8* 2983 %call12113 = call i8* (i8*, i8*, ...) @objc_msgSend(i8* %tmp120, i8* %tmp119, %1* %call117, %1* %tmp118, i8* null) 2984 %tmp122 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_55", align 8 2985 %tmp123 = bitcast %struct._class_t* %tmp113 to i8* 2986 %call12414 = call i8* (i8*, i8*, ...) @objc_msgSend(i8* %tmp123, i8* %tmp122, %1* %tmp114, i64 258, i8* %call12113) 2987 %tmp23 = call i8* @objc_retain(i8* %call12414) nounwind 2988 %tmp25 = call i8* @objc_autorelease(i8* %tmp23) nounwind 2989 %tmp28 = bitcast i8* %tmp25 to %4* 2990 store %4* %tmp28, %4** %err, align 8 2991 br label %if.end125 2992 2993 if.end125: ; preds = %if.then112, %if.then109 2994 %tmp127 = phi %4* [ %tmp110, %if.then109 ], [ %tmp28, %if.then112 ] 2995 %tmp126 = load %struct._class_t*, %struct._class_t** @"\01L_OBJC_CLASSLIST_REFERENCES_$_56", align 8 2996 %tmp128 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_58", align 8 2997 %tmp129 = bitcast %struct._class_t* %tmp126 to i8* 2998 %call13015 = call i8* (i8*, i8*, ...) @objc_msgSend(i8* %tmp129, i8* %tmp128, %4* %tmp127) 2999 %tmp131 = load i8*, i8** @"\01L_OBJC_SELECTOR_REFERENCES_60", align 8 3000 %call13317 = call i8* (i8*, i8*, ...) @objc_msgSend(i8* %call13015, i8* %tmp131) 3001 br label %end 3002 3003 end: ; preds = %if.end125, %if.end106, %if.end, %land.lhs.true, %entry 3004 %filename.2 = phi %1* [ %filename.0, %if.end106 ], [ %filename.0, %if.end125 ], [ %tmp, %land.lhs.true ], [ null, %entry ], [ %tmp, %if.end ] 3005 %origFilename.0 = phi %1* [ %tmp, %if.end106 ], [ %tmp, %if.end125 ], [ %tmp, %land.lhs.true ], [ null, %entry ], [ %tmp, %if.end ] 3006 %url.2 = phi %5* [ %tmp20, %if.end106 ], [ %url.129, %if.end125 ], [ null, %land.lhs.true ], [ null, %entry ], [ %tmp13, %if.end ] 3007 call void @objc_release(i8* %tmp9) nounwind, !clang.imprecise_release !0 3008 %tmp29 = bitcast %5* %url.2 to i8* 3009 call void @objc_release(i8* %tmp29) nounwind, !clang.imprecise_release !0 3010 %tmp30 = bitcast %1* %origFilename.0 to i8* 3011 call void @objc_release(i8* %tmp30) nounwind, !clang.imprecise_release !0 3012 %tmp31 = bitcast %1* %filename.2 to i8* 3013 call void @objc_release(i8* %tmp31) nounwind, !clang.imprecise_release !0 3014 call void @objc_release(i8* %tmp7) nounwind, !clang.imprecise_release !0 3015 ret void 3016 } 3017 3018 declare i32 @__gxx_personality_v0(...) 3019 3020 declare i32 @objc_sync_enter(i8*) 3021 declare i32 @objc_sync_exit(i8*) 3022 3023 ; Make sure that we understand that objc_sync_{enter,exit} are IC_User not 3024 ; IC_Call/IC_CallOrUser. 3025 3026 ; CHECK-LABEL: define void @test67( 3027 ; CHECK-NEXT: call i32 @objc_sync_enter(i8* %x) 3028 ; CHECK-NEXT: call i32 @objc_sync_exit(i8* %x) 3029 ; CHECK-NEXT: ret void 3030 ; CHECK-NEXT: } 3031 define void @test67(i8* %x) { 3032 call i8* @objc_retain(i8* %x) 3033 call i32 @objc_sync_enter(i8* %x) 3034 call i32 @objc_sync_exit(i8* %x) 3035 call void @objc_release(i8* %x), !clang.imprecise_release !0 3036 ret void 3037 } 3038 3039 !llvm.module.flags = !{!1} 3040 !llvm.dbg.cu = !{!3} 3041 3042 !0 = !{} 3043 !1 = !{i32 1, !"Debug Info Version", i32 3} 3044 !2 = distinct !DISubprogram(unit: !3) 3045 !3 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang", 3046 file: !4, 3047 isOptimized: true, flags: "-O2", 3048 splitDebugFilename: "abc.debug", emissionKind: 2) 3049 !4 = !DIFile(filename: "path/to/file", directory: "/path/to/dir") 3050 !5 = !{i32 2, !"Debug Info Version", i32 3} 3051 3052 ; CHECK: attributes #0 = { nounwind readnone } 3053 ; CHECK: attributes [[NUW]] = { nounwind } 3054 ; CHECK: ![[RELEASE]] = !{} 3055