blob: 66614c06cb7994bd8169e2f8fc29595e476002a4 [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//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Michael Gottesman68b91db2015-03-05 23:29:03 +00006//
7//===----------------------------------------------------------------------===//
8//
9// This file contains declarations for the ARC state associated with a ptr. It
10// is only used by the ARC Sequence Dataflow computation. By separating this
11// from the actual dataflow, it is easier to consider the mechanics of the ARC
12// optimization separate from the actual predicates being used.
13//
14//===----------------------------------------------------------------------===//
15
16#ifndef LLVM_LIB_TRANSFORMS_OBJCARC_PTRSTATE_H
17#define LLVM_LIB_TRANSFORMS_OBJCARC_PTRSTATE_H
18
19#include "llvm/ADT/SmallPtrSet.h"
Chandler Carruth0f792182015-08-20 08:06:03 +000020#include "llvm/Analysis/ObjCARCInstKind.h"
Eugene Zelenko57bd5a02017-10-27 01:09:08 +000021#include "llvm/Support/Compiler.h"
Michael Gottesman68b91db2015-03-05 23:29:03 +000022
23namespace llvm {
Eugene Zelenko57bd5a02017-10-27 01:09:08 +000024
25class BasicBlock;
26class Instruction;
27class MDNode;
28class raw_ostream;
29class Value;
30
Michael Gottesman68b91db2015-03-05 23:29:03 +000031namespace objcarc {
32
Michael Gottesman65cb7372015-03-16 07:02:27 +000033class ARCMDKindCache;
Michael Gottesman16e6a202015-03-06 02:07:12 +000034class ProvenanceAnalysis;
Michael Gottesman4eae3962015-03-06 00:34:39 +000035
Michael Gottesman68b91db2015-03-05 23:29:03 +000036/// \enum Sequence
37///
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000038/// A sequence of states that a pointer may go through in which an
Michael Gottesman68b91db2015-03-05 23:29:03 +000039/// objc_retain and objc_release are actually needed.
40enum Sequence {
41 S_None,
42 S_Retain, ///< objc_retain(x).
43 S_CanRelease, ///< foo(x) -- x could possibly see a ref count decrement.
44 S_Use, ///< any use of x.
45 S_Stop, ///< like S_Release, but code motion is stopped.
46 S_Release, ///< objc_release(x).
47 S_MovableRelease ///< objc_release(x), !clang.imprecise_release.
48};
49
50raw_ostream &operator<<(raw_ostream &OS,
51 const Sequence S) LLVM_ATTRIBUTE_UNUSED;
52
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000053/// Unidirectional information about either a
Michael Gottesman68b91db2015-03-05 23:29:03 +000054/// retain-decrement-use-release sequence or release-use-decrement-retain
55/// reverse sequence.
56struct RRInfo {
57 /// After an objc_retain, the reference count of the referenced
58 /// object is known to be positive. Similarly, before an objc_release, the
59 /// reference count of the referenced object is known to be positive. If
60 /// there are retain-release pairs in code regions where the retain count
61 /// is known to be positive, they can be eliminated, regardless of any side
62 /// effects between them.
63 ///
64 /// Also, a retain+release pair nested within another retain+release
65 /// pair all on the known same pointer value can be eliminated, regardless
66 /// of any intervening side effects.
67 ///
68 /// KnownSafe is true when either of these conditions is satisfied.
Eugene Zelenko57bd5a02017-10-27 01:09:08 +000069 bool KnownSafe = false;
Michael Gottesman68b91db2015-03-05 23:29:03 +000070
71 /// True of the objc_release calls are all marked with the "tail" keyword.
Eugene Zelenko57bd5a02017-10-27 01:09:08 +000072 bool IsTailCallRelease = false;
Michael Gottesman68b91db2015-03-05 23:29:03 +000073
74 /// If the Calls are objc_release calls and they all have a
75 /// clang.imprecise_release tag, this is the metadata tag.
Eugene Zelenko57bd5a02017-10-27 01:09:08 +000076 MDNode *ReleaseMetadata = nullptr;
Michael Gottesman68b91db2015-03-05 23:29:03 +000077
78 /// For a top-down sequence, the set of objc_retains or
79 /// objc_retainBlocks. For bottom-up, the set of objc_releases.
80 SmallPtrSet<Instruction *, 2> Calls;
81
82 /// The set of optimal insert positions for moving calls in the opposite
83 /// sequence.
84 SmallPtrSet<Instruction *, 2> ReverseInsertPts;
85
86 /// If this is true, we cannot perform code motion but can still remove
87 /// retain/release pairs.
Eugene Zelenko57bd5a02017-10-27 01:09:08 +000088 bool CFGHazardAfflicted = false;
Michael Gottesman68b91db2015-03-05 23:29:03 +000089
Eugene Zelenko57bd5a02017-10-27 01:09:08 +000090 RRInfo() = default;
Michael Gottesman68b91db2015-03-05 23:29:03 +000091
92 void clear();
93
94 /// Conservatively merge the two RRInfo. Returns true if a partial merge has
95 /// occurred, false otherwise.
96 bool Merge(const RRInfo &Other);
97};
98
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000099/// This class summarizes several per-pointer runtime properties which
Benjamin Kramerdf005cb2015-08-08 18:27:36 +0000100/// are propagated through the flow graph.
Michael Gottesman68b91db2015-03-05 23:29:03 +0000101class PtrState {
Michael Gottesmanfeb138e2015-03-06 00:34:36 +0000102protected:
Michael Gottesman68b91db2015-03-05 23:29:03 +0000103 /// True if the reference count is known to be incremented.
Eugene Zelenko57bd5a02017-10-27 01:09:08 +0000104 bool KnownPositiveRefCount = false;
Michael Gottesman68b91db2015-03-05 23:29:03 +0000105
106 /// True if we've seen an opportunity for partial RR elimination, such as
107 /// pushing calls into a CFG triangle or into one side of a CFG diamond.
Eugene Zelenko57bd5a02017-10-27 01:09:08 +0000108 bool Partial = false;
Michael Gottesman68b91db2015-03-05 23:29:03 +0000109
110 /// The current position in the sequence.
111 unsigned char Seq : 8;
112
113 /// Unidirectional information about the current sequence.
114 RRInfo RRI;
115
Eugene Zelenko57bd5a02017-10-27 01:09:08 +0000116 PtrState() : Seq(S_None) {}
Michael Gottesman68b91db2015-03-05 23:29:03 +0000117
Michael Gottesmanfeb138e2015-03-06 00:34:36 +0000118public:
Michael Gottesman68b91db2015-03-05 23:29:03 +0000119 bool IsKnownSafe() const { return RRI.KnownSafe; }
120
121 void SetKnownSafe(const bool NewValue) { RRI.KnownSafe = NewValue; }
122
123 bool IsTailCallRelease() const { return RRI.IsTailCallRelease; }
124
125 void SetTailCallRelease(const bool NewValue) {
126 RRI.IsTailCallRelease = NewValue;
127 }
128
129 bool IsTrackingImpreciseReleases() const {
130 return RRI.ReleaseMetadata != nullptr;
131 }
132
133 const MDNode *GetReleaseMetadata() const { return RRI.ReleaseMetadata; }
134
135 void SetReleaseMetadata(MDNode *NewValue) { RRI.ReleaseMetadata = NewValue; }
136
137 bool IsCFGHazardAfflicted() const { return RRI.CFGHazardAfflicted; }
138
139 void SetCFGHazardAfflicted(const bool NewValue) {
140 RRI.CFGHazardAfflicted = NewValue;
141 }
142
Michael Gottesmand45907b2015-03-05 23:57:07 +0000143 void SetKnownPositiveRefCount();
144 void ClearKnownPositiveRefCount();
Michael Gottesman68b91db2015-03-05 23:29:03 +0000145
146 bool HasKnownPositiveRefCount() const { return KnownPositiveRefCount; }
147
Michael Gottesmand45907b2015-03-05 23:57:07 +0000148 void SetSeq(Sequence NewSeq);
Michael Gottesman68b91db2015-03-05 23:29:03 +0000149
150 Sequence GetSeq() const { return static_cast<Sequence>(Seq); }
151
152 void ClearSequenceProgress() { ResetSequenceProgress(S_None); }
153
Michael Gottesmand45907b2015-03-05 23:57:07 +0000154 void ResetSequenceProgress(Sequence NewSeq);
Michael Gottesman68b91db2015-03-05 23:29:03 +0000155 void Merge(const PtrState &Other, bool TopDown);
156
157 void InsertCall(Instruction *I) { RRI.Calls.insert(I); }
158
159 void InsertReverseInsertPt(Instruction *I) { RRI.ReverseInsertPts.insert(I); }
160
161 void ClearReverseInsertPts() { RRI.ReverseInsertPts.clear(); }
162
163 bool HasReverseInsertPts() const { return !RRI.ReverseInsertPts.empty(); }
164
165 const RRInfo &GetRRInfo() const { return RRI; }
166};
167
Michael Gottesmanfeb138e2015-03-06 00:34:36 +0000168struct BottomUpPtrState : PtrState {
Eugene Zelenko57bd5a02017-10-27 01:09:08 +0000169 BottomUpPtrState() = default;
Michael Gottesman4eae3962015-03-06 00:34:39 +0000170
171 /// (Re-)Initialize this bottom up pointer returning true if we detected a
172 /// pointer with nested releases.
173 bool InitBottomUp(ARCMDKindCache &Cache, Instruction *I);
Michael Gottesman60805962015-03-06 00:34:42 +0000174
175 /// Return true if this set of releases can be paired with a release. Modifies
Benjamin Kramerdf005cb2015-08-08 18:27:36 +0000176 /// state appropriately to reflect that the matching occurred if it is
Michael Gottesman60805962015-03-06 00:34:42 +0000177 /// successful.
178 ///
179 /// It is assumed that one has already checked that the RCIdentity of the
180 /// retain and the RCIdentity of this ptr state are the same.
181 bool MatchWithRetain();
Michael Gottesman16e6a202015-03-06 02:07:12 +0000182
183 void HandlePotentialUse(BasicBlock *BB, Instruction *Inst, const Value *Ptr,
184 ProvenanceAnalysis &PA, ARCInstKind Class);
185 bool HandlePotentialAlterRefCount(Instruction *Inst, const Value *Ptr,
186 ProvenanceAnalysis &PA, ARCInstKind Class);
Michael Gottesmanfeb138e2015-03-06 00:34:36 +0000187};
188
Michael Gottesmanfeb138e2015-03-06 00:34:36 +0000189struct TopDownPtrState : PtrState {
Eugene Zelenko57bd5a02017-10-27 01:09:08 +0000190 TopDownPtrState() = default;
Michael Gottesman4eae3962015-03-06 00:34:39 +0000191
192 /// (Re-)Initialize this bottom up pointer returning true if we detected a
193 /// pointer with nested releases.
194 bool InitTopDown(ARCInstKind Kind, Instruction *I);
Michael Gottesman60805962015-03-06 00:34:42 +0000195
196 /// Return true if this set of retains can be paired with the given
197 /// release. Modifies state appropriately to reflect that the matching
Benjamin Kramerdf005cb2015-08-08 18:27:36 +0000198 /// occurred.
Michael Gottesman60805962015-03-06 00:34:42 +0000199 bool MatchWithRelease(ARCMDKindCache &Cache, Instruction *Release);
Michael Gottesman16e6a202015-03-06 02:07:12 +0000200
201 void HandlePotentialUse(Instruction *Inst, const Value *Ptr,
202 ProvenanceAnalysis &PA, ARCInstKind Class);
203
204 bool HandlePotentialAlterRefCount(Instruction *Inst, const Value *Ptr,
205 ProvenanceAnalysis &PA, ARCInstKind Class);
Michael Gottesmanfeb138e2015-03-06 00:34:36 +0000206};
207
Michael Gottesman68b91db2015-03-05 23:29:03 +0000208} // end namespace objcarc
Eugene Zelenko57bd5a02017-10-27 01:09:08 +0000209
Michael Gottesman68b91db2015-03-05 23:29:03 +0000210} // end namespace llvm
211
Eugene Zelenko57bd5a02017-10-27 01:09:08 +0000212#endif // LLVM_LIB_TRANSFORMS_OBJCARC_PTRSTATE_H