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