xref: /llvm-project/llvm/lib/Transforms/ObjCARC/PtrState.h (revision 1900503595cbb84a4c6e140a9ba1a2c574c0586d)
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