Fix build error.
[oota-llvm.git] / lib / Transforms / ObjCARC / PtrState.cpp
1 //===--- PtrState.cpp -----------------------------------------------------===//
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 #define DEBUG_TYPE "objc-arc-ptr-state"
11 #include "llvm/Support/Debug.h"
12 #include "PtrState.h"
13
14 using namespace llvm;
15 using namespace llvm::objcarc;
16
17 raw_ostream &llvm::objcarc::operator<<(raw_ostream &OS, const Sequence S) {
18   switch (S) {
19   case S_None:
20     return OS << "S_None";
21   case S_Retain:
22     return OS << "S_Retain";
23   case S_CanRelease:
24     return OS << "S_CanRelease";
25   case S_Use:
26     return OS << "S_Use";
27   case S_Release:
28     return OS << "S_Release";
29   case S_MovableRelease:
30     return OS << "S_MovableRelease";
31   case S_Stop:
32     return OS << "S_Stop";
33   }
34   llvm_unreachable("Unknown sequence type.");
35 }
36
37 static Sequence MergeSeqs(Sequence A, Sequence B, bool TopDown) {
38   // The easy cases.
39   if (A == B)
40     return A;
41   if (A == S_None || B == S_None)
42     return S_None;
43
44   if (A > B)
45     std::swap(A, B);
46   if (TopDown) {
47     // Choose the side which is further along in the sequence.
48     if ((A == S_Retain || A == S_CanRelease) &&
49         (B == S_CanRelease || B == S_Use))
50       return B;
51   } else {
52     // Choose the side which is further along in the sequence.
53     if ((A == S_Use || A == S_CanRelease) &&
54         (B == S_Use || B == S_Release || B == S_Stop || B == S_MovableRelease))
55       return A;
56     // If both sides are releases, choose the more conservative one.
57     if (A == S_Stop && (B == S_Release || B == S_MovableRelease))
58       return A;
59     if (A == S_Release && B == S_MovableRelease)
60       return A;
61   }
62
63   return S_None;
64 }
65
66 void RRInfo::clear() {
67   KnownSafe = false;
68   IsTailCallRelease = false;
69   ReleaseMetadata = nullptr;
70   Calls.clear();
71   ReverseInsertPts.clear();
72   CFGHazardAfflicted = false;
73 }
74
75 bool RRInfo::Merge(const RRInfo &Other) {
76   // Conservatively merge the ReleaseMetadata information.
77   if (ReleaseMetadata != Other.ReleaseMetadata)
78     ReleaseMetadata = nullptr;
79
80   // Conservatively merge the boolean state.
81   KnownSafe &= Other.KnownSafe;
82   IsTailCallRelease &= Other.IsTailCallRelease;
83   CFGHazardAfflicted |= Other.CFGHazardAfflicted;
84
85   // Merge the call sets.
86   Calls.insert(Other.Calls.begin(), Other.Calls.end());
87
88   // Merge the insert point sets. If there are any differences,
89   // that makes this a partial merge.
90   bool Partial = ReverseInsertPts.size() != Other.ReverseInsertPts.size();
91   for (Instruction *Inst : Other.ReverseInsertPts)
92     Partial |= ReverseInsertPts.insert(Inst).second;
93   return Partial;
94 }
95
96 void PtrState::SetKnownPositiveRefCount() {
97   DEBUG(dbgs() << "Setting Known Positive.\n");
98   KnownPositiveRefCount = true;
99 }
100
101 void PtrState::ClearKnownPositiveRefCount() {
102   DEBUG(dbgs() << "Clearing Known Positive.\n");
103   KnownPositiveRefCount = false;
104 }
105
106 void PtrState::SetSeq(Sequence NewSeq) {
107   DEBUG(dbgs() << "Old: " << Seq << "; New: " << NewSeq << "\n");
108   Seq = NewSeq;
109 }
110
111 void PtrState::ResetSequenceProgress(Sequence NewSeq) {
112   DEBUG(dbgs() << "Resetting sequence progress.\n");
113   SetSeq(NewSeq);
114   Partial = false;
115   RRI.clear();
116 }
117
118 void PtrState::Merge(const PtrState &Other, bool TopDown) {
119   Seq = MergeSeqs(GetSeq(), Other.GetSeq(), TopDown);
120   KnownPositiveRefCount &= Other.KnownPositiveRefCount;
121
122   // If we're not in a sequence (anymore), drop all associated state.
123   if (Seq == S_None) {
124     Partial = false;
125     RRI.clear();
126   } else if (Partial || Other.Partial) {
127     // If we're doing a merge on a path that's previously seen a partial
128     // merge, conservatively drop the sequence, to avoid doing partial
129     // RR elimination. If the branch predicates for the two merge differ,
130     // mixing them is unsafe.
131     ClearSequenceProgress();
132   } else {
133     // Otherwise merge the other PtrState's RRInfo into our RRInfo. At this
134     // point, we know that currently we are not partial. Stash whether or not
135     // the merge operation caused us to undergo a partial merging of reverse
136     // insertion points.
137     Partial = RRI.Merge(Other.RRI);
138   }
139 }