[objc-arc] Add the predicate CanDecrementRefCount.
authorMichael Gottesman <mgottesman@apple.com>
Fri, 20 Feb 2015 00:02:45 +0000 (00:02 +0000)
committerMichael Gottesman <mgottesman@apple.com>
Fri, 20 Feb 2015 00:02:45 +0000 (00:02 +0000)
This is different from CanAlterRefCount since CanDecrementRefCount is
attempting to prove specifically whether or not an instruction can
decrement instead of the more general question of whether it can
decrement or increment.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@229936 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/ObjCARC/ARCInstKind.cpp
lib/Transforms/ObjCARC/ARCInstKind.h
lib/Transforms/ObjCARC/DependencyAnalysis.cpp
lib/Transforms/ObjCARC/DependencyAnalysis.h

index e086e1f5239671e3c5e99412b3cfc03abc1f2fdf..f1e9dcecfc83af81bea8a66517a29a8c83025d98 100644 (file)
@@ -605,3 +605,41 @@ bool llvm::objcarc::CanInterruptRV(ARCInstKind Class) {
   }
   llvm_unreachable("covered switch isn't covered?");
 }
+
+bool llvm::objcarc::CanDecrementRefCount(ARCInstKind Kind) {
+  switch (Kind) {
+  case ARCInstKind::Retain:
+  case ARCInstKind::RetainRV:
+  case ARCInstKind::Autorelease:
+  case ARCInstKind::AutoreleaseRV:
+  case ARCInstKind::NoopCast:
+  case ARCInstKind::FusedRetainAutorelease:
+  case ARCInstKind::FusedRetainAutoreleaseRV:
+  case ARCInstKind::IntrinsicUser:
+  case ARCInstKind::User:
+  case ARCInstKind::None:
+    return false;
+
+  // The cases below are conservative.
+
+  // RetainBlock can result in user defined copy constructors being called
+  // implying releases may occur.
+  case ARCInstKind::RetainBlock:
+  case ARCInstKind::Release:
+  case ARCInstKind::AutoreleasepoolPush:
+  case ARCInstKind::AutoreleasepoolPop:
+  case ARCInstKind::LoadWeakRetained:
+  case ARCInstKind::StoreWeak:
+  case ARCInstKind::InitWeak:
+  case ARCInstKind::LoadWeak:
+  case ARCInstKind::MoveWeak:
+  case ARCInstKind::CopyWeak:
+  case ARCInstKind::DestroyWeak:
+  case ARCInstKind::StoreStrong:
+  case ARCInstKind::CallOrUser:
+  case ARCInstKind::Call:
+    return true;
+  }
+
+  llvm_unreachable("covered switch isn't covered?");
+}
index e8e4fed54895cff5a10816001546f2a534113a2d..636c65c9b627de247768207f97a2399b570e015a 100644 (file)
@@ -51,7 +51,7 @@ enum class ARCInstKind {
   CallOrUser,               ///< could call objc_release and/or "use" pointers
   Call,                     ///< could call objc_release
   User,                     ///< could "use" a pointer
-  None                      ///< anything else
+  None                      ///< anything that is inert from an ARC perspective.
 };
 
 raw_ostream &operator<<(raw_ostream &OS, const ARCInstKind Class);
@@ -110,9 +110,13 @@ static inline ARCInstKind GetBasicARCInstKind(const Value *V) {
   return isa<InvokeInst>(V) ? ARCInstKind::CallOrUser : ARCInstKind::User;
 }
 
-/// \brief Determine what kind of construct V is.
+/// Map V to its ARCInstKind equivalence class.
 ARCInstKind GetARCInstKind(const Value *V);
 
+/// Returns false if conservatively we can prove that any instruction mapped to
+/// this kind can not decrement ref counts. Returns true otherwise.
+bool CanDecrementRefCount(ARCInstKind Kind);
+
 } // end namespace objcarc
 } // end namespace llvm
 
index 9eb91a55a0170bf22aa521340da856ec7164d877..4985d0ebfd0ae8ad5243290941faac621967858c 100644 (file)
@@ -66,6 +66,18 @@ bool llvm::objcarc::CanAlterRefCount(const Instruction *Inst, const Value *Ptr,
   return true;
 }
 
+bool llvm::objcarc::CanDecrementRefCount(const Instruction *Inst,
+                                         const Value *Ptr,
+                                         ProvenanceAnalysis &PA,
+                                         ARCInstKind Class) {
+  // First perform a quick check if Class can not touch ref counts.
+  if (!CanDecrementRefCount(Class))
+    return false;
+
+  // Otherwise, just use CanAlterRefCount for now.
+  return CanAlterRefCount(Inst, Ptr, PA, Class);
+}
+
 /// Test whether the given instruction can "use" the given pointer's object in a
 /// way that requires the reference count to be positive.
 bool llvm::objcarc::CanUse(const Instruction *Inst, const Value *Ptr,
index 77e4bdf5021095bbeab419e72b71c6ef6f479e6b..e5f9db9ada1201a41798de0bedfe5e6b53e515e4 100644 (file)
@@ -71,6 +71,11 @@ bool CanUse(const Instruction *Inst, const Value *Ptr, ProvenanceAnalysis &PA,
 bool CanAlterRefCount(const Instruction *Inst, const Value *Ptr,
                       ProvenanceAnalysis &PA, ARCInstKind Class);
 
+/// Returns true if we can not conservatively prove that Inst can not decrement
+/// the reference count of Ptr. Returns false if we can.
+bool CanDecrementRefCount(const Instruction *Inst, const Value *Ptr,
+                          ProvenanceAnalysis &PA, ARCInstKind Class);
+
 } // namespace objcarc
 } // namespace llvm