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