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