blob: f5b9b853d8e381e0c9a554fa7438b9bd90e7a8ea [file] [log] [blame]
Eugene Zelenko57bd5a02017-10-27 01:09:08 +00001//===- PtrState.h - ARC State for a Ptr -------------------------*- C++ -*-===//
Michael Gottesman68b91db2015-03-05 23:29:03 +00002//
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"
Eugene Zelenko57bd5a02017-10-27 01:09:08 +000022#include "llvm/Support/Compiler.h"
Michael Gottesman68b91db2015-03-05 23:29:03 +000023
24namespace llvm {
Eugene Zelenko57bd5a02017-10-27 01:09:08 +000025
26class BasicBlock;
27class Instruction;
28class MDNode;
29class raw_ostream;
30class Value;
31
Michael Gottesman68b91db2015-03-05 23:29:03 +000032namespace objcarc {
33
Michael Gottesman65cb7372015-03-16 07:02:27 +000034class ARCMDKindCache;
Michael Gottesman16e6a202015-03-06 02:07:12 +000035class ProvenanceAnalysis;
Michael Gottesman4eae3962015-03-06 00:34:39 +000036
Michael Gottesman68b91db2015-03-05 23:29:03 +000037/// \enum Sequence
38///
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000039/// A sequence of states that a pointer may go through in which an
Michael Gottesman68b91db2015-03-05 23:29:03 +000040/// objc_retain and objc_release are actually needed.
41enum Sequence {
42 S_None,
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.
49};
50
51raw_ostream &operator<<(raw_ostream &OS,
52 const Sequence S) LLVM_ATTRIBUTE_UNUSED;
53
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000054/// Unidirectional information about either a
Michael Gottesman68b91db2015-03-05 23:29:03 +000055/// retain-decrement-use-release sequence or release-use-decrement-retain
56/// reverse sequence.
57struct RRInfo {
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.
64 ///
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.
68 ///
69 /// KnownSafe is true when either of these conditions is satisfied.
Eugene Zelenko57bd5a02017-10-27 01:09:08 +000070 bool KnownSafe = false;
Michael Gottesman68b91db2015-03-05 23:29:03 +000071
72 /// True of the objc_release calls are all marked with the "tail" keyword.
Eugene Zelenko57bd5a02017-10-27 01:09:08 +000073 bool IsTailCallRelease = false;
Michael Gottesman68b91db2015-03-05 23:29:03 +000074
75 /// If the Calls are objc_release calls and they all have a
76 /// clang.imprecise_release tag, this is the metadata tag.
Eugene Zelenko57bd5a02017-10-27 01:09:08 +000077 MDNode *ReleaseMetadata = nullptr;
Michael Gottesman68b91db2015-03-05 23:29:03 +000078
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;
82
83 /// The set of optimal insert positions for moving calls in the opposite
84 /// sequence.
85 SmallPtrSet<Instruction *, 2> ReverseInsertPts;
86
87 /// If this is true, we cannot perform code motion but can still remove
88 /// retain/release pairs.
Eugene Zelenko57bd5a02017-10-27 01:09:08 +000089 bool CFGHazardAfflicted = false;
Michael Gottesman68b91db2015-03-05 23:29:03 +000090
Eugene Zelenko57bd5a02017-10-27 01:09:08 +000091 RRInfo() = default;
Michael Gottesman68b91db2015-03-05 23:29:03 +000092
93 void clear();
94
95 /// Conservatively merge the two RRInfo. Returns true if a partial merge has
96 /// occurred, false otherwise.
97 bool Merge(const RRInfo &Other);
98};
99
Adrian Prantl5f8f34e42018-05-01 15:54:18 +0000100/// This class summarizes several per-pointer runtime properties which
Benjamin Kramerdf005cb2015-08-08 18:27:36 +0000101/// are propagated through the flow graph.
Michael Gottesman68b91db2015-03-05 23:29:03 +0000102class PtrState {
Michael Gottesmanfeb138e2015-03-06 00:34:36 +0000103protected:
Michael Gottesman68b91db2015-03-05 23:29:03 +0000104 /// True if the reference count is known to be incremented.
Eugene Zelenko57bd5a02017-10-27 01:09:08 +0000105 bool KnownPositiveRefCount = false;
Michael Gottesman68b91db2015-03-05 23:29:03 +0000106
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.
Eugene Zelenko57bd5a02017-10-27 01:09:08 +0000109 bool Partial = false;
Michael Gottesman68b91db2015-03-05 23:29:03 +0000110
111 /// The current position in the sequence.
112 unsigned char Seq : 8;
113
114 /// Unidirectional information about the current sequence.
115 RRInfo RRI;
116
Eugene Zelenko57bd5a02017-10-27 01:09:08 +0000117 PtrState() : Seq(S_None) {}
Michael Gottesman68b91db2015-03-05 23:29:03 +0000118
Michael Gottesmanfeb138e2015-03-06 00:34:36 +0000119public:
Michael Gottesman68b91db2015-03-05 23:29:03 +0000120 bool IsKnownSafe() const { return RRI.KnownSafe; }
121
122 void SetKnownSafe(const bool NewValue) { RRI.KnownSafe = NewValue; }
123
124 bool IsTailCallRelease() const { return RRI.IsTailCallRelease; }
125
126 void SetTailCallRelease(const bool NewValue) {
127 RRI.IsTailCallRelease = NewValue;
128 }
129
130 bool IsTrackingImpreciseReleases() const {
131 return RRI.ReleaseMetadata != nullptr;
132 }
133
134 const MDNode *GetReleaseMetadata() const { return RRI.ReleaseMetadata; }
135
136 void SetReleaseMetadata(MDNode *NewValue) { RRI.ReleaseMetadata = NewValue; }
137
138 bool IsCFGHazardAfflicted() const { return RRI.CFGHazardAfflicted; }
139
140 void SetCFGHazardAfflicted(const bool NewValue) {
141 RRI.CFGHazardAfflicted = NewValue;
142 }
143
Michael Gottesmand45907b2015-03-05 23:57:07 +0000144 void SetKnownPositiveRefCount();
145 void ClearKnownPositiveRefCount();
Michael Gottesman68b91db2015-03-05 23:29:03 +0000146
147 bool HasKnownPositiveRefCount() const { return KnownPositiveRefCount; }
148
Michael Gottesmand45907b2015-03-05 23:57:07 +0000149 void SetSeq(Sequence NewSeq);
Michael Gottesman68b91db2015-03-05 23:29:03 +0000150
151 Sequence GetSeq() const { return static_cast<Sequence>(Seq); }
152
153 void ClearSequenceProgress() { ResetSequenceProgress(S_None); }
154
Michael Gottesmand45907b2015-03-05 23:57:07 +0000155 void ResetSequenceProgress(Sequence NewSeq);
Michael Gottesman68b91db2015-03-05 23:29:03 +0000156 void Merge(const PtrState &Other, bool TopDown);
157
158 void InsertCall(Instruction *I) { RRI.Calls.insert(I); }
159
160 void InsertReverseInsertPt(Instruction *I) { RRI.ReverseInsertPts.insert(I); }
161
162 void ClearReverseInsertPts() { RRI.ReverseInsertPts.clear(); }
163
164 bool HasReverseInsertPts() const { return !RRI.ReverseInsertPts.empty(); }
165
166 const RRInfo &GetRRInfo() const { return RRI; }
167};
168
Michael Gottesmanfeb138e2015-03-06 00:34:36 +0000169struct BottomUpPtrState : PtrState {
Eugene Zelenko57bd5a02017-10-27 01:09:08 +0000170 BottomUpPtrState() = default;
Michael Gottesman4eae3962015-03-06 00:34:39 +0000171
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);
Michael Gottesman60805962015-03-06 00:34:42 +0000175
176 /// Return true if this set of releases can be paired with a release. Modifies
Benjamin Kramerdf005cb2015-08-08 18:27:36 +0000177 /// state appropriately to reflect that the matching occurred if it is
Michael Gottesman60805962015-03-06 00:34:42 +0000178 /// successful.
179 ///
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();
Michael Gottesman16e6a202015-03-06 02:07:12 +0000183
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);
Michael Gottesmanfeb138e2015-03-06 00:34:36 +0000188};
189
Michael Gottesmanfeb138e2015-03-06 00:34:36 +0000190struct TopDownPtrState : PtrState {
Eugene Zelenko57bd5a02017-10-27 01:09:08 +0000191 TopDownPtrState() = default;
Michael Gottesman4eae3962015-03-06 00:34:39 +0000192
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);
Michael Gottesman60805962015-03-06 00:34:42 +0000196
197 /// Return true if this set of retains can be paired with the given
198 /// release. Modifies state appropriately to reflect that the matching
Benjamin Kramerdf005cb2015-08-08 18:27:36 +0000199 /// occurred.
Michael Gottesman60805962015-03-06 00:34:42 +0000200 bool MatchWithRelease(ARCMDKindCache &Cache, Instruction *Release);
Michael Gottesman16e6a202015-03-06 02:07:12 +0000201
202 void HandlePotentialUse(Instruction *Inst, const Value *Ptr,
203 ProvenanceAnalysis &PA, ARCInstKind Class);
204
205 bool HandlePotentialAlterRefCount(Instruction *Inst, const Value *Ptr,
206 ProvenanceAnalysis &PA, ARCInstKind Class);
Michael Gottesmanfeb138e2015-03-06 00:34:36 +0000207};
208
Michael Gottesman68b91db2015-03-05 23:29:03 +0000209} // end namespace objcarc
Eugene Zelenko57bd5a02017-10-27 01:09:08 +0000210
Michael Gottesman68b91db2015-03-05 23:29:03 +0000211} // end namespace llvm
212
Eugene Zelenko57bd5a02017-10-27 01:09:08 +0000213#endif // LLVM_LIB_TRANSFORMS_OBJCARC_PTRSTATE_H