1 //===- PtrState.h - ARC State for a Ptr -------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file contains declarations for the ARC state associated with a ptr. It
11 // is only used by the ARC Sequence Dataflow computation. By separating this
12 // from the actual dataflow, it is easier to consider the mechanics of the ARC
13 // optimization separate from the actual predicates being used.
15 //===----------------------------------------------------------------------===//
17 #ifndef LLVM_LIB_TRANSFORMS_OBJCARC_PTRSTATE_H
18 #define LLVM_LIB_TRANSFORMS_OBJCARC_PTRSTATE_H
20 #include "llvm/ADT/SmallPtrSet.h"
21 #include "llvm/Analysis/ObjCARCInstKind.h"
22 #include "llvm/Support/Compiler.h"
35 class ProvenanceAnalysis;
39 /// \brief A sequence of states that a pointer may go through in which an
40 /// objc_retain and objc_release are actually needed.
43 S_Retain, ///< objc_retain(x).
44 S_CanRelease, ///< foo(x) -- x could possibly see a ref count decrement.
45 S_Use, ///< any use of x.
46 S_Stop, ///< like S_Release, but code motion is stopped.
47 S_Release, ///< objc_release(x).
48 S_MovableRelease ///< objc_release(x), !clang.imprecise_release.
51 raw_ostream &operator<<(raw_ostream &OS,
52 const Sequence S) LLVM_ATTRIBUTE_UNUSED;
54 /// \brief Unidirectional information about either a
55 /// retain-decrement-use-release sequence or release-use-decrement-retain
58 /// After an objc_retain, the reference count of the referenced
59 /// object is known to be positive. Similarly, before an objc_release, the
60 /// reference count of the referenced object is known to be positive. If
61 /// there are retain-release pairs in code regions where the retain count
62 /// is known to be positive, they can be eliminated, regardless of any side
63 /// effects between them.
65 /// Also, a retain+release pair nested within another retain+release
66 /// pair all on the known same pointer value can be eliminated, regardless
67 /// of any intervening side effects.
69 /// KnownSafe is true when either of these conditions is satisfied.
70 bool KnownSafe = false;
72 /// True of the objc_release calls are all marked with the "tail" keyword.
73 bool IsTailCallRelease = false;
75 /// If the Calls are objc_release calls and they all have a
76 /// clang.imprecise_release tag, this is the metadata tag.
77 MDNode *ReleaseMetadata = nullptr;
79 /// For a top-down sequence, the set of objc_retains or
80 /// objc_retainBlocks. For bottom-up, the set of objc_releases.
81 SmallPtrSet<Instruction *, 2> Calls;
83 /// The set of optimal insert positions for moving calls in the opposite
85 SmallPtrSet<Instruction *, 2> ReverseInsertPts;
87 /// If this is true, we cannot perform code motion but can still remove
88 /// retain/release pairs.
89 bool CFGHazardAfflicted = false;
95 /// Conservatively merge the two RRInfo. Returns true if a partial merge has
96 /// occurred, false otherwise.
97 bool Merge(const RRInfo &Other);
100 /// \brief This class summarizes several per-pointer runtime properties which
101 /// are propagated through the flow graph.
104 /// True if the reference count is known to be incremented.
105 bool KnownPositiveRefCount = false;
107 /// True if we've seen an opportunity for partial RR elimination, such as
108 /// pushing calls into a CFG triangle or into one side of a CFG diamond.
109 bool Partial = false;
111 /// The current position in the sequence.
112 unsigned char Seq : 8;
114 /// Unidirectional information about the current sequence.
117 PtrState() : Seq(S_None) {}
120 bool IsKnownSafe() const { return RRI.KnownSafe; }
122 void SetKnownSafe(const bool NewValue) { RRI.KnownSafe = NewValue; }
124 bool IsTailCallRelease() const { return RRI.IsTailCallRelease; }
126 void SetTailCallRelease(const bool NewValue) {
127 RRI.IsTailCallRelease = NewValue;
130 bool IsTrackingImpreciseReleases() const {
131 return RRI.ReleaseMetadata != nullptr;
134 const MDNode *GetReleaseMetadata() const { return RRI.ReleaseMetadata; }
136 void SetReleaseMetadata(MDNode *NewValue) { RRI.ReleaseMetadata = NewValue; }
138 bool IsCFGHazardAfflicted() const { return RRI.CFGHazardAfflicted; }
140 void SetCFGHazardAfflicted(const bool NewValue) {
141 RRI.CFGHazardAfflicted = NewValue;
144 void SetKnownPositiveRefCount();
145 void ClearKnownPositiveRefCount();
147 bool HasKnownPositiveRefCount() const { return KnownPositiveRefCount; }
149 void SetSeq(Sequence NewSeq);
151 Sequence GetSeq() const { return static_cast<Sequence>(Seq); }
153 void ClearSequenceProgress() { ResetSequenceProgress(S_None); }
155 void ResetSequenceProgress(Sequence NewSeq);
156 void Merge(const PtrState &Other, bool TopDown);
158 void InsertCall(Instruction *I) { RRI.Calls.insert(I); }
160 void InsertReverseInsertPt(Instruction *I) { RRI.ReverseInsertPts.insert(I); }
162 void ClearReverseInsertPts() { RRI.ReverseInsertPts.clear(); }
164 bool HasReverseInsertPts() const { return !RRI.ReverseInsertPts.empty(); }
166 const RRInfo &GetRRInfo() const { return RRI; }
169 struct BottomUpPtrState : PtrState {
170 BottomUpPtrState() = default;
172 /// (Re-)Initialize this bottom up pointer returning true if we detected a
173 /// pointer with nested releases.
174 bool InitBottomUp(ARCMDKindCache &Cache, Instruction *I);
176 /// Return true if this set of releases can be paired with a release. Modifies
177 /// state appropriately to reflect that the matching occurred if it is
180 /// It is assumed that one has already checked that the RCIdentity of the
181 /// retain and the RCIdentity of this ptr state are the same.
182 bool MatchWithRetain();
184 void HandlePotentialUse(BasicBlock *BB, Instruction *Inst, const Value *Ptr,
185 ProvenanceAnalysis &PA, ARCInstKind Class);
186 bool HandlePotentialAlterRefCount(Instruction *Inst, const Value *Ptr,
187 ProvenanceAnalysis &PA, ARCInstKind Class);
190 struct TopDownPtrState : PtrState {
191 TopDownPtrState() = default;
193 /// (Re-)Initialize this bottom up pointer returning true if we detected a
194 /// pointer with nested releases.
195 bool InitTopDown(ARCInstKind Kind, Instruction *I);
197 /// Return true if this set of retains can be paired with the given
198 /// release. Modifies state appropriately to reflect that the matching
200 bool MatchWithRelease(ARCMDKindCache &Cache, Instruction *Release);
202 void HandlePotentialUse(Instruction *Inst, const Value *Ptr,
203 ProvenanceAnalysis &PA, ARCInstKind Class);
205 bool HandlePotentialAlterRefCount(Instruction *Inst, const Value *Ptr,
206 ProvenanceAnalysis &PA, ARCInstKind Class);
209 } // end namespace objcarc
211 } // end namespace llvm
213 #endif // LLVM_LIB_TRANSFORMS_OBJCARC_PTRSTATE_H