From 24ee447d0fcd12c1915919e835b26fbdfde74a9f Mon Sep 17 00:00:00 2001 From: Michael Gottesman Date: Fri, 20 Feb 2015 00:02:45 +0000 Subject: [PATCH] [objc-arc] Add the predicate CanDecrementRefCount. 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 | 38 +++++++++++++++++++ lib/Transforms/ObjCARC/ARCInstKind.h | 8 +++- lib/Transforms/ObjCARC/DependencyAnalysis.cpp | 12 ++++++ lib/Transforms/ObjCARC/DependencyAnalysis.h | 5 +++ 4 files changed, 61 insertions(+), 2 deletions(-) diff --git a/lib/Transforms/ObjCARC/ARCInstKind.cpp b/lib/Transforms/ObjCARC/ARCInstKind.cpp index e086e1f5239..f1e9dcecfc8 100644 --- a/lib/Transforms/ObjCARC/ARCInstKind.cpp +++ b/lib/Transforms/ObjCARC/ARCInstKind.cpp @@ -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?"); +} diff --git a/lib/Transforms/ObjCARC/ARCInstKind.h b/lib/Transforms/ObjCARC/ARCInstKind.h index e8e4fed5489..636c65c9b62 100644 --- a/lib/Transforms/ObjCARC/ARCInstKind.h +++ b/lib/Transforms/ObjCARC/ARCInstKind.h @@ -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(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 diff --git a/lib/Transforms/ObjCARC/DependencyAnalysis.cpp b/lib/Transforms/ObjCARC/DependencyAnalysis.cpp index 9eb91a55a01..4985d0ebfd0 100644 --- a/lib/Transforms/ObjCARC/DependencyAnalysis.cpp +++ b/lib/Transforms/ObjCARC/DependencyAnalysis.cpp @@ -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, diff --git a/lib/Transforms/ObjCARC/DependencyAnalysis.h b/lib/Transforms/ObjCARC/DependencyAnalysis.h index 77e4bdf5021..e5f9db9ada1 100644 --- a/lib/Transforms/ObjCARC/DependencyAnalysis.h +++ b/lib/Transforms/ObjCARC/DependencyAnalysis.h @@ -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 -- 2.34.1