LCOV - code coverage report
Current view: top level - lib/Analysis - ObjCARCInstKind.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 59 122 48.4 %
Date: 2018-10-20 13:21:21 Functions: 13 14 92.9 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13