Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Transforms/ObjCARC/PtrState.h
35269 views
1
//===- PtrState.h - ARC State for a Ptr -------------------------*- C++ -*-===//
2
//
3
// 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
6
//
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"
20
#include "llvm/Analysis/ObjCARCInstKind.h"
21
#include "llvm/Support/Compiler.h"
22
23
namespace llvm {
24
25
class BasicBlock;
26
class Instruction;
27
class MDNode;
28
class raw_ostream;
29
class Value;
30
31
namespace objcarc {
32
33
class ARCMDKindCache;
34
class BundledRetainClaimRVs;
35
class ProvenanceAnalysis;
36
37
/// \enum Sequence
38
///
39
/// A sequence of states that a pointer may go through in which an
40
/// objc_retain and objc_release are actually needed.
41
enum 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, ///< code motion is stopped.
47
S_MovableRelease ///< objc_release(x), !clang.imprecise_release.
48
};
49
50
raw_ostream &operator<<(raw_ostream &OS,
51
const Sequence S) LLVM_ATTRIBUTE_UNUSED;
52
53
/// Unidirectional information about either a
54
/// retain-decrement-use-release sequence or release-use-decrement-retain
55
/// reverse sequence.
56
struct 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.
69
bool KnownSafe = false;
70
71
/// True of the objc_release calls are all marked with the "tail" keyword.
72
bool IsTailCallRelease = false;
73
74
/// If the Calls are objc_release calls and they all have a
75
/// clang.imprecise_release tag, this is the metadata tag.
76
MDNode *ReleaseMetadata = nullptr;
77
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.
88
bool CFGHazardAfflicted = false;
89
90
RRInfo() = default;
91
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
99
/// This class summarizes several per-pointer runtime properties which
100
/// are propagated through the flow graph.
101
class PtrState {
102
protected:
103
/// True if the reference count is known to be incremented.
104
bool KnownPositiveRefCount = false;
105
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.
108
bool Partial = false;
109
110
/// The current position in the sequence.
111
unsigned char Seq : 8;
112
113
/// Unidirectional information about the current sequence.
114
RRInfo RRI;
115
116
PtrState() : Seq(S_None) {}
117
118
public:
119
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
143
void SetKnownPositiveRefCount();
144
void ClearKnownPositiveRefCount();
145
146
bool HasKnownPositiveRefCount() const { return KnownPositiveRefCount; }
147
148
void SetSeq(Sequence NewSeq);
149
150
Sequence GetSeq() const { return static_cast<Sequence>(Seq); }
151
152
void ClearSequenceProgress() { ResetSequenceProgress(S_None); }
153
154
void ResetSequenceProgress(Sequence NewSeq);
155
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
168
struct BottomUpPtrState : PtrState {
169
BottomUpPtrState() = default;
170
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);
174
175
/// Return true if this set of releases can be paired with a release. Modifies
176
/// state appropriately to reflect that the matching occurred if it is
177
/// 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();
182
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);
187
};
188
189
struct TopDownPtrState : PtrState {
190
TopDownPtrState() = default;
191
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);
195
196
/// Return true if this set of retains can be paired with the given
197
/// release. Modifies state appropriately to reflect that the matching
198
/// occurred.
199
bool MatchWithRelease(ARCMDKindCache &Cache, Instruction *Release);
200
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,
206
const BundledRetainClaimRVs &BundledRVs);
207
};
208
209
} // end namespace objcarc
210
211
} // end namespace llvm
212
213
#endif // LLVM_LIB_TRANSFORMS_OBJCARC_PTRSTATE_H
214
215