brintos

brintos / llvm-project-archived public Read only

0
0
Text · 85.1 KiB · aa0c53b Raw
2957 lines · plain
1; RUN: opt -aa-pipeline=basic-aa -passes=objc-arc -S < %s | FileCheck %s2 3target datalayout = "e-p:64:64:64"4 5declare ptr @llvm.objc.retain(ptr)6declare ptr @llvm.objc.retainAutoreleasedReturnValue(ptr)7declare ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr)8declare void @llvm.objc.release(ptr)9declare ptr @llvm.objc.autorelease(ptr)10declare ptr @llvm.objc.autoreleaseReturnValue(ptr)11declare void @llvm.objc.autoreleasePoolPop(ptr)12declare ptr @llvm.objc.autoreleasePoolPush()13declare ptr @llvm.objc.retainBlock(ptr)14 15declare ptr @llvm.objc.retainedObject(ptr)16declare ptr @llvm.objc.unretainedObject(ptr)17declare ptr @llvm.objc.unretainedPointer(ptr)18 19declare void @use_pointer(ptr)20declare void @callee()21declare void @callee2(ptr, ptr)22declare void @callee_fnptr(ptr)23declare void @invokee()24declare ptr @returner()25declare void @bar(ptr)26 27declare void @llvm.dbg.value(metadata, metadata, metadata)28 29declare ptr @objc_msgSend(ptr, ptr, ...)30 31; Simple retain+release pair deletion, with some intervening control32; flow and harmless instructions.33 34; CHECK: define void @test0_precise(ptr %x, i1 %p) [[NUW:#[0-9]+]] {35; CHECK: @llvm.objc.retain36; CHECK: @llvm.objc.release37; CHECK: {{^}}}38define void @test0_precise(ptr %x, i1 %p) nounwind {39entry:40  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind41  br i1 %p, label %t, label %f42 43t:44  store i8 3, ptr %x45  store float 2.0, ptr %x46  br label %return47 48f:49  store i32 7, ptr %x50  br label %return51 52return:53  call void @llvm.objc.release(ptr %x) nounwind54  ret void55}56 57; CHECK: define void @test0_imprecise(ptr %x, i1 %p) [[NUW]] {58; CHECK-NOT: @llvm.objc.59; CHECK: {{^}}}60define void @test0_imprecise(ptr %x, i1 %p) nounwind {61entry:62  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind63  br i1 %p, label %t, label %f64 65t:66  store i8 3, ptr %x67  store float 2.0, ptr %x68  br label %return69 70f:71  store i32 7, ptr %x72  br label %return73 74return:75  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !076  ret void77}78 79; Like test0 but the release isn't always executed when the retain is,80; so the optimization is not safe.81 82; TODO: Make the llvm.objc.release's argument be %0.83 84; CHECK: define void @test1_precise(ptr %x, i1 %p, i1 %q) [[NUW]] {85; CHECK: @llvm.objc.retain(ptr %x)86; CHECK: @llvm.objc.release(ptr %x)87; CHECK: {{^}}}88define void @test1_precise(ptr %x, i1 %p, i1 %q) nounwind {89entry:90  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind91  br i1 %p, label %t, label %f92 93t:94  store i8 3, ptr %x95  store float 2.0, ptr %x96  br label %return97 98f:99  store i32 7, ptr %x100  call void @callee()101  br i1 %q, label %return, label %alt_return102 103return:104  call void @llvm.objc.release(ptr %x) nounwind105  ret void106 107alt_return:108  ret void109}110 111; CHECK: define void @test1_imprecise(ptr %x, i1 %p, i1 %q) [[NUW]] {112; CHECK: @llvm.objc.retain(ptr %x)113; CHECK: @llvm.objc.release114; CHECK: {{^}}}115define void @test1_imprecise(ptr %x, i1 %p, i1 %q) nounwind {116entry:117  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind118  br i1 %p, label %t, label %f119 120t:121  store i8 3, ptr %x122  store float 2.0, ptr %x123  br label %return124 125f:126  store i32 7, ptr %x127  call void @callee()128  br i1 %q, label %return, label %alt_return129 130return:131  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0132  ret void133 134alt_return:135  ret void136}137 138 139; Don't do partial elimination into two different CFG diamonds.140 141; CHECK: define void @test1b_precise(ptr %x, i1 %p, i1 %q) {142; CHECK: entry:143; CHECK:   tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]144; CHECK-NOT: @llvm.objc.145; CHECK: if.end5:146; CHECK:   tail call void @llvm.objc.release(ptr %x) [[NUW]]147; CHECK-NOT: @llvm.objc.148; CHECK: {{^}}}149define void @test1b_precise(ptr %x, i1 %p, i1 %q) {150entry:151  tail call ptr @llvm.objc.retain(ptr %x) nounwind152  br i1 %p, label %if.then, label %if.end153 154if.then:                                          ; preds = %entry155  tail call void @callee()156  br label %if.end157 158if.end:                                           ; preds = %if.then, %entry159  br i1 %q, label %if.then3, label %if.end5160 161if.then3:                                         ; preds = %if.end162  tail call void @use_pointer(ptr %x)163  br label %if.end5164 165if.end5:                                          ; preds = %if.then3, %if.end166  tail call void @llvm.objc.release(ptr %x) nounwind167  ret void168}169 170; CHECK-LABEL: define void @test1b_imprecise(171; CHECK: entry:172; CHECK:   tail call ptr @llvm.objc.retain(ptr %x) [[NUW:#[0-9]+]]173; CHECK-NOT: @llvm.objc.174; CHECK: if.end5:175; CHECK:   tail call void @llvm.objc.release(ptr %x) [[NUW]], !clang.imprecise_release ![[RELEASE:[0-9]+]]176; CHECK-NOT: @llvm.objc.177; CHECK: {{^}}}178define void @test1b_imprecise(ptr %x, i1 %p, i1 %q) {179entry:180  tail call ptr @llvm.objc.retain(ptr %x) nounwind181  br i1 %p, label %if.then, label %if.end182 183if.then:                                          ; preds = %entry184  tail call void @callee()185  br label %if.end186 187if.end:                                           ; preds = %if.then, %entry188  br i1 %q, label %if.then3, label %if.end5189 190if.then3:                                         ; preds = %if.end191  tail call void @use_pointer(ptr %x)192  br label %if.end5193 194if.end5:                                          ; preds = %if.then3, %if.end195  tail call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0196  ret void197}198 199 200; Like test0 but the pointer is passed to an intervening call,201; so the optimization is not safe.202 203; CHECK-LABEL: define void @test2_precise(204; CHECK: @llvm.objc.retain(ptr %x)205; CHECK: @llvm.objc.release206; CHECK: {{^}}}207define void @test2_precise(ptr %x, i1 %p) nounwind {208entry:209  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind210  br i1 %p, label %t, label %f211 212t:213  store i8 3, ptr %x214  store float 2.0, ptr %x215  br label %return216 217f:218  store i32 7, ptr %x219  call void @use_pointer(ptr %0)220  store float 3.0, ptr %x221  br label %return222 223return:224  call void @llvm.objc.release(ptr %x) nounwind225  ret void226}227 228; CHECK-LABEL: define void @test2_imprecise(229; CHECK: @llvm.objc.retain(ptr %x)230; CHECK: @llvm.objc.release231; CHECK: {{^}}}232define void @test2_imprecise(ptr %x, i1 %p) nounwind {233entry:234  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind235  br i1 %p, label %t, label %f236 237t:238  store i8 3, ptr %x239  store float 2.0, ptr %x240  br label %return241 242f:243  store i32 7, ptr %x244  call void @use_pointer(ptr %0)245  store float 3.0, ptr %x246  br label %return247 248return:249  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0250  ret void251}252 253; Like test0 but the release is in a loop,254; so the optimization is not safe.255 256; TODO: For now, assume this can't happen.257 258; CHECK-LABEL: define void @test3_precise(259; TODO: @llvm.objc.retain(ptr %a)260; TODO: @llvm.objc.release261; CHECK: {{^}}}262define void @test3_precise(ptr %x, ptr %q) nounwind {263entry:264  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind265  br label %loop266 267loop:268  call void @llvm.objc.release(ptr %x) nounwind269  %j = load volatile i1, ptr %q270  br i1 %j, label %loop, label %return271 272return:273  ret void274}275 276; CHECK-LABEL: define void @test3_imprecise(277; TODO: @llvm.objc.retain(ptr %a)278; TODO: @llvm.objc.release279; CHECK: {{^}}}280define void @test3_imprecise(ptr %x, ptr %q) nounwind {281entry:282  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind283  br label %loop284 285loop:286  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0287  %j = load volatile i1, ptr %q288  br i1 %j, label %loop, label %return289 290return:291  ret void292}293 294 295; TODO: For now, assume this can't happen.296 297; Like test0 but the retain is in a loop,298; so the optimization is not safe.299 300; CHECK-LABEL: define void @test4_precise(301; TODO: @llvm.objc.retain(ptr %a)302; TODO: @llvm.objc.release303; CHECK: {{^}}}304define void @test4_precise(ptr %x, ptr %q) nounwind {305entry:306  br label %loop307 308loop:309  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind310  %j = load volatile i1, ptr %q311  br i1 %j, label %loop, label %return312 313return:314  call void @llvm.objc.release(ptr %x) nounwind315  ret void316}317 318; CHECK-LABEL: define void @test4_imprecise(319; TODO: @llvm.objc.retain(ptr %a)320; TODO: @llvm.objc.release321; CHECK: {{^}}}322define void @test4_imprecise(ptr %x, ptr %q) nounwind {323entry:324  br label %loop325 326loop:327  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind328  %j = load volatile i1, ptr %q329  br i1 %j, label %loop, label %return330 331return:332  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0333  ret void334}335 336 337; Like test0 but the pointer is conditionally passed to an intervening call,338; so the optimization is not safe.339 340; CHECK-LABEL: define void @test5a(341; CHECK: @llvm.objc.retain(ptr342; CHECK: @llvm.objc.release343; CHECK: {{^}}}344define void @test5a(ptr %x, i1 %q, ptr %y) nounwind {345entry:346  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind347  %s = select i1 %q, ptr %y, ptr %0348  call void @use_pointer(ptr %s)349  store i32 7, ptr %x350  call void @llvm.objc.release(ptr %x) nounwind351  ret void352}353 354; CHECK-LABEL: define void @test5b(355; CHECK: @llvm.objc.retain(ptr356; CHECK: @llvm.objc.release357; CHECK: {{^}}}358define void @test5b(ptr %x, i1 %q, ptr %y) nounwind {359entry:360  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind361  %s = select i1 %q, ptr %y, ptr %0362  call void @use_pointer(ptr %s)363  store i32 7, ptr %x364  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0365  ret void366}367 368 369; retain+release pair deletion, where the release happens on two different370; flow paths.371 372; CHECK-LABEL: define void @test6a(373; CHECK: entry:374; CHECK:   tail call ptr @llvm.objc.retain375; CHECK: t:376; CHECK:   call void @llvm.objc.release377; CHECK: f:378; CHECK:   call void @llvm.objc.release379; CHECK: return:380; CHECK: {{^}}}381define void @test6a(ptr %x, i1 %p) nounwind {382entry:383  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind384  br i1 %p, label %t, label %f385 386t:387  store i8 3, ptr %x388  store float 2.0, ptr %x389  call void @llvm.objc.release(ptr %x) nounwind390  br label %return391 392f:393  store i32 7, ptr %x394  call void @callee()395  call void @llvm.objc.release(ptr %x) nounwind396  br label %return397 398return:399  ret void400}401 402; CHECK-LABEL: define void @test6b(403; CHECK-NOT: @llvm.objc.404; CHECK: {{^}}}405define void @test6b(ptr %x, i1 %p) nounwind {406entry:407  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind408  br i1 %p, label %t, label %f409 410t:411  store i8 3, ptr %x412  store float 2.0, ptr %x413  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0414  br label %return415 416f:417  store i32 7, ptr %x418  call void @callee()419  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0420  br label %return421 422return:423  ret void424}425 426; CHECK-LABEL: define void @test6c(427; CHECK: entry:428; CHECK:   tail call ptr @llvm.objc.retain429; CHECK: t:430; CHECK:   call void @llvm.objc.release431; CHECK: f:432; CHECK:   call void @llvm.objc.release433; CHECK: return:434; CHECK: {{^}}}435define void @test6c(ptr %x, i1 %p) nounwind {436entry:437  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind438  br i1 %p, label %t, label %f439 440t:441  store i8 3, ptr %x442  store float 2.0, ptr %x443  call void @llvm.objc.release(ptr %x) nounwind444  br label %return445 446f:447  store i32 7, ptr %x448  call void @callee()449  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0450  br label %return451 452return:453  ret void454}455 456; CHECK-LABEL: define void @test6d(457; CHECK: entry:458; CHECK:   tail call ptr @llvm.objc.retain459; CHECK: t:460; CHECK:   call void @llvm.objc.release461; CHECK: f:462; CHECK:   call void @llvm.objc.release463; CHECK: return:464; CHECK: {{^}}}465define void @test6d(ptr %x, i1 %p) nounwind {466entry:467  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind468  br i1 %p, label %t, label %f469 470t:471  store i8 3, ptr %x472  store float 2.0, ptr %x473  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0474  br label %return475 476f:477  store i32 7, ptr %x478  call void @callee()479  call void @llvm.objc.release(ptr %x) nounwind480  br label %return481 482return:483  ret void484}485 486 487; retain+release pair deletion, where the retain happens on two different488; flow paths.489 490; CHECK-LABEL:     define void @test7(491; CHECK:     entry:492; CHECK-NOT:   llvm.objc.493; CHECK:     t:494; CHECK:       call ptr @llvm.objc.retain495; CHECK:     f:496; CHECK:       call ptr @llvm.objc.retain497; CHECK:     return:498; CHECK:       call void @llvm.objc.release499; CHECK: {{^}}}500define void @test7(ptr %x, i1 %p) nounwind {501entry:502  br i1 %p, label %t, label %f503 504t:505  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind506  store i8 3, ptr %x507  store float 2.0, ptr %x508  br label %return509 510f:511  %1 = call ptr @llvm.objc.retain(ptr %x) nounwind512  store i32 7, ptr %x513  call void @callee()514  br label %return515 516return:517  call void @llvm.objc.release(ptr %x) nounwind518  ret void519}520 521; CHECK-LABEL: define void @test7b(522; CHECK-NOT: @llvm.objc.523; CHECK: {{^}}}524define void @test7b(ptr %x, i1 %p) nounwind {525entry:526  br i1 %p, label %t, label %f527 528t:529  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind530  store i8 3, ptr %x531  store float 2.0, ptr %x532  br label %return533 534f:535  %1 = call ptr @llvm.objc.retain(ptr %x) nounwind536  store i32 7, ptr %x537  call void @callee()538  br label %return539 540return:541  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0542  ret void543}544 545; Like test7, but there's a retain/retainBlock mismatch. Don't delete!546 547; CHECK-LABEL: define void @test7c(548; CHECK: t:549; CHECK:   call ptr @llvm.objc.retainBlock550; CHECK: f:551; CHECK:   call ptr @llvm.objc.retain552; CHECK: return:553; CHECK:   call void @llvm.objc.release554; CHECK: {{^}}}555define void @test7c(ptr %x, i1 %p) nounwind {556entry:557  br i1 %p, label %t, label %f558 559t:560  %0 = call ptr @llvm.objc.retainBlock(ptr %x) nounwind561  store i8 3, ptr %x562  store float 2.0, ptr %x563  br label %return564 565f:566  %1 = call ptr @llvm.objc.retain(ptr %x) nounwind567  store i32 7, ptr %x568  call void @callee()569  br label %return570 571return:572  call void @llvm.objc.release(ptr %x) nounwind573  ret void574}575 576; retain+release pair deletion, where the retain and release both happen on577; different flow paths. Wild!578 579; CHECK-LABEL: define void @test8a(580; CHECK: entry:581; CHECK: t:582; CHECK:   @llvm.objc.retain583; CHECK: f:584; CHECK:   @llvm.objc.retain585; CHECK: mid:586; CHECK: u:587; CHECK:   @llvm.objc.release588; CHECK: g:589; CHECK:   @llvm.objc.release590; CHECK: return:591; CHECK: {{^}}}592define void @test8a(ptr %x, i1 %p, i1 %q) nounwind {593entry:594  br i1 %p, label %t, label %f595 596t:597  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind598  store i8 3, ptr %x599  store float 2.0, ptr %x600  br label %mid601 602f:603  %1 = call ptr @llvm.objc.retain(ptr %x) nounwind604  store i32 7, ptr %x605  br label %mid606 607mid:608  br i1 %q, label %u, label %g609 610u:611  call void @callee()612  call void @llvm.objc.release(ptr %x) nounwind613  br label %return614 615g:616  call void @llvm.objc.release(ptr %x) nounwind617  br label %return618 619return:620  ret void621}622 623; CHECK-LABEL: define void @test8b(624; CHECK-NOT: @llvm.objc.625; CHECK: {{^}}}626define void @test8b(ptr %x, i1 %p, i1 %q) nounwind {627entry:628  br i1 %p, label %t, label %f629 630t:631  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind632  store i8 3, ptr %x633  store float 2.0, ptr %x634  br label %mid635 636f:637  %1 = call ptr @llvm.objc.retain(ptr %x) nounwind638  store i32 7, ptr %x639  br label %mid640 641mid:642  br i1 %q, label %u, label %g643 644u:645  call void @callee()646  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0647  br label %return648 649g:650  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0651  br label %return652 653return:654  ret void655}656 657; CHECK-LABEL: define void @test8c(658; CHECK: entry:659; CHECK: t:660; CHECK-NOT: @llvm.objc.661; CHECK: f:662; CHECK-NOT: @llvm.objc.663; CHECK: mid:664; CHECK: u:665; CHECK:   @llvm.objc.retain666; CHECK:   @llvm.objc.release667; CHECK: g:668; CHECK-NOT: @llvm.objc.669; CHECK: return:670; CHECK: {{^}}}671define void @test8c(ptr %x, i1 %p, i1 %q) nounwind {672entry:673  br i1 %p, label %t, label %f674 675t:676  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind677  store i8 3, ptr %x678  store float 2.0, ptr %x679  br label %mid680 681f:682  %1 = call ptr @llvm.objc.retain(ptr %x) nounwind683  store i32 7, ptr %x684  br label %mid685 686mid:687  br i1 %q, label %u, label %g688 689u:690  call void @callee()691  call void @llvm.objc.release(ptr %x) nounwind692  br label %return693 694g:695  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0696  br label %return697 698return:699  ret void700}701 702; CHECK-LABEL: define void @test8d(703; CHECK: entry:704; CHECK: t:705; CHECK:   @llvm.objc.retain706; CHECK: f:707; CHECK:   @llvm.objc.retain708; CHECK: mid:709; CHECK: u:710; CHECK:   @llvm.objc.release711; CHECK: g:712; CHECK:   @llvm.objc.release713; CHECK: return:714; CHECK: {{^}}}715define void @test8d(ptr %x, i1 %p, i1 %q) nounwind {716entry:717  br i1 %p, label %t, label %f718 719t:720  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind721  store i8 3, ptr %x722  store float 2.0, ptr %x723  br label %mid724 725f:726  %1 = call ptr @llvm.objc.retain(ptr %x) nounwind727  store i32 7, ptr %x728  br label %mid729 730mid:731  br i1 %q, label %u, label %g732 733u:734  call void @callee()735  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !0736  br label %return737 738g:739  call void @llvm.objc.release(ptr %x) nounwind740  br label %return741 742return:743  ret void744}745 746; Trivial retain+release pair deletion.747 748; CHECK-LABEL: define void @test9(749; CHECK-NOT: @llvm.objc.750; CHECK: {{^}}}751define void @test9(ptr %x) nounwind {752entry:753  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind754  call void @llvm.objc.release(ptr %0) nounwind755  ret void756}757 758; Retain+release pair, but on an unknown pointer relationship. Don't delete!759 760; CHECK-LABEL: define void @test9b(761; CHECK: @llvm.objc.retain(ptr %x)762; CHECK: @llvm.objc.release(ptr %s)763; CHECK: {{^}}}764define void @test9b(ptr %x, i1 %j, ptr %p) nounwind {765entry:766  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind767  %s = select i1 %j, ptr %x, ptr %p768  call void @llvm.objc.release(ptr %s) nounwind769  ret void770}771 772; Trivial retain+release pair with intervening calls - don't delete!773 774; CHECK-LABEL: define void @test10(775; CHECK: @llvm.objc.retain(ptr %x)776; CHECK: @callee777; CHECK: @use_pointer778; CHECK: @llvm.objc.release779; CHECK: {{^}}}780define void @test10(ptr %x) nounwind {781entry:782  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind783  call void @callee()784  call void @use_pointer(ptr %x)785  call void @llvm.objc.release(ptr %0) nounwind786  ret void787}788 789; Trivial retain+autoreleaserelease pair. Don't delete!790; Also, add a tail keyword, since llvm.objc.retain can never be passed791; a stack argument.792 793; CHECK-LABEL: define void @test11(794; CHECK: tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]795; CHECK: call ptr @llvm.objc.autorelease(ptr %0) [[NUW]]796; CHECK: {{^}}}797define void @test11(ptr %x) nounwind {798entry:799  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind800  call ptr @llvm.objc.autorelease(ptr %0) nounwind801  call void @use_pointer(ptr %x)802  ret void803}804 805; Same as test11 but with no use_pointer call. Delete the pair!806 807; CHECK-LABEL: define void @test11a(808; CHECK: entry:809; CHECK-NEXT: ret void810; CHECK: {{^}}}811define void @test11a(ptr %x) nounwind {812entry:813  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind814  call ptr @llvm.objc.autorelease(ptr %0) nounwind815  ret void816}817 818; Same as test11 but the value is returned. Do not perform an RV optimization819; since if the frontend emitted code for an __autoreleasing variable, we may820; want it to be in the autorelease pool.821 822; CHECK-LABEL: define ptr @test11b(823; CHECK: tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]824; CHECK: call ptr @llvm.objc.autorelease(ptr %0) [[NUW]]825; CHECK: {{^}}}826define ptr @test11b(ptr %x) nounwind {827entry:828  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind829  call ptr @llvm.objc.autorelease(ptr %0) nounwind830  ret ptr %x831}832 833; We can not delete this retain, release since we do not have a post-dominating834; use of the release.835 836; CHECK-LABEL: define void @test12(837; CHECK-NEXT: entry:838; CHECK-NEXT: @llvm.objc.retain(ptr %x)839; CHECK-NEXT: @llvm.objc.retain840; CHECK: @llvm.objc.release841; CHECK: {{^}}}842define void @test12(ptr %x, i64 %n) {843entry:844  call ptr @llvm.objc.retain(ptr %x) nounwind845  call ptr @llvm.objc.retain(ptr %x) nounwind846  call void @use_pointer(ptr %x)847  call void @use_pointer(ptr %x)848  call void @llvm.objc.release(ptr %x) nounwind849  ret void850}851 852; Trivial retain,autorelease pair. Don't delete!853 854; CHECK-LABEL: define void @test13(855; CHECK: tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]856; CHECK: tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]857; CHECK: @use_pointer(ptr %x)858; CHECK: call ptr @llvm.objc.autorelease(ptr %x) [[NUW]]859; CHECK: {{^}}}860define void @test13(ptr %x, i64 %n) {861entry:862  call ptr @llvm.objc.retain(ptr %x) nounwind863  call ptr @llvm.objc.retain(ptr %x) nounwind864  call void @use_pointer(ptr %x)865  call ptr @llvm.objc.autorelease(ptr %x) nounwind866  ret void867}868 869; Delete the retain+release pair.870 871; CHECK-LABEL: define void @test13b(872; CHECK-NEXT: entry:873; CHECK-NEXT: @llvm.objc.retain(ptr %x)874; CHECK-NEXT: @use_pointer875; CHECK-NEXT: @use_pointer876; CHECK-NEXT: @use_pointer877; CHECK-NEXT: @llvm.objc.release878; CHECK-NEXT: ret void879; CHECK-NEXT: }880define void @test13b(ptr %x, i64 %n) {881entry:882  call ptr @llvm.objc.retain(ptr %x) nounwind883  call ptr @llvm.objc.retain(ptr %x) nounwind884  call void @use_pointer(ptr %x)885  call void @use_pointer(ptr %x)886  call void @llvm.objc.release(ptr %x) nounwind887  call void @use_pointer(ptr %x)888  call void @llvm.objc.release(ptr %x) nounwind889  ret void890}891 892; Don't delete the retain+release pair because there's an893; autoreleasePoolPop in the way.894 895; CHECK-LABEL: define void @test13c(896; CHECK: @llvm.objc.retain(ptr %x)897; CHECK: @llvm.objc.autoreleasePoolPop898; CHECK: @llvm.objc.retain(ptr %x)899; CHECK: @use_pointer900; CHECK: @llvm.objc.release901; CHECK: {{^}}}902define void @test13c(ptr %x, i64 %n) {903entry:904  call ptr @llvm.objc.retain(ptr %x) nounwind905  call void @llvm.objc.autoreleasePoolPop(ptr undef)906  call ptr @llvm.objc.retain(ptr %x) nounwind907  call void @use_pointer(ptr %x)908  call void @use_pointer(ptr %x)909  call void @llvm.objc.release(ptr %x) nounwind910  ret void911}912 913; Like test13c, but there's an autoreleasePoolPush in the way, but that914; doesn't matter.915 916; CHECK-LABEL: define void @test13d(917; CHECK-NEXT: entry:918; CHECK-NEXT: @llvm.objc.retain(ptr %x)919; CHECK-NEXT: @llvm.objc.autoreleasePoolPush920; CHECK-NEXT: @use_pointer921; CHECK-NEXT: @use_pointer922; CHECK-NEXT: @use_pointer923; CHECK-NEXT: @llvm.objc.release924; CHECK-NEXT: ret void925; CHECK-NEXT: }926define void @test13d(ptr %x, i64 %n) {927entry:928  call ptr @llvm.objc.retain(ptr %x) nounwind929  call ptr @llvm.objc.autoreleasePoolPush()930  call ptr @llvm.objc.retain(ptr %x) nounwind931  call void @use_pointer(ptr %x)932  call void @use_pointer(ptr %x)933  call void @llvm.objc.release(ptr %x) nounwind934  call void @use_pointer(ptr %x)935  call void @llvm.objc.release(ptr %x) nounwind936  ret void937}938 939; Trivial retain,release pair with intervening call, and it's post-dominated by940; another release. But it is not known safe in the top down direction. We can941; not eliminate it.942 943; CHECK-LABEL: define void @test14(944; CHECK-NEXT: entry:945; CHECK-NEXT: @llvm.objc.retain946; CHECK-NEXT: @use_pointer947; CHECK-NEXT: @use_pointer948; CHECK-NEXT: @llvm.objc.release949; CHECK-NEXT: @llvm.objc.release950; CHECK-NEXT: ret void951; CHECK-NEXT: }952define void @test14(ptr %x, i64 %n) {953entry:954  call ptr @llvm.objc.retain(ptr %x) nounwind955  call void @use_pointer(ptr %x)956  call void @use_pointer(ptr %x)957  call void @llvm.objc.release(ptr %x) nounwind958  call void @llvm.objc.release(ptr %x) nounwind959  ret void960}961 962; Trivial retain,autorelease pair with intervening call, but it's post-dominated963; by another release. Don't delete anything.964 965; CHECK-LABEL: define void @test15(966; CHECK-NEXT: entry:967; CHECK-NEXT: @llvm.objc.retain(ptr %x)968; CHECK-NEXT: @use_pointer969; CHECK-NEXT: @llvm.objc.autorelease(ptr %x)970; CHECK-NEXT: @llvm.objc.release971; CHECK-NEXT: ret void972; CHECK-NEXT: }973define void @test15(ptr %x, i64 %n) {974entry:975  call ptr @llvm.objc.retain(ptr %x) nounwind976  call void @use_pointer(ptr %x)977  call ptr @llvm.objc.autorelease(ptr %x) nounwind978  call void @llvm.objc.release(ptr %x) nounwind979  ret void980}981 982; Trivial retain,autorelease pair, post-dominated983; by another release. Delete the retain and release.984 985; CHECK-LABEL: define void @test15b(986; CHECK-NEXT: entry:987; CHECK-NEXT: @llvm.objc.retain988; CHECK-NEXT: @llvm.objc.autorelease989; CHECK-NEXT: @llvm.objc.release990; CHECK-NEXT: ret void991; CHECK-NEXT: }992define void @test15b(ptr %x, i64 %n) {993entry:994  call ptr @llvm.objc.retain(ptr %x) nounwind995  call ptr @llvm.objc.autorelease(ptr %x) nounwind996  call void @llvm.objc.release(ptr %x) nounwind997  ret void998}999 1000; CHECK-LABEL: define void @test15c(1001; CHECK-NEXT: entry:1002; CHECK-NEXT: @llvm.objc.autorelease1003; CHECK-NEXT: ret void1004; CHECK-NEXT: }1005define void @test15c(ptr %x, i64 %n) {1006entry:1007  call ptr @llvm.objc.retain(ptr %x) nounwind1008  call ptr @llvm.objc.autorelease(ptr %x) nounwind1009  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !01010  ret void1011}1012 1013; Retain+release pairs in diamonds, all dominated by a retain.1014 1015; CHECK-LABEL: define void @test16a(1016; CHECK: @llvm.objc.retain(ptr %x)1017; CHECK-NOT: @objc1018; CHECK: purple:1019; CHECK: @use_pointer1020; CHECK: @llvm.objc.release1021; CHECK: {{^}}}1022define void @test16a(i1 %a, i1 %b, ptr %x) {1023entry:1024  call ptr @llvm.objc.retain(ptr %x) nounwind1025  br i1 %a, label %red, label %orange1026 1027red:1028  call ptr @llvm.objc.retain(ptr %x) nounwind1029  br label %yellow1030 1031orange:1032  call ptr @llvm.objc.retain(ptr %x) nounwind1033  br label %yellow1034 1035yellow:1036  call void @use_pointer(ptr %x)1037  call void @use_pointer(ptr %x)1038  br i1 %b, label %green, label %blue1039 1040green:1041  call void @llvm.objc.release(ptr %x) nounwind1042  br label %purple1043 1044blue:1045  call void @llvm.objc.release(ptr %x) nounwind1046  br label %purple1047 1048purple:1049  call void @use_pointer(ptr %x)1050  call void @llvm.objc.release(ptr %x) nounwind1051  ret void1052}1053 1054; CHECK-LABEL: define void @test16b(1055; CHECK: @llvm.objc.retain(ptr %x)1056; CHECK-NOT: @objc1057; CHECK: purple:1058; CHECK-NEXT: @use_pointer1059; CHECK-NEXT: @use_pointer1060; CHECK-NEXT: @llvm.objc.release1061; CHECK: {{^}}}1062define void @test16b(i1 %a, i1 %b, ptr %x) {1063entry:1064  call ptr @llvm.objc.retain(ptr %x) nounwind1065  br i1 %a, label %red, label %orange1066 1067red:1068  call ptr @llvm.objc.retain(ptr %x) nounwind1069  br label %yellow1070 1071orange:1072  call ptr @llvm.objc.retain(ptr %x) nounwind1073  br label %yellow1074 1075yellow:1076  call void @use_pointer(ptr %x)1077  call void @use_pointer(ptr %x)1078  br i1 %b, label %green, label %blue1079 1080green:1081  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !01082  br label %purple1083 1084blue:1085  call void @llvm.objc.release(ptr %x) nounwind1086  br label %purple1087 1088purple:1089  call void @use_pointer(ptr %x)1090  call void @use_pointer(ptr %x)1091  call void @llvm.objc.release(ptr %x) nounwind1092  ret void1093}1094 1095; CHECK-LABEL: define void @test16c(1096; CHECK: @llvm.objc.retain(ptr %x)1097; CHECK-NOT: @objc1098; CHECK: purple:1099; CHECK: @use_pointer1100; CHECK: @llvm.objc.release1101; CHECK: {{^}}}1102define void @test16c(i1 %a, i1 %b, ptr %x) {1103entry:1104  call ptr @llvm.objc.retain(ptr %x) nounwind1105  br i1 %a, label %red, label %orange1106 1107red:1108  call ptr @llvm.objc.retain(ptr %x) nounwind1109  br label %yellow1110 1111orange:1112  call ptr @llvm.objc.retain(ptr %x) nounwind1113  br label %yellow1114 1115yellow:1116  call void @use_pointer(ptr %x)1117  call void @use_pointer(ptr %x)1118  br i1 %b, label %green, label %blue1119 1120green:1121  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !01122  br label %purple1123 1124blue:1125  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !01126  br label %purple1127 1128purple:1129  call void @use_pointer(ptr %x)1130  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !01131  ret void1132}1133 1134; CHECK-LABEL: define void @test16d(1135; CHECK: @llvm.objc.retain(ptr %x)1136; CHECK: @llvm.objc1137; CHECK: {{^}}}1138define void @test16d(i1 %a, i1 %b, ptr %x) {1139entry:1140  call ptr @llvm.objc.retain(ptr %x) nounwind1141  br i1 %a, label %red, label %orange1142 1143red:1144  call ptr @llvm.objc.retain(ptr %x) nounwind1145  br label %yellow1146 1147orange:1148  call ptr @llvm.objc.retain(ptr %x) nounwind1149  br label %yellow1150 1151yellow:1152  call void @use_pointer(ptr %x)1153  call void @use_pointer(ptr %x)1154  br i1 %b, label %green, label %blue1155 1156green:1157  call void @llvm.objc.release(ptr %x) nounwind1158  br label %purple1159 1160blue:1161  call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !01162  br label %purple1163 1164purple:1165  ret void1166}1167 1168; Delete no-ops.1169 1170; CHECK-LABEL: define void @test18(1171; CHECK-NOT: @llvm.objc.1172; CHECK: {{^}}}1173define void @test18() {1174  call ptr @llvm.objc.retain(ptr null)1175  call void @llvm.objc.release(ptr null)1176  call ptr @llvm.objc.autorelease(ptr null)1177  ret void1178}1179 1180; Delete no-ops where undef can be assumed to be null.1181 1182; CHECK-LABEL: define void @test18b(1183; CHECK-NOT: @llvm.objc.1184; CHECK: {{^}}}1185define void @test18b() {1186  call ptr @llvm.objc.retain(ptr undef)1187  call void @llvm.objc.release(ptr undef)1188  call ptr @llvm.objc.autorelease(ptr undef)1189  ret void1190}1191 1192; Replace uses of arguments with uses of return values, to reduce1193; register pressure.1194 1195; CHECK: define void @test19(ptr %y) {1196; CHECK:   %0 = tail call ptr @llvm.objc.retain(ptr %y)1197; CHECK:   call void @use_pointer(ptr %y)1198; CHECK:   call void @use_pointer(ptr %y)1199; CHECK:   call void @llvm.objc.release(ptr %y)1200; CHECK:   ret void1201; CHECK: {{^}}}1202define void @test19(ptr %y) {1203entry:1204  %0 = call ptr @llvm.objc.retain(ptr %y) nounwind1205  call void @use_pointer(ptr %y)1206  call void @use_pointer(ptr %y)1207  call void @llvm.objc.release(ptr %y)1208  ret void1209}1210 1211; Bitcast insertion1212 1213; CHECK-LABEL: define void @test20(1214; CHECK: %tmp1 = tail call ptr @llvm.objc.retain(ptr %self) [[NUW]]1215; CHECK-NEXT: invoke1216; CHECK: {{^}}}1217define void @test20(ptr %self) personality ptr @__gxx_personality_v0 {1218if.then12:1219  %tmp1 = call ptr @llvm.objc.retain(ptr %self) nounwind1220  invoke void @invokee()1221          to label %invoke.cont23 unwind label %lpad201222 1223invoke.cont23:                                    ; preds = %if.then121224  invoke void @invokee()1225          to label %if.end unwind label %lpad201226 1227lpad20:                                           ; preds = %invoke.cont23, %if.then121228  %tmp502 = phi ptr [ undef, %invoke.cont23 ], [ %self, %if.then12 ]1229  %exn = landingpad {ptr, i32}1230           cleanup1231  unreachable1232 1233if.end:                                           ; preds = %invoke.cont231234  ret void1235}1236 1237; Delete a redundant retain,autorelease when forwaring a call result1238; directly to a return value.1239 1240; CHECK-LABEL: define ptr @test21(1241; CHECK: call ptr @returner()1242; CHECK-NEXT: ret ptr %call1243; CHECK-NEXT: }1244define ptr @test21() {1245entry:1246  %call = call ptr @returner()1247  %0 = call ptr @llvm.objc.retain(ptr %call) nounwind1248  %1 = call ptr @llvm.objc.autorelease(ptr %0) nounwind1249  ret ptr %11250}1251 1252; Move an objc call up through a phi that has null operands.1253 1254; CHECK-LABEL: define void @test22(1255; CHECK: B:1256; CHECK:   call void @llvm.objc.release(ptr %p)1257; CHECK:   br label %C1258; CHECK: C:                                                ; preds = %B, %A1259; CHECK-NOT: @llvm.objc.release1260; CHECK: {{^}}}1261define void @test22(ptr %p, i1 %a) {1262  br i1 %a, label %A, label %B1263A:1264  br label %C1265B:1266  br label %C1267C:1268  %h = phi ptr [ null, %A ], [ %p, %B ]1269  call void @llvm.objc.release(ptr %h), !clang.imprecise_release !01270  ret void1271}1272 1273; Do not move an llvm.objc.release that doesn't have the clang.imprecise_release tag.1274 1275; CHECK-LABEL: define void @test22_precise(1276; CHECK: %[[P0:.*]] = phi ptr1277; CHECK: call void @llvm.objc.release(ptr %[[P0]])1278; CHECK: ret void1279define void @test22_precise(ptr %p, i1 %a) {1280  br i1 %a, label %A, label %B1281A:1282  br label %C1283B:1284  br label %C1285C:1286  %h = phi ptr [ null, %A ], [ %p, %B ]1287  call void @llvm.objc.release(ptr %h)1288  ret void1289}1290 1291; Any call can decrement a retain count.1292 1293; CHECK-LABEL: define void @test24(1294; CHECK: @llvm.objc.retain(ptr %a)1295; CHECK: @llvm.objc.release1296; CHECK: {{^}}}1297define void @test24(ptr %r, ptr %a) {1298  call ptr @llvm.objc.retain(ptr %a)1299  call void @use_pointer(ptr %r)1300  %q = load i8, ptr %a1301  call void @llvm.objc.release(ptr %a)1302  ret void1303}1304 1305; Don't move a retain/release pair if the release can be moved1306; but the retain can't be moved to balance it.1307 1308; CHECK-LABEL: define void @test25(1309; CHECK: entry:1310; CHECK:   call ptr @llvm.objc.retain(ptr %p)1311; CHECK: true:1312; CHECK: done:1313; CHECK:   call void @llvm.objc.release(ptr %p)1314; CHECK: {{^}}}1315define void @test25(ptr %p, i1 %x) {1316entry:1317  %f0 = call ptr @llvm.objc.retain(ptr %p)1318  call void @callee()1319  br i1 %x, label %true, label %done1320 1321true:1322  store i8 0, ptr %p1323  br label %done1324 1325done:1326  call void @llvm.objc.release(ptr %p)1327  ret void1328}1329 1330; Don't move a retain/release pair if the retain can be moved1331; but the release can't be moved to balance it.1332 1333; CHECK-LABEL: define void @test26(1334; CHECK: entry:1335; CHECK:   call ptr @llvm.objc.retain(ptr %p)1336; CHECK: true:1337; CHECK: done:1338; CHECK:   call void @llvm.objc.release(ptr %p)1339; CHECK: {{^}}}1340define void @test26(ptr %p, i1 %x) {1341entry:1342  %f0 = call ptr @llvm.objc.retain(ptr %p)1343  br i1 %x, label %true, label %done1344 1345true:1346  call void @callee()1347  br label %done1348 1349done:1350  store i8 0, ptr %p1351  call void @llvm.objc.release(ptr %p)1352  ret void1353}1354 1355; Don't sink the retain,release into the loop.1356 1357; CHECK-LABEL: define void @test27(1358; CHECK: entry:1359; CHECK: call ptr @llvm.objc.retain(ptr %p)1360; CHECK: loop:1361; CHECK-NOT: @llvm.objc.1362; CHECK: done:1363; CHECK: call void @llvm.objc.release1364; CHECK: {{^}}}1365define void @test27(ptr %p, i1 %x, i1 %y) {1366entry:1367  %f0 = call ptr @llvm.objc.retain(ptr %p)1368  br i1 %x, label %loop, label %done1369 1370loop:1371  call void @callee()1372  store i8 0, ptr %p1373  br i1 %y, label %done, label %loop1374 1375done:1376  call void @llvm.objc.release(ptr %p)1377  ret void1378}1379 1380; Trivial code motion case: Triangle.1381 1382; CHECK-LABEL: define void @test28(1383; CHECK-NOT: @llvm.objc.1384; CHECK: true:1385; CHECK: call ptr @llvm.objc.retain1386; CHECK: call void @callee()1387; CHECK: store1388; CHECK: call void @llvm.objc.release1389; CHECK: done:1390; CHECK-NOT: @llvm.objc.1391; CHECK: {{^}}}1392define void @test28(ptr %p, i1 %x) {1393entry:1394  %f0 = call ptr @llvm.objc.retain(ptr %p)1395  br i1 %x, label %true, label %done1396 1397true:1398  call void @callee()1399  store i8 0, ptr %p1400  br label %done1401 1402done:1403  call void @llvm.objc.release(ptr %p), !clang.imprecise_release !01404  ret void1405}1406 1407; Trivial code motion case: Triangle, but no metadata. Don't move past1408; unrelated memory references!1409 1410; CHECK-LABEL: define void @test28b(1411; CHECK: call ptr @llvm.objc.retain1412; CHECK: true:1413; CHECK-NOT: @llvm.objc.1414; CHECK: call void @callee()1415; CHECK-NOT: @llvm.objc.1416; CHECK: store1417; CHECK-NOT: @llvm.objc.1418; CHECK: done:1419; CHECK: @llvm.objc.release1420; CHECK: {{^}}}1421define void @test28b(ptr %p, i1 %x, ptr noalias %t) {1422entry:1423  %f0 = call ptr @llvm.objc.retain(ptr %p)1424  br i1 %x, label %true, label %done1425 1426true:1427  call void @callee()1428  store i8 0, ptr %p1429  br label %done1430 1431done:1432  store i8 0, ptr %t1433  call void @llvm.objc.release(ptr %p)1434  ret void1435}1436 1437; Trivial code motion case: Triangle, with metadata. Do move past1438; unrelated memory references! And preserve the metadata.1439 1440; CHECK-LABEL: define void @test28c(1441; CHECK-NOT: @llvm.objc.1442; CHECK: true:1443; CHECK: call ptr @llvm.objc.retain1444; CHECK: call void @callee()1445; CHECK: store1446; CHECK: call void @llvm.objc.release(ptr %p) [[NUW]], !clang.imprecise_release1447; CHECK: done:1448; CHECK-NOT: @llvm.objc.1449; CHECK: {{^}}}1450define void @test28c(ptr %p, i1 %x, ptr noalias %t) {1451entry:1452  %f0 = call ptr @llvm.objc.retain(ptr %p)1453  br i1 %x, label %true, label %done1454 1455true:1456  call void @callee()1457  store i8 0, ptr %p1458  br label %done1459 1460done:1461  store i8 0, ptr %t1462  call void @llvm.objc.release(ptr %p), !clang.imprecise_release !01463  ret void1464}1465 1466; Like test28. but with two releases.1467 1468; CHECK-LABEL: define void @test29(1469; CHECK: call ptr @llvm.objc.retain1470; CHECK: true:1471; CHECK: call void @callee()1472; CHECK: store1473; CHECK: done:1474; CHECK: call void @llvm.objc.release1475; CHECK: ohno:1476; CHECK: call void @llvm.objc.release1477; CHECK: {{^}}}1478define void @test29(ptr %p, i1 %x, i1 %y) {1479entry:1480  %f0 = call ptr @llvm.objc.retain(ptr %p)1481  br i1 %x, label %true, label %done1482 1483true:1484  call void @callee()1485  store i8 0, ptr %p1486  br i1 %y, label %done, label %ohno1487 1488done:1489  call void @llvm.objc.release(ptr %p)1490  ret void1491 1492ohno:1493  call void @llvm.objc.release(ptr %p)1494  ret void1495}1496 1497; Basic case with the use and call in a diamond1498; with an extra release.1499 1500; CHECK-LABEL: define void @test30(1501; CHECK: call ptr @llvm.objc.retain1502; CHECK: true:1503; CHECK: call void @callee()1504; CHECK: store1505; CHECK: false:1506; CHECK: done:1507; CHECK: call void @llvm.objc.release1508; CHECK: ohno:1509; CHECK: call void @llvm.objc.release1510; CHECK: {{^}}}1511define void @test30(ptr %p, i1 %x, i1 %y, i1 %z) {1512entry:1513  %f0 = call ptr @llvm.objc.retain(ptr %p)1514  br i1 %x, label %true, label %false1515 1516true:1517  call void @callee()1518  store i8 0, ptr %p1519  br i1 %y, label %done, label %ohno1520 1521false:1522  br i1 %z, label %done, label %ohno1523 1524done:1525  call void @llvm.objc.release(ptr %p)1526  ret void1527 1528ohno:1529  call void @llvm.objc.release(ptr %p)1530  ret void1531}1532 1533; Basic case with a mergeable release.1534 1535; CHECK-LABEL: define void @test31(1536; CHECK: call ptr @llvm.objc.retain(ptr %p)1537; CHECK: call void @callee()1538; CHECK: store1539; CHECK: true:1540; CHECK: call void @llvm.objc.release1541; CHECK: false:1542; CHECK: call void @llvm.objc.release1543; CHECK: ret void1544; CHECK: {{^}}}1545define void @test31(ptr %p, i1 %x) {1546entry:1547  %f0 = call ptr @llvm.objc.retain(ptr %p)1548  call void @callee()1549  store i8 0, ptr %p1550  br i1 %x, label %true, label %false1551true:1552  call void @llvm.objc.release(ptr %p)1553  ret void1554false:1555  call void @llvm.objc.release(ptr %p)1556  ret void1557}1558 1559; Don't consider bitcasts or getelementptrs direct uses.1560 1561; CHECK-LABEL: define void @test32(1562; CHECK: call ptr @llvm.objc.retain1563; CHECK: true:1564; CHECK: call void @callee()1565; CHECK: store1566; CHECK: done:1567; CHECK: call void @llvm.objc.release1568; CHECK: {{^}}}1569define void @test32(ptr %p, i1 %x) {1570entry:1571  %f0 = call ptr @llvm.objc.retain(ptr %p)1572  br i1 %x, label %true, label %done1573 1574true:1575  call void @callee()1576  store i8 0, ptr %p1577  br label %done1578 1579done:1580  call void @llvm.objc.release(ptr %p)1581  ret void1582}1583 1584; Do consider icmps to be direct uses.1585 1586; CHECK-LABEL: define void @test33(1587; CHECK: call ptr @llvm.objc.retain1588; CHECK: true:1589; CHECK: call void @callee()1590; CHECK: icmp1591; CHECK: done:1592; CHECK: call void @llvm.objc.release1593; CHECK: {{^}}}1594define void @test33(ptr %p, i1 %x, ptr %y) {1595entry:1596  %f0 = call ptr @llvm.objc.retain(ptr %p)1597  br i1 %x, label %true, label %done1598 1599true:1600  call void @callee()1601  %v = icmp eq ptr %p, %y1602  br label %done1603 1604done:1605  call void @llvm.objc.release(ptr %p)1606  ret void1607}1608 1609; Delete retain,release if there's just a possible dec and we have imprecise1610; releases.1611 1612; CHECK-LABEL: define void @test34a(1613; CHECK:   call ptr @llvm.objc.retain1614; CHECK: true:1615; CHECK: done:1616; CHECK: call void @llvm.objc.release1617; CHECK: {{^}}}1618define void @test34a(ptr %p, i1 %x, ptr %y) {1619entry:1620  %f0 = call ptr @llvm.objc.retain(ptr %p)1621  br i1 %x, label %true, label %done1622 1623true:1624  call void @callee()1625  br label %done1626 1627done:1628  call void @llvm.objc.release(ptr %p)1629  ret void1630}1631 1632; CHECK-LABEL: define void @test34b(1633; CHECK-NOT: @llvm.objc.1634; CHECK: {{^}}}1635define void @test34b(ptr %p, i1 %x, ptr %y) {1636entry:1637  %f0 = call ptr @llvm.objc.retain(ptr %p)1638  br i1 %x, label %true, label %done1639 1640true:1641  call void @callee()1642  br label %done1643 1644done:1645  call void @llvm.objc.release(ptr %p), !clang.imprecise_release !01646  ret void1647}1648 1649 1650; Delete retain,release if there's just a use and we do not have a precise1651; release.1652 1653; Precise.1654; CHECK-LABEL: define void @test35a(1655; CHECK: entry:1656; CHECK:   call ptr @llvm.objc.retain1657; CHECK: true:1658; CHECK: done:1659; CHECK:   call void @llvm.objc.release1660; CHECK: {{^}}}1661define void @test35a(ptr %p, i1 %x, ptr %y) {1662entry:1663  %f0 = call ptr @llvm.objc.retain(ptr %p)1664  br i1 %x, label %true, label %done1665 1666true:1667  %v = icmp eq ptr %p, %y1668  br label %done1669 1670done:1671  call void @llvm.objc.release(ptr %p)1672  ret void1673}1674 1675; Imprecise.1676; CHECK-LABEL: define void @test35b(1677; CHECK-NOT: @llvm.objc.1678; CHECK: {{^}}}1679define void @test35b(ptr %p, i1 %x, ptr %y) {1680entry:1681  %f0 = call ptr @llvm.objc.retain(ptr %p)1682  br i1 %x, label %true, label %done1683 1684true:1685  %v = icmp eq ptr %p, %y1686  br label %done1687 1688done:1689  call void @llvm.objc.release(ptr %p), !clang.imprecise_release !01690  ret void1691}1692 1693; Delete a retain,release if there's no actual use and we have precise release.1694 1695; CHECK-LABEL: define void @test36a(1696; CHECK: @llvm.objc.retain1697; CHECK: call void @callee()1698; CHECK-NOT: @llvm.objc.1699; CHECK: call void @callee()1700; CHECK: @llvm.objc.release1701; CHECK: {{^}}}1702define void @test36a(ptr %p) {1703entry:1704  call ptr @llvm.objc.retain(ptr %p)1705  call void @callee()1706  call void @callee()1707  call void @llvm.objc.release(ptr %p)1708  ret void1709}1710 1711; Like test36, but with metadata.1712 1713; CHECK-LABEL: define void @test36b(1714; CHECK-NOT: @llvm.objc.1715; CHECK: {{^}}}1716define void @test36b(ptr %p) {1717entry:1718  call ptr @llvm.objc.retain(ptr %p)1719  call void @callee()1720  call void @callee()1721  call void @llvm.objc.release(ptr %p), !clang.imprecise_release !01722  ret void1723}1724 1725; Be aggressive about analyzing phis to eliminate possible uses.1726 1727; CHECK-LABEL: define void @test38(1728; CHECK-NOT: @llvm.objc.1729; CHECK: {{^}}}1730define void @test38(ptr %p, i1 %u, i1 %m, ptr %z, ptr %y, ptr %x, ptr %w) {1731entry:1732  call ptr @llvm.objc.retain(ptr %p)1733  br i1 %u, label %true, label %false1734true:1735  br i1 %m, label %a, label %b1736false:1737  br i1 %m, label %c, label %d1738a:1739  br label %e1740b:1741  br label %e1742c:1743  br label %f1744d:1745  br label %f1746e:1747  %j = phi ptr [ %z, %a ], [ %y, %b ]1748  br label %g1749f:1750  %k = phi ptr [ %w, %c ], [ %x, %d ]1751  br label %g1752g:1753  %h = phi ptr [ %j, %e ], [ %k, %f ]1754  call void @use_pointer(ptr %h)1755  call void @llvm.objc.release(ptr %p), !clang.imprecise_release !01756  ret void1757}1758 1759; Delete retain,release pairs around loops.1760 1761; CHECK-LABEL: define void @test39(1762; CHECK-NOT: @llvm.objc.1763; CHECK: {{^}}}1764define void @test39(ptr %p, i1 %arg) {1765entry:1766  %0 = call ptr @llvm.objc.retain(ptr %p)1767  br label %loop1768 1769loop:                                             ; preds = %loop, %entry1770  br i1 %arg, label %loop, label %exit1771 1772exit:                                             ; preds = %loop1773  call void @llvm.objc.release(ptr %0), !clang.imprecise_release !01774  ret void1775}1776 1777; Delete retain,release pairs around loops containing uses.1778 1779; CHECK-LABEL: define void @test39b(1780; CHECK-NOT: @llvm.objc.1781; CHECK: {{^}}}1782define void @test39b(ptr %p, i1 %arg) {1783entry:1784  %0 = call ptr @llvm.objc.retain(ptr %p)1785  br label %loop1786 1787loop:                                             ; preds = %loop, %entry1788  store i8 0, ptr %01789  br i1 %arg, label %loop, label %exit1790 1791exit:                                             ; preds = %loop1792  call void @llvm.objc.release(ptr %0), !clang.imprecise_release !01793  ret void1794}1795 1796; Delete retain,release pairs around loops containing potential decrements.1797 1798; CHECK-LABEL: define void @test39c(1799; CHECK-NOT: @llvm.objc.1800; CHECK: {{^}}}1801define void @test39c(ptr %p, i1 %arg) {1802entry:1803  %0 = call ptr @llvm.objc.retain(ptr %p)1804  br label %loop1805 1806loop:                                             ; preds = %loop, %entry1807  call void @use_pointer(ptr %0)1808  br i1 %arg, label %loop, label %exit1809 1810exit:                                             ; preds = %loop1811  call void @llvm.objc.release(ptr %0), !clang.imprecise_release !01812  ret void1813}1814 1815; Delete retain,release pairs around loops even if1816; the successors are in a different order.1817 1818; CHECK-LABEL: define void @test40(1819; CHECK-NOT: @llvm.objc.1820; CHECK: {{^}}}1821define void @test40(ptr %p, i1 %arg) {1822entry:1823  %0 = call ptr @llvm.objc.retain(ptr %p)1824  br label %loop1825 1826loop:                                             ; preds = %loop, %entry1827  call void @use_pointer(ptr %0)1828  br i1 %arg, label %exit, label %loop1829 1830exit:                                             ; preds = %loop1831  call void @llvm.objc.release(ptr %0), !clang.imprecise_release !01832  ret void1833}1834 1835; Do the known-incremented retain+release elimination even if the pointer1836; is also autoreleased.1837 1838; CHECK-LABEL: define void @test42(1839; CHECK-NEXT: entry:1840; CHECK-NEXT: call ptr @llvm.objc.retain(ptr %p)1841; CHECK-NEXT: call ptr @llvm.objc.autorelease(ptr %p)1842; CHECK-NEXT: call void @use_pointer(ptr %p)1843; CHECK-NEXT: call void @use_pointer(ptr %p)1844; CHECK-NEXT: call void @use_pointer(ptr %p)1845; CHECK-NEXT: call void @use_pointer(ptr %p)1846; CHECK-NEXT: call void @llvm.objc.release(ptr %p)1847; CHECK-NEXT: ret void1848; CHECK-NEXT: }1849define void @test42(ptr %p) {1850entry:1851  call ptr @llvm.objc.retain(ptr %p)1852  call ptr @llvm.objc.autorelease(ptr %p)1853  call ptr @llvm.objc.retain(ptr %p)1854  call void @use_pointer(ptr %p)1855  call void @use_pointer(ptr %p)1856  call void @llvm.objc.release(ptr %p)1857  call void @use_pointer(ptr %p)1858  call void @use_pointer(ptr %p)1859  call void @llvm.objc.release(ptr %p)1860  ret void1861}1862 1863; Don't the known-incremented retain+release elimination if the pointer is1864; autoreleased and there's an autoreleasePoolPop.1865 1866; CHECK-LABEL: define void @test43(1867; CHECK-NEXT: entry:1868; CHECK-NEXT: call ptr @llvm.objc.retain(ptr %p)1869; CHECK-NEXT: call ptr @llvm.objc.autorelease(ptr %p)1870; CHECK-NEXT: call ptr @llvm.objc.retain1871; CHECK-NEXT: call void @use_pointer(ptr %p)1872; CHECK-NEXT: call void @use_pointer(ptr %p)1873; CHECK-NEXT: call void @llvm.objc.autoreleasePoolPop(ptr undef)1874; CHECK-NEXT: call void @llvm.objc.release1875; CHECK-NEXT: ret void1876; CHECK-NEXT: }1877define void @test43(ptr %p) {1878entry:1879  call ptr @llvm.objc.retain(ptr %p)1880  call ptr @llvm.objc.autorelease(ptr %p)1881  call ptr @llvm.objc.retain(ptr %p)1882  call void @use_pointer(ptr %p)1883  call void @use_pointer(ptr %p)1884  call void @llvm.objc.autoreleasePoolPop(ptr undef)1885  call void @llvm.objc.release(ptr %p)1886  ret void1887}1888 1889; Do the known-incremented retain+release elimination if the pointer is1890; autoreleased and there's an autoreleasePoolPush.1891 1892; CHECK-LABEL: define void @test43b(1893; CHECK-NEXT: entry:1894; CHECK-NEXT: call ptr @llvm.objc.retain(ptr %p)1895; CHECK-NEXT: call ptr @llvm.objc.autorelease(ptr %p)1896; CHECK-NEXT: call void @use_pointer(ptr %p)1897; CHECK-NEXT: call void @use_pointer(ptr %p)1898; CHECK-NEXT: call ptr @llvm.objc.autoreleasePoolPush()1899; CHECK-NEXT: call void @use_pointer(ptr %p)1900; CHECK-NEXT: call void @llvm.objc.release1901; CHECK-NEXT: ret void1902; CHECK-NEXT: }1903define void @test43b(ptr %p) {1904entry:1905  call ptr @llvm.objc.retain(ptr %p)1906  call ptr @llvm.objc.autorelease(ptr %p)1907  call ptr @llvm.objc.retain(ptr %p)1908  call void @use_pointer(ptr %p)1909  call void @use_pointer(ptr %p)1910  call ptr @llvm.objc.autoreleasePoolPush()1911  call void @llvm.objc.release(ptr %p)1912  call void @use_pointer(ptr %p)1913  call void @llvm.objc.release(ptr %p)1914  ret void1915}1916 1917; Do retain+release elimination for non-provenance pointers.1918 1919; CHECK-LABEL: define void @test44(1920; CHECK-NOT: llvm.objc.1921; CHECK: {{^}}}1922define void @test44(ptr %pp) {1923  %p = load ptr, ptr %pp1924  %q = call ptr @llvm.objc.retain(ptr %p)1925  call void @llvm.objc.release(ptr %q)1926  ret void1927}1928 1929; Don't delete retain+release with an unknown-provenance1930; may-alias llvm.objc.release between them.1931 1932; CHECK-LABEL: define void @test45(1933; CHECK: call ptr @llvm.objc.retain(ptr %p)1934; CHECK: call void @llvm.objc.release(ptr %q)1935; CHECK: call void @use_pointer(ptr %p)1936; CHECK: call void @llvm.objc.release(ptr %p)1937; CHECK: {{^}}}1938define void @test45(ptr %pp, ptr %qq) {1939  %p = load ptr, ptr %pp1940  %q = load ptr, ptr %qq1941  call ptr @llvm.objc.retain(ptr %p)1942  call void @llvm.objc.release(ptr %q)1943  call void @use_pointer(ptr %p)1944  call void @llvm.objc.release(ptr %p)1945  ret void1946}1947 1948; Don't delete retain and autorelease here.1949 1950; CHECK-LABEL: define void @test46(1951; CHECK: tail call ptr @llvm.objc.retain(ptr %p) [[NUW]]1952; CHECK: true:1953; CHECK: call ptr @llvm.objc.autorelease(ptr %p) [[NUW]]1954; CHECK: {{^}}}1955define void @test46(ptr %p, i1 %a) {1956entry:1957  call ptr @llvm.objc.retain(ptr %p)1958  br i1 %a, label %true, label %false1959 1960true:1961  call ptr @llvm.objc.autorelease(ptr %p)1962  call void @use_pointer(ptr %p)1963  ret void1964 1965false:1966  ret void1967}1968 1969; Delete no-op cast calls.1970 1971; CHECK-LABEL: define ptr @test47(1972; CHECK-NOT: call1973; CHECK: ret ptr %p1974; CHECK: {{^}}}1975define ptr @test47(ptr %p) nounwind {1976  %x = call ptr @llvm.objc.retainedObject(ptr %p)1977  ret ptr %x1978}1979 1980; Delete no-op cast calls.1981 1982; CHECK-LABEL: define ptr @test48(1983; CHECK-NOT: call1984; CHECK: ret ptr %p1985; CHECK: {{^}}}1986define ptr @test48(ptr %p) nounwind {1987  %x = call ptr @llvm.objc.unretainedObject(ptr %p)1988  ret ptr %x1989}1990 1991; Delete no-op cast calls.1992 1993; CHECK-LABEL: define ptr @test49(1994; CHECK-NOT: call1995; CHECK: ret ptr %p1996; CHECK: {{^}}}1997define ptr @test49(ptr %p) nounwind {1998  %x = call ptr @llvm.objc.unretainedPointer(ptr %p)1999  ret ptr %x2000}2001 2002; Do delete retain+release with intervening stores of the address value if we2003; have imprecise release attached to llvm.objc.release.2004 2005; CHECK-LABEL:      define void @test50a(2006; CHECK-NEXT:   call ptr @llvm.objc.retain2007; CHECK-NEXT:   call void @callee2008; CHECK-NEXT:   store2009; CHECK-NEXT:   call void @llvm.objc.release2010; CHECK-NEXT:   ret void2011; CHECK-NEXT: }2012define void @test50a(ptr %p, ptr %pp) {2013  call ptr @llvm.objc.retain(ptr %p)2014  call void @callee()2015  store ptr %p, ptr %pp2016  call void @llvm.objc.release(ptr %p)2017  ret void2018}2019 2020; CHECK-LABEL: define void @test50b(2021; CHECK-NOT: @llvm.objc.2022; CHECK: {{^}}}2023define void @test50b(ptr %p, ptr %pp) {2024  call ptr @llvm.objc.retain(ptr %p)2025  call void @callee()2026  store ptr %p, ptr %pp2027  call void @llvm.objc.release(ptr %p), !clang.imprecise_release !02028  ret void2029}2030 2031 2032; Don't delete retain+release with intervening stores through the2033; address value.2034 2035; CHECK-LABEL: define void @test51a(2036; CHECK: call ptr @llvm.objc.retain(ptr %p)2037; CHECK: call void @llvm.objc.release(ptr %p)2038; CHECK: ret void2039; CHECK: {{^}}}2040define void @test51a(ptr %p) {2041  call ptr @llvm.objc.retain(ptr %p)2042  call void @callee()2043  store i8 0, ptr %p2044  call void @llvm.objc.release(ptr %p)2045  ret void2046}2047 2048; CHECK-LABEL: define void @test51b(2049; CHECK: call ptr @llvm.objc.retain(ptr %p)2050; CHECK: call void @llvm.objc.release(ptr %p)2051; CHECK: ret void2052; CHECK: {{^}}}2053define void @test51b(ptr %p) {2054  call ptr @llvm.objc.retain(ptr %p)2055  call void @callee()2056  store i8 0, ptr %p2057  call void @llvm.objc.release(ptr %p), !clang.imprecise_release !02058  ret void2059}2060 2061; Don't delete retain+release with intervening use of a pointer of2062; unknown provenance.2063 2064; CHECK-LABEL: define void @test52a(2065; CHECK: call ptr @llvm.objc.retain2066; CHECK: call void @callee()2067; CHECK: call void @use_pointer(ptr %z)2068; CHECK: call void @llvm.objc.release2069; CHECK: ret void2070; CHECK: {{^}}}2071define void @test52a(ptr %zz, ptr %pp) {2072  %p = load ptr, ptr %pp2073  %1 = call ptr @llvm.objc.retain(ptr %p)2074  call void @callee()2075  %z = load ptr, ptr %zz2076  call void @use_pointer(ptr %z)2077  call void @llvm.objc.release(ptr %p)2078  ret void2079}2080 2081; CHECK-LABEL: define void @test52b(2082; CHECK: call ptr @llvm.objc.retain2083; CHECK: call void @callee()2084; CHECK: call void @use_pointer(ptr %z)2085; CHECK: call void @llvm.objc.release2086; CHECK: ret void2087; CHECK: {{^}}}2088define void @test52b(ptr %zz, ptr %pp) {2089  %p = load ptr, ptr %pp2090  %1 = call ptr @llvm.objc.retain(ptr %p)2091  call void @callee()2092  %z = load ptr, ptr %zz2093  call void @use_pointer(ptr %z)2094  call void @llvm.objc.release(ptr %p), !clang.imprecise_release !02095  ret void2096}2097 2098; Like test52, but the pointer has function type, so it's assumed to2099; be not reference counted.2100; Oops. That's wrong. Clang sometimes uses function types gratuitously.2101; See rdar://10551239.2102 2103; CHECK-LABEL: define void @test53(2104; CHECK: @llvm.objc.2105; CHECK: {{^}}}2106define void @test53(ptr %zz, ptr %pp) {2107  %p = load ptr, ptr %pp2108  %1 = call ptr @llvm.objc.retain(ptr %p)2109  call void @callee()2110  %z = load ptr, ptr %zz2111  call void @callee_fnptr(ptr %z)2112  call void @llvm.objc.release(ptr %p)2113  ret void2114}2115 2116; Convert autorelease to release if the value is unused.2117 2118; CHECK-LABEL: define void @test54(2119; CHECK: call ptr @returner()2120; CHECK-NEXT: call void @llvm.objc.release(ptr %t) [[NUW]], !clang.imprecise_release ![[RELEASE]]2121; CHECK-NEXT: ret void2122; CHECK: {{^}}}2123define void @test54() {2124  %t = call ptr @returner()2125  call ptr @llvm.objc.autorelease(ptr %t)2126  ret void2127}2128 2129; Nested retain+release pairs. Delete them both.2130 2131; CHECK-LABEL: define void @test55(2132; CHECK-NOT: @objc2133; CHECK: {{^}}}2134define void @test55(ptr %x) {2135entry:2136  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind2137  %1 = call ptr @llvm.objc.retain(ptr %x) nounwind2138  call void @llvm.objc.release(ptr %x) nounwind2139  call void @llvm.objc.release(ptr %x) nounwind2140  ret void2141}2142 2143; Nested retain+release pairs where the inner pair depends2144; on the outer pair to be removed, and then the outer pair2145; can be partially eliminated. Plus an extra outer pair to2146; eliminate, for fun.2147 2148; CHECK-LABEL: define void @test56(2149; CHECK-NOT: @objc2150; CHECK: if.then:2151; CHECK-NEXT: %0 = tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]2152; CHECK-NEXT: tail call void @use_pointer(ptr %x)2153; CHECK-NEXT: tail call void @use_pointer(ptr %x)2154; CHECK-NEXT: tail call void @llvm.objc.release(ptr %x) [[NUW]], !clang.imprecise_release ![[RELEASE]]2155; CHECK-NEXT: br label %if.end2156; CHECK-NOT: @objc2157; CHECK: {{^}}}2158define void @test56(ptr %x, i32 %n) {2159entry:2160  %0 = tail call ptr @llvm.objc.retain(ptr %x) nounwind2161  %1 = tail call ptr @llvm.objc.retain(ptr %0) nounwind2162  %tobool = icmp eq i32 %n, 02163  br i1 %tobool, label %if.end, label %if.then2164 2165if.then:                                          ; preds = %entry2166  %2 = tail call ptr @llvm.objc.retain(ptr %1) nounwind2167  tail call void @use_pointer(ptr %2)2168  tail call void @use_pointer(ptr %2)2169  tail call void @llvm.objc.release(ptr %2) nounwind, !clang.imprecise_release !02170  br label %if.end2171 2172if.end:                                           ; preds = %entry, %if.then2173  tail call void @llvm.objc.release(ptr %1) nounwind, !clang.imprecise_release !02174  tail call void @llvm.objc.release(ptr %0) nounwind, !clang.imprecise_release !02175  ret void2176}2177 2178; When there are adjacent retain+release pairs, the first one is known2179; unnecessary because the presence of the second one means that the first one2180; won't be deleting the object.2181 2182; CHECK-LABEL:      define void @test57(2183; CHECK-NEXT: entry:2184; CHECK-NEXT:   tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]2185; CHECK-NEXT:   call void @use_pointer(ptr %x)2186; CHECK-NEXT:   call void @use_pointer(ptr %x)2187; CHECK-NEXT:   tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]2188; CHECK-NEXT:   call void @use_pointer(ptr %x)2189; CHECK-NEXT:   call void @use_pointer(ptr %x)2190; CHECK-NEXT:   call void @llvm.objc.release(ptr %x) [[NUW]]2191; CHECK-NEXT:   ret void2192; CHECK-NEXT: }2193define void @test57(ptr %x) nounwind {2194entry:2195  call ptr @llvm.objc.retain(ptr %x) nounwind2196  call ptr @llvm.objc.retain(ptr %x) nounwind2197  call void @use_pointer(ptr %x)2198  call void @use_pointer(ptr %x)2199  call void @llvm.objc.release(ptr %x) nounwind2200  call ptr @llvm.objc.retain(ptr %x) nounwind2201  call void @use_pointer(ptr %x)2202  call void @use_pointer(ptr %x)2203  call void @llvm.objc.release(ptr %x) nounwind2204  ret void2205}2206 2207; An adjacent retain+release pair is sufficient even if it will be2208; removed itself.2209 2210; CHECK-LABEL:      define void @test58(2211; CHECK-NEXT: entry:2212; CHECK-NEXT:   @llvm.objc.retain2213; CHECK-NEXT:   call void @use_pointer(ptr %x)2214; CHECK-NEXT:   call void @use_pointer(ptr %x)2215; CHECK-NEXT:   ret void2216; CHECK-NEXT: }2217define void @test58(ptr %x) nounwind {2218entry:2219  call ptr @llvm.objc.retain(ptr %x) nounwind2220  call ptr @llvm.objc.retain(ptr %x) nounwind2221  call void @use_pointer(ptr %x)2222  call void @use_pointer(ptr %x)2223  call void @llvm.objc.release(ptr %x) nounwind2224  call ptr @llvm.objc.retain(ptr %x) nounwind2225  call void @llvm.objc.release(ptr %x) nounwind2226  ret void2227}2228 2229; Don't delete the second retain+release pair in an adjacent set.2230 2231; CHECK-LABEL:      define void @test59(2232; CHECK-NEXT: entry:2233; CHECK-NEXT:   %0 = tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]2234; CHECK-NEXT:   call void @use_pointer(ptr %x)2235; CHECK-NEXT:   call void @use_pointer(ptr %x)2236; CHECK-NEXT:   call void @llvm.objc.release(ptr %x) [[NUW]]2237; CHECK-NEXT:   ret void2238; CHECK-NEXT: }2239define void @test59(ptr %x) nounwind {2240entry:2241  %a = call ptr @llvm.objc.retain(ptr %x) nounwind2242  call void @llvm.objc.release(ptr %x) nounwind2243  %b = call ptr @llvm.objc.retain(ptr %x) nounwind2244  call void @use_pointer(ptr %x)2245  call void @use_pointer(ptr %x)2246  call void @llvm.objc.release(ptr %x) nounwind2247  ret void2248}2249 2250; Constant pointers to objects don't need reference counting.2251 2252@constptr = external constant ptr2253@something = external global ptr2254 2255; We have a precise lifetime retain/release here. We can not remove them since2256; @something is not constant.2257 2258; CHECK-LABEL: define void @test60a(2259; CHECK: call ptr @llvm.objc.retain2260; CHECK: call void @llvm.objc.release2261; CHECK: {{^}}}2262define void @test60a() {2263  %t = load ptr, ptr @constptr2264  %s = load ptr, ptr @something2265  call ptr @llvm.objc.retain(ptr %s)2266  call void @callee()2267  call void @use_pointer(ptr %t)2268  call void @llvm.objc.release(ptr %s)2269  ret void2270}2271 2272; CHECK-LABEL: define void @test60b(2273; CHECK: call ptr @llvm.objc.retain2274; CHECK-NOT: call ptr @llvm.objc.retain2275; CHECK-NOT: call ptr @llvm.objc.release2276; CHECK: {{^}}}2277define void @test60b() {2278  %t = load ptr, ptr @constptr2279  %s = load ptr, ptr @something2280  call ptr @llvm.objc.retain(ptr %t)2281  call ptr @llvm.objc.retain(ptr %t)2282  call void @callee()2283  call void @use_pointer(ptr %s)2284  call void @llvm.objc.release(ptr %t)2285  ret void2286}2287 2288; CHECK-LABEL: define void @test60c(2289; CHECK-NOT: @llvm.objc.2290; CHECK: {{^}}}2291define void @test60c() {2292  %t = load ptr, ptr @constptr2293  %s = load ptr, ptr @something2294  call ptr @llvm.objc.retain(ptr %t)2295  call void @callee()2296  call void @use_pointer(ptr %s)2297  call void @llvm.objc.release(ptr %t), !clang.imprecise_release !02298  ret void2299}2300 2301; CHECK-LABEL: define void @test60d(2302; CHECK-NOT: @llvm.objc.2303; CHECK: {{^}}}2304define void @test60d() {2305  %t = load ptr, ptr @constptr2306  %s = load ptr, ptr @something2307  call ptr @llvm.objc.retain(ptr %t)2308  call void @callee()2309  call void @use_pointer(ptr %s)2310  call void @llvm.objc.release(ptr %t)2311  ret void2312}2313 2314; CHECK-LABEL: define void @test60e(2315; CHECK-NOT: @llvm.objc.2316; CHECK: {{^}}}2317define void @test60e() {2318  %t = load ptr, ptr @constptr2319  %s = load ptr, ptr @something2320  call ptr @llvm.objc.retain(ptr %t)2321  call void @callee()2322  call void @use_pointer(ptr %s)2323  call void @llvm.objc.release(ptr %t), !clang.imprecise_release !02324  ret void2325}2326 2327; Constant pointers to objects don't need to be considered related to other2328; pointers.2329 2330; CHECK-LABEL: define void @test61(2331; CHECK-NOT: @llvm.objc.2332; CHECK: {{^}}}2333define void @test61() {2334  %t = load ptr, ptr @constptr2335  call ptr @llvm.objc.retain(ptr %t)2336  call void @callee()2337  call void @use_pointer(ptr %t)2338  call void @llvm.objc.release(ptr %t)2339  ret void2340}2341 2342; Delete a retain matched by releases when one is inside the loop and the2343; other is outside the loop.2344 2345; CHECK-LABEL: define void @test62(2346; CHECK-NOT: @llvm.objc.2347; CHECK: {{^}}}2348define void @test62(ptr %x, ptr %p) nounwind {2349entry:2350  br label %loop2351 2352loop:2353  call ptr @llvm.objc.retain(ptr %x)2354  %q = load i1, ptr %p2355  br i1 %q, label %loop.more, label %exit2356 2357loop.more:2358  call void @llvm.objc.release(ptr %x)2359  br label %loop2360 2361exit:2362  call void @llvm.objc.release(ptr %x)2363  ret void2364}2365 2366; Like test62 but with no release in exit.2367; Don't delete anything!2368 2369; CHECK-LABEL: define void @test63(2370; CHECK: loop:2371; CHECK:   tail call ptr @llvm.objc.retain(ptr %x)2372; CHECK: loop.more:2373; CHECK:   call void @llvm.objc.release(ptr %x)2374; CHECK: {{^}}}2375define void @test63(ptr %x, ptr %p) nounwind {2376entry:2377  br label %loop2378 2379loop:2380  call ptr @llvm.objc.retain(ptr %x)2381  %q = load i1, ptr %p2382  br i1 %q, label %loop.more, label %exit2383 2384loop.more:2385  call void @llvm.objc.release(ptr %x)2386  br label %loop2387 2388exit:2389  ret void2390}2391 2392; Like test62 but with no release in loop.more.2393; Don't delete anything!2394 2395; CHECK-LABEL: define void @test64(2396; CHECK: loop:2397; CHECK:   tail call ptr @llvm.objc.retain(ptr %x)2398; CHECK: exit:2399; CHECK:   call void @llvm.objc.release(ptr %x)2400; CHECK: {{^}}}2401define void @test64(ptr %x, ptr %p) nounwind {2402entry:2403  br label %loop2404 2405loop:2406  call ptr @llvm.objc.retain(ptr %x)2407  %q = load i1, ptr %p2408  br i1 %q, label %loop.more, label %exit2409 2410loop.more:2411  br label %loop2412 2413exit:2414  call void @llvm.objc.release(ptr %x)2415  ret void2416}2417 2418; Move an autorelease past a phi with a null.2419 2420; CHECK-LABEL: define ptr @test65(2421; CHECK: if.then:2422; CHECK:   call ptr @llvm.objc.autorelease(2423; CHECK: return:2424; CHECK-NOT: @llvm.objc.autorelease2425; CHECK: {{^}}}2426define ptr @test65(i1 %x) {2427entry:2428  br i1 %x, label %return, label %if.then2429 2430if.then:                                          ; preds = %entry2431  %c = call ptr @returner()2432  %s = call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %c) nounwind2433  br label %return2434 2435return:                                           ; preds = %if.then, %entry2436  %retval = phi ptr [ %s, %if.then ], [ null, %entry ]2437  %q = call ptr @llvm.objc.autorelease(ptr %retval) nounwind2438  ret ptr %retval2439}2440 2441; Don't move an autorelease past an autorelease pool boundary.2442 2443; CHECK-LABEL: define ptr @test65b(2444; CHECK: if.then:2445; CHECK-NOT: @llvm.objc.autorelease2446; CHECK: return:2447; CHECK:   call ptr @llvm.objc.autorelease(2448; CHECK: {{^}}}2449define ptr @test65b(i1 %x) {2450entry:2451  %t = call ptr @llvm.objc.autoreleasePoolPush()2452  br i1 %x, label %return, label %if.then2453 2454if.then:                                          ; preds = %entry2455  %c = call ptr @returner()2456  %s = call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %c) nounwind2457  br label %return2458 2459return:                                           ; preds = %if.then, %entry2460  %retval = phi ptr [ %s, %if.then ], [ null, %entry ]2461  call void @llvm.objc.autoreleasePoolPop(ptr %t)2462  %q = call ptr @llvm.objc.autorelease(ptr %retval) nounwind2463  ret ptr %retval2464}2465 2466; Don't move an autoreleaseReuturnValue, which would break2467; the RV optimization.2468 2469; CHECK-LABEL: define ptr @test65c(2470; CHECK: if.then:2471; CHECK-NOT: @llvm.objc.autorelease2472; CHECK: return:2473; CHECK:   call ptr @llvm.objc.autoreleaseReturnValue(2474; CHECK: {{^}}}2475define ptr @test65c(i1 %x) {2476entry:2477  br i1 %x, label %return, label %if.then2478 2479if.then:                                          ; preds = %entry2480  %c = call ptr @returner()2481  %s = call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %c) nounwind2482  br label %return2483 2484return:                                           ; preds = %if.then, %entry2485  %retval = phi ptr [ %s, %if.then ], [ null, %entry ]2486  %q = call ptr @llvm.objc.autoreleaseReturnValue(ptr %retval) nounwind2487  ret ptr %retval2488}2489 2490; CHECK-LABEL: define ptr @test65d(2491; CHECK: if.then:2492; CHECK-NOT: @llvm.objc.autorelease2493; CHECK: return:2494; CHECK:   call ptr @llvm.objc.autoreleaseReturnValue(2495; CHECK: {{^}}}2496define ptr @test65d(i1 %x) {2497entry:2498  br i1 %x, label %return, label %if.then2499 2500if.then:                                          ; preds = %entry2501  %c = call ptr @returner()2502  %s = call ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr %c) nounwind2503  br label %return2504 2505return:                                           ; preds = %if.then, %entry2506  %retval = phi ptr [ %s, %if.then ], [ null, %entry ]2507  %q = call ptr @llvm.objc.autoreleaseReturnValue(ptr %retval) nounwind2508  ret ptr %retval2509}2510 2511; An llvm.objc.retain can serve as a may-use for a different pointer.2512; rdar://119318232513 2514; CHECK-LABEL: define void @test66a(2515; CHECK:   tail call ptr @llvm.objc.retain(ptr %cond) [[NUW]]2516; CHECK:   tail call void @llvm.objc.release(ptr %call) [[NUW]]2517; CHECK:   tail call ptr @llvm.objc.retain(ptr %tmp8) [[NUW]]2518; CHECK:   tail call void @llvm.objc.release(ptr %cond) [[NUW]]2519; CHECK: {{^}}}2520define void @test66a(ptr %tmp5, ptr %bar, i1 %tobool, i1 %tobool1, ptr %call) {2521entry:2522  br i1 %tobool, label %cond.true, label %cond.end2523 2524cond.true:2525  br label %cond.end2526 2527cond.end:                                         ; preds = %cond.true, %entry2528  %cond = phi ptr [ %tmp5, %cond.true ], [ %call, %entry ]2529  %tmp7 = tail call ptr @llvm.objc.retain(ptr %cond) nounwind2530  tail call void @llvm.objc.release(ptr %call) nounwind2531  %tmp8 = select i1 %tobool1, ptr %cond, ptr %bar2532  %tmp9 = tail call ptr @llvm.objc.retain(ptr %tmp8) nounwind2533  tail call void @llvm.objc.release(ptr %cond) nounwind2534  ret void2535}2536 2537; CHECK-LABEL: define void @test66b(2538; CHECK:   tail call ptr @llvm.objc.retain(ptr %cond) [[NUW]]2539; CHECK:   tail call void @llvm.objc.release(ptr %call) [[NUW]]2540; CHECK:   tail call ptr @llvm.objc.retain(ptr %tmp8) [[NUW]]2541; CHECK:   tail call void @llvm.objc.release(ptr %cond) [[NUW]]2542; CHECK: {{^}}}2543define void @test66b(ptr %tmp5, ptr %bar, i1 %tobool, i1 %tobool1, ptr %call) {2544entry:2545  br i1 %tobool, label %cond.true, label %cond.end2546 2547cond.true:2548  br label %cond.end2549 2550cond.end:                                         ; preds = %cond.true, %entry2551  %cond = phi ptr [ %tmp5, %cond.true ], [ %call, %entry ]2552  %tmp7 = tail call ptr @llvm.objc.retain(ptr %cond) nounwind2553  tail call void @llvm.objc.release(ptr %call) nounwind, !clang.imprecise_release !02554  %tmp8 = select i1 %tobool1, ptr %cond, ptr %bar2555  %tmp9 = tail call ptr @llvm.objc.retain(ptr %tmp8) nounwind2556  tail call void @llvm.objc.release(ptr %cond) nounwind2557  ret void2558}2559 2560; CHECK-LABEL: define void @test66c(2561; CHECK:   tail call ptr @llvm.objc.retain(ptr %cond) [[NUW]]2562; CHECK:   tail call void @llvm.objc.release(ptr %call) [[NUW]]2563; CHECK:   tail call ptr @llvm.objc.retain(ptr %tmp8) [[NUW]]2564; CHECK:   tail call void @llvm.objc.release(ptr %cond) [[NUW]]2565; CHECK: {{^}}}2566define void @test66c(ptr %tmp5, ptr %bar, i1 %tobool, i1 %tobool1, ptr %call) {2567entry:2568  br i1 %tobool, label %cond.true, label %cond.end2569 2570cond.true:2571  br label %cond.end2572 2573cond.end:                                         ; preds = %cond.true, %entry2574  %cond = phi ptr [ %tmp5, %cond.true ], [ %call, %entry ]2575  %tmp7 = tail call ptr @llvm.objc.retain(ptr %cond) nounwind2576  tail call void @llvm.objc.release(ptr %call) nounwind2577  %tmp8 = select i1 %tobool1, ptr %cond, ptr %bar2578  %tmp9 = tail call ptr @llvm.objc.retain(ptr %tmp8) nounwind, !clang.imprecise_release !02579  tail call void @llvm.objc.release(ptr %cond) nounwind2580  ret void2581}2582 2583; CHECK-LABEL: define void @test66d(2584; CHECK:   tail call ptr @llvm.objc.retain(ptr %cond) [[NUW]]2585; CHECK:   tail call void @llvm.objc.release(ptr %call) [[NUW]]2586; CHECK:   tail call ptr @llvm.objc.retain(ptr %tmp8) [[NUW]]2587; CHECK:   tail call void @llvm.objc.release(ptr %cond) [[NUW]]2588; CHECK: {{^}}}2589define void @test66d(ptr %tmp5, ptr %bar, i1 %tobool, i1 %tobool1, ptr %call) {2590entry:2591  br i1 %tobool, label %cond.true, label %cond.end2592 2593cond.true:2594  br label %cond.end2595 2596cond.end:                                         ; preds = %cond.true, %entry2597  %cond = phi ptr [ %tmp5, %cond.true ], [ %call, %entry ]2598  %tmp7 = tail call ptr @llvm.objc.retain(ptr %cond) nounwind2599  tail call void @llvm.objc.release(ptr %call) nounwind, !clang.imprecise_release !02600  %tmp8 = select i1 %tobool1, ptr %cond, ptr %bar2601  %tmp9 = tail call ptr @llvm.objc.retain(ptr %tmp8) nounwind2602  tail call void @llvm.objc.release(ptr %cond) nounwind, !clang.imprecise_release !02603  ret void2604}2605 2606; A few real-world testcases.2607 2608@.str4 = private unnamed_addr constant [33 x i8] c"-[A z] = { %f, %f, { %f, %f } }\0A\00"2609@"OBJC_IVAR_$_A.myZ" = global i64 20, section "__DATA, __objc_const", align 82610declare i32 @printf(ptr captures(none), ...) nounwind2611declare i32 @puts(ptr captures(none)) nounwind2612@str = internal constant [16 x i8] c"-[ Top0 _getX ]\00"2613 2614; FIXME: Should be able to eliminate the retain and release2615; CHECK-LABEL: define { <2 x float>, <2 x float> } @"\01-[A z]"(ptr %self, ptr captures(none) %_cmd)2616; CHECK: tail call ptr @llvm.objc.retain(ptr %self)2617; CHECK-NEXT: %call = tail call i32 (ptr, ...) @printf(2618; CHECK: tail call void @llvm.objc.release(ptr %self)2619; CHECK: {{^}}}2620define { <2 x float>, <2 x float> } @"\01-[A z]"(ptr %self, ptr captures(none) %_cmd) nounwind {2621invoke.cont:2622  %i1 = tail call ptr @llvm.objc.retain(ptr %self) nounwind2623  tail call void @llvm.dbg.value(metadata ptr %self, metadata !DILocalVariable(scope: !2), metadata !DIExpression()), !dbg !DILocation(scope: !2)2624  tail call void @llvm.dbg.value(metadata ptr %self, metadata !DILocalVariable(scope: !2), metadata !DIExpression()), !dbg !DILocation(scope: !2)2625  %ivar = load i64, ptr @"OBJC_IVAR_$_A.myZ", align 82626  %add.ptr = getelementptr i8, ptr %self, i64 %ivar2627  %tmp2 = load float, ptr %add.ptr, align 42628  %conv = fpext float %tmp2 to double2629  %add.ptr.sum = add i64 %ivar, 42630  %tmp6 = getelementptr inbounds i8, ptr %self, i64 %add.ptr.sum2631  %tmp7 = load float, ptr %tmp6, align 42632  %conv8 = fpext float %tmp7 to double2633  %add.ptr.sum36 = add i64 %ivar, 82634  %tmp12 = getelementptr inbounds i8, ptr %self, i64 %add.ptr.sum362635  %tmp13 = load float, ptr %tmp12, align 42636  %conv14 = fpext float %tmp13 to double2637  %tmp12.sum = add i64 %ivar, 122638  %arrayidx19 = getelementptr inbounds i8, ptr %self, i64 %tmp12.sum2639  %tmp20 = load float, ptr %arrayidx19, align 42640  %conv21 = fpext float %tmp20 to double2641  %call = tail call i32 (ptr, ...) @printf(ptr @.str4, double %conv, double %conv8, double %conv14, double %conv21)2642  %ivar23 = load i64, ptr @"OBJC_IVAR_$_A.myZ", align 82643  %add.ptr24 = getelementptr i8, ptr %self, i64 %ivar232644  %srcval = load i128, ptr %add.ptr24, align 42645  tail call void @llvm.objc.release(ptr %self) nounwind2646  %tmp29 = trunc i128 %srcval to i642647  %tmp30 = bitcast i64 %tmp29 to <2 x float>2648  %tmp31 = insertvalue { <2 x float>, <2 x float> } undef, <2 x float> %tmp30, 02649  %tmp32 = lshr i128 %srcval, 642650  %tmp33 = trunc i128 %tmp32 to i642651  %tmp34 = bitcast i64 %tmp33 to <2 x float>2652  %tmp35 = insertvalue { <2 x float>, <2 x float> } %tmp31, <2 x float> %tmp34, 12653  ret { <2 x float>, <2 x float> } %tmp352654}2655 2656; FIXME: Should be able to eliminate the retain and release2657; CHECK-LABEL: @"\01-[Top0 _getX]"(ptr %self, ptr captures(none) %_cmd)2658; CHECK: tail call ptr @llvm.objc.retain(ptr %self)2659; CHECK: %puts = tail call i32 @puts2660; CHECK: tail call void @llvm.objc.release(ptr %self)2661define i32 @"\01-[Top0 _getX]"(ptr %self, ptr captures(none) %_cmd) nounwind {2662invoke.cont:2663  %i1 = tail call ptr @llvm.objc.retain(ptr %self) nounwind2664  %puts = tail call i32 @puts(ptr @str)2665  tail call void @llvm.objc.release(ptr %self) nounwind2666  ret i32 02667}2668 2669@"\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 ptr @"\01L_OBJC_METH_VAR_NAME_", section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"2670@"\01L_OBJC_IMAGE_INFO" = internal constant [2 x i32] [i32 0, i32 16], section "__DATA, __objc_imageinfo, regular, no_dead_strip"2671@llvm.used = appending global [3 x ptr] [ptr @"\01L_OBJC_METH_VAR_NAME_", ptr @"\01L_OBJC_SELECTOR_REFERENCES_", ptr @"\01L_OBJC_IMAGE_INFO"], section "llvm.metadata"2672 2673; A simple loop. Eliminate the retain and release inside of it!2674 2675; CHECK: define void @loop(ptr %x, i64 %n) {2676; CHECK: for.body:2677; CHECK-NOT: @llvm.objc.2678; CHECK: @objc_msgSend2679; CHECK-NOT: @llvm.objc.2680; CHECK: for.end:2681; CHECK: {{^}}}2682define void @loop(ptr %x, i64 %n) {2683entry:2684  %0 = tail call ptr @llvm.objc.retain(ptr %x) nounwind2685  %cmp9 = icmp sgt i64 %n, 02686  br i1 %cmp9, label %for.body, label %for.end2687 2688for.body:                                         ; preds = %entry, %for.body2689  %i.010 = phi i64 [ %inc, %for.body ], [ 0, %entry ]2690  %1 = tail call ptr @llvm.objc.retain(ptr %x) nounwind2691  %tmp5 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 82692  %call = tail call ptr (ptr, ptr, ...) @objc_msgSend(ptr %1, ptr %tmp5)2693  tail call void @llvm.objc.release(ptr %1) nounwind, !clang.imprecise_release !02694  %inc = add nsw i64 %i.010, 12695  %exitcond = icmp eq i64 %inc, %n2696  br i1 %exitcond, label %for.end, label %for.body2697 2698for.end:                                          ; preds = %for.body, %entry2699  tail call void @llvm.objc.release(ptr %x) nounwind, !clang.imprecise_release !02700  ret void2701}2702 2703; ObjCARCOpt can delete the retain,release on self.2704 2705; CHECK: define void @TextEditTest(ptr %self, ptr %pboard) {2706; CHECK-NOT: call ptr @llvm.objc.retain(ptr %tmp7)2707; CHECK: {{^}}}2708 2709%0 = type { ptr, ptr }2710%1 = type opaque2711%2 = type opaque2712%3 = type opaque2713%4 = type opaque2714%5 = type opaque2715%struct.NSConstantString = type { ptr, i32, ptr, i64 }2716%struct._NSRange = type { i64, i64 }2717%struct.__CFString = type opaque2718%struct.__method_list_t = type { i32, i32, [0 x %struct._objc_method] }2719%struct._class_ro_t = type { i32, i32, i32, ptr, ptr, ptr, ptr, ptr, ptr, ptr }2720%struct._class_t = type { ptr, ptr, ptr, ptr, ptr }2721%struct._ivar_list_t = type { i32, i32, [0 x %struct._ivar_t] }2722%struct._ivar_t = type { ptr, ptr, ptr, i32, i32 }2723%struct._message_ref_t = type { ptr, ptr }2724%struct._objc_cache = type opaque2725%struct._objc_method = type { ptr, ptr, ptr }2726%struct._objc_protocol_list = type { i64, [0 x ptr] }2727%struct._prop_list_t = type { i32, i32, [0 x %struct._message_ref_t] }2728%struct._protocol_t = type { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, i32, i32 }2729 2730@"\01L_OBJC_CLASSLIST_REFERENCES_$_17" = external hidden global ptr, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 82731@kUTTypePlainText = external constant ptr2732@"\01L_OBJC_SELECTOR_REFERENCES_19" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"2733@"\01L_OBJC_SELECTOR_REFERENCES_21" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"2734@"\01L_OBJC_SELECTOR_REFERENCES_23" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"2735@"\01L_OBJC_SELECTOR_REFERENCES_25" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"2736@"\01L_OBJC_CLASSLIST_REFERENCES_$_26" = external hidden global ptr, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 82737@"\01L_OBJC_SELECTOR_REFERENCES_28" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"2738@"\01L_OBJC_CLASSLIST_REFERENCES_$_29" = external hidden global ptr, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 82739@"\01L_OBJC_SELECTOR_REFERENCES_31" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"2740@"\01L_OBJC_SELECTOR_REFERENCES_33" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"2741@"\01L_OBJC_SELECTOR_REFERENCES_35" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"2742@"\01L_OBJC_SELECTOR_REFERENCES_37" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"2743@"\01L_OBJC_CLASSLIST_REFERENCES_$_38" = external hidden global ptr, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 82744@"\01L_OBJC_SELECTOR_REFERENCES_40" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"2745@"\01L_OBJC_SELECTOR_REFERENCES_42" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"2746@_unnamed_cfstring_44 = external hidden constant %struct.NSConstantString, section "__DATA,__cfstring"2747@"\01L_OBJC_SELECTOR_REFERENCES_46" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"2748@"\01L_OBJC_SELECTOR_REFERENCES_48" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"2749@"\01l_objc_msgSend_fixup_isEqual_" = external hidden global %0, section "__DATA, __objc_msgrefs, coalesced", align 162750@"\01L_OBJC_CLASSLIST_REFERENCES_$_50" = external hidden global ptr, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 82751@NSCocoaErrorDomain = external constant ptr2752@"\01L_OBJC_CLASSLIST_REFERENCES_$_51" = external hidden global ptr, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 82753@NSFilePathErrorKey = external constant ptr2754@"\01L_OBJC_SELECTOR_REFERENCES_53" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"2755@"\01L_OBJC_SELECTOR_REFERENCES_55" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"2756@"\01L_OBJC_CLASSLIST_REFERENCES_$_56" = external hidden global ptr, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 82757@"\01L_OBJC_SELECTOR_REFERENCES_58" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"2758@"\01L_OBJC_SELECTOR_REFERENCES_60" = external hidden global ptr, section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"2759 2760declare ptr @truncatedString(ptr, i64)2761define void @TextEditTest(ptr %self, ptr %pboard) {2762entry:2763  %err = alloca ptr, align 82764  %tmp8 = call ptr @llvm.objc.retain(ptr %self) nounwind2765  store ptr null, ptr %err, align 82766  %tmp1 = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_17", align 82767  %tmp2 = load ptr, ptr @kUTTypePlainText, align 82768  %tmp3 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_19", align 82769  %call5 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %tmp1, ptr %tmp3, ptr %tmp2)2770  %tmp5 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_21", align 82771  %call76 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %pboard, ptr %tmp5, ptr %call5)2772  %tmp9 = call ptr @llvm.objc.retain(ptr %call76) nounwind2773  %tobool = icmp eq ptr %tmp9, null2774  br i1 %tobool, label %end, label %land.lhs.true2775 2776land.lhs.true:                                    ; preds = %entry2777  %tmp11 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_23", align 82778  %call137 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %pboard, ptr %tmp11, ptr %tmp9)2779  %tmp10 = call ptr @llvm.objc.retain(ptr %call137) nounwind2780  call void @llvm.objc.release(ptr null) nounwind2781  %tmp12 = call ptr @llvm.objc.retain(ptr %call137) nounwind2782  call void @llvm.objc.release(ptr null) nounwind2783  %tobool16 = icmp eq ptr %call137, null2784  br i1 %tobool16, label %end, label %if.then2785 2786if.then:                                          ; preds = %land.lhs.true2787  %tmp19 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_25", align 82788  %call21 = call signext i8 @objc_msgSend(ptr %call137, ptr %tmp19)2789  %tobool22 = icmp eq i8 %call21, 02790  br i1 %tobool22, label %if.then44, label %land.lhs.true232791 2792land.lhs.true23:                                  ; preds = %if.then2793  %tmp24 = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_26", align 82794  %tmp26 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_28", align 82795  %call2822 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %tmp24, ptr %tmp26, ptr %call137)2796  %tmp14 = call ptr @llvm.objc.retain(ptr %call2822) nounwind2797  call void @llvm.objc.release(ptr null) nounwind2798  %tobool30 = icmp eq ptr %call2822, null2799  br i1 %tobool30, label %if.then44, label %if.end2800 2801if.end:                                           ; preds = %land.lhs.true232802  %tmp32 = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_29", align 82803  %tmp33 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_31", align 82804  %call35 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %tmp32, ptr %tmp33)2805  %tmp37 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_33", align 82806  %call3923 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %call35, ptr %tmp37, ptr %call2822, i32 signext 1, ptr %err)2807  %cmp = icmp eq ptr %call3923, null2808  br i1 %cmp, label %if.then44, label %end2809 2810if.then44:                                        ; preds = %if.end, %land.lhs.true23, %if.then2811  %url.025 = phi ptr [ %call2822, %if.end ], [ %call2822, %land.lhs.true23 ], [ null, %if.then ]2812  %tmp49 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_35", align 82813  %call51 = call %struct._NSRange @objc_msgSend(ptr %call137, ptr %tmp49, i64 0, i64 0)2814  %call513 = extractvalue %struct._NSRange %call51, 02815  %call514 = extractvalue %struct._NSRange %call51, 12816  %tmp52 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_37", align 82817  %call548 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %call137, ptr %tmp52, i64 %call513, i64 %call514)2818  %tmp55 = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_38", align 82819  %tmp56 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_40", align 82820  %call58 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %tmp55, ptr %tmp56)2821  %tmp59 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_42", align 82822  %call6110 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %call548, ptr %tmp59, ptr %call58)2823  %tmp15 = call ptr @llvm.objc.retain(ptr %call6110) nounwind2824  call void @llvm.objc.release(ptr %call137) nounwind2825  %tmp64 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_46", align 82826  %call66 = call signext i8 @objc_msgSend(ptr %call6110, ptr %tmp64, ptr @_unnamed_cfstring_44)2827  %tobool67 = icmp eq i8 %call66, 02828  br i1 %tobool67, label %if.end74, label %if.then682829 2830if.then68:                                        ; preds = %if.then442831  %tmp70 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_48", align 82832  %call7220 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %call6110, ptr %tmp70)2833  %tmp16 = call ptr @llvm.objc.retain(ptr %call7220) nounwind2834  call void @llvm.objc.release(ptr %call6110) nounwind2835  br label %if.end742836 2837if.end74:                                         ; preds = %if.then68, %if.then442838  %filename.0.in = phi ptr [ %call7220, %if.then68 ], [ %call6110, %if.then44 ]2839  %tmp17 = load ptr, ptr @"\01l_objc_msgSend_fixup_isEqual_", align 162840  %call78 = call signext i8 (ptr, ptr, ptr, ...) %tmp17(ptr %call137, ptr @"\01l_objc_msgSend_fixup_isEqual_", ptr %filename.0.in)2841  %tobool79 = icmp eq i8 %call78, 02842  br i1 %tobool79, label %land.lhs.true80, label %if.then1092843 2844land.lhs.true80:                                  ; preds = %if.end742845  %tmp82 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_25", align 82846  %call84 = call signext i8 @objc_msgSend(ptr %filename.0.in, ptr %tmp82)2847  %tobool86 = icmp eq i8 %call84, 02848  br i1 %tobool86, label %if.then109, label %if.end1062849 2850if.end106:                                        ; preds = %land.lhs.true802851  %tmp88 = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_26", align 82852  %tmp90 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_28", align 82853  %call9218 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %tmp88, ptr %tmp90, ptr %filename.0.in)2854  %tmp21 = call ptr @llvm.objc.retain(ptr %call9218) nounwind2855  call void @llvm.objc.release(ptr %url.025) nounwind2856  %tmp94 = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_29", align 82857  %tmp95 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_31", align 82858  %call97 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %tmp94, ptr %tmp95)2859  %tmp99 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_33", align 82860  %call10119 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %call97, ptr %tmp99, ptr %call9218, i32 signext 1, ptr %err)2861  %phitmp = icmp eq ptr %call10119, null2862  br i1 %phitmp, label %if.then109, label %end2863 2864if.then109:                                       ; preds = %if.end106, %land.lhs.true80, %if.end742865  %url.129 = phi ptr [ %call9218, %if.end106 ], [ %url.025, %if.end74 ], [ %url.025, %land.lhs.true80 ]2866  %tmp110 = load ptr, ptr %err, align 82867  %tobool111 = icmp eq ptr %tmp110, null2868  br i1 %tobool111, label %if.then112, label %if.end1252869 2870if.then112:                                       ; preds = %if.then1092871  %tmp113 = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_50", align 82872  %tmp114 = load ptr, ptr @NSCocoaErrorDomain, align 82873  %tmp115 = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_51", align 82874  %call117 = call ptr @truncatedString(ptr %filename.0.in, i64 1034)2875  %tmp118 = load ptr, ptr @NSFilePathErrorKey, align 82876  %tmp119 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_53", align 82877  %call12113 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %tmp115, ptr %tmp119, ptr %call117, ptr %tmp118, ptr null)2878  %tmp122 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_55", align 82879  %call12414 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %tmp113, ptr %tmp122, ptr %tmp114, i64 258, ptr %call12113)2880  %tmp23 = call ptr @llvm.objc.retain(ptr %call12414) nounwind2881  %tmp25 = call ptr @llvm.objc.autorelease(ptr %tmp23) nounwind2882  store ptr %tmp25, ptr %err, align 82883  br label %if.end1252884 2885if.end125:                                        ; preds = %if.then112, %if.then1092886  %tmp127 = phi ptr [ %tmp110, %if.then109 ], [ %tmp25, %if.then112 ]2887  %tmp126 = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_56", align 82888  %tmp128 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_58", align 82889  %call13015 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %tmp126, ptr %tmp128, ptr %tmp127)2890  %tmp131 = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_60", align 82891  %call13317 = call ptr (ptr, ptr, ...) @objc_msgSend(ptr %call13015, ptr %tmp131)2892  br label %end2893 2894end:                                              ; preds = %if.end125, %if.end106, %if.end, %land.lhs.true, %entry2895  %filename.2 = phi ptr [ %filename.0.in, %if.end106 ], [ %filename.0.in, %if.end125 ], [ %call137, %land.lhs.true ], [ null, %entry ], [ %call137, %if.end ]2896  %origFilename.0 = phi ptr [ %call137, %if.end106 ], [ %call137, %if.end125 ], [ %call137, %land.lhs.true ], [ null, %entry ], [ %call137, %if.end ]2897  %url.2 = phi ptr [ %call9218, %if.end106 ], [ %url.129, %if.end125 ], [ null, %land.lhs.true ], [ null, %entry ], [ %call2822, %if.end ]2898  call void @llvm.objc.release(ptr %tmp9) nounwind, !clang.imprecise_release !02899  call void @llvm.objc.release(ptr %url.2) nounwind, !clang.imprecise_release !02900  call void @llvm.objc.release(ptr %origFilename.0) nounwind, !clang.imprecise_release !02901  call void @llvm.objc.release(ptr %filename.2) nounwind, !clang.imprecise_release !02902  call void @llvm.objc.release(ptr %self) nounwind, !clang.imprecise_release !02903  ret void2904}2905 2906declare i32 @__gxx_personality_v0(...)2907 2908declare i32 @llvm.objc.sync.enter(ptr)2909declare i32 @llvm.objc.sync.exit(ptr)2910 2911; Make sure that we understand that objc_sync_{enter,exit} are IC_User not2912; IC_Call/IC_CallOrUser.2913 2914; CHECK-LABEL:      define void @test67(2915; CHECK-NEXT:   call i32 @llvm.objc.sync.enter(ptr %x)2916; CHECK-NEXT:   call i32 @llvm.objc.sync.exit(ptr %x)2917; CHECK-NEXT:   ret void2918; CHECK-NEXT: }2919define void @test67(ptr %x) {2920  call ptr @llvm.objc.retain(ptr %x)2921  call i32 @llvm.objc.sync.enter(ptr %x)2922  call i32 @llvm.objc.sync.exit(ptr %x)2923  call void @llvm.objc.release(ptr %x), !clang.imprecise_release !02924  ret void2925}2926 2927; CHECK-LABEL: define void @test68(2928; CHECK-NOT:     call2929; CHECK:         call void @callee2(2930; CHECK-NOT:     call2931; CHECK:         ret void2932 2933define void @test68(ptr %a, ptr %b) {2934  call ptr @llvm.objc.retain(ptr %a)2935  call ptr @llvm.objc.retain(ptr %b)2936  call void @callee2(ptr %a, ptr %b)2937  call void @llvm.objc.release(ptr %b), !clang.imprecise_release !02938  call void @llvm.objc.release(ptr %a), !clang.imprecise_release !02939  ret void2940}2941 2942!llvm.module.flags = !{!1}2943!llvm.dbg.cu = !{!3}2944 2945!0 = !{}2946!1 = !{i32 1, !"Debug Info Version", i32 3}2947!2 = distinct !DISubprogram(unit: !3)2948!3 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang",2949                             file: !4,2950                             isOptimized: true, flags: "-O2",2951                             splitDebugFilename: "abc.debug", emissionKind: 2)2952!4 = !DIFile(filename: "path/to/file", directory: "/path/to/dir")2953!5 = !{i32 2, !"Debug Info Version", i32 3}2954 2955; CHECK: attributes [[NUW]] = { nounwind }2956; CHECK: ![[RELEASE]] = !{}2957