1 //===- PtrState.h - ARC State for a Ptr -------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
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.
14 //===----------------------------------------------------------------------===//
16 #ifndef LLVM_LIB_TRANSFORMS_OBJCARC_PTRSTATE_H
17 #define LLVM_LIB_TRANSFORMS_OBJCARC_PTRSTATE_H
19 #include "llvm/ADT/SmallPtrSet.h"
20 #include "llvm/Analysis/ObjCARCInstKind.h"
21 #include "llvm/Support/Compiler.h"
34 class BundledRetainClaimRVs
;
35 class ProvenanceAnalysis
;
39 /// A sequence of states that a pointer may go through in which an
40 /// objc_retain and objc_release are actually needed.
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.
50 raw_ostream
&operator<<(raw_ostream
&OS
,
51 const Sequence S
) LLVM_ATTRIBUTE_UNUSED
;
53 /// Unidirectional information about either a
54 /// retain-decrement-use-release sequence or release-use-decrement-retain
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.
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.
68 /// KnownSafe is true when either of these conditions is satisfied.
69 bool KnownSafe
= false;
71 /// True of the objc_release calls are all marked with the "tail" keyword.
72 bool IsTailCallRelease
= false;
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;
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
;
82 /// The set of optimal insert positions for moving calls in the opposite
84 SmallPtrSet
<Instruction
*, 2> ReverseInsertPts
;
86 /// If this is true, we cannot perform code motion but can still remove
87 /// retain/release pairs.
88 bool CFGHazardAfflicted
= false;
94 /// Conservatively merge the two RRInfo. Returns true if a partial merge has
95 /// occurred, false otherwise.
96 bool Merge(const RRInfo
&Other
);
99 /// This class summarizes several per-pointer runtime properties which
100 /// are propagated through the flow graph.
103 /// True if the reference count is known to be incremented.
104 bool KnownPositiveRefCount
= false;
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;
110 /// The current position in the sequence.
111 unsigned char Seq
: 8;
113 /// Unidirectional information about the current sequence.
116 PtrState() : Seq(S_None
) {}
119 bool IsKnownSafe() const { return RRI
.KnownSafe
; }
121 void SetKnownSafe(const bool NewValue
) { RRI
.KnownSafe
= NewValue
; }
123 bool IsTailCallRelease() const { return RRI
.IsTailCallRelease
; }
125 void SetTailCallRelease(const bool NewValue
) {
126 RRI
.IsTailCallRelease
= NewValue
;
129 bool IsTrackingImpreciseReleases() const {
130 return RRI
.ReleaseMetadata
!= nullptr;
133 const MDNode
*GetReleaseMetadata() const { return RRI
.ReleaseMetadata
; }
135 void SetReleaseMetadata(MDNode
*NewValue
) { RRI
.ReleaseMetadata
= NewValue
; }
137 bool IsCFGHazardAfflicted() const { return RRI
.CFGHazardAfflicted
; }
139 void SetCFGHazardAfflicted(const bool NewValue
) {
140 RRI
.CFGHazardAfflicted
= NewValue
;
143 void SetKnownPositiveRefCount();
144 void ClearKnownPositiveRefCount();
146 bool HasKnownPositiveRefCount() const { return KnownPositiveRefCount
; }
148 void SetSeq(Sequence NewSeq
);
150 Sequence
GetSeq() const { return static_cast<Sequence
>(Seq
); }
152 void ClearSequenceProgress() { ResetSequenceProgress(S_None
); }
154 void ResetSequenceProgress(Sequence NewSeq
);
155 void Merge(const PtrState
&Other
, bool TopDown
);
157 void InsertCall(Instruction
*I
) { RRI
.Calls
.insert(I
); }
159 void InsertReverseInsertPt(Instruction
*I
) { RRI
.ReverseInsertPts
.insert(I
); }
161 void ClearReverseInsertPts() { RRI
.ReverseInsertPts
.clear(); }
163 bool HasReverseInsertPts() const { return !RRI
.ReverseInsertPts
.empty(); }
165 const RRInfo
&GetRRInfo() const { return RRI
; }
168 struct BottomUpPtrState
: PtrState
{
169 BottomUpPtrState() = default;
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
);
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
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();
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
);
189 struct TopDownPtrState
: PtrState
{
190 TopDownPtrState() = default;
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
);
196 /// Return true if this set of retains can be paired with the given
197 /// release. Modifies state appropriately to reflect that the matching
199 bool MatchWithRelease(ARCMDKindCache
&Cache
, Instruction
*Release
);
201 void HandlePotentialUse(Instruction
*Inst
, const Value
*Ptr
,
202 ProvenanceAnalysis
&PA
, ARCInstKind Class
);
204 bool HandlePotentialAlterRefCount(Instruction
*Inst
, const Value
*Ptr
,
205 ProvenanceAnalysis
&PA
, ARCInstKind Class
,
206 const BundledRetainClaimRVs
&BundledRVs
);
209 } // end namespace objcarc
211 } // end namespace llvm
213 #endif // LLVM_LIB_TRANSFORMS_OBJCARC_PTRSTATE_H