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