Coverage Report

Created: 2017-10-03 07:32

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/Transforms/ObjCARC/PtrState.h
Line
Count
Source (jump to first uncovered line)
1
//===--- PtrState.h - ARC State for a Ptr -------------------*- C++ -*-----===//
2
//
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"
21
#include "llvm/Analysis/ObjCARCInstKind.h"
22
#include "llvm/IR/Instruction.h"
23
#include "llvm/IR/Value.h"
24
#include "llvm/Support/Debug.h"
25
#include "llvm/Support/raw_ostream.h"
26
27
namespace llvm {
28
namespace objcarc {
29
30
class ARCMDKindCache;
31
class ProvenanceAnalysis;
32
33
/// \enum Sequence
34
///
35
/// \brief A sequence of states that a pointer may go through in which an
36
/// objc_retain and objc_release are actually needed.
37
enum Sequence {
38
  S_None,
39
  S_Retain,        ///< objc_retain(x).
40
  S_CanRelease,    ///< foo(x) -- x could possibly see a ref count decrement.
41
  S_Use,           ///< any use of x.
42
  S_Stop,          ///< like S_Release, but code motion is stopped.
43
  S_Release,       ///< objc_release(x).
44
  S_MovableRelease ///< objc_release(x), !clang.imprecise_release.
45
};
46
47
raw_ostream &operator<<(raw_ostream &OS,
48
                        const Sequence S) LLVM_ATTRIBUTE_UNUSED;
49
50
/// \brief Unidirectional information about either a
51
/// retain-decrement-use-release sequence or release-use-decrement-retain
52
/// reverse sequence.
53
struct RRInfo {
54
  /// After an objc_retain, the reference count of the referenced
55
  /// object is known to be positive. Similarly, before an objc_release, the
56
  /// reference count of the referenced object is known to be positive. If
57
  /// there are retain-release pairs in code regions where the retain count
58
  /// is known to be positive, they can be eliminated, regardless of any side
59
  /// effects between them.
60
  ///
61
  /// Also, a retain+release pair nested within another retain+release
62
  /// pair all on the known same pointer value can be eliminated, regardless
63
  /// of any intervening side effects.
64
  ///
65
  /// KnownSafe is true when either of these conditions is satisfied.
66
  bool KnownSafe;
67
68
  /// True of the objc_release calls are all marked with the "tail" keyword.
69
  bool IsTailCallRelease;
70
71
  /// If the Calls are objc_release calls and they all have a
72
  /// clang.imprecise_release tag, this is the metadata tag.
73
  MDNode *ReleaseMetadata;
74
75
  /// For a top-down sequence, the set of objc_retains or
76
  /// objc_retainBlocks. For bottom-up, the set of objc_releases.
77
  SmallPtrSet<Instruction *, 2> Calls;
78
79
  /// The set of optimal insert positions for moving calls in the opposite
80
  /// sequence.
81
  SmallPtrSet<Instruction *, 2> ReverseInsertPts;
82
83
  /// If this is true, we cannot perform code motion but can still remove
84
  /// retain/release pairs.
85
  bool CFGHazardAfflicted;
86
87
  RRInfo()
88
      : KnownSafe(false), IsTailCallRelease(false), ReleaseMetadata(nullptr),
89
1.57k
        CFGHazardAfflicted(false) {}
90
91
  void clear();
92
93
  /// Conservatively merge the two RRInfo. Returns true if a partial merge has
94
  /// occurred, false otherwise.
95
  bool Merge(const RRInfo &Other);
96
};
97
98
/// \brief This class summarizes several per-pointer runtime properties which
99
/// are propagated through the flow graph.
100
class PtrState {
101
protected:
102
  /// True if the reference count is known to be incremented.
103
  bool KnownPositiveRefCount;
104
105
  /// True if we've seen an opportunity for partial RR elimination, such as
106
  /// pushing calls into a CFG triangle or into one side of a CFG diamond.
107
  bool Partial;
108
109
  /// The current position in the sequence.
110
  unsigned char Seq : 8;
111
112
  /// Unidirectional information about the current sequence.
113
  RRInfo RRI;
114
115
824
  PtrState() : KnownPositiveRefCount(false), Partial(false), Seq(S_None) {}
116
117
public:
118
911
  bool IsKnownSafe() const { return RRI.KnownSafe; }
119
120
597
  void SetKnownSafe(const bool NewValue) { RRI.KnownSafe = NewValue; }
121
122
0
  bool IsTailCallRelease() const { return RRI.IsTailCallRelease; }
123
124
489
  void SetTailCallRelease(const bool NewValue) {
125
489
    RRI.IsTailCallRelease = NewValue;
126
489
  }
127
128
40
  bool IsTrackingImpreciseReleases() const {
129
40
    return RRI.ReleaseMetadata != nullptr;
130
40
  }
131
132
0
  const MDNode *GetReleaseMetadata() const { return RRI.ReleaseMetadata; }
133
134
489
  void SetReleaseMetadata(MDNode *NewValue) { RRI.ReleaseMetadata = NewValue; }
135
136
0
  bool IsCFGHazardAfflicted() const { return RRI.CFGHazardAfflicted; }
137
138
114
  void SetCFGHazardAfflicted(const bool NewValue) {
139
114
    RRI.CFGHazardAfflicted = NewValue;
140
114
  }
141
142
  void SetKnownPositiveRefCount();
143
  void ClearKnownPositiveRefCount();
144
145
597
  bool HasKnownPositiveRefCount() const { return KnownPositiveRefCount; }
146
147
  void SetSeq(Sequence NewSeq);
148
149
10.9k
  Sequence GetSeq() const { return static_cast<Sequence>(Seq); }
150
151
461
  void ClearSequenceProgress() { ResetSequenceProgress(S_None); }
152
153
  void ResetSequenceProgress(Sequence NewSeq);
154
  void Merge(const PtrState &Other, bool TopDown);
155
156
597
  void InsertCall(Instruction *I) { RRI.Calls.insert(I); }
157
158
408
  void InsertReverseInsertPt(Instruction *I) { RRI.ReverseInsertPts.insert(I); }
159
160
129
  void ClearReverseInsertPts() { RRI.ReverseInsertPts.clear(); }
161
162
0
  bool HasReverseInsertPts() const { return !RRI.ReverseInsertPts.empty(); }
163
164
372
  const RRInfo &GetRRInfo() const { return RRI; }
165
};
166
167
struct BottomUpPtrState : PtrState {
168
517
  BottomUpPtrState() : PtrState() {}
169
170
  /// (Re-)Initialize this bottom up pointer returning true if we detected a
171
  /// pointer with nested releases.
172
  bool InitBottomUp(ARCMDKindCache &Cache, Instruction *I);
173
174
  /// Return true if this set of releases can be paired with a release. Modifies
175
  /// state appropriately to reflect that the matching occurred if it is
176
  /// successful.
177
  ///
178
  /// It is assumed that one has already checked that the RCIdentity of the
179
  /// retain and the RCIdentity of this ptr state are the same.
180
  bool MatchWithRetain();
181
182
  void HandlePotentialUse(BasicBlock *BB, Instruction *Inst, const Value *Ptr,
183
                          ProvenanceAnalysis &PA, ARCInstKind Class);
184
  bool HandlePotentialAlterRefCount(Instruction *Inst, const Value *Ptr,
185
                                    ProvenanceAnalysis &PA, ARCInstKind Class);
186
};
187
188
struct TopDownPtrState : PtrState {
189
307
  TopDownPtrState() : PtrState() {}
190
191
  /// (Re-)Initialize this bottom up pointer returning true if we detected a
192
  /// pointer with nested releases.
193
  bool InitTopDown(ARCInstKind Kind, Instruction *I);
194
195
  /// Return true if this set of retains can be paired with the given
196
  /// release. Modifies state appropriately to reflect that the matching
197
  /// occurred.
198
  bool MatchWithRelease(ARCMDKindCache &Cache, Instruction *Release);
199
200
  void HandlePotentialUse(Instruction *Inst, const Value *Ptr,
201
                          ProvenanceAnalysis &PA, ARCInstKind Class);
202
203
  bool HandlePotentialAlterRefCount(Instruction *Inst, const Value *Ptr,
204
                                    ProvenanceAnalysis &PA, ARCInstKind Class);
205
};
206
207
} // end namespace objcarc
208
} // end namespace llvm
209
210
#endif