blob: 9749e44822b2d8aeedd10cf8ff86c9fe3824d348 [file] [log] [blame]
Michael Gottesman68b91db2015-03-05 23:29:03 +00001//===--- PtrState.h - ARC State for a Ptr -------------------*- C++ -*-----===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
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.
14//
15//===----------------------------------------------------------------------===//
16
17#ifndef LLVM_LIB_TRANSFORMS_OBJCARC_PTRSTATE_H
18#define LLVM_LIB_TRANSFORMS_OBJCARC_PTRSTATE_H
19
20#include "llvm/ADT/SmallPtrSet.h"
Chandler Carruth0f792182015-08-20 08:06:03 +000021#include "llvm/Analysis/ObjCARCInstKind.h"
Michael Gottesman68b91db2015-03-05 23:29:03 +000022#include "llvm/IR/Instruction.h"
23#include "llvm/IR/Value.h"
24#include "llvm/Support/raw_ostream.h"
25#include "llvm/Support/Debug.h"
26
27namespace llvm {
28namespace objcarc {
29
Michael Gottesman65cb7372015-03-16 07:02:27 +000030class ARCMDKindCache;
Michael Gottesman16e6a202015-03-06 02:07:12 +000031class ProvenanceAnalysis;
Michael Gottesman4eae3962015-03-06 00:34:39 +000032
Michael Gottesman68b91db2015-03-05 23:29:03 +000033/// \enum Sequence
34///
35/// \brief A sequence of states that a pointer may go through in which an
36/// objc_retain and objc_release are actually needed.
37enum Sequence {
38 S_None,
39 S_Retain, ///< objc_retain(x).
40 S_CanRelease, ///< foo(x) -- x could possibly see a ref count decrement.
41 S_Use, ///< any use of x.
42 S_Stop, ///< like S_Release, but code motion is stopped.
43 S_Release, ///< objc_release(x).
44 S_MovableRelease ///< objc_release(x), !clang.imprecise_release.
45};
46
47raw_ostream &operator<<(raw_ostream &OS,
48 const Sequence S) LLVM_ATTRIBUTE_UNUSED;
49
50/// \brief Unidirectional information about either a
51/// retain-decrement-use-release sequence or release-use-decrement-retain
52/// reverse sequence.
53struct RRInfo {
54 /// After an objc_retain, the reference count of the referenced
55 /// object is known to be positive. Similarly, before an objc_release, the
56 /// reference count of the referenced object is known to be positive. If
57 /// there are retain-release pairs in code regions where the retain count
58 /// is known to be positive, they can be eliminated, regardless of any side
59 /// effects between them.
60 ///
61 /// Also, a retain+release pair nested within another retain+release
62 /// pair all on the known same pointer value can be eliminated, regardless
63 /// of any intervening side effects.
64 ///
65 /// KnownSafe is true when either of these conditions is satisfied.
66 bool KnownSafe;
67
68 /// True of the objc_release calls are all marked with the "tail" keyword.
69 bool IsTailCallRelease;
70
71 /// If the Calls are objc_release calls and they all have a
72 /// clang.imprecise_release tag, this is the metadata tag.
73 MDNode *ReleaseMetadata;
74
75 /// For a top-down sequence, the set of objc_retains or
76 /// objc_retainBlocks. For bottom-up, the set of objc_releases.
77 SmallPtrSet<Instruction *, 2> Calls;
78
79 /// The set of optimal insert positions for moving calls in the opposite
80 /// sequence.
81 SmallPtrSet<Instruction *, 2> ReverseInsertPts;
82
83 /// If this is true, we cannot perform code motion but can still remove
84 /// retain/release pairs.
85 bool CFGHazardAfflicted;
86
87 RRInfo()
88 : KnownSafe(false), IsTailCallRelease(false), ReleaseMetadata(nullptr),
89 CFGHazardAfflicted(false) {}
90
91 void clear();
92
93 /// Conservatively merge the two RRInfo. Returns true if a partial merge has
94 /// occurred, false otherwise.
95 bool Merge(const RRInfo &Other);
96};
97
98/// \brief This class summarizes several per-pointer runtime properties which
Benjamin Kramerdf005cb2015-08-08 18:27:36 +000099/// are propagated through the flow graph.
Michael Gottesman68b91db2015-03-05 23:29:03 +0000100class PtrState {
Michael Gottesmanfeb138e2015-03-06 00:34:36 +0000101protected:
Michael Gottesman68b91db2015-03-05 23:29:03 +0000102 /// True if the reference count is known to be incremented.
103 bool KnownPositiveRefCount;
104
105 /// True if we've seen an opportunity for partial RR elimination, such as
106 /// pushing calls into a CFG triangle or into one side of a CFG diamond.
107 bool Partial;
108
109 /// The current position in the sequence.
110 unsigned char Seq : 8;
111
112 /// Unidirectional information about the current sequence.
113 RRInfo RRI;
114
Michael Gottesman68b91db2015-03-05 23:29:03 +0000115 PtrState() : KnownPositiveRefCount(false), Partial(false), Seq(S_None) {}
116
Michael Gottesmanfeb138e2015-03-06 00:34:36 +0000117public:
Michael Gottesman68b91db2015-03-05 23:29:03 +0000118 bool IsKnownSafe() const { return RRI.KnownSafe; }
119
120 void SetKnownSafe(const bool NewValue) { RRI.KnownSafe = NewValue; }
121
122 bool IsTailCallRelease() const { return RRI.IsTailCallRelease; }
123
124 void SetTailCallRelease(const bool NewValue) {
125 RRI.IsTailCallRelease = NewValue;
126 }
127
128 bool IsTrackingImpreciseReleases() const {
129 return RRI.ReleaseMetadata != nullptr;
130 }
131
132 const MDNode *GetReleaseMetadata() const { return RRI.ReleaseMetadata; }
133
134 void SetReleaseMetadata(MDNode *NewValue) { RRI.ReleaseMetadata = NewValue; }
135
136 bool IsCFGHazardAfflicted() const { return RRI.CFGHazardAfflicted; }
137
138 void SetCFGHazardAfflicted(const bool NewValue) {
139 RRI.CFGHazardAfflicted = NewValue;
140 }
141
Michael Gottesmand45907b2015-03-05 23:57:07 +0000142 void SetKnownPositiveRefCount();
143 void ClearKnownPositiveRefCount();
Michael Gottesman68b91db2015-03-05 23:29:03 +0000144
145 bool HasKnownPositiveRefCount() const { return KnownPositiveRefCount; }
146
Michael Gottesmand45907b2015-03-05 23:57:07 +0000147 void SetSeq(Sequence NewSeq);
Michael Gottesman68b91db2015-03-05 23:29:03 +0000148
149 Sequence GetSeq() const { return static_cast<Sequence>(Seq); }
150
151 void ClearSequenceProgress() { ResetSequenceProgress(S_None); }
152
Michael Gottesmand45907b2015-03-05 23:57:07 +0000153 void ResetSequenceProgress(Sequence NewSeq);
Michael Gottesman68b91db2015-03-05 23:29:03 +0000154 void Merge(const PtrState &Other, bool TopDown);
155
156 void InsertCall(Instruction *I) { RRI.Calls.insert(I); }
157
158 void InsertReverseInsertPt(Instruction *I) { RRI.ReverseInsertPts.insert(I); }
159
160 void ClearReverseInsertPts() { RRI.ReverseInsertPts.clear(); }
161
162 bool HasReverseInsertPts() const { return !RRI.ReverseInsertPts.empty(); }
163
164 const RRInfo &GetRRInfo() const { return RRI; }
165};
166
Michael Gottesmanfeb138e2015-03-06 00:34:36 +0000167struct BottomUpPtrState : PtrState {
168 BottomUpPtrState() : PtrState() {}
Michael Gottesman4eae3962015-03-06 00:34:39 +0000169
170 /// (Re-)Initialize this bottom up pointer returning true if we detected a
171 /// pointer with nested releases.
172 bool InitBottomUp(ARCMDKindCache &Cache, Instruction *I);
Michael Gottesman60805962015-03-06 00:34:42 +0000173
174 /// Return true if this set of releases can be paired with a release. Modifies
Benjamin Kramerdf005cb2015-08-08 18:27:36 +0000175 /// state appropriately to reflect that the matching occurred if it is
Michael Gottesman60805962015-03-06 00:34:42 +0000176 /// successful.
177 ///
178 /// It is assumed that one has already checked that the RCIdentity of the
179 /// retain and the RCIdentity of this ptr state are the same.
180 bool MatchWithRetain();
Michael Gottesman16e6a202015-03-06 02:07:12 +0000181
182 void HandlePotentialUse(BasicBlock *BB, Instruction *Inst, const Value *Ptr,
183 ProvenanceAnalysis &PA, ARCInstKind Class);
184 bool HandlePotentialAlterRefCount(Instruction *Inst, const Value *Ptr,
185 ProvenanceAnalysis &PA, ARCInstKind Class);
Michael Gottesmanfeb138e2015-03-06 00:34:36 +0000186};
187
Michael Gottesmanfeb138e2015-03-06 00:34:36 +0000188struct TopDownPtrState : PtrState {
189 TopDownPtrState() : PtrState() {}
Michael Gottesman4eae3962015-03-06 00:34:39 +0000190
191 /// (Re-)Initialize this bottom up pointer returning true if we detected a
192 /// pointer with nested releases.
193 bool InitTopDown(ARCInstKind Kind, Instruction *I);
Michael Gottesman60805962015-03-06 00:34:42 +0000194
195 /// Return true if this set of retains can be paired with the given
196 /// release. Modifies state appropriately to reflect that the matching
Benjamin Kramerdf005cb2015-08-08 18:27:36 +0000197 /// occurred.
Michael Gottesman60805962015-03-06 00:34:42 +0000198 bool MatchWithRelease(ARCMDKindCache &Cache, Instruction *Release);
Michael Gottesman16e6a202015-03-06 02:07:12 +0000199
200 void HandlePotentialUse(Instruction *Inst, const Value *Ptr,
201 ProvenanceAnalysis &PA, ARCInstKind Class);
202
203 bool HandlePotentialAlterRefCount(Instruction *Inst, const Value *Ptr,
204 ProvenanceAnalysis &PA, ARCInstKind Class);
Michael Gottesmanfeb138e2015-03-06 00:34:36 +0000205};
206
Michael Gottesman68b91db2015-03-05 23:29:03 +0000207} // end namespace objcarc
208} // end namespace llvm
209
210#endif