llvm-project
704 строки · 23.2 Кб
1//===- ARCInstKind.cpp - ObjC ARC Optimization ----------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file
9/// This file defines several utility functions used by various ARC
10/// optimizations which are IMHO too big to be in a header file.
11///
12/// WARNING: This file knows about certain library functions. It recognizes them
13/// by name, and hardwires knowledge of their semantics.
14///
15/// WARNING: This file knows about how certain Objective-C library functions are
16/// used. Naive LLVM IR transformations which would otherwise be
17/// behavior-preserving may break these assumptions.
18///
19//===----------------------------------------------------------------------===//
20
21#include "llvm/Analysis/ObjCARCInstKind.h"22#include "llvm/Analysis/ObjCARCAnalysisUtils.h"23#include "llvm/IR/Intrinsics.h"24
25using namespace llvm;26using namespace llvm::objcarc;27
28raw_ostream &llvm::objcarc::operator<<(raw_ostream &OS,29const ARCInstKind Class) {30switch (Class) {31case ARCInstKind::Retain:32return OS << "ARCInstKind::Retain";33case ARCInstKind::RetainRV:34return OS << "ARCInstKind::RetainRV";35case ARCInstKind::UnsafeClaimRV:36return OS << "ARCInstKind::UnsafeClaimRV";37case ARCInstKind::RetainBlock:38return OS << "ARCInstKind::RetainBlock";39case ARCInstKind::Release:40return OS << "ARCInstKind::Release";41case ARCInstKind::Autorelease:42return OS << "ARCInstKind::Autorelease";43case ARCInstKind::AutoreleaseRV:44return OS << "ARCInstKind::AutoreleaseRV";45case ARCInstKind::AutoreleasepoolPush:46return OS << "ARCInstKind::AutoreleasepoolPush";47case ARCInstKind::AutoreleasepoolPop:48return OS << "ARCInstKind::AutoreleasepoolPop";49case ARCInstKind::NoopCast:50return OS << "ARCInstKind::NoopCast";51case ARCInstKind::FusedRetainAutorelease:52return OS << "ARCInstKind::FusedRetainAutorelease";53case ARCInstKind::FusedRetainAutoreleaseRV:54return OS << "ARCInstKind::FusedRetainAutoreleaseRV";55case ARCInstKind::LoadWeakRetained:56return OS << "ARCInstKind::LoadWeakRetained";57case ARCInstKind::StoreWeak:58return OS << "ARCInstKind::StoreWeak";59case ARCInstKind::InitWeak:60return OS << "ARCInstKind::InitWeak";61case ARCInstKind::LoadWeak:62return OS << "ARCInstKind::LoadWeak";63case ARCInstKind::MoveWeak:64return OS << "ARCInstKind::MoveWeak";65case ARCInstKind::CopyWeak:66return OS << "ARCInstKind::CopyWeak";67case ARCInstKind::DestroyWeak:68return OS << "ARCInstKind::DestroyWeak";69case ARCInstKind::StoreStrong:70return OS << "ARCInstKind::StoreStrong";71case ARCInstKind::CallOrUser:72return OS << "ARCInstKind::CallOrUser";73case ARCInstKind::Call:74return OS << "ARCInstKind::Call";75case ARCInstKind::User:76return OS << "ARCInstKind::User";77case ARCInstKind::IntrinsicUser:78return OS << "ARCInstKind::IntrinsicUser";79case ARCInstKind::None:80return OS << "ARCInstKind::None";81}82llvm_unreachable("Unknown instruction class!");83}
84
85ARCInstKind llvm::objcarc::GetFunctionClass(const Function *F) {86
87Intrinsic::ID ID = F->getIntrinsicID();88switch (ID) {89default:90return ARCInstKind::CallOrUser;91case Intrinsic::objc_autorelease:92return ARCInstKind::Autorelease;93case Intrinsic::objc_autoreleasePoolPop:94return ARCInstKind::AutoreleasepoolPop;95case Intrinsic::objc_autoreleasePoolPush:96return ARCInstKind::AutoreleasepoolPush;97case Intrinsic::objc_autoreleaseReturnValue:98return ARCInstKind::AutoreleaseRV;99case Intrinsic::objc_copyWeak:100return ARCInstKind::CopyWeak;101case Intrinsic::objc_destroyWeak:102return ARCInstKind::DestroyWeak;103case Intrinsic::objc_initWeak:104return ARCInstKind::InitWeak;105case Intrinsic::objc_loadWeak:106return ARCInstKind::LoadWeak;107case Intrinsic::objc_loadWeakRetained:108return ARCInstKind::LoadWeakRetained;109case Intrinsic::objc_moveWeak:110return ARCInstKind::MoveWeak;111case Intrinsic::objc_release:112return ARCInstKind::Release;113case Intrinsic::objc_retain:114return ARCInstKind::Retain;115case Intrinsic::objc_retainAutorelease:116return ARCInstKind::FusedRetainAutorelease;117case Intrinsic::objc_retainAutoreleaseReturnValue:118return ARCInstKind::FusedRetainAutoreleaseRV;119case Intrinsic::objc_retainAutoreleasedReturnValue:120return ARCInstKind::RetainRV;121case Intrinsic::objc_retainBlock:122return ARCInstKind::RetainBlock;123case Intrinsic::objc_storeStrong:124return ARCInstKind::StoreStrong;125case Intrinsic::objc_storeWeak:126return ARCInstKind::StoreWeak;127case Intrinsic::objc_clang_arc_use:128return ARCInstKind::IntrinsicUser;129case Intrinsic::objc_unsafeClaimAutoreleasedReturnValue:130return ARCInstKind::UnsafeClaimRV;131case Intrinsic::objc_retainedObject:132return ARCInstKind::NoopCast;133case Intrinsic::objc_unretainedObject:134return ARCInstKind::NoopCast;135case Intrinsic::objc_unretainedPointer:136return ARCInstKind::NoopCast;137case Intrinsic::objc_retain_autorelease:138return ARCInstKind::FusedRetainAutorelease;139case Intrinsic::objc_sync_enter:140return ARCInstKind::User;141case Intrinsic::objc_sync_exit:142return ARCInstKind::User;143case Intrinsic::objc_clang_arc_noop_use:144case Intrinsic::objc_arc_annotation_topdown_bbstart:145case Intrinsic::objc_arc_annotation_topdown_bbend:146case Intrinsic::objc_arc_annotation_bottomup_bbstart:147case Intrinsic::objc_arc_annotation_bottomup_bbend:148// Ignore annotation calls. This is important to stop the149// optimizer from treating annotations as uses which would150// make the state of the pointers they are attempting to151// elucidate to be incorrect.152return ARCInstKind::None;153}154}
155
156// A list of intrinsics that we know do not use objc pointers or decrement
157// ref counts.
158static bool isInertIntrinsic(unsigned ID) {159// TODO: Make this into a covered switch.160switch (ID) {161case Intrinsic::returnaddress:162case Intrinsic::addressofreturnaddress:163case Intrinsic::frameaddress:164case Intrinsic::stacksave:165case Intrinsic::stackrestore:166case Intrinsic::vastart:167case Intrinsic::vacopy:168case Intrinsic::vaend:169case Intrinsic::objectsize:170case Intrinsic::prefetch:171case Intrinsic::stackprotector:172case Intrinsic::eh_return_i32:173case Intrinsic::eh_return_i64:174case Intrinsic::eh_typeid_for:175case Intrinsic::eh_dwarf_cfa:176case Intrinsic::eh_sjlj_lsda:177case Intrinsic::eh_sjlj_functioncontext:178case Intrinsic::init_trampoline:179case Intrinsic::adjust_trampoline:180case Intrinsic::lifetime_start:181case Intrinsic::lifetime_end:182case Intrinsic::invariant_start:183case Intrinsic::invariant_end:184// Don't let dbg info affect our results.185case Intrinsic::dbg_declare:186case Intrinsic::dbg_value:187case Intrinsic::dbg_label:188// Short cut: Some intrinsics obviously don't use ObjC pointers.189return true;190default:191return false;192}193}
194
195// A list of intrinsics that we know do not use objc pointers or decrement
196// ref counts.
197static bool isUseOnlyIntrinsic(unsigned ID) {198// We are conservative and even though intrinsics are unlikely to touch199// reference counts, we white list them for safety.200//201// TODO: Expand this into a covered switch. There is a lot more here.202switch (ID) {203case Intrinsic::memcpy:204case Intrinsic::memmove:205case Intrinsic::memset:206return true;207default:208return false;209}210}
211
212/// Determine what kind of construct V is.
213ARCInstKind llvm::objcarc::GetARCInstKind(const Value *V) {214if (const Instruction *I = dyn_cast<Instruction>(V)) {215// Any instruction other than bitcast and gep with a pointer operand have a216// use of an objc pointer. Bitcasts, GEPs, Selects, PHIs transfer a pointer217// to a subsequent use, rather than using it themselves, in this sense.218// As a short cut, several other opcodes are known to have no pointer219// operands of interest. And ret is never followed by a release, so it's220// not interesting to examine.221switch (I->getOpcode()) {222case Instruction::Call: {223const CallInst *CI = cast<CallInst>(I);224// See if we have a function that we know something about.225if (const Function *F = CI->getCalledFunction()) {226ARCInstKind Class = GetFunctionClass(F);227if (Class != ARCInstKind::CallOrUser)228return Class;229Intrinsic::ID ID = F->getIntrinsicID();230if (isInertIntrinsic(ID))231return ARCInstKind::None;232if (isUseOnlyIntrinsic(ID))233return ARCInstKind::User;234}235
236// Otherwise, be conservative.237return GetCallSiteClass(*CI);238}239case Instruction::Invoke:240// Otherwise, be conservative.241return GetCallSiteClass(cast<InvokeInst>(*I));242case Instruction::BitCast:243case Instruction::GetElementPtr:244case Instruction::Select:245case Instruction::PHI:246case Instruction::Ret:247case Instruction::Br:248case Instruction::Switch:249case Instruction::IndirectBr:250case Instruction::Alloca:251case Instruction::VAArg:252case Instruction::Add:253case Instruction::FAdd:254case Instruction::Sub:255case Instruction::FSub:256case Instruction::Mul:257case Instruction::FMul:258case Instruction::SDiv:259case Instruction::UDiv:260case Instruction::FDiv:261case Instruction::SRem:262case Instruction::URem:263case Instruction::FRem:264case Instruction::Shl:265case Instruction::LShr:266case Instruction::AShr:267case Instruction::And:268case Instruction::Or:269case Instruction::Xor:270case Instruction::SExt:271case Instruction::ZExt:272case Instruction::Trunc:273case Instruction::IntToPtr:274case Instruction::FCmp:275case Instruction::FPTrunc:276case Instruction::FPExt:277case Instruction::FPToUI:278case Instruction::FPToSI:279case Instruction::UIToFP:280case Instruction::SIToFP:281case Instruction::InsertElement:282case Instruction::ExtractElement:283case Instruction::ShuffleVector:284case Instruction::ExtractValue:285break;286case Instruction::ICmp:287// Comparing a pointer with null, or any other constant, isn't an288// interesting use, because we don't care what the pointer points to, or289// about the values of any other dynamic reference-counted pointers.290if (IsPotentialRetainableObjPtr(I->getOperand(1)))291return ARCInstKind::User;292break;293default:294// For anything else, check all the operands.295// Note that this includes both operands of a Store: while the first296// operand isn't actually being dereferenced, it is being stored to297// memory where we can no longer track who might read it and dereference298// it, so we have to consider it potentially used.299for (const Use &U : I->operands())300if (IsPotentialRetainableObjPtr(U))301return ARCInstKind::User;302}303}304
305// Otherwise, it's totally inert for ARC purposes.306return ARCInstKind::None;307}
308
309/// Test if the given class is a kind of user.
310bool llvm::objcarc::IsUser(ARCInstKind Class) {311switch (Class) {312case ARCInstKind::User:313case ARCInstKind::CallOrUser:314case ARCInstKind::IntrinsicUser:315return true;316case ARCInstKind::Retain:317case ARCInstKind::RetainRV:318case ARCInstKind::RetainBlock:319case ARCInstKind::Release:320case ARCInstKind::Autorelease:321case ARCInstKind::AutoreleaseRV:322case ARCInstKind::AutoreleasepoolPush:323case ARCInstKind::AutoreleasepoolPop:324case ARCInstKind::NoopCast:325case ARCInstKind::FusedRetainAutorelease:326case ARCInstKind::FusedRetainAutoreleaseRV:327case ARCInstKind::LoadWeakRetained:328case ARCInstKind::StoreWeak:329case ARCInstKind::InitWeak:330case ARCInstKind::LoadWeak:331case ARCInstKind::MoveWeak:332case ARCInstKind::CopyWeak:333case ARCInstKind::DestroyWeak:334case ARCInstKind::StoreStrong:335case ARCInstKind::Call:336case ARCInstKind::None:337case ARCInstKind::UnsafeClaimRV:338return false;339}340llvm_unreachable("covered switch isn't covered?");341}
342
343/// Test if the given class is objc_retain or equivalent.
344bool llvm::objcarc::IsRetain(ARCInstKind Class) {345switch (Class) {346case ARCInstKind::Retain:347case ARCInstKind::RetainRV:348return true;349// I believe we treat retain block as not a retain since it can copy its350// block.351case ARCInstKind::RetainBlock:352case ARCInstKind::Release:353case ARCInstKind::Autorelease:354case ARCInstKind::AutoreleaseRV:355case ARCInstKind::AutoreleasepoolPush:356case ARCInstKind::AutoreleasepoolPop:357case ARCInstKind::NoopCast:358case ARCInstKind::FusedRetainAutorelease:359case ARCInstKind::FusedRetainAutoreleaseRV:360case ARCInstKind::LoadWeakRetained:361case ARCInstKind::StoreWeak:362case ARCInstKind::InitWeak:363case ARCInstKind::LoadWeak:364case ARCInstKind::MoveWeak:365case ARCInstKind::CopyWeak:366case ARCInstKind::DestroyWeak:367case ARCInstKind::StoreStrong:368case ARCInstKind::IntrinsicUser:369case ARCInstKind::CallOrUser:370case ARCInstKind::Call:371case ARCInstKind::User:372case ARCInstKind::None:373case ARCInstKind::UnsafeClaimRV:374return false;375}376llvm_unreachable("covered switch isn't covered?");377}
378
379/// Test if the given class is objc_autorelease or equivalent.
380bool llvm::objcarc::IsAutorelease(ARCInstKind Class) {381switch (Class) {382case ARCInstKind::Autorelease:383case ARCInstKind::AutoreleaseRV:384return true;385case ARCInstKind::Retain:386case ARCInstKind::RetainRV:387case ARCInstKind::UnsafeClaimRV:388case ARCInstKind::RetainBlock:389case ARCInstKind::Release:390case ARCInstKind::AutoreleasepoolPush:391case ARCInstKind::AutoreleasepoolPop:392case ARCInstKind::NoopCast:393case ARCInstKind::FusedRetainAutorelease:394case ARCInstKind::FusedRetainAutoreleaseRV:395case ARCInstKind::LoadWeakRetained:396case ARCInstKind::StoreWeak:397case ARCInstKind::InitWeak:398case ARCInstKind::LoadWeak:399case ARCInstKind::MoveWeak:400case ARCInstKind::CopyWeak:401case ARCInstKind::DestroyWeak:402case ARCInstKind::StoreStrong:403case ARCInstKind::IntrinsicUser:404case ARCInstKind::CallOrUser:405case ARCInstKind::Call:406case ARCInstKind::User:407case ARCInstKind::None:408return false;409}410llvm_unreachable("covered switch isn't covered?");411}
412
413/// Test if the given class represents instructions which return their
414/// argument verbatim.
415bool llvm::objcarc::IsForwarding(ARCInstKind Class) {416switch (Class) {417case ARCInstKind::Retain:418case ARCInstKind::RetainRV:419case ARCInstKind::UnsafeClaimRV:420case ARCInstKind::Autorelease:421case ARCInstKind::AutoreleaseRV:422case ARCInstKind::NoopCast:423return true;424case ARCInstKind::RetainBlock:425case ARCInstKind::Release:426case ARCInstKind::AutoreleasepoolPush:427case ARCInstKind::AutoreleasepoolPop:428case ARCInstKind::FusedRetainAutorelease:429case ARCInstKind::FusedRetainAutoreleaseRV:430case ARCInstKind::LoadWeakRetained:431case ARCInstKind::StoreWeak:432case ARCInstKind::InitWeak:433case ARCInstKind::LoadWeak:434case ARCInstKind::MoveWeak:435case ARCInstKind::CopyWeak:436case ARCInstKind::DestroyWeak:437case ARCInstKind::StoreStrong:438case ARCInstKind::IntrinsicUser:439case ARCInstKind::CallOrUser:440case ARCInstKind::Call:441case ARCInstKind::User:442case ARCInstKind::None:443return false;444}445llvm_unreachable("covered switch isn't covered?");446}
447
448/// Test if the given class represents instructions which do nothing if
449/// passed a null pointer.
450bool llvm::objcarc::IsNoopOnNull(ARCInstKind Class) {451switch (Class) {452case ARCInstKind::Retain:453case ARCInstKind::RetainRV:454case ARCInstKind::UnsafeClaimRV:455case ARCInstKind::Release:456case ARCInstKind::Autorelease:457case ARCInstKind::AutoreleaseRV:458case ARCInstKind::RetainBlock:459return true;460case ARCInstKind::AutoreleasepoolPush:461case ARCInstKind::AutoreleasepoolPop:462case ARCInstKind::FusedRetainAutorelease:463case ARCInstKind::FusedRetainAutoreleaseRV:464case ARCInstKind::LoadWeakRetained:465case ARCInstKind::StoreWeak:466case ARCInstKind::InitWeak:467case ARCInstKind::LoadWeak:468case ARCInstKind::MoveWeak:469case ARCInstKind::CopyWeak:470case ARCInstKind::DestroyWeak:471case ARCInstKind::StoreStrong:472case ARCInstKind::IntrinsicUser:473case ARCInstKind::CallOrUser:474case ARCInstKind::Call:475case ARCInstKind::User:476case ARCInstKind::None:477case ARCInstKind::NoopCast:478return false;479}480llvm_unreachable("covered switch isn't covered?");481}
482
483/// Test if the given class represents instructions which do nothing if
484/// passed a global variable.
485bool llvm::objcarc::IsNoopOnGlobal(ARCInstKind Class) {486switch (Class) {487case ARCInstKind::Retain:488case ARCInstKind::RetainRV:489case ARCInstKind::UnsafeClaimRV:490case ARCInstKind::Release:491case ARCInstKind::Autorelease:492case ARCInstKind::AutoreleaseRV:493case ARCInstKind::RetainBlock:494case ARCInstKind::FusedRetainAutorelease:495case ARCInstKind::FusedRetainAutoreleaseRV:496return true;497case ARCInstKind::AutoreleasepoolPush:498case ARCInstKind::AutoreleasepoolPop:499case ARCInstKind::LoadWeakRetained:500case ARCInstKind::StoreWeak:501case ARCInstKind::InitWeak:502case ARCInstKind::LoadWeak:503case ARCInstKind::MoveWeak:504case ARCInstKind::CopyWeak:505case ARCInstKind::DestroyWeak:506case ARCInstKind::StoreStrong:507case ARCInstKind::IntrinsicUser:508case ARCInstKind::CallOrUser:509case ARCInstKind::Call:510case ARCInstKind::User:511case ARCInstKind::None:512case ARCInstKind::NoopCast:513return false;514}515llvm_unreachable("covered switch isn't covered?");516}
517
518/// Test if the given class represents instructions which are always safe
519/// to mark with the "tail" keyword.
520bool llvm::objcarc::IsAlwaysTail(ARCInstKind Class) {521// ARCInstKind::RetainBlock may be given a stack argument.522switch (Class) {523case ARCInstKind::Retain:524case ARCInstKind::RetainRV:525case ARCInstKind::UnsafeClaimRV:526case ARCInstKind::AutoreleaseRV:527return true;528case ARCInstKind::Release:529case ARCInstKind::Autorelease:530case ARCInstKind::RetainBlock:531case ARCInstKind::AutoreleasepoolPush:532case ARCInstKind::AutoreleasepoolPop:533case ARCInstKind::FusedRetainAutorelease:534case ARCInstKind::FusedRetainAutoreleaseRV:535case ARCInstKind::LoadWeakRetained:536case ARCInstKind::StoreWeak:537case ARCInstKind::InitWeak:538case ARCInstKind::LoadWeak:539case ARCInstKind::MoveWeak:540case ARCInstKind::CopyWeak:541case ARCInstKind::DestroyWeak:542case ARCInstKind::StoreStrong:543case ARCInstKind::IntrinsicUser:544case ARCInstKind::CallOrUser:545case ARCInstKind::Call:546case ARCInstKind::User:547case ARCInstKind::None:548case ARCInstKind::NoopCast:549return false;550}551llvm_unreachable("covered switch isn't covered?");552}
553
554/// Test if the given class represents instructions which are never safe
555/// to mark with the "tail" keyword.
556bool llvm::objcarc::IsNeverTail(ARCInstKind Class) {557/// It is never safe to tail call objc_autorelease since by tail calling558/// objc_autorelease: fast autoreleasing causing our object to be potentially559/// reclaimed from the autorelease pool which violates the semantics of560/// __autoreleasing types in ARC.561switch (Class) {562case ARCInstKind::Autorelease:563return true;564case ARCInstKind::Retain:565case ARCInstKind::RetainRV:566case ARCInstKind::UnsafeClaimRV:567case ARCInstKind::AutoreleaseRV:568case ARCInstKind::Release:569case ARCInstKind::RetainBlock:570case ARCInstKind::AutoreleasepoolPush:571case ARCInstKind::AutoreleasepoolPop:572case ARCInstKind::FusedRetainAutorelease:573case ARCInstKind::FusedRetainAutoreleaseRV:574case ARCInstKind::LoadWeakRetained:575case ARCInstKind::StoreWeak:576case ARCInstKind::InitWeak:577case ARCInstKind::LoadWeak:578case ARCInstKind::MoveWeak:579case ARCInstKind::CopyWeak:580case ARCInstKind::DestroyWeak:581case ARCInstKind::StoreStrong:582case ARCInstKind::IntrinsicUser:583case ARCInstKind::CallOrUser:584case ARCInstKind::Call:585case ARCInstKind::User:586case ARCInstKind::None:587case ARCInstKind::NoopCast:588return false;589}590llvm_unreachable("covered switch isn't covered?");591}
592
593/// Test if the given class represents instructions which are always safe
594/// to mark with the nounwind attribute.
595bool llvm::objcarc::IsNoThrow(ARCInstKind Class) {596// objc_retainBlock is not nounwind because it calls user copy constructors597// which could theoretically throw.598switch (Class) {599case ARCInstKind::Retain:600case ARCInstKind::RetainRV:601case ARCInstKind::UnsafeClaimRV:602case ARCInstKind::Release:603case ARCInstKind::Autorelease:604case ARCInstKind::AutoreleaseRV:605case ARCInstKind::AutoreleasepoolPush:606case ARCInstKind::AutoreleasepoolPop:607return true;608case ARCInstKind::RetainBlock:609case ARCInstKind::FusedRetainAutorelease:610case ARCInstKind::FusedRetainAutoreleaseRV:611case ARCInstKind::LoadWeakRetained:612case ARCInstKind::StoreWeak:613case ARCInstKind::InitWeak:614case ARCInstKind::LoadWeak:615case ARCInstKind::MoveWeak:616case ARCInstKind::CopyWeak:617case ARCInstKind::DestroyWeak:618case ARCInstKind::StoreStrong:619case ARCInstKind::IntrinsicUser:620case ARCInstKind::CallOrUser:621case ARCInstKind::Call:622case ARCInstKind::User:623case ARCInstKind::None:624case ARCInstKind::NoopCast:625return false;626}627llvm_unreachable("covered switch isn't covered?");628}
629
630/// Test whether the given instruction can autorelease any pointer or cause an
631/// autoreleasepool pop.
632///
633/// This means that it *could* interrupt the RV optimization.
634bool llvm::objcarc::CanInterruptRV(ARCInstKind Class) {635switch (Class) {636case ARCInstKind::AutoreleasepoolPop:637case ARCInstKind::CallOrUser:638case ARCInstKind::Call:639case ARCInstKind::Autorelease:640case ARCInstKind::AutoreleaseRV:641case ARCInstKind::FusedRetainAutorelease:642case ARCInstKind::FusedRetainAutoreleaseRV:643return true;644case ARCInstKind::Retain:645case ARCInstKind::RetainRV:646case ARCInstKind::UnsafeClaimRV:647case ARCInstKind::Release:648case ARCInstKind::AutoreleasepoolPush:649case ARCInstKind::RetainBlock:650case ARCInstKind::LoadWeakRetained:651case ARCInstKind::StoreWeak:652case ARCInstKind::InitWeak:653case ARCInstKind::LoadWeak:654case ARCInstKind::MoveWeak:655case ARCInstKind::CopyWeak:656case ARCInstKind::DestroyWeak:657case ARCInstKind::StoreStrong:658case ARCInstKind::IntrinsicUser:659case ARCInstKind::User:660case ARCInstKind::None:661case ARCInstKind::NoopCast:662return false;663}664llvm_unreachable("covered switch isn't covered?");665}
666
667bool llvm::objcarc::CanDecrementRefCount(ARCInstKind Kind) {668switch (Kind) {669case ARCInstKind::Retain:670case ARCInstKind::RetainRV:671case ARCInstKind::Autorelease:672case ARCInstKind::AutoreleaseRV:673case ARCInstKind::NoopCast:674case ARCInstKind::FusedRetainAutorelease:675case ARCInstKind::FusedRetainAutoreleaseRV:676case ARCInstKind::IntrinsicUser:677case ARCInstKind::User:678case ARCInstKind::None:679return false;680
681// The cases below are conservative.682
683// RetainBlock can result in user defined copy constructors being called684// implying releases may occur.685case ARCInstKind::RetainBlock:686case ARCInstKind::Release:687case ARCInstKind::AutoreleasepoolPush:688case ARCInstKind::AutoreleasepoolPop:689case ARCInstKind::LoadWeakRetained:690case ARCInstKind::StoreWeak:691case ARCInstKind::InitWeak:692case ARCInstKind::LoadWeak:693case ARCInstKind::MoveWeak:694case ARCInstKind::CopyWeak:695case ARCInstKind::DestroyWeak:696case ARCInstKind::StoreStrong:697case ARCInstKind::CallOrUser:698case ARCInstKind::Call:699case ARCInstKind::UnsafeClaimRV:700return true;701}702
703llvm_unreachable("covered switch isn't covered?");704}
705