[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.

llvm-svn: 229936

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

index e086e1f..f1e9dce 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 e8e4fed..636c65c 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 9eb91a5..4985d0e 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 77e4bdf..e5f9db9 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