]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/llvm/lib/Transforms/ObjCARC/PtrState.h
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm-project / llvm / lib / Transforms / ObjCARC / PtrState.h
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 ProvenanceAnalysis;
35
36 /// \enum Sequence
37 ///
38 /// A sequence of states that a pointer may go through in which an
39 /// objc_retain and objc_release are actually needed.
40 enum 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
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 };
207
208 } // end namespace objcarc
209
210 } // end namespace llvm
211
212 #endif // LLVM_LIB_TRANSFORMS_OBJCARC_PTRSTATE_H