157bd5a02SEugene Zelenko //===- PtrState.h - ARC State for a Ptr -------------------------*- C++ -*-===// 268b91dbfSMichael Gottesman // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 668b91dbfSMichael Gottesman // 768b91dbfSMichael Gottesman //===----------------------------------------------------------------------===// 868b91dbfSMichael Gottesman // 968b91dbfSMichael Gottesman // This file contains declarations for the ARC state associated with a ptr. It 1068b91dbfSMichael Gottesman // is only used by the ARC Sequence Dataflow computation. By separating this 1168b91dbfSMichael Gottesman // from the actual dataflow, it is easier to consider the mechanics of the ARC 1268b91dbfSMichael Gottesman // optimization separate from the actual predicates being used. 1368b91dbfSMichael Gottesman // 1468b91dbfSMichael Gottesman //===----------------------------------------------------------------------===// 1568b91dbfSMichael Gottesman 1668b91dbfSMichael Gottesman #ifndef LLVM_LIB_TRANSFORMS_OBJCARC_PTRSTATE_H 1768b91dbfSMichael Gottesman #define LLVM_LIB_TRANSFORMS_OBJCARC_PTRSTATE_H 1868b91dbfSMichael Gottesman 1968b91dbfSMichael Gottesman #include "llvm/ADT/SmallPtrSet.h" 200f792189SChandler Carruth #include "llvm/Analysis/ObjCARCInstKind.h" 2157bd5a02SEugene Zelenko #include "llvm/Support/Compiler.h" 2268b91dbfSMichael Gottesman 2368b91dbfSMichael Gottesman namespace llvm { 2457bd5a02SEugene Zelenko 2557bd5a02SEugene Zelenko class BasicBlock; 2657bd5a02SEugene Zelenko class Instruction; 2757bd5a02SEugene Zelenko class MDNode; 2857bd5a02SEugene Zelenko class raw_ostream; 2957bd5a02SEugene Zelenko class Value; 3057bd5a02SEugene Zelenko 3168b91dbfSMichael Gottesman namespace objcarc { 3268b91dbfSMichael Gottesman 3365cb7377SMichael Gottesman class ARCMDKindCache; 34*19005035SAkira Hatanaka class BundledRetainClaimRVs; 3516e6a205SMichael Gottesman class ProvenanceAnalysis; 364eae396aSMichael Gottesman 3768b91dbfSMichael Gottesman /// \enum Sequence 3868b91dbfSMichael Gottesman /// 395f8f34e4SAdrian Prantl /// A sequence of states that a pointer may go through in which an 4068b91dbfSMichael Gottesman /// objc_retain and objc_release are actually needed. 4168b91dbfSMichael Gottesman enum Sequence { 4268b91dbfSMichael Gottesman S_None, 4368b91dbfSMichael Gottesman S_Retain, ///< objc_retain(x). 4468b91dbfSMichael Gottesman S_CanRelease, ///< foo(x) -- x could possibly see a ref count decrement. 4568b91dbfSMichael Gottesman S_Use, ///< any use of x. 4632dc79c5SAkira Hatanaka S_Stop, ///< code motion is stopped. 4768b91dbfSMichael Gottesman S_MovableRelease ///< objc_release(x), !clang.imprecise_release. 4868b91dbfSMichael Gottesman }; 4968b91dbfSMichael Gottesman 5068b91dbfSMichael Gottesman raw_ostream &operator<<(raw_ostream &OS, 5168b91dbfSMichael Gottesman const Sequence S) LLVM_ATTRIBUTE_UNUSED; 5268b91dbfSMichael Gottesman 535f8f34e4SAdrian Prantl /// Unidirectional information about either a 5468b91dbfSMichael Gottesman /// retain-decrement-use-release sequence or release-use-decrement-retain 5568b91dbfSMichael Gottesman /// reverse sequence. 5668b91dbfSMichael Gottesman struct RRInfo { 5768b91dbfSMichael Gottesman /// After an objc_retain, the reference count of the referenced 5868b91dbfSMichael Gottesman /// object is known to be positive. Similarly, before an objc_release, the 5968b91dbfSMichael Gottesman /// reference count of the referenced object is known to be positive. If 6068b91dbfSMichael Gottesman /// there are retain-release pairs in code regions where the retain count 6168b91dbfSMichael Gottesman /// is known to be positive, they can be eliminated, regardless of any side 6268b91dbfSMichael Gottesman /// effects between them. 6368b91dbfSMichael Gottesman /// 6468b91dbfSMichael Gottesman /// Also, a retain+release pair nested within another retain+release 6568b91dbfSMichael Gottesman /// pair all on the known same pointer value can be eliminated, regardless 6668b91dbfSMichael Gottesman /// of any intervening side effects. 6768b91dbfSMichael Gottesman /// 6868b91dbfSMichael Gottesman /// KnownSafe is true when either of these conditions is satisfied. 6957bd5a02SEugene Zelenko bool KnownSafe = false; 7068b91dbfSMichael Gottesman 7168b91dbfSMichael Gottesman /// True of the objc_release calls are all marked with the "tail" keyword. 7257bd5a02SEugene Zelenko bool IsTailCallRelease = false; 7368b91dbfSMichael Gottesman 7468b91dbfSMichael Gottesman /// If the Calls are objc_release calls and they all have a 7568b91dbfSMichael Gottesman /// clang.imprecise_release tag, this is the metadata tag. 7657bd5a02SEugene Zelenko MDNode *ReleaseMetadata = nullptr; 7768b91dbfSMichael Gottesman 7868b91dbfSMichael Gottesman /// For a top-down sequence, the set of objc_retains or 7968b91dbfSMichael Gottesman /// objc_retainBlocks. For bottom-up, the set of objc_releases. 8068b91dbfSMichael Gottesman SmallPtrSet<Instruction *, 2> Calls; 8168b91dbfSMichael Gottesman 8268b91dbfSMichael Gottesman /// The set of optimal insert positions for moving calls in the opposite 8368b91dbfSMichael Gottesman /// sequence. 8468b91dbfSMichael Gottesman SmallPtrSet<Instruction *, 2> ReverseInsertPts; 8568b91dbfSMichael Gottesman 8668b91dbfSMichael Gottesman /// If this is true, we cannot perform code motion but can still remove 8768b91dbfSMichael Gottesman /// retain/release pairs. 8857bd5a02SEugene Zelenko bool CFGHazardAfflicted = false; 8968b91dbfSMichael Gottesman 9057bd5a02SEugene Zelenko RRInfo() = default; 9168b91dbfSMichael Gottesman 9268b91dbfSMichael Gottesman void clear(); 9368b91dbfSMichael Gottesman 9468b91dbfSMichael Gottesman /// Conservatively merge the two RRInfo. Returns true if a partial merge has 9568b91dbfSMichael Gottesman /// occurred, false otherwise. 9668b91dbfSMichael Gottesman bool Merge(const RRInfo &Other); 9768b91dbfSMichael Gottesman }; 9868b91dbfSMichael Gottesman 995f8f34e4SAdrian Prantl /// This class summarizes several per-pointer runtime properties which 100df005cbeSBenjamin Kramer /// are propagated through the flow graph. 10168b91dbfSMichael Gottesman class PtrState { 102feb138e2SMichael Gottesman protected: 10368b91dbfSMichael Gottesman /// True if the reference count is known to be incremented. 10457bd5a02SEugene Zelenko bool KnownPositiveRefCount = false; 10568b91dbfSMichael Gottesman 10668b91dbfSMichael Gottesman /// True if we've seen an opportunity for partial RR elimination, such as 10768b91dbfSMichael Gottesman /// pushing calls into a CFG triangle or into one side of a CFG diamond. 10857bd5a02SEugene Zelenko bool Partial = false; 10968b91dbfSMichael Gottesman 11068b91dbfSMichael Gottesman /// The current position in the sequence. 11168b91dbfSMichael Gottesman unsigned char Seq : 8; 11268b91dbfSMichael Gottesman 11368b91dbfSMichael Gottesman /// Unidirectional information about the current sequence. 11468b91dbfSMichael Gottesman RRInfo RRI; 11568b91dbfSMichael Gottesman PtrState()11657bd5a02SEugene Zelenko PtrState() : Seq(S_None) {} 11768b91dbfSMichael Gottesman 118feb138e2SMichael Gottesman public: IsKnownSafe()11968b91dbfSMichael Gottesman bool IsKnownSafe() const { return RRI.KnownSafe; } 12068b91dbfSMichael Gottesman SetKnownSafe(const bool NewValue)12168b91dbfSMichael Gottesman void SetKnownSafe(const bool NewValue) { RRI.KnownSafe = NewValue; } 12268b91dbfSMichael Gottesman IsTailCallRelease()12368b91dbfSMichael Gottesman bool IsTailCallRelease() const { return RRI.IsTailCallRelease; } 12468b91dbfSMichael Gottesman SetTailCallRelease(const bool NewValue)12568b91dbfSMichael Gottesman void SetTailCallRelease(const bool NewValue) { 12668b91dbfSMichael Gottesman RRI.IsTailCallRelease = NewValue; 12768b91dbfSMichael Gottesman } 12868b91dbfSMichael Gottesman IsTrackingImpreciseReleases()12968b91dbfSMichael Gottesman bool IsTrackingImpreciseReleases() const { 13068b91dbfSMichael Gottesman return RRI.ReleaseMetadata != nullptr; 13168b91dbfSMichael Gottesman } 13268b91dbfSMichael Gottesman GetReleaseMetadata()13368b91dbfSMichael Gottesman const MDNode *GetReleaseMetadata() const { return RRI.ReleaseMetadata; } 13468b91dbfSMichael Gottesman SetReleaseMetadata(MDNode * NewValue)13568b91dbfSMichael Gottesman void SetReleaseMetadata(MDNode *NewValue) { RRI.ReleaseMetadata = NewValue; } 13668b91dbfSMichael Gottesman IsCFGHazardAfflicted()13768b91dbfSMichael Gottesman bool IsCFGHazardAfflicted() const { return RRI.CFGHazardAfflicted; } 13868b91dbfSMichael Gottesman SetCFGHazardAfflicted(const bool NewValue)13968b91dbfSMichael Gottesman void SetCFGHazardAfflicted(const bool NewValue) { 14068b91dbfSMichael Gottesman RRI.CFGHazardAfflicted = NewValue; 14168b91dbfSMichael Gottesman } 14268b91dbfSMichael Gottesman 143d45907bdSMichael Gottesman void SetKnownPositiveRefCount(); 144d45907bdSMichael Gottesman void ClearKnownPositiveRefCount(); 14568b91dbfSMichael Gottesman HasKnownPositiveRefCount()14668b91dbfSMichael Gottesman bool HasKnownPositiveRefCount() const { return KnownPositiveRefCount; } 14768b91dbfSMichael Gottesman 148d45907bdSMichael Gottesman void SetSeq(Sequence NewSeq); 14968b91dbfSMichael Gottesman GetSeq()15068b91dbfSMichael Gottesman Sequence GetSeq() const { return static_cast<Sequence>(Seq); } 15168b91dbfSMichael Gottesman ClearSequenceProgress()15268b91dbfSMichael Gottesman void ClearSequenceProgress() { ResetSequenceProgress(S_None); } 15368b91dbfSMichael Gottesman 154d45907bdSMichael Gottesman void ResetSequenceProgress(Sequence NewSeq); 15568b91dbfSMichael Gottesman void Merge(const PtrState &Other, bool TopDown); 15668b91dbfSMichael Gottesman InsertCall(Instruction * I)15768b91dbfSMichael Gottesman void InsertCall(Instruction *I) { RRI.Calls.insert(I); } 15868b91dbfSMichael Gottesman InsertReverseInsertPt(Instruction * I)15968b91dbfSMichael Gottesman void InsertReverseInsertPt(Instruction *I) { RRI.ReverseInsertPts.insert(I); } 16068b91dbfSMichael Gottesman ClearReverseInsertPts()16168b91dbfSMichael Gottesman void ClearReverseInsertPts() { RRI.ReverseInsertPts.clear(); } 16268b91dbfSMichael Gottesman HasReverseInsertPts()16368b91dbfSMichael Gottesman bool HasReverseInsertPts() const { return !RRI.ReverseInsertPts.empty(); } 16468b91dbfSMichael Gottesman GetRRInfo()16568b91dbfSMichael Gottesman const RRInfo &GetRRInfo() const { return RRI; } 16668b91dbfSMichael Gottesman }; 16768b91dbfSMichael Gottesman 168feb138e2SMichael Gottesman struct BottomUpPtrState : PtrState { 16957bd5a02SEugene Zelenko BottomUpPtrState() = default; 1704eae396aSMichael Gottesman 1714eae396aSMichael Gottesman /// (Re-)Initialize this bottom up pointer returning true if we detected a 1724eae396aSMichael Gottesman /// pointer with nested releases. 1734eae396aSMichael Gottesman bool InitBottomUp(ARCMDKindCache &Cache, Instruction *I); 17460805963SMichael Gottesman 17560805963SMichael Gottesman /// Return true if this set of releases can be paired with a release. Modifies 176df005cbeSBenjamin Kramer /// state appropriately to reflect that the matching occurred if it is 17760805963SMichael Gottesman /// successful. 17860805963SMichael Gottesman /// 17960805963SMichael Gottesman /// It is assumed that one has already checked that the RCIdentity of the 18060805963SMichael Gottesman /// retain and the RCIdentity of this ptr state are the same. 18160805963SMichael Gottesman bool MatchWithRetain(); 18216e6a205SMichael Gottesman 18316e6a205SMichael Gottesman void HandlePotentialUse(BasicBlock *BB, Instruction *Inst, const Value *Ptr, 18416e6a205SMichael Gottesman ProvenanceAnalysis &PA, ARCInstKind Class); 18516e6a205SMichael Gottesman bool HandlePotentialAlterRefCount(Instruction *Inst, const Value *Ptr, 18616e6a205SMichael Gottesman ProvenanceAnalysis &PA, ARCInstKind Class); 187feb138e2SMichael Gottesman }; 188feb138e2SMichael Gottesman 189feb138e2SMichael Gottesman struct TopDownPtrState : PtrState { 19057bd5a02SEugene Zelenko TopDownPtrState() = default; 1914eae396aSMichael Gottesman 1924eae396aSMichael Gottesman /// (Re-)Initialize this bottom up pointer returning true if we detected a 1934eae396aSMichael Gottesman /// pointer with nested releases. 1944eae396aSMichael Gottesman bool InitTopDown(ARCInstKind Kind, Instruction *I); 19560805963SMichael Gottesman 19660805963SMichael Gottesman /// Return true if this set of retains can be paired with the given 19760805963SMichael Gottesman /// release. Modifies state appropriately to reflect that the matching 198df005cbeSBenjamin Kramer /// occurred. 19960805963SMichael Gottesman bool MatchWithRelease(ARCMDKindCache &Cache, Instruction *Release); 20016e6a205SMichael Gottesman 20116e6a205SMichael Gottesman void HandlePotentialUse(Instruction *Inst, const Value *Ptr, 20216e6a205SMichael Gottesman ProvenanceAnalysis &PA, ARCInstKind Class); 20316e6a205SMichael Gottesman 20416e6a205SMichael Gottesman bool HandlePotentialAlterRefCount(Instruction *Inst, const Value *Ptr, 205*19005035SAkira Hatanaka ProvenanceAnalysis &PA, ARCInstKind Class, 206*19005035SAkira Hatanaka const BundledRetainClaimRVs &BundledRVs); 207feb138e2SMichael Gottesman }; 208feb138e2SMichael Gottesman 20968b91dbfSMichael Gottesman } // end namespace objcarc 21057bd5a02SEugene Zelenko 21168b91dbfSMichael Gottesman } // end namespace llvm 21268b91dbfSMichael Gottesman 21357bd5a02SEugene Zelenko #endif // LLVM_LIB_TRANSFORMS_OBJCARC_PTRSTATE_H 214