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/IR/Instruction.h"
22 #include "llvm/IR/Value.h"
23 #include "llvm/Support/raw_ostream.h"
24 #include "llvm/Support/Debug.h"
31 /// \brief A sequence of states that a pointer may go through in which an
32 /// objc_retain and objc_release are actually needed.
35 S_Retain, ///< objc_retain(x).
36 S_CanRelease, ///< foo(x) -- x could possibly see a ref count decrement.
37 S_Use, ///< any use of x.
38 S_Stop, ///< like S_Release, but code motion is stopped.
39 S_Release, ///< objc_release(x).
40 S_MovableRelease ///< objc_release(x), !clang.imprecise_release.
43 raw_ostream &operator<<(raw_ostream &OS,
44 const Sequence S) LLVM_ATTRIBUTE_UNUSED;
46 /// \brief Unidirectional information about either a
47 /// retain-decrement-use-release sequence or release-use-decrement-retain
50 /// After an objc_retain, the reference count of the referenced
51 /// object is known to be positive. Similarly, before an objc_release, the
52 /// reference count of the referenced object is known to be positive. If
53 /// there are retain-release pairs in code regions where the retain count
54 /// is known to be positive, they can be eliminated, regardless of any side
55 /// effects between them.
57 /// Also, a retain+release pair nested within another retain+release
58 /// pair all on the known same pointer value can be eliminated, regardless
59 /// of any intervening side effects.
61 /// KnownSafe is true when either of these conditions is satisfied.
64 /// True of the objc_release calls are all marked with the "tail" keyword.
65 bool IsTailCallRelease;
67 /// If the Calls are objc_release calls and they all have a
68 /// clang.imprecise_release tag, this is the metadata tag.
69 MDNode *ReleaseMetadata;
71 /// For a top-down sequence, the set of objc_retains or
72 /// objc_retainBlocks. For bottom-up, the set of objc_releases.
73 SmallPtrSet<Instruction *, 2> Calls;
75 /// The set of optimal insert positions for moving calls in the opposite
77 SmallPtrSet<Instruction *, 2> ReverseInsertPts;
79 /// If this is true, we cannot perform code motion but can still remove
80 /// retain/release pairs.
81 bool CFGHazardAfflicted;
84 : KnownSafe(false), IsTailCallRelease(false), ReleaseMetadata(nullptr),
85 CFGHazardAfflicted(false) {}
89 /// Conservatively merge the two RRInfo. Returns true if a partial merge has
90 /// occurred, false otherwise.
91 bool Merge(const RRInfo &Other);
94 /// \brief This class summarizes several per-pointer runtime properties which
95 /// are propogated through the flow graph.
97 /// True if the reference count is known to be incremented.
98 bool KnownPositiveRefCount;
100 /// True if we've seen an opportunity for partial RR elimination, such as
101 /// pushing calls into a CFG triangle or into one side of a CFG diamond.
104 /// The current position in the sequence.
105 unsigned char Seq : 8;
107 /// Unidirectional information about the current sequence.
111 PtrState() : KnownPositiveRefCount(false), Partial(false), Seq(S_None) {}
113 bool IsKnownSafe() const { return RRI.KnownSafe; }
115 void SetKnownSafe(const bool NewValue) { RRI.KnownSafe = NewValue; }
117 bool IsTailCallRelease() const { return RRI.IsTailCallRelease; }
119 void SetTailCallRelease(const bool NewValue) {
120 RRI.IsTailCallRelease = NewValue;
123 bool IsTrackingImpreciseReleases() const {
124 return RRI.ReleaseMetadata != nullptr;
127 const MDNode *GetReleaseMetadata() const { return RRI.ReleaseMetadata; }
129 void SetReleaseMetadata(MDNode *NewValue) { RRI.ReleaseMetadata = NewValue; }
131 bool IsCFGHazardAfflicted() const { return RRI.CFGHazardAfflicted; }
133 void SetCFGHazardAfflicted(const bool NewValue) {
134 RRI.CFGHazardAfflicted = NewValue;
137 void SetKnownPositiveRefCount() {
138 DEBUG(dbgs() << "Setting Known Positive.\n");
139 KnownPositiveRefCount = true;
142 void ClearKnownPositiveRefCount() {
143 DEBUG(dbgs() << "Clearing Known Positive.\n");
144 KnownPositiveRefCount = false;
147 bool HasKnownPositiveRefCount() const { return KnownPositiveRefCount; }
149 void SetSeq(Sequence NewSeq) {
150 DEBUG(dbgs() << "Old: " << Seq << "; New: " << NewSeq << "\n");
154 Sequence GetSeq() const { return static_cast<Sequence>(Seq); }
156 void ClearSequenceProgress() { ResetSequenceProgress(S_None); }
158 void ResetSequenceProgress(Sequence NewSeq) {
159 DEBUG(dbgs() << "Resetting sequence progress.\n");
165 void Merge(const PtrState &Other, bool TopDown);
167 void InsertCall(Instruction *I) { RRI.Calls.insert(I); }
169 void InsertReverseInsertPt(Instruction *I) { RRI.ReverseInsertPts.insert(I); }
171 void ClearReverseInsertPts() { RRI.ReverseInsertPts.clear(); }
173 bool HasReverseInsertPts() const { return !RRI.ReverseInsertPts.empty(); }
175 const RRInfo &GetRRInfo() const { return RRI; }
178 } // end namespace objcarc
179 } // end namespace llvm