1*9880d681SAndroid Build Coastguard Worker //===- ObjCARCOpts.cpp - ObjC ARC Optimization ----------------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker /// \file
10*9880d681SAndroid Build Coastguard Worker /// This file defines ObjC ARC optimizations. ARC stands for Automatic
11*9880d681SAndroid Build Coastguard Worker /// Reference Counting and is a system for managing reference counts for objects
12*9880d681SAndroid Build Coastguard Worker /// in Objective C.
13*9880d681SAndroid Build Coastguard Worker ///
14*9880d681SAndroid Build Coastguard Worker /// The optimizations performed include elimination of redundant, partially
15*9880d681SAndroid Build Coastguard Worker /// redundant, and inconsequential reference count operations, elimination of
16*9880d681SAndroid Build Coastguard Worker /// redundant weak pointer operations, and numerous minor simplifications.
17*9880d681SAndroid Build Coastguard Worker ///
18*9880d681SAndroid Build Coastguard Worker /// WARNING: This file knows about certain library functions. It recognizes them
19*9880d681SAndroid Build Coastguard Worker /// by name, and hardwires knowledge of their semantics.
20*9880d681SAndroid Build Coastguard Worker ///
21*9880d681SAndroid Build Coastguard Worker /// WARNING: This file knows about how certain Objective-C library functions are
22*9880d681SAndroid Build Coastguard Worker /// used. Naive LLVM IR transformations which would otherwise be
23*9880d681SAndroid Build Coastguard Worker /// behavior-preserving may break these assumptions.
24*9880d681SAndroid Build Coastguard Worker ///
25*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
26*9880d681SAndroid Build Coastguard Worker
27*9880d681SAndroid Build Coastguard Worker #include "ObjCARC.h"
28*9880d681SAndroid Build Coastguard Worker #include "ARCRuntimeEntryPoints.h"
29*9880d681SAndroid Build Coastguard Worker #include "BlotMapVector.h"
30*9880d681SAndroid Build Coastguard Worker #include "DependencyAnalysis.h"
31*9880d681SAndroid Build Coastguard Worker #include "ProvenanceAnalysis.h"
32*9880d681SAndroid Build Coastguard Worker #include "PtrState.h"
33*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/DenseMap.h"
34*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/DenseSet.h"
35*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/STLExtras.h"
36*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallPtrSet.h"
37*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Statistic.h"
38*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/ObjCARCAliasAnalysis.h"
39*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/CFG.h"
40*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/IRBuilder.h"
41*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/LLVMContext.h"
42*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
43*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
44*9880d681SAndroid Build Coastguard Worker
45*9880d681SAndroid Build Coastguard Worker using namespace llvm;
46*9880d681SAndroid Build Coastguard Worker using namespace llvm::objcarc;
47*9880d681SAndroid Build Coastguard Worker
48*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "objc-arc-opts"
49*9880d681SAndroid Build Coastguard Worker
50*9880d681SAndroid Build Coastguard Worker /// \defgroup ARCUtilities Utility declarations/definitions specific to ARC.
51*9880d681SAndroid Build Coastguard Worker /// @{
52*9880d681SAndroid Build Coastguard Worker
53*9880d681SAndroid Build Coastguard Worker /// \brief This is similar to GetRCIdentityRoot but it stops as soon
54*9880d681SAndroid Build Coastguard Worker /// as it finds a value with multiple uses.
FindSingleUseIdentifiedObject(const Value * Arg)55*9880d681SAndroid Build Coastguard Worker static const Value *FindSingleUseIdentifiedObject(const Value *Arg) {
56*9880d681SAndroid Build Coastguard Worker if (Arg->hasOneUse()) {
57*9880d681SAndroid Build Coastguard Worker if (const BitCastInst *BC = dyn_cast<BitCastInst>(Arg))
58*9880d681SAndroid Build Coastguard Worker return FindSingleUseIdentifiedObject(BC->getOperand(0));
59*9880d681SAndroid Build Coastguard Worker if (const GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Arg))
60*9880d681SAndroid Build Coastguard Worker if (GEP->hasAllZeroIndices())
61*9880d681SAndroid Build Coastguard Worker return FindSingleUseIdentifiedObject(GEP->getPointerOperand());
62*9880d681SAndroid Build Coastguard Worker if (IsForwarding(GetBasicARCInstKind(Arg)))
63*9880d681SAndroid Build Coastguard Worker return FindSingleUseIdentifiedObject(
64*9880d681SAndroid Build Coastguard Worker cast<CallInst>(Arg)->getArgOperand(0));
65*9880d681SAndroid Build Coastguard Worker if (!IsObjCIdentifiedObject(Arg))
66*9880d681SAndroid Build Coastguard Worker return nullptr;
67*9880d681SAndroid Build Coastguard Worker return Arg;
68*9880d681SAndroid Build Coastguard Worker }
69*9880d681SAndroid Build Coastguard Worker
70*9880d681SAndroid Build Coastguard Worker // If we found an identifiable object but it has multiple uses, but they are
71*9880d681SAndroid Build Coastguard Worker // trivial uses, we can still consider this to be a single-use value.
72*9880d681SAndroid Build Coastguard Worker if (IsObjCIdentifiedObject(Arg)) {
73*9880d681SAndroid Build Coastguard Worker for (const User *U : Arg->users())
74*9880d681SAndroid Build Coastguard Worker if (!U->use_empty() || GetRCIdentityRoot(U) != Arg)
75*9880d681SAndroid Build Coastguard Worker return nullptr;
76*9880d681SAndroid Build Coastguard Worker
77*9880d681SAndroid Build Coastguard Worker return Arg;
78*9880d681SAndroid Build Coastguard Worker }
79*9880d681SAndroid Build Coastguard Worker
80*9880d681SAndroid Build Coastguard Worker return nullptr;
81*9880d681SAndroid Build Coastguard Worker }
82*9880d681SAndroid Build Coastguard Worker
83*9880d681SAndroid Build Coastguard Worker /// This is a wrapper around getUnderlyingObjCPtr along the lines of
84*9880d681SAndroid Build Coastguard Worker /// GetUnderlyingObjects except that it returns early when it sees the first
85*9880d681SAndroid Build Coastguard Worker /// alloca.
AreAnyUnderlyingObjectsAnAlloca(const Value * V,const DataLayout & DL)86*9880d681SAndroid Build Coastguard Worker static inline bool AreAnyUnderlyingObjectsAnAlloca(const Value *V,
87*9880d681SAndroid Build Coastguard Worker const DataLayout &DL) {
88*9880d681SAndroid Build Coastguard Worker SmallPtrSet<const Value *, 4> Visited;
89*9880d681SAndroid Build Coastguard Worker SmallVector<const Value *, 4> Worklist;
90*9880d681SAndroid Build Coastguard Worker Worklist.push_back(V);
91*9880d681SAndroid Build Coastguard Worker do {
92*9880d681SAndroid Build Coastguard Worker const Value *P = Worklist.pop_back_val();
93*9880d681SAndroid Build Coastguard Worker P = GetUnderlyingObjCPtr(P, DL);
94*9880d681SAndroid Build Coastguard Worker
95*9880d681SAndroid Build Coastguard Worker if (isa<AllocaInst>(P))
96*9880d681SAndroid Build Coastguard Worker return true;
97*9880d681SAndroid Build Coastguard Worker
98*9880d681SAndroid Build Coastguard Worker if (!Visited.insert(P).second)
99*9880d681SAndroid Build Coastguard Worker continue;
100*9880d681SAndroid Build Coastguard Worker
101*9880d681SAndroid Build Coastguard Worker if (const SelectInst *SI = dyn_cast<const SelectInst>(P)) {
102*9880d681SAndroid Build Coastguard Worker Worklist.push_back(SI->getTrueValue());
103*9880d681SAndroid Build Coastguard Worker Worklist.push_back(SI->getFalseValue());
104*9880d681SAndroid Build Coastguard Worker continue;
105*9880d681SAndroid Build Coastguard Worker }
106*9880d681SAndroid Build Coastguard Worker
107*9880d681SAndroid Build Coastguard Worker if (const PHINode *PN = dyn_cast<const PHINode>(P)) {
108*9880d681SAndroid Build Coastguard Worker for (Value *IncValue : PN->incoming_values())
109*9880d681SAndroid Build Coastguard Worker Worklist.push_back(IncValue);
110*9880d681SAndroid Build Coastguard Worker continue;
111*9880d681SAndroid Build Coastguard Worker }
112*9880d681SAndroid Build Coastguard Worker } while (!Worklist.empty());
113*9880d681SAndroid Build Coastguard Worker
114*9880d681SAndroid Build Coastguard Worker return false;
115*9880d681SAndroid Build Coastguard Worker }
116*9880d681SAndroid Build Coastguard Worker
117*9880d681SAndroid Build Coastguard Worker
118*9880d681SAndroid Build Coastguard Worker /// @}
119*9880d681SAndroid Build Coastguard Worker ///
120*9880d681SAndroid Build Coastguard Worker /// \defgroup ARCOpt ARC Optimization.
121*9880d681SAndroid Build Coastguard Worker /// @{
122*9880d681SAndroid Build Coastguard Worker
123*9880d681SAndroid Build Coastguard Worker // TODO: On code like this:
124*9880d681SAndroid Build Coastguard Worker //
125*9880d681SAndroid Build Coastguard Worker // objc_retain(%x)
126*9880d681SAndroid Build Coastguard Worker // stuff_that_cannot_release()
127*9880d681SAndroid Build Coastguard Worker // objc_autorelease(%x)
128*9880d681SAndroid Build Coastguard Worker // stuff_that_cannot_release()
129*9880d681SAndroid Build Coastguard Worker // objc_retain(%x)
130*9880d681SAndroid Build Coastguard Worker // stuff_that_cannot_release()
131*9880d681SAndroid Build Coastguard Worker // objc_autorelease(%x)
132*9880d681SAndroid Build Coastguard Worker //
133*9880d681SAndroid Build Coastguard Worker // The second retain and autorelease can be deleted.
134*9880d681SAndroid Build Coastguard Worker
135*9880d681SAndroid Build Coastguard Worker // TODO: It should be possible to delete
136*9880d681SAndroid Build Coastguard Worker // objc_autoreleasePoolPush and objc_autoreleasePoolPop
137*9880d681SAndroid Build Coastguard Worker // pairs if nothing is actually autoreleased between them. Also, autorelease
138*9880d681SAndroid Build Coastguard Worker // calls followed by objc_autoreleasePoolPop calls (perhaps in ObjC++ code
139*9880d681SAndroid Build Coastguard Worker // after inlining) can be turned into plain release calls.
140*9880d681SAndroid Build Coastguard Worker
141*9880d681SAndroid Build Coastguard Worker // TODO: Critical-edge splitting. If the optimial insertion point is
142*9880d681SAndroid Build Coastguard Worker // a critical edge, the current algorithm has to fail, because it doesn't
143*9880d681SAndroid Build Coastguard Worker // know how to split edges. It should be possible to make the optimizer
144*9880d681SAndroid Build Coastguard Worker // think in terms of edges, rather than blocks, and then split critical
145*9880d681SAndroid Build Coastguard Worker // edges on demand.
146*9880d681SAndroid Build Coastguard Worker
147*9880d681SAndroid Build Coastguard Worker // TODO: OptimizeSequences could generalized to be Interprocedural.
148*9880d681SAndroid Build Coastguard Worker
149*9880d681SAndroid Build Coastguard Worker // TODO: Recognize that a bunch of other objc runtime calls have
150*9880d681SAndroid Build Coastguard Worker // non-escaping arguments and non-releasing arguments, and may be
151*9880d681SAndroid Build Coastguard Worker // non-autoreleasing.
152*9880d681SAndroid Build Coastguard Worker
153*9880d681SAndroid Build Coastguard Worker // TODO: Sink autorelease calls as far as possible. Unfortunately we
154*9880d681SAndroid Build Coastguard Worker // usually can't sink them past other calls, which would be the main
155*9880d681SAndroid Build Coastguard Worker // case where it would be useful.
156*9880d681SAndroid Build Coastguard Worker
157*9880d681SAndroid Build Coastguard Worker // TODO: The pointer returned from objc_loadWeakRetained is retained.
158*9880d681SAndroid Build Coastguard Worker
159*9880d681SAndroid Build Coastguard Worker // TODO: Delete release+retain pairs (rare).
160*9880d681SAndroid Build Coastguard Worker
161*9880d681SAndroid Build Coastguard Worker STATISTIC(NumNoops, "Number of no-op objc calls eliminated");
162*9880d681SAndroid Build Coastguard Worker STATISTIC(NumPartialNoops, "Number of partially no-op objc calls eliminated");
163*9880d681SAndroid Build Coastguard Worker STATISTIC(NumAutoreleases,"Number of autoreleases converted to releases");
164*9880d681SAndroid Build Coastguard Worker STATISTIC(NumRets, "Number of return value forwarding "
165*9880d681SAndroid Build Coastguard Worker "retain+autoreleases eliminated");
166*9880d681SAndroid Build Coastguard Worker STATISTIC(NumRRs, "Number of retain+release paths eliminated");
167*9880d681SAndroid Build Coastguard Worker STATISTIC(NumPeeps, "Number of calls peephole-optimized");
168*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
169*9880d681SAndroid Build Coastguard Worker STATISTIC(NumRetainsBeforeOpt,
170*9880d681SAndroid Build Coastguard Worker "Number of retains before optimization");
171*9880d681SAndroid Build Coastguard Worker STATISTIC(NumReleasesBeforeOpt,
172*9880d681SAndroid Build Coastguard Worker "Number of releases before optimization");
173*9880d681SAndroid Build Coastguard Worker STATISTIC(NumRetainsAfterOpt,
174*9880d681SAndroid Build Coastguard Worker "Number of retains after optimization");
175*9880d681SAndroid Build Coastguard Worker STATISTIC(NumReleasesAfterOpt,
176*9880d681SAndroid Build Coastguard Worker "Number of releases after optimization");
177*9880d681SAndroid Build Coastguard Worker #endif
178*9880d681SAndroid Build Coastguard Worker
179*9880d681SAndroid Build Coastguard Worker namespace {
180*9880d681SAndroid Build Coastguard Worker /// \brief Per-BasicBlock state.
181*9880d681SAndroid Build Coastguard Worker class BBState {
182*9880d681SAndroid Build Coastguard Worker /// The number of unique control paths from the entry which can reach this
183*9880d681SAndroid Build Coastguard Worker /// block.
184*9880d681SAndroid Build Coastguard Worker unsigned TopDownPathCount;
185*9880d681SAndroid Build Coastguard Worker
186*9880d681SAndroid Build Coastguard Worker /// The number of unique control paths to exits from this block.
187*9880d681SAndroid Build Coastguard Worker unsigned BottomUpPathCount;
188*9880d681SAndroid Build Coastguard Worker
189*9880d681SAndroid Build Coastguard Worker /// The top-down traversal uses this to record information known about a
190*9880d681SAndroid Build Coastguard Worker /// pointer at the bottom of each block.
191*9880d681SAndroid Build Coastguard Worker BlotMapVector<const Value *, TopDownPtrState> PerPtrTopDown;
192*9880d681SAndroid Build Coastguard Worker
193*9880d681SAndroid Build Coastguard Worker /// The bottom-up traversal uses this to record information known about a
194*9880d681SAndroid Build Coastguard Worker /// pointer at the top of each block.
195*9880d681SAndroid Build Coastguard Worker BlotMapVector<const Value *, BottomUpPtrState> PerPtrBottomUp;
196*9880d681SAndroid Build Coastguard Worker
197*9880d681SAndroid Build Coastguard Worker /// Effective predecessors of the current block ignoring ignorable edges and
198*9880d681SAndroid Build Coastguard Worker /// ignored backedges.
199*9880d681SAndroid Build Coastguard Worker SmallVector<BasicBlock *, 2> Preds;
200*9880d681SAndroid Build Coastguard Worker
201*9880d681SAndroid Build Coastguard Worker /// Effective successors of the current block ignoring ignorable edges and
202*9880d681SAndroid Build Coastguard Worker /// ignored backedges.
203*9880d681SAndroid Build Coastguard Worker SmallVector<BasicBlock *, 2> Succs;
204*9880d681SAndroid Build Coastguard Worker
205*9880d681SAndroid Build Coastguard Worker public:
206*9880d681SAndroid Build Coastguard Worker static const unsigned OverflowOccurredValue;
207*9880d681SAndroid Build Coastguard Worker
BBState()208*9880d681SAndroid Build Coastguard Worker BBState() : TopDownPathCount(0), BottomUpPathCount(0) { }
209*9880d681SAndroid Build Coastguard Worker
210*9880d681SAndroid Build Coastguard Worker typedef decltype(PerPtrTopDown)::iterator top_down_ptr_iterator;
211*9880d681SAndroid Build Coastguard Worker typedef decltype(PerPtrTopDown)::const_iterator const_top_down_ptr_iterator;
212*9880d681SAndroid Build Coastguard Worker
top_down_ptr_begin()213*9880d681SAndroid Build Coastguard Worker top_down_ptr_iterator top_down_ptr_begin() { return PerPtrTopDown.begin(); }
top_down_ptr_end()214*9880d681SAndroid Build Coastguard Worker top_down_ptr_iterator top_down_ptr_end() { return PerPtrTopDown.end(); }
top_down_ptr_begin() const215*9880d681SAndroid Build Coastguard Worker const_top_down_ptr_iterator top_down_ptr_begin() const {
216*9880d681SAndroid Build Coastguard Worker return PerPtrTopDown.begin();
217*9880d681SAndroid Build Coastguard Worker }
top_down_ptr_end() const218*9880d681SAndroid Build Coastguard Worker const_top_down_ptr_iterator top_down_ptr_end() const {
219*9880d681SAndroid Build Coastguard Worker return PerPtrTopDown.end();
220*9880d681SAndroid Build Coastguard Worker }
hasTopDownPtrs() const221*9880d681SAndroid Build Coastguard Worker bool hasTopDownPtrs() const {
222*9880d681SAndroid Build Coastguard Worker return !PerPtrTopDown.empty();
223*9880d681SAndroid Build Coastguard Worker }
224*9880d681SAndroid Build Coastguard Worker
225*9880d681SAndroid Build Coastguard Worker typedef decltype(PerPtrBottomUp)::iterator bottom_up_ptr_iterator;
226*9880d681SAndroid Build Coastguard Worker typedef decltype(
227*9880d681SAndroid Build Coastguard Worker PerPtrBottomUp)::const_iterator const_bottom_up_ptr_iterator;
228*9880d681SAndroid Build Coastguard Worker
bottom_up_ptr_begin()229*9880d681SAndroid Build Coastguard Worker bottom_up_ptr_iterator bottom_up_ptr_begin() {
230*9880d681SAndroid Build Coastguard Worker return PerPtrBottomUp.begin();
231*9880d681SAndroid Build Coastguard Worker }
bottom_up_ptr_end()232*9880d681SAndroid Build Coastguard Worker bottom_up_ptr_iterator bottom_up_ptr_end() { return PerPtrBottomUp.end(); }
bottom_up_ptr_begin() const233*9880d681SAndroid Build Coastguard Worker const_bottom_up_ptr_iterator bottom_up_ptr_begin() const {
234*9880d681SAndroid Build Coastguard Worker return PerPtrBottomUp.begin();
235*9880d681SAndroid Build Coastguard Worker }
bottom_up_ptr_end() const236*9880d681SAndroid Build Coastguard Worker const_bottom_up_ptr_iterator bottom_up_ptr_end() const {
237*9880d681SAndroid Build Coastguard Worker return PerPtrBottomUp.end();
238*9880d681SAndroid Build Coastguard Worker }
hasBottomUpPtrs() const239*9880d681SAndroid Build Coastguard Worker bool hasBottomUpPtrs() const {
240*9880d681SAndroid Build Coastguard Worker return !PerPtrBottomUp.empty();
241*9880d681SAndroid Build Coastguard Worker }
242*9880d681SAndroid Build Coastguard Worker
243*9880d681SAndroid Build Coastguard Worker /// Mark this block as being an entry block, which has one path from the
244*9880d681SAndroid Build Coastguard Worker /// entry by definition.
SetAsEntry()245*9880d681SAndroid Build Coastguard Worker void SetAsEntry() { TopDownPathCount = 1; }
246*9880d681SAndroid Build Coastguard Worker
247*9880d681SAndroid Build Coastguard Worker /// Mark this block as being an exit block, which has one path to an exit by
248*9880d681SAndroid Build Coastguard Worker /// definition.
SetAsExit()249*9880d681SAndroid Build Coastguard Worker void SetAsExit() { BottomUpPathCount = 1; }
250*9880d681SAndroid Build Coastguard Worker
251*9880d681SAndroid Build Coastguard Worker /// Attempt to find the PtrState object describing the top down state for
252*9880d681SAndroid Build Coastguard Worker /// pointer Arg. Return a new initialized PtrState describing the top down
253*9880d681SAndroid Build Coastguard Worker /// state for Arg if we do not find one.
getPtrTopDownState(const Value * Arg)254*9880d681SAndroid Build Coastguard Worker TopDownPtrState &getPtrTopDownState(const Value *Arg) {
255*9880d681SAndroid Build Coastguard Worker return PerPtrTopDown[Arg];
256*9880d681SAndroid Build Coastguard Worker }
257*9880d681SAndroid Build Coastguard Worker
258*9880d681SAndroid Build Coastguard Worker /// Attempt to find the PtrState object describing the bottom up state for
259*9880d681SAndroid Build Coastguard Worker /// pointer Arg. Return a new initialized PtrState describing the bottom up
260*9880d681SAndroid Build Coastguard Worker /// state for Arg if we do not find one.
getPtrBottomUpState(const Value * Arg)261*9880d681SAndroid Build Coastguard Worker BottomUpPtrState &getPtrBottomUpState(const Value *Arg) {
262*9880d681SAndroid Build Coastguard Worker return PerPtrBottomUp[Arg];
263*9880d681SAndroid Build Coastguard Worker }
264*9880d681SAndroid Build Coastguard Worker
265*9880d681SAndroid Build Coastguard Worker /// Attempt to find the PtrState object describing the bottom up state for
266*9880d681SAndroid Build Coastguard Worker /// pointer Arg.
findPtrBottomUpState(const Value * Arg)267*9880d681SAndroid Build Coastguard Worker bottom_up_ptr_iterator findPtrBottomUpState(const Value *Arg) {
268*9880d681SAndroid Build Coastguard Worker return PerPtrBottomUp.find(Arg);
269*9880d681SAndroid Build Coastguard Worker }
270*9880d681SAndroid Build Coastguard Worker
clearBottomUpPointers()271*9880d681SAndroid Build Coastguard Worker void clearBottomUpPointers() {
272*9880d681SAndroid Build Coastguard Worker PerPtrBottomUp.clear();
273*9880d681SAndroid Build Coastguard Worker }
274*9880d681SAndroid Build Coastguard Worker
clearTopDownPointers()275*9880d681SAndroid Build Coastguard Worker void clearTopDownPointers() {
276*9880d681SAndroid Build Coastguard Worker PerPtrTopDown.clear();
277*9880d681SAndroid Build Coastguard Worker }
278*9880d681SAndroid Build Coastguard Worker
279*9880d681SAndroid Build Coastguard Worker void InitFromPred(const BBState &Other);
280*9880d681SAndroid Build Coastguard Worker void InitFromSucc(const BBState &Other);
281*9880d681SAndroid Build Coastguard Worker void MergePred(const BBState &Other);
282*9880d681SAndroid Build Coastguard Worker void MergeSucc(const BBState &Other);
283*9880d681SAndroid Build Coastguard Worker
284*9880d681SAndroid Build Coastguard Worker /// Compute the number of possible unique paths from an entry to an exit
285*9880d681SAndroid Build Coastguard Worker /// which pass through this block. This is only valid after both the
286*9880d681SAndroid Build Coastguard Worker /// top-down and bottom-up traversals are complete.
287*9880d681SAndroid Build Coastguard Worker ///
288*9880d681SAndroid Build Coastguard Worker /// Returns true if overflow occurred. Returns false if overflow did not
289*9880d681SAndroid Build Coastguard Worker /// occur.
GetAllPathCountWithOverflow(unsigned & PathCount) const290*9880d681SAndroid Build Coastguard Worker bool GetAllPathCountWithOverflow(unsigned &PathCount) const {
291*9880d681SAndroid Build Coastguard Worker if (TopDownPathCount == OverflowOccurredValue ||
292*9880d681SAndroid Build Coastguard Worker BottomUpPathCount == OverflowOccurredValue)
293*9880d681SAndroid Build Coastguard Worker return true;
294*9880d681SAndroid Build Coastguard Worker unsigned long long Product =
295*9880d681SAndroid Build Coastguard Worker (unsigned long long)TopDownPathCount*BottomUpPathCount;
296*9880d681SAndroid Build Coastguard Worker // Overflow occurred if any of the upper bits of Product are set or if all
297*9880d681SAndroid Build Coastguard Worker // the lower bits of Product are all set.
298*9880d681SAndroid Build Coastguard Worker return (Product >> 32) ||
299*9880d681SAndroid Build Coastguard Worker ((PathCount = Product) == OverflowOccurredValue);
300*9880d681SAndroid Build Coastguard Worker }
301*9880d681SAndroid Build Coastguard Worker
302*9880d681SAndroid Build Coastguard Worker // Specialized CFG utilities.
303*9880d681SAndroid Build Coastguard Worker typedef SmallVectorImpl<BasicBlock *>::const_iterator edge_iterator;
pred_begin() const304*9880d681SAndroid Build Coastguard Worker edge_iterator pred_begin() const { return Preds.begin(); }
pred_end() const305*9880d681SAndroid Build Coastguard Worker edge_iterator pred_end() const { return Preds.end(); }
succ_begin() const306*9880d681SAndroid Build Coastguard Worker edge_iterator succ_begin() const { return Succs.begin(); }
succ_end() const307*9880d681SAndroid Build Coastguard Worker edge_iterator succ_end() const { return Succs.end(); }
308*9880d681SAndroid Build Coastguard Worker
addSucc(BasicBlock * Succ)309*9880d681SAndroid Build Coastguard Worker void addSucc(BasicBlock *Succ) { Succs.push_back(Succ); }
addPred(BasicBlock * Pred)310*9880d681SAndroid Build Coastguard Worker void addPred(BasicBlock *Pred) { Preds.push_back(Pred); }
311*9880d681SAndroid Build Coastguard Worker
isExit() const312*9880d681SAndroid Build Coastguard Worker bool isExit() const { return Succs.empty(); }
313*9880d681SAndroid Build Coastguard Worker };
314*9880d681SAndroid Build Coastguard Worker
315*9880d681SAndroid Build Coastguard Worker const unsigned BBState::OverflowOccurredValue = 0xffffffff;
316*9880d681SAndroid Build Coastguard Worker }
317*9880d681SAndroid Build Coastguard Worker
318*9880d681SAndroid Build Coastguard Worker namespace llvm {
319*9880d681SAndroid Build Coastguard Worker raw_ostream &operator<<(raw_ostream &OS,
320*9880d681SAndroid Build Coastguard Worker BBState &BBState) LLVM_ATTRIBUTE_UNUSED;
321*9880d681SAndroid Build Coastguard Worker }
322*9880d681SAndroid Build Coastguard Worker
InitFromPred(const BBState & Other)323*9880d681SAndroid Build Coastguard Worker void BBState::InitFromPred(const BBState &Other) {
324*9880d681SAndroid Build Coastguard Worker PerPtrTopDown = Other.PerPtrTopDown;
325*9880d681SAndroid Build Coastguard Worker TopDownPathCount = Other.TopDownPathCount;
326*9880d681SAndroid Build Coastguard Worker }
327*9880d681SAndroid Build Coastguard Worker
InitFromSucc(const BBState & Other)328*9880d681SAndroid Build Coastguard Worker void BBState::InitFromSucc(const BBState &Other) {
329*9880d681SAndroid Build Coastguard Worker PerPtrBottomUp = Other.PerPtrBottomUp;
330*9880d681SAndroid Build Coastguard Worker BottomUpPathCount = Other.BottomUpPathCount;
331*9880d681SAndroid Build Coastguard Worker }
332*9880d681SAndroid Build Coastguard Worker
333*9880d681SAndroid Build Coastguard Worker /// The top-down traversal uses this to merge information about predecessors to
334*9880d681SAndroid Build Coastguard Worker /// form the initial state for a new block.
MergePred(const BBState & Other)335*9880d681SAndroid Build Coastguard Worker void BBState::MergePred(const BBState &Other) {
336*9880d681SAndroid Build Coastguard Worker if (TopDownPathCount == OverflowOccurredValue)
337*9880d681SAndroid Build Coastguard Worker return;
338*9880d681SAndroid Build Coastguard Worker
339*9880d681SAndroid Build Coastguard Worker // Other.TopDownPathCount can be 0, in which case it is either dead or a
340*9880d681SAndroid Build Coastguard Worker // loop backedge. Loop backedges are special.
341*9880d681SAndroid Build Coastguard Worker TopDownPathCount += Other.TopDownPathCount;
342*9880d681SAndroid Build Coastguard Worker
343*9880d681SAndroid Build Coastguard Worker // In order to be consistent, we clear the top down pointers when by adding
344*9880d681SAndroid Build Coastguard Worker // TopDownPathCount becomes OverflowOccurredValue even though "true" overflow
345*9880d681SAndroid Build Coastguard Worker // has not occurred.
346*9880d681SAndroid Build Coastguard Worker if (TopDownPathCount == OverflowOccurredValue) {
347*9880d681SAndroid Build Coastguard Worker clearTopDownPointers();
348*9880d681SAndroid Build Coastguard Worker return;
349*9880d681SAndroid Build Coastguard Worker }
350*9880d681SAndroid Build Coastguard Worker
351*9880d681SAndroid Build Coastguard Worker // Check for overflow. If we have overflow, fall back to conservative
352*9880d681SAndroid Build Coastguard Worker // behavior.
353*9880d681SAndroid Build Coastguard Worker if (TopDownPathCount < Other.TopDownPathCount) {
354*9880d681SAndroid Build Coastguard Worker TopDownPathCount = OverflowOccurredValue;
355*9880d681SAndroid Build Coastguard Worker clearTopDownPointers();
356*9880d681SAndroid Build Coastguard Worker return;
357*9880d681SAndroid Build Coastguard Worker }
358*9880d681SAndroid Build Coastguard Worker
359*9880d681SAndroid Build Coastguard Worker // For each entry in the other set, if our set has an entry with the same key,
360*9880d681SAndroid Build Coastguard Worker // merge the entries. Otherwise, copy the entry and merge it with an empty
361*9880d681SAndroid Build Coastguard Worker // entry.
362*9880d681SAndroid Build Coastguard Worker for (auto MI = Other.top_down_ptr_begin(), ME = Other.top_down_ptr_end();
363*9880d681SAndroid Build Coastguard Worker MI != ME; ++MI) {
364*9880d681SAndroid Build Coastguard Worker auto Pair = PerPtrTopDown.insert(*MI);
365*9880d681SAndroid Build Coastguard Worker Pair.first->second.Merge(Pair.second ? TopDownPtrState() : MI->second,
366*9880d681SAndroid Build Coastguard Worker /*TopDown=*/true);
367*9880d681SAndroid Build Coastguard Worker }
368*9880d681SAndroid Build Coastguard Worker
369*9880d681SAndroid Build Coastguard Worker // For each entry in our set, if the other set doesn't have an entry with the
370*9880d681SAndroid Build Coastguard Worker // same key, force it to merge with an empty entry.
371*9880d681SAndroid Build Coastguard Worker for (auto MI = top_down_ptr_begin(), ME = top_down_ptr_end(); MI != ME; ++MI)
372*9880d681SAndroid Build Coastguard Worker if (Other.PerPtrTopDown.find(MI->first) == Other.PerPtrTopDown.end())
373*9880d681SAndroid Build Coastguard Worker MI->second.Merge(TopDownPtrState(), /*TopDown=*/true);
374*9880d681SAndroid Build Coastguard Worker }
375*9880d681SAndroid Build Coastguard Worker
376*9880d681SAndroid Build Coastguard Worker /// The bottom-up traversal uses this to merge information about successors to
377*9880d681SAndroid Build Coastguard Worker /// form the initial state for a new block.
MergeSucc(const BBState & Other)378*9880d681SAndroid Build Coastguard Worker void BBState::MergeSucc(const BBState &Other) {
379*9880d681SAndroid Build Coastguard Worker if (BottomUpPathCount == OverflowOccurredValue)
380*9880d681SAndroid Build Coastguard Worker return;
381*9880d681SAndroid Build Coastguard Worker
382*9880d681SAndroid Build Coastguard Worker // Other.BottomUpPathCount can be 0, in which case it is either dead or a
383*9880d681SAndroid Build Coastguard Worker // loop backedge. Loop backedges are special.
384*9880d681SAndroid Build Coastguard Worker BottomUpPathCount += Other.BottomUpPathCount;
385*9880d681SAndroid Build Coastguard Worker
386*9880d681SAndroid Build Coastguard Worker // In order to be consistent, we clear the top down pointers when by adding
387*9880d681SAndroid Build Coastguard Worker // BottomUpPathCount becomes OverflowOccurredValue even though "true" overflow
388*9880d681SAndroid Build Coastguard Worker // has not occurred.
389*9880d681SAndroid Build Coastguard Worker if (BottomUpPathCount == OverflowOccurredValue) {
390*9880d681SAndroid Build Coastguard Worker clearBottomUpPointers();
391*9880d681SAndroid Build Coastguard Worker return;
392*9880d681SAndroid Build Coastguard Worker }
393*9880d681SAndroid Build Coastguard Worker
394*9880d681SAndroid Build Coastguard Worker // Check for overflow. If we have overflow, fall back to conservative
395*9880d681SAndroid Build Coastguard Worker // behavior.
396*9880d681SAndroid Build Coastguard Worker if (BottomUpPathCount < Other.BottomUpPathCount) {
397*9880d681SAndroid Build Coastguard Worker BottomUpPathCount = OverflowOccurredValue;
398*9880d681SAndroid Build Coastguard Worker clearBottomUpPointers();
399*9880d681SAndroid Build Coastguard Worker return;
400*9880d681SAndroid Build Coastguard Worker }
401*9880d681SAndroid Build Coastguard Worker
402*9880d681SAndroid Build Coastguard Worker // For each entry in the other set, if our set has an entry with the
403*9880d681SAndroid Build Coastguard Worker // same key, merge the entries. Otherwise, copy the entry and merge
404*9880d681SAndroid Build Coastguard Worker // it with an empty entry.
405*9880d681SAndroid Build Coastguard Worker for (auto MI = Other.bottom_up_ptr_begin(), ME = Other.bottom_up_ptr_end();
406*9880d681SAndroid Build Coastguard Worker MI != ME; ++MI) {
407*9880d681SAndroid Build Coastguard Worker auto Pair = PerPtrBottomUp.insert(*MI);
408*9880d681SAndroid Build Coastguard Worker Pair.first->second.Merge(Pair.second ? BottomUpPtrState() : MI->second,
409*9880d681SAndroid Build Coastguard Worker /*TopDown=*/false);
410*9880d681SAndroid Build Coastguard Worker }
411*9880d681SAndroid Build Coastguard Worker
412*9880d681SAndroid Build Coastguard Worker // For each entry in our set, if the other set doesn't have an entry
413*9880d681SAndroid Build Coastguard Worker // with the same key, force it to merge with an empty entry.
414*9880d681SAndroid Build Coastguard Worker for (auto MI = bottom_up_ptr_begin(), ME = bottom_up_ptr_end(); MI != ME;
415*9880d681SAndroid Build Coastguard Worker ++MI)
416*9880d681SAndroid Build Coastguard Worker if (Other.PerPtrBottomUp.find(MI->first) == Other.PerPtrBottomUp.end())
417*9880d681SAndroid Build Coastguard Worker MI->second.Merge(BottomUpPtrState(), /*TopDown=*/false);
418*9880d681SAndroid Build Coastguard Worker }
419*9880d681SAndroid Build Coastguard Worker
operator <<(raw_ostream & OS,BBState & BBInfo)420*9880d681SAndroid Build Coastguard Worker raw_ostream &llvm::operator<<(raw_ostream &OS, BBState &BBInfo) {
421*9880d681SAndroid Build Coastguard Worker // Dump the pointers we are tracking.
422*9880d681SAndroid Build Coastguard Worker OS << " TopDown State:\n";
423*9880d681SAndroid Build Coastguard Worker if (!BBInfo.hasTopDownPtrs()) {
424*9880d681SAndroid Build Coastguard Worker DEBUG(llvm::dbgs() << " NONE!\n");
425*9880d681SAndroid Build Coastguard Worker } else {
426*9880d681SAndroid Build Coastguard Worker for (auto I = BBInfo.top_down_ptr_begin(), E = BBInfo.top_down_ptr_end();
427*9880d681SAndroid Build Coastguard Worker I != E; ++I) {
428*9880d681SAndroid Build Coastguard Worker const PtrState &P = I->second;
429*9880d681SAndroid Build Coastguard Worker OS << " Ptr: " << *I->first
430*9880d681SAndroid Build Coastguard Worker << "\n KnownSafe: " << (P.IsKnownSafe()?"true":"false")
431*9880d681SAndroid Build Coastguard Worker << "\n ImpreciseRelease: "
432*9880d681SAndroid Build Coastguard Worker << (P.IsTrackingImpreciseReleases()?"true":"false") << "\n"
433*9880d681SAndroid Build Coastguard Worker << " HasCFGHazards: "
434*9880d681SAndroid Build Coastguard Worker << (P.IsCFGHazardAfflicted()?"true":"false") << "\n"
435*9880d681SAndroid Build Coastguard Worker << " KnownPositive: "
436*9880d681SAndroid Build Coastguard Worker << (P.HasKnownPositiveRefCount()?"true":"false") << "\n"
437*9880d681SAndroid Build Coastguard Worker << " Seq: "
438*9880d681SAndroid Build Coastguard Worker << P.GetSeq() << "\n";
439*9880d681SAndroid Build Coastguard Worker }
440*9880d681SAndroid Build Coastguard Worker }
441*9880d681SAndroid Build Coastguard Worker
442*9880d681SAndroid Build Coastguard Worker OS << " BottomUp State:\n";
443*9880d681SAndroid Build Coastguard Worker if (!BBInfo.hasBottomUpPtrs()) {
444*9880d681SAndroid Build Coastguard Worker DEBUG(llvm::dbgs() << " NONE!\n");
445*9880d681SAndroid Build Coastguard Worker } else {
446*9880d681SAndroid Build Coastguard Worker for (auto I = BBInfo.bottom_up_ptr_begin(), E = BBInfo.bottom_up_ptr_end();
447*9880d681SAndroid Build Coastguard Worker I != E; ++I) {
448*9880d681SAndroid Build Coastguard Worker const PtrState &P = I->second;
449*9880d681SAndroid Build Coastguard Worker OS << " Ptr: " << *I->first
450*9880d681SAndroid Build Coastguard Worker << "\n KnownSafe: " << (P.IsKnownSafe()?"true":"false")
451*9880d681SAndroid Build Coastguard Worker << "\n ImpreciseRelease: "
452*9880d681SAndroid Build Coastguard Worker << (P.IsTrackingImpreciseReleases()?"true":"false") << "\n"
453*9880d681SAndroid Build Coastguard Worker << " HasCFGHazards: "
454*9880d681SAndroid Build Coastguard Worker << (P.IsCFGHazardAfflicted()?"true":"false") << "\n"
455*9880d681SAndroid Build Coastguard Worker << " KnownPositive: "
456*9880d681SAndroid Build Coastguard Worker << (P.HasKnownPositiveRefCount()?"true":"false") << "\n"
457*9880d681SAndroid Build Coastguard Worker << " Seq: "
458*9880d681SAndroid Build Coastguard Worker << P.GetSeq() << "\n";
459*9880d681SAndroid Build Coastguard Worker }
460*9880d681SAndroid Build Coastguard Worker }
461*9880d681SAndroid Build Coastguard Worker
462*9880d681SAndroid Build Coastguard Worker return OS;
463*9880d681SAndroid Build Coastguard Worker }
464*9880d681SAndroid Build Coastguard Worker
465*9880d681SAndroid Build Coastguard Worker namespace {
466*9880d681SAndroid Build Coastguard Worker
467*9880d681SAndroid Build Coastguard Worker /// \brief The main ARC optimization pass.
468*9880d681SAndroid Build Coastguard Worker class ObjCARCOpt : public FunctionPass {
469*9880d681SAndroid Build Coastguard Worker bool Changed;
470*9880d681SAndroid Build Coastguard Worker ProvenanceAnalysis PA;
471*9880d681SAndroid Build Coastguard Worker
472*9880d681SAndroid Build Coastguard Worker /// A cache of references to runtime entry point constants.
473*9880d681SAndroid Build Coastguard Worker ARCRuntimeEntryPoints EP;
474*9880d681SAndroid Build Coastguard Worker
475*9880d681SAndroid Build Coastguard Worker /// A cache of MDKinds that can be passed into other functions to propagate
476*9880d681SAndroid Build Coastguard Worker /// MDKind identifiers.
477*9880d681SAndroid Build Coastguard Worker ARCMDKindCache MDKindCache;
478*9880d681SAndroid Build Coastguard Worker
479*9880d681SAndroid Build Coastguard Worker // This is used to track if a pointer is stored into an alloca.
480*9880d681SAndroid Build Coastguard Worker DenseSet<const Value *> MultiOwnersSet;
481*9880d681SAndroid Build Coastguard Worker
482*9880d681SAndroid Build Coastguard Worker /// A flag indicating whether this optimization pass should run.
483*9880d681SAndroid Build Coastguard Worker bool Run;
484*9880d681SAndroid Build Coastguard Worker
485*9880d681SAndroid Build Coastguard Worker /// Flags which determine whether each of the interesting runtime functions
486*9880d681SAndroid Build Coastguard Worker /// is in fact used in the current function.
487*9880d681SAndroid Build Coastguard Worker unsigned UsedInThisFunction;
488*9880d681SAndroid Build Coastguard Worker
489*9880d681SAndroid Build Coastguard Worker bool OptimizeRetainRVCall(Function &F, Instruction *RetainRV);
490*9880d681SAndroid Build Coastguard Worker void OptimizeAutoreleaseRVCall(Function &F, Instruction *AutoreleaseRV,
491*9880d681SAndroid Build Coastguard Worker ARCInstKind &Class);
492*9880d681SAndroid Build Coastguard Worker void OptimizeIndividualCalls(Function &F);
493*9880d681SAndroid Build Coastguard Worker
494*9880d681SAndroid Build Coastguard Worker void CheckForCFGHazards(const BasicBlock *BB,
495*9880d681SAndroid Build Coastguard Worker DenseMap<const BasicBlock *, BBState> &BBStates,
496*9880d681SAndroid Build Coastguard Worker BBState &MyStates) const;
497*9880d681SAndroid Build Coastguard Worker bool VisitInstructionBottomUp(Instruction *Inst, BasicBlock *BB,
498*9880d681SAndroid Build Coastguard Worker BlotMapVector<Value *, RRInfo> &Retains,
499*9880d681SAndroid Build Coastguard Worker BBState &MyStates);
500*9880d681SAndroid Build Coastguard Worker bool VisitBottomUp(BasicBlock *BB,
501*9880d681SAndroid Build Coastguard Worker DenseMap<const BasicBlock *, BBState> &BBStates,
502*9880d681SAndroid Build Coastguard Worker BlotMapVector<Value *, RRInfo> &Retains);
503*9880d681SAndroid Build Coastguard Worker bool VisitInstructionTopDown(Instruction *Inst,
504*9880d681SAndroid Build Coastguard Worker DenseMap<Value *, RRInfo> &Releases,
505*9880d681SAndroid Build Coastguard Worker BBState &MyStates);
506*9880d681SAndroid Build Coastguard Worker bool VisitTopDown(BasicBlock *BB,
507*9880d681SAndroid Build Coastguard Worker DenseMap<const BasicBlock *, BBState> &BBStates,
508*9880d681SAndroid Build Coastguard Worker DenseMap<Value *, RRInfo> &Releases);
509*9880d681SAndroid Build Coastguard Worker bool Visit(Function &F, DenseMap<const BasicBlock *, BBState> &BBStates,
510*9880d681SAndroid Build Coastguard Worker BlotMapVector<Value *, RRInfo> &Retains,
511*9880d681SAndroid Build Coastguard Worker DenseMap<Value *, RRInfo> &Releases);
512*9880d681SAndroid Build Coastguard Worker
513*9880d681SAndroid Build Coastguard Worker void MoveCalls(Value *Arg, RRInfo &RetainsToMove, RRInfo &ReleasesToMove,
514*9880d681SAndroid Build Coastguard Worker BlotMapVector<Value *, RRInfo> &Retains,
515*9880d681SAndroid Build Coastguard Worker DenseMap<Value *, RRInfo> &Releases,
516*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<Instruction *> &DeadInsts, Module *M);
517*9880d681SAndroid Build Coastguard Worker
518*9880d681SAndroid Build Coastguard Worker bool
519*9880d681SAndroid Build Coastguard Worker PairUpRetainsAndReleases(DenseMap<const BasicBlock *, BBState> &BBStates,
520*9880d681SAndroid Build Coastguard Worker BlotMapVector<Value *, RRInfo> &Retains,
521*9880d681SAndroid Build Coastguard Worker DenseMap<Value *, RRInfo> &Releases, Module *M,
522*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<Instruction *> &NewRetains,
523*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<Instruction *> &NewReleases,
524*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<Instruction *> &DeadInsts,
525*9880d681SAndroid Build Coastguard Worker RRInfo &RetainsToMove, RRInfo &ReleasesToMove,
526*9880d681SAndroid Build Coastguard Worker Value *Arg, bool KnownSafe,
527*9880d681SAndroid Build Coastguard Worker bool &AnyPairsCompletelyEliminated);
528*9880d681SAndroid Build Coastguard Worker
529*9880d681SAndroid Build Coastguard Worker bool PerformCodePlacement(DenseMap<const BasicBlock *, BBState> &BBStates,
530*9880d681SAndroid Build Coastguard Worker BlotMapVector<Value *, RRInfo> &Retains,
531*9880d681SAndroid Build Coastguard Worker DenseMap<Value *, RRInfo> &Releases, Module *M);
532*9880d681SAndroid Build Coastguard Worker
533*9880d681SAndroid Build Coastguard Worker void OptimizeWeakCalls(Function &F);
534*9880d681SAndroid Build Coastguard Worker
535*9880d681SAndroid Build Coastguard Worker bool OptimizeSequences(Function &F);
536*9880d681SAndroid Build Coastguard Worker
537*9880d681SAndroid Build Coastguard Worker void OptimizeReturns(Function &F);
538*9880d681SAndroid Build Coastguard Worker
539*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
540*9880d681SAndroid Build Coastguard Worker void GatherStatistics(Function &F, bool AfterOptimization = false);
541*9880d681SAndroid Build Coastguard Worker #endif
542*9880d681SAndroid Build Coastguard Worker
543*9880d681SAndroid Build Coastguard Worker void getAnalysisUsage(AnalysisUsage &AU) const override;
544*9880d681SAndroid Build Coastguard Worker bool doInitialization(Module &M) override;
545*9880d681SAndroid Build Coastguard Worker bool runOnFunction(Function &F) override;
546*9880d681SAndroid Build Coastguard Worker void releaseMemory() override;
547*9880d681SAndroid Build Coastguard Worker
548*9880d681SAndroid Build Coastguard Worker public:
549*9880d681SAndroid Build Coastguard Worker static char ID;
ObjCARCOpt()550*9880d681SAndroid Build Coastguard Worker ObjCARCOpt() : FunctionPass(ID) {
551*9880d681SAndroid Build Coastguard Worker initializeObjCARCOptPass(*PassRegistry::getPassRegistry());
552*9880d681SAndroid Build Coastguard Worker }
553*9880d681SAndroid Build Coastguard Worker };
554*9880d681SAndroid Build Coastguard Worker }
555*9880d681SAndroid Build Coastguard Worker
556*9880d681SAndroid Build Coastguard Worker char ObjCARCOpt::ID = 0;
557*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_BEGIN(ObjCARCOpt,
558*9880d681SAndroid Build Coastguard Worker "objc-arc", "ObjC ARC optimization", false, false)
INITIALIZE_PASS_DEPENDENCY(ObjCARCAAWrapperPass)559*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_DEPENDENCY(ObjCARCAAWrapperPass)
560*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_END(ObjCARCOpt,
561*9880d681SAndroid Build Coastguard Worker "objc-arc", "ObjC ARC optimization", false, false)
562*9880d681SAndroid Build Coastguard Worker
563*9880d681SAndroid Build Coastguard Worker Pass *llvm::createObjCARCOptPass() {
564*9880d681SAndroid Build Coastguard Worker return new ObjCARCOpt();
565*9880d681SAndroid Build Coastguard Worker }
566*9880d681SAndroid Build Coastguard Worker
getAnalysisUsage(AnalysisUsage & AU) const567*9880d681SAndroid Build Coastguard Worker void ObjCARCOpt::getAnalysisUsage(AnalysisUsage &AU) const {
568*9880d681SAndroid Build Coastguard Worker AU.addRequired<ObjCARCAAWrapperPass>();
569*9880d681SAndroid Build Coastguard Worker AU.addRequired<AAResultsWrapperPass>();
570*9880d681SAndroid Build Coastguard Worker // ARC optimization doesn't currently split critical edges.
571*9880d681SAndroid Build Coastguard Worker AU.setPreservesCFG();
572*9880d681SAndroid Build Coastguard Worker }
573*9880d681SAndroid Build Coastguard Worker
574*9880d681SAndroid Build Coastguard Worker /// Turn objc_retainAutoreleasedReturnValue into objc_retain if the operand is
575*9880d681SAndroid Build Coastguard Worker /// not a return value. Or, if it can be paired with an
576*9880d681SAndroid Build Coastguard Worker /// objc_autoreleaseReturnValue, delete the pair and return true.
577*9880d681SAndroid Build Coastguard Worker bool
OptimizeRetainRVCall(Function & F,Instruction * RetainRV)578*9880d681SAndroid Build Coastguard Worker ObjCARCOpt::OptimizeRetainRVCall(Function &F, Instruction *RetainRV) {
579*9880d681SAndroid Build Coastguard Worker // Check for the argument being from an immediately preceding call or invoke.
580*9880d681SAndroid Build Coastguard Worker const Value *Arg = GetArgRCIdentityRoot(RetainRV);
581*9880d681SAndroid Build Coastguard Worker ImmutableCallSite CS(Arg);
582*9880d681SAndroid Build Coastguard Worker if (const Instruction *Call = CS.getInstruction()) {
583*9880d681SAndroid Build Coastguard Worker if (Call->getParent() == RetainRV->getParent()) {
584*9880d681SAndroid Build Coastguard Worker BasicBlock::const_iterator I(Call);
585*9880d681SAndroid Build Coastguard Worker ++I;
586*9880d681SAndroid Build Coastguard Worker while (IsNoopInstruction(&*I))
587*9880d681SAndroid Build Coastguard Worker ++I;
588*9880d681SAndroid Build Coastguard Worker if (&*I == RetainRV)
589*9880d681SAndroid Build Coastguard Worker return false;
590*9880d681SAndroid Build Coastguard Worker } else if (const InvokeInst *II = dyn_cast<InvokeInst>(Call)) {
591*9880d681SAndroid Build Coastguard Worker BasicBlock *RetainRVParent = RetainRV->getParent();
592*9880d681SAndroid Build Coastguard Worker if (II->getNormalDest() == RetainRVParent) {
593*9880d681SAndroid Build Coastguard Worker BasicBlock::const_iterator I = RetainRVParent->begin();
594*9880d681SAndroid Build Coastguard Worker while (IsNoopInstruction(&*I))
595*9880d681SAndroid Build Coastguard Worker ++I;
596*9880d681SAndroid Build Coastguard Worker if (&*I == RetainRV)
597*9880d681SAndroid Build Coastguard Worker return false;
598*9880d681SAndroid Build Coastguard Worker }
599*9880d681SAndroid Build Coastguard Worker }
600*9880d681SAndroid Build Coastguard Worker }
601*9880d681SAndroid Build Coastguard Worker
602*9880d681SAndroid Build Coastguard Worker // Check for being preceded by an objc_autoreleaseReturnValue on the same
603*9880d681SAndroid Build Coastguard Worker // pointer. In this case, we can delete the pair.
604*9880d681SAndroid Build Coastguard Worker BasicBlock::iterator I = RetainRV->getIterator(),
605*9880d681SAndroid Build Coastguard Worker Begin = RetainRV->getParent()->begin();
606*9880d681SAndroid Build Coastguard Worker if (I != Begin) {
607*9880d681SAndroid Build Coastguard Worker do
608*9880d681SAndroid Build Coastguard Worker --I;
609*9880d681SAndroid Build Coastguard Worker while (I != Begin && IsNoopInstruction(&*I));
610*9880d681SAndroid Build Coastguard Worker if (GetBasicARCInstKind(&*I) == ARCInstKind::AutoreleaseRV &&
611*9880d681SAndroid Build Coastguard Worker GetArgRCIdentityRoot(&*I) == Arg) {
612*9880d681SAndroid Build Coastguard Worker Changed = true;
613*9880d681SAndroid Build Coastguard Worker ++NumPeeps;
614*9880d681SAndroid Build Coastguard Worker
615*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Erasing autoreleaseRV,retainRV pair: " << *I << "\n"
616*9880d681SAndroid Build Coastguard Worker << "Erasing " << *RetainRV << "\n");
617*9880d681SAndroid Build Coastguard Worker
618*9880d681SAndroid Build Coastguard Worker EraseInstruction(&*I);
619*9880d681SAndroid Build Coastguard Worker EraseInstruction(RetainRV);
620*9880d681SAndroid Build Coastguard Worker return true;
621*9880d681SAndroid Build Coastguard Worker }
622*9880d681SAndroid Build Coastguard Worker }
623*9880d681SAndroid Build Coastguard Worker
624*9880d681SAndroid Build Coastguard Worker // Turn it to a plain objc_retain.
625*9880d681SAndroid Build Coastguard Worker Changed = true;
626*9880d681SAndroid Build Coastguard Worker ++NumPeeps;
627*9880d681SAndroid Build Coastguard Worker
628*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Transforming objc_retainAutoreleasedReturnValue => "
629*9880d681SAndroid Build Coastguard Worker "objc_retain since the operand is not a return value.\n"
630*9880d681SAndroid Build Coastguard Worker "Old = " << *RetainRV << "\n");
631*9880d681SAndroid Build Coastguard Worker
632*9880d681SAndroid Build Coastguard Worker Constant *NewDecl = EP.get(ARCRuntimeEntryPointKind::Retain);
633*9880d681SAndroid Build Coastguard Worker cast<CallInst>(RetainRV)->setCalledFunction(NewDecl);
634*9880d681SAndroid Build Coastguard Worker
635*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "New = " << *RetainRV << "\n");
636*9880d681SAndroid Build Coastguard Worker
637*9880d681SAndroid Build Coastguard Worker return false;
638*9880d681SAndroid Build Coastguard Worker }
639*9880d681SAndroid Build Coastguard Worker
640*9880d681SAndroid Build Coastguard Worker /// Turn objc_autoreleaseReturnValue into objc_autorelease if the result is not
641*9880d681SAndroid Build Coastguard Worker /// used as a return value.
OptimizeAutoreleaseRVCall(Function & F,Instruction * AutoreleaseRV,ARCInstKind & Class)642*9880d681SAndroid Build Coastguard Worker void ObjCARCOpt::OptimizeAutoreleaseRVCall(Function &F,
643*9880d681SAndroid Build Coastguard Worker Instruction *AutoreleaseRV,
644*9880d681SAndroid Build Coastguard Worker ARCInstKind &Class) {
645*9880d681SAndroid Build Coastguard Worker // Check for a return of the pointer value.
646*9880d681SAndroid Build Coastguard Worker const Value *Ptr = GetArgRCIdentityRoot(AutoreleaseRV);
647*9880d681SAndroid Build Coastguard Worker SmallVector<const Value *, 2> Users;
648*9880d681SAndroid Build Coastguard Worker Users.push_back(Ptr);
649*9880d681SAndroid Build Coastguard Worker do {
650*9880d681SAndroid Build Coastguard Worker Ptr = Users.pop_back_val();
651*9880d681SAndroid Build Coastguard Worker for (const User *U : Ptr->users()) {
652*9880d681SAndroid Build Coastguard Worker if (isa<ReturnInst>(U) || GetBasicARCInstKind(U) == ARCInstKind::RetainRV)
653*9880d681SAndroid Build Coastguard Worker return;
654*9880d681SAndroid Build Coastguard Worker if (isa<BitCastInst>(U))
655*9880d681SAndroid Build Coastguard Worker Users.push_back(U);
656*9880d681SAndroid Build Coastguard Worker }
657*9880d681SAndroid Build Coastguard Worker } while (!Users.empty());
658*9880d681SAndroid Build Coastguard Worker
659*9880d681SAndroid Build Coastguard Worker Changed = true;
660*9880d681SAndroid Build Coastguard Worker ++NumPeeps;
661*9880d681SAndroid Build Coastguard Worker
662*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Transforming objc_autoreleaseReturnValue => "
663*9880d681SAndroid Build Coastguard Worker "objc_autorelease since its operand is not used as a return "
664*9880d681SAndroid Build Coastguard Worker "value.\n"
665*9880d681SAndroid Build Coastguard Worker "Old = " << *AutoreleaseRV << "\n");
666*9880d681SAndroid Build Coastguard Worker
667*9880d681SAndroid Build Coastguard Worker CallInst *AutoreleaseRVCI = cast<CallInst>(AutoreleaseRV);
668*9880d681SAndroid Build Coastguard Worker Constant *NewDecl = EP.get(ARCRuntimeEntryPointKind::Autorelease);
669*9880d681SAndroid Build Coastguard Worker AutoreleaseRVCI->setCalledFunction(NewDecl);
670*9880d681SAndroid Build Coastguard Worker AutoreleaseRVCI->setTailCall(false); // Never tail call objc_autorelease.
671*9880d681SAndroid Build Coastguard Worker Class = ARCInstKind::Autorelease;
672*9880d681SAndroid Build Coastguard Worker
673*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "New: " << *AutoreleaseRV << "\n");
674*9880d681SAndroid Build Coastguard Worker
675*9880d681SAndroid Build Coastguard Worker }
676*9880d681SAndroid Build Coastguard Worker
677*9880d681SAndroid Build Coastguard Worker /// Visit each call, one at a time, and make simplifications without doing any
678*9880d681SAndroid Build Coastguard Worker /// additional analysis.
OptimizeIndividualCalls(Function & F)679*9880d681SAndroid Build Coastguard Worker void ObjCARCOpt::OptimizeIndividualCalls(Function &F) {
680*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "\n== ObjCARCOpt::OptimizeIndividualCalls ==\n");
681*9880d681SAndroid Build Coastguard Worker // Reset all the flags in preparation for recomputing them.
682*9880d681SAndroid Build Coastguard Worker UsedInThisFunction = 0;
683*9880d681SAndroid Build Coastguard Worker
684*9880d681SAndroid Build Coastguard Worker // Visit all objc_* calls in F.
685*9880d681SAndroid Build Coastguard Worker for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E; ) {
686*9880d681SAndroid Build Coastguard Worker Instruction *Inst = &*I++;
687*9880d681SAndroid Build Coastguard Worker
688*9880d681SAndroid Build Coastguard Worker ARCInstKind Class = GetBasicARCInstKind(Inst);
689*9880d681SAndroid Build Coastguard Worker
690*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Visiting: Class: " << Class << "; " << *Inst << "\n");
691*9880d681SAndroid Build Coastguard Worker
692*9880d681SAndroid Build Coastguard Worker switch (Class) {
693*9880d681SAndroid Build Coastguard Worker default: break;
694*9880d681SAndroid Build Coastguard Worker
695*9880d681SAndroid Build Coastguard Worker // Delete no-op casts. These function calls have special semantics, but
696*9880d681SAndroid Build Coastguard Worker // the semantics are entirely implemented via lowering in the front-end,
697*9880d681SAndroid Build Coastguard Worker // so by the time they reach the optimizer, they are just no-op calls
698*9880d681SAndroid Build Coastguard Worker // which return their argument.
699*9880d681SAndroid Build Coastguard Worker //
700*9880d681SAndroid Build Coastguard Worker // There are gray areas here, as the ability to cast reference-counted
701*9880d681SAndroid Build Coastguard Worker // pointers to raw void* and back allows code to break ARC assumptions,
702*9880d681SAndroid Build Coastguard Worker // however these are currently considered to be unimportant.
703*9880d681SAndroid Build Coastguard Worker case ARCInstKind::NoopCast:
704*9880d681SAndroid Build Coastguard Worker Changed = true;
705*9880d681SAndroid Build Coastguard Worker ++NumNoops;
706*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Erasing no-op cast: " << *Inst << "\n");
707*9880d681SAndroid Build Coastguard Worker EraseInstruction(Inst);
708*9880d681SAndroid Build Coastguard Worker continue;
709*9880d681SAndroid Build Coastguard Worker
710*9880d681SAndroid Build Coastguard Worker // If the pointer-to-weak-pointer is null, it's undefined behavior.
711*9880d681SAndroid Build Coastguard Worker case ARCInstKind::StoreWeak:
712*9880d681SAndroid Build Coastguard Worker case ARCInstKind::LoadWeak:
713*9880d681SAndroid Build Coastguard Worker case ARCInstKind::LoadWeakRetained:
714*9880d681SAndroid Build Coastguard Worker case ARCInstKind::InitWeak:
715*9880d681SAndroid Build Coastguard Worker case ARCInstKind::DestroyWeak: {
716*9880d681SAndroid Build Coastguard Worker CallInst *CI = cast<CallInst>(Inst);
717*9880d681SAndroid Build Coastguard Worker if (IsNullOrUndef(CI->getArgOperand(0))) {
718*9880d681SAndroid Build Coastguard Worker Changed = true;
719*9880d681SAndroid Build Coastguard Worker Type *Ty = CI->getArgOperand(0)->getType();
720*9880d681SAndroid Build Coastguard Worker new StoreInst(UndefValue::get(cast<PointerType>(Ty)->getElementType()),
721*9880d681SAndroid Build Coastguard Worker Constant::getNullValue(Ty),
722*9880d681SAndroid Build Coastguard Worker CI);
723*9880d681SAndroid Build Coastguard Worker llvm::Value *NewValue = UndefValue::get(CI->getType());
724*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "A null pointer-to-weak-pointer is undefined behavior."
725*9880d681SAndroid Build Coastguard Worker "\nOld = " << *CI << "\nNew = " << *NewValue << "\n");
726*9880d681SAndroid Build Coastguard Worker CI->replaceAllUsesWith(NewValue);
727*9880d681SAndroid Build Coastguard Worker CI->eraseFromParent();
728*9880d681SAndroid Build Coastguard Worker continue;
729*9880d681SAndroid Build Coastguard Worker }
730*9880d681SAndroid Build Coastguard Worker break;
731*9880d681SAndroid Build Coastguard Worker }
732*9880d681SAndroid Build Coastguard Worker case ARCInstKind::CopyWeak:
733*9880d681SAndroid Build Coastguard Worker case ARCInstKind::MoveWeak: {
734*9880d681SAndroid Build Coastguard Worker CallInst *CI = cast<CallInst>(Inst);
735*9880d681SAndroid Build Coastguard Worker if (IsNullOrUndef(CI->getArgOperand(0)) ||
736*9880d681SAndroid Build Coastguard Worker IsNullOrUndef(CI->getArgOperand(1))) {
737*9880d681SAndroid Build Coastguard Worker Changed = true;
738*9880d681SAndroid Build Coastguard Worker Type *Ty = CI->getArgOperand(0)->getType();
739*9880d681SAndroid Build Coastguard Worker new StoreInst(UndefValue::get(cast<PointerType>(Ty)->getElementType()),
740*9880d681SAndroid Build Coastguard Worker Constant::getNullValue(Ty),
741*9880d681SAndroid Build Coastguard Worker CI);
742*9880d681SAndroid Build Coastguard Worker
743*9880d681SAndroid Build Coastguard Worker llvm::Value *NewValue = UndefValue::get(CI->getType());
744*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "A null pointer-to-weak-pointer is undefined behavior."
745*9880d681SAndroid Build Coastguard Worker "\nOld = " << *CI << "\nNew = " << *NewValue << "\n");
746*9880d681SAndroid Build Coastguard Worker
747*9880d681SAndroid Build Coastguard Worker CI->replaceAllUsesWith(NewValue);
748*9880d681SAndroid Build Coastguard Worker CI->eraseFromParent();
749*9880d681SAndroid Build Coastguard Worker continue;
750*9880d681SAndroid Build Coastguard Worker }
751*9880d681SAndroid Build Coastguard Worker break;
752*9880d681SAndroid Build Coastguard Worker }
753*9880d681SAndroid Build Coastguard Worker case ARCInstKind::RetainRV:
754*9880d681SAndroid Build Coastguard Worker if (OptimizeRetainRVCall(F, Inst))
755*9880d681SAndroid Build Coastguard Worker continue;
756*9880d681SAndroid Build Coastguard Worker break;
757*9880d681SAndroid Build Coastguard Worker case ARCInstKind::AutoreleaseRV:
758*9880d681SAndroid Build Coastguard Worker OptimizeAutoreleaseRVCall(F, Inst, Class);
759*9880d681SAndroid Build Coastguard Worker break;
760*9880d681SAndroid Build Coastguard Worker }
761*9880d681SAndroid Build Coastguard Worker
762*9880d681SAndroid Build Coastguard Worker // objc_autorelease(x) -> objc_release(x) if x is otherwise unused.
763*9880d681SAndroid Build Coastguard Worker if (IsAutorelease(Class) && Inst->use_empty()) {
764*9880d681SAndroid Build Coastguard Worker CallInst *Call = cast<CallInst>(Inst);
765*9880d681SAndroid Build Coastguard Worker const Value *Arg = Call->getArgOperand(0);
766*9880d681SAndroid Build Coastguard Worker Arg = FindSingleUseIdentifiedObject(Arg);
767*9880d681SAndroid Build Coastguard Worker if (Arg) {
768*9880d681SAndroid Build Coastguard Worker Changed = true;
769*9880d681SAndroid Build Coastguard Worker ++NumAutoreleases;
770*9880d681SAndroid Build Coastguard Worker
771*9880d681SAndroid Build Coastguard Worker // Create the declaration lazily.
772*9880d681SAndroid Build Coastguard Worker LLVMContext &C = Inst->getContext();
773*9880d681SAndroid Build Coastguard Worker
774*9880d681SAndroid Build Coastguard Worker Constant *Decl = EP.get(ARCRuntimeEntryPointKind::Release);
775*9880d681SAndroid Build Coastguard Worker CallInst *NewCall = CallInst::Create(Decl, Call->getArgOperand(0), "",
776*9880d681SAndroid Build Coastguard Worker Call);
777*9880d681SAndroid Build Coastguard Worker NewCall->setMetadata(MDKindCache.get(ARCMDKindID::ImpreciseRelease),
778*9880d681SAndroid Build Coastguard Worker MDNode::get(C, None));
779*9880d681SAndroid Build Coastguard Worker
780*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Replacing autorelease{,RV}(x) with objc_release(x) "
781*9880d681SAndroid Build Coastguard Worker "since x is otherwise unused.\nOld: " << *Call << "\nNew: "
782*9880d681SAndroid Build Coastguard Worker << *NewCall << "\n");
783*9880d681SAndroid Build Coastguard Worker
784*9880d681SAndroid Build Coastguard Worker EraseInstruction(Call);
785*9880d681SAndroid Build Coastguard Worker Inst = NewCall;
786*9880d681SAndroid Build Coastguard Worker Class = ARCInstKind::Release;
787*9880d681SAndroid Build Coastguard Worker }
788*9880d681SAndroid Build Coastguard Worker }
789*9880d681SAndroid Build Coastguard Worker
790*9880d681SAndroid Build Coastguard Worker // For functions which can never be passed stack arguments, add
791*9880d681SAndroid Build Coastguard Worker // a tail keyword.
792*9880d681SAndroid Build Coastguard Worker if (IsAlwaysTail(Class)) {
793*9880d681SAndroid Build Coastguard Worker Changed = true;
794*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Adding tail keyword to function since it can never be "
795*9880d681SAndroid Build Coastguard Worker "passed stack args: " << *Inst << "\n");
796*9880d681SAndroid Build Coastguard Worker cast<CallInst>(Inst)->setTailCall();
797*9880d681SAndroid Build Coastguard Worker }
798*9880d681SAndroid Build Coastguard Worker
799*9880d681SAndroid Build Coastguard Worker // Ensure that functions that can never have a "tail" keyword due to the
800*9880d681SAndroid Build Coastguard Worker // semantics of ARC truly do not do so.
801*9880d681SAndroid Build Coastguard Worker if (IsNeverTail(Class)) {
802*9880d681SAndroid Build Coastguard Worker Changed = true;
803*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Removing tail keyword from function: " << *Inst <<
804*9880d681SAndroid Build Coastguard Worker "\n");
805*9880d681SAndroid Build Coastguard Worker cast<CallInst>(Inst)->setTailCall(false);
806*9880d681SAndroid Build Coastguard Worker }
807*9880d681SAndroid Build Coastguard Worker
808*9880d681SAndroid Build Coastguard Worker // Set nounwind as needed.
809*9880d681SAndroid Build Coastguard Worker if (IsNoThrow(Class)) {
810*9880d681SAndroid Build Coastguard Worker Changed = true;
811*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Found no throw class. Setting nounwind on: " << *Inst
812*9880d681SAndroid Build Coastguard Worker << "\n");
813*9880d681SAndroid Build Coastguard Worker cast<CallInst>(Inst)->setDoesNotThrow();
814*9880d681SAndroid Build Coastguard Worker }
815*9880d681SAndroid Build Coastguard Worker
816*9880d681SAndroid Build Coastguard Worker if (!IsNoopOnNull(Class)) {
817*9880d681SAndroid Build Coastguard Worker UsedInThisFunction |= 1 << unsigned(Class);
818*9880d681SAndroid Build Coastguard Worker continue;
819*9880d681SAndroid Build Coastguard Worker }
820*9880d681SAndroid Build Coastguard Worker
821*9880d681SAndroid Build Coastguard Worker const Value *Arg = GetArgRCIdentityRoot(Inst);
822*9880d681SAndroid Build Coastguard Worker
823*9880d681SAndroid Build Coastguard Worker // ARC calls with null are no-ops. Delete them.
824*9880d681SAndroid Build Coastguard Worker if (IsNullOrUndef(Arg)) {
825*9880d681SAndroid Build Coastguard Worker Changed = true;
826*9880d681SAndroid Build Coastguard Worker ++NumNoops;
827*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "ARC calls with null are no-ops. Erasing: " << *Inst
828*9880d681SAndroid Build Coastguard Worker << "\n");
829*9880d681SAndroid Build Coastguard Worker EraseInstruction(Inst);
830*9880d681SAndroid Build Coastguard Worker continue;
831*9880d681SAndroid Build Coastguard Worker }
832*9880d681SAndroid Build Coastguard Worker
833*9880d681SAndroid Build Coastguard Worker // Keep track of which of retain, release, autorelease, and retain_block
834*9880d681SAndroid Build Coastguard Worker // are actually present in this function.
835*9880d681SAndroid Build Coastguard Worker UsedInThisFunction |= 1 << unsigned(Class);
836*9880d681SAndroid Build Coastguard Worker
837*9880d681SAndroid Build Coastguard Worker // If Arg is a PHI, and one or more incoming values to the
838*9880d681SAndroid Build Coastguard Worker // PHI are null, and the call is control-equivalent to the PHI, and there
839*9880d681SAndroid Build Coastguard Worker // are no relevant side effects between the PHI and the call, the call
840*9880d681SAndroid Build Coastguard Worker // could be pushed up to just those paths with non-null incoming values.
841*9880d681SAndroid Build Coastguard Worker // For now, don't bother splitting critical edges for this.
842*9880d681SAndroid Build Coastguard Worker SmallVector<std::pair<Instruction *, const Value *>, 4> Worklist;
843*9880d681SAndroid Build Coastguard Worker Worklist.push_back(std::make_pair(Inst, Arg));
844*9880d681SAndroid Build Coastguard Worker do {
845*9880d681SAndroid Build Coastguard Worker std::pair<Instruction *, const Value *> Pair = Worklist.pop_back_val();
846*9880d681SAndroid Build Coastguard Worker Inst = Pair.first;
847*9880d681SAndroid Build Coastguard Worker Arg = Pair.second;
848*9880d681SAndroid Build Coastguard Worker
849*9880d681SAndroid Build Coastguard Worker const PHINode *PN = dyn_cast<PHINode>(Arg);
850*9880d681SAndroid Build Coastguard Worker if (!PN) continue;
851*9880d681SAndroid Build Coastguard Worker
852*9880d681SAndroid Build Coastguard Worker // Determine if the PHI has any null operands, or any incoming
853*9880d681SAndroid Build Coastguard Worker // critical edges.
854*9880d681SAndroid Build Coastguard Worker bool HasNull = false;
855*9880d681SAndroid Build Coastguard Worker bool HasCriticalEdges = false;
856*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
857*9880d681SAndroid Build Coastguard Worker Value *Incoming =
858*9880d681SAndroid Build Coastguard Worker GetRCIdentityRoot(PN->getIncomingValue(i));
859*9880d681SAndroid Build Coastguard Worker if (IsNullOrUndef(Incoming))
860*9880d681SAndroid Build Coastguard Worker HasNull = true;
861*9880d681SAndroid Build Coastguard Worker else if (cast<TerminatorInst>(PN->getIncomingBlock(i)->back())
862*9880d681SAndroid Build Coastguard Worker .getNumSuccessors() != 1) {
863*9880d681SAndroid Build Coastguard Worker HasCriticalEdges = true;
864*9880d681SAndroid Build Coastguard Worker break;
865*9880d681SAndroid Build Coastguard Worker }
866*9880d681SAndroid Build Coastguard Worker }
867*9880d681SAndroid Build Coastguard Worker // If we have null operands and no critical edges, optimize.
868*9880d681SAndroid Build Coastguard Worker if (!HasCriticalEdges && HasNull) {
869*9880d681SAndroid Build Coastguard Worker SmallPtrSet<Instruction *, 4> DependingInstructions;
870*9880d681SAndroid Build Coastguard Worker SmallPtrSet<const BasicBlock *, 4> Visited;
871*9880d681SAndroid Build Coastguard Worker
872*9880d681SAndroid Build Coastguard Worker // Check that there is nothing that cares about the reference
873*9880d681SAndroid Build Coastguard Worker // count between the call and the phi.
874*9880d681SAndroid Build Coastguard Worker switch (Class) {
875*9880d681SAndroid Build Coastguard Worker case ARCInstKind::Retain:
876*9880d681SAndroid Build Coastguard Worker case ARCInstKind::RetainBlock:
877*9880d681SAndroid Build Coastguard Worker // These can always be moved up.
878*9880d681SAndroid Build Coastguard Worker break;
879*9880d681SAndroid Build Coastguard Worker case ARCInstKind::Release:
880*9880d681SAndroid Build Coastguard Worker // These can't be moved across things that care about the retain
881*9880d681SAndroid Build Coastguard Worker // count.
882*9880d681SAndroid Build Coastguard Worker FindDependencies(NeedsPositiveRetainCount, Arg,
883*9880d681SAndroid Build Coastguard Worker Inst->getParent(), Inst,
884*9880d681SAndroid Build Coastguard Worker DependingInstructions, Visited, PA);
885*9880d681SAndroid Build Coastguard Worker break;
886*9880d681SAndroid Build Coastguard Worker case ARCInstKind::Autorelease:
887*9880d681SAndroid Build Coastguard Worker // These can't be moved across autorelease pool scope boundaries.
888*9880d681SAndroid Build Coastguard Worker FindDependencies(AutoreleasePoolBoundary, Arg,
889*9880d681SAndroid Build Coastguard Worker Inst->getParent(), Inst,
890*9880d681SAndroid Build Coastguard Worker DependingInstructions, Visited, PA);
891*9880d681SAndroid Build Coastguard Worker break;
892*9880d681SAndroid Build Coastguard Worker case ARCInstKind::ClaimRV:
893*9880d681SAndroid Build Coastguard Worker case ARCInstKind::RetainRV:
894*9880d681SAndroid Build Coastguard Worker case ARCInstKind::AutoreleaseRV:
895*9880d681SAndroid Build Coastguard Worker // Don't move these; the RV optimization depends on the autoreleaseRV
896*9880d681SAndroid Build Coastguard Worker // being tail called, and the retainRV being immediately after a call
897*9880d681SAndroid Build Coastguard Worker // (which might still happen if we get lucky with codegen layout, but
898*9880d681SAndroid Build Coastguard Worker // it's not worth taking the chance).
899*9880d681SAndroid Build Coastguard Worker continue;
900*9880d681SAndroid Build Coastguard Worker default:
901*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Invalid dependence flavor");
902*9880d681SAndroid Build Coastguard Worker }
903*9880d681SAndroid Build Coastguard Worker
904*9880d681SAndroid Build Coastguard Worker if (DependingInstructions.size() == 1 &&
905*9880d681SAndroid Build Coastguard Worker *DependingInstructions.begin() == PN) {
906*9880d681SAndroid Build Coastguard Worker Changed = true;
907*9880d681SAndroid Build Coastguard Worker ++NumPartialNoops;
908*9880d681SAndroid Build Coastguard Worker // Clone the call into each predecessor that has a non-null value.
909*9880d681SAndroid Build Coastguard Worker CallInst *CInst = cast<CallInst>(Inst);
910*9880d681SAndroid Build Coastguard Worker Type *ParamTy = CInst->getArgOperand(0)->getType();
911*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
912*9880d681SAndroid Build Coastguard Worker Value *Incoming =
913*9880d681SAndroid Build Coastguard Worker GetRCIdentityRoot(PN->getIncomingValue(i));
914*9880d681SAndroid Build Coastguard Worker if (!IsNullOrUndef(Incoming)) {
915*9880d681SAndroid Build Coastguard Worker CallInst *Clone = cast<CallInst>(CInst->clone());
916*9880d681SAndroid Build Coastguard Worker Value *Op = PN->getIncomingValue(i);
917*9880d681SAndroid Build Coastguard Worker Instruction *InsertPos = &PN->getIncomingBlock(i)->back();
918*9880d681SAndroid Build Coastguard Worker if (Op->getType() != ParamTy)
919*9880d681SAndroid Build Coastguard Worker Op = new BitCastInst(Op, ParamTy, "", InsertPos);
920*9880d681SAndroid Build Coastguard Worker Clone->setArgOperand(0, Op);
921*9880d681SAndroid Build Coastguard Worker Clone->insertBefore(InsertPos);
922*9880d681SAndroid Build Coastguard Worker
923*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Cloning "
924*9880d681SAndroid Build Coastguard Worker << *CInst << "\n"
925*9880d681SAndroid Build Coastguard Worker "And inserting clone at " << *InsertPos << "\n");
926*9880d681SAndroid Build Coastguard Worker Worklist.push_back(std::make_pair(Clone, Incoming));
927*9880d681SAndroid Build Coastguard Worker }
928*9880d681SAndroid Build Coastguard Worker }
929*9880d681SAndroid Build Coastguard Worker // Erase the original call.
930*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Erasing: " << *CInst << "\n");
931*9880d681SAndroid Build Coastguard Worker EraseInstruction(CInst);
932*9880d681SAndroid Build Coastguard Worker continue;
933*9880d681SAndroid Build Coastguard Worker }
934*9880d681SAndroid Build Coastguard Worker }
935*9880d681SAndroid Build Coastguard Worker } while (!Worklist.empty());
936*9880d681SAndroid Build Coastguard Worker }
937*9880d681SAndroid Build Coastguard Worker }
938*9880d681SAndroid Build Coastguard Worker
939*9880d681SAndroid Build Coastguard Worker /// If we have a top down pointer in the S_Use state, make sure that there are
940*9880d681SAndroid Build Coastguard Worker /// no CFG hazards by checking the states of various bottom up pointers.
CheckForUseCFGHazard(const Sequence SuccSSeq,const bool SuccSRRIKnownSafe,TopDownPtrState & S,bool & SomeSuccHasSame,bool & AllSuccsHaveSame,bool & NotAllSeqEqualButKnownSafe,bool & ShouldContinue)941*9880d681SAndroid Build Coastguard Worker static void CheckForUseCFGHazard(const Sequence SuccSSeq,
942*9880d681SAndroid Build Coastguard Worker const bool SuccSRRIKnownSafe,
943*9880d681SAndroid Build Coastguard Worker TopDownPtrState &S,
944*9880d681SAndroid Build Coastguard Worker bool &SomeSuccHasSame,
945*9880d681SAndroid Build Coastguard Worker bool &AllSuccsHaveSame,
946*9880d681SAndroid Build Coastguard Worker bool &NotAllSeqEqualButKnownSafe,
947*9880d681SAndroid Build Coastguard Worker bool &ShouldContinue) {
948*9880d681SAndroid Build Coastguard Worker switch (SuccSSeq) {
949*9880d681SAndroid Build Coastguard Worker case S_CanRelease: {
950*9880d681SAndroid Build Coastguard Worker if (!S.IsKnownSafe() && !SuccSRRIKnownSafe) {
951*9880d681SAndroid Build Coastguard Worker S.ClearSequenceProgress();
952*9880d681SAndroid Build Coastguard Worker break;
953*9880d681SAndroid Build Coastguard Worker }
954*9880d681SAndroid Build Coastguard Worker S.SetCFGHazardAfflicted(true);
955*9880d681SAndroid Build Coastguard Worker ShouldContinue = true;
956*9880d681SAndroid Build Coastguard Worker break;
957*9880d681SAndroid Build Coastguard Worker }
958*9880d681SAndroid Build Coastguard Worker case S_Use:
959*9880d681SAndroid Build Coastguard Worker SomeSuccHasSame = true;
960*9880d681SAndroid Build Coastguard Worker break;
961*9880d681SAndroid Build Coastguard Worker case S_Stop:
962*9880d681SAndroid Build Coastguard Worker case S_Release:
963*9880d681SAndroid Build Coastguard Worker case S_MovableRelease:
964*9880d681SAndroid Build Coastguard Worker if (!S.IsKnownSafe() && !SuccSRRIKnownSafe)
965*9880d681SAndroid Build Coastguard Worker AllSuccsHaveSame = false;
966*9880d681SAndroid Build Coastguard Worker else
967*9880d681SAndroid Build Coastguard Worker NotAllSeqEqualButKnownSafe = true;
968*9880d681SAndroid Build Coastguard Worker break;
969*9880d681SAndroid Build Coastguard Worker case S_Retain:
970*9880d681SAndroid Build Coastguard Worker llvm_unreachable("bottom-up pointer in retain state!");
971*9880d681SAndroid Build Coastguard Worker case S_None:
972*9880d681SAndroid Build Coastguard Worker llvm_unreachable("This should have been handled earlier.");
973*9880d681SAndroid Build Coastguard Worker }
974*9880d681SAndroid Build Coastguard Worker }
975*9880d681SAndroid Build Coastguard Worker
976*9880d681SAndroid Build Coastguard Worker /// If we have a Top Down pointer in the S_CanRelease state, make sure that
977*9880d681SAndroid Build Coastguard Worker /// there are no CFG hazards by checking the states of various bottom up
978*9880d681SAndroid Build Coastguard Worker /// pointers.
CheckForCanReleaseCFGHazard(const Sequence SuccSSeq,const bool SuccSRRIKnownSafe,TopDownPtrState & S,bool & SomeSuccHasSame,bool & AllSuccsHaveSame,bool & NotAllSeqEqualButKnownSafe)979*9880d681SAndroid Build Coastguard Worker static void CheckForCanReleaseCFGHazard(const Sequence SuccSSeq,
980*9880d681SAndroid Build Coastguard Worker const bool SuccSRRIKnownSafe,
981*9880d681SAndroid Build Coastguard Worker TopDownPtrState &S,
982*9880d681SAndroid Build Coastguard Worker bool &SomeSuccHasSame,
983*9880d681SAndroid Build Coastguard Worker bool &AllSuccsHaveSame,
984*9880d681SAndroid Build Coastguard Worker bool &NotAllSeqEqualButKnownSafe) {
985*9880d681SAndroid Build Coastguard Worker switch (SuccSSeq) {
986*9880d681SAndroid Build Coastguard Worker case S_CanRelease:
987*9880d681SAndroid Build Coastguard Worker SomeSuccHasSame = true;
988*9880d681SAndroid Build Coastguard Worker break;
989*9880d681SAndroid Build Coastguard Worker case S_Stop:
990*9880d681SAndroid Build Coastguard Worker case S_Release:
991*9880d681SAndroid Build Coastguard Worker case S_MovableRelease:
992*9880d681SAndroid Build Coastguard Worker case S_Use:
993*9880d681SAndroid Build Coastguard Worker if (!S.IsKnownSafe() && !SuccSRRIKnownSafe)
994*9880d681SAndroid Build Coastguard Worker AllSuccsHaveSame = false;
995*9880d681SAndroid Build Coastguard Worker else
996*9880d681SAndroid Build Coastguard Worker NotAllSeqEqualButKnownSafe = true;
997*9880d681SAndroid Build Coastguard Worker break;
998*9880d681SAndroid Build Coastguard Worker case S_Retain:
999*9880d681SAndroid Build Coastguard Worker llvm_unreachable("bottom-up pointer in retain state!");
1000*9880d681SAndroid Build Coastguard Worker case S_None:
1001*9880d681SAndroid Build Coastguard Worker llvm_unreachable("This should have been handled earlier.");
1002*9880d681SAndroid Build Coastguard Worker }
1003*9880d681SAndroid Build Coastguard Worker }
1004*9880d681SAndroid Build Coastguard Worker
1005*9880d681SAndroid Build Coastguard Worker /// Check for critical edges, loop boundaries, irreducible control flow, or
1006*9880d681SAndroid Build Coastguard Worker /// other CFG structures where moving code across the edge would result in it
1007*9880d681SAndroid Build Coastguard Worker /// being executed more.
1008*9880d681SAndroid Build Coastguard Worker void
CheckForCFGHazards(const BasicBlock * BB,DenseMap<const BasicBlock *,BBState> & BBStates,BBState & MyStates) const1009*9880d681SAndroid Build Coastguard Worker ObjCARCOpt::CheckForCFGHazards(const BasicBlock *BB,
1010*9880d681SAndroid Build Coastguard Worker DenseMap<const BasicBlock *, BBState> &BBStates,
1011*9880d681SAndroid Build Coastguard Worker BBState &MyStates) const {
1012*9880d681SAndroid Build Coastguard Worker // If any top-down local-use or possible-dec has a succ which is earlier in
1013*9880d681SAndroid Build Coastguard Worker // the sequence, forget it.
1014*9880d681SAndroid Build Coastguard Worker for (auto I = MyStates.top_down_ptr_begin(), E = MyStates.top_down_ptr_end();
1015*9880d681SAndroid Build Coastguard Worker I != E; ++I) {
1016*9880d681SAndroid Build Coastguard Worker TopDownPtrState &S = I->second;
1017*9880d681SAndroid Build Coastguard Worker const Sequence Seq = I->second.GetSeq();
1018*9880d681SAndroid Build Coastguard Worker
1019*9880d681SAndroid Build Coastguard Worker // We only care about S_Retain, S_CanRelease, and S_Use.
1020*9880d681SAndroid Build Coastguard Worker if (Seq == S_None)
1021*9880d681SAndroid Build Coastguard Worker continue;
1022*9880d681SAndroid Build Coastguard Worker
1023*9880d681SAndroid Build Coastguard Worker // Make sure that if extra top down states are added in the future that this
1024*9880d681SAndroid Build Coastguard Worker // code is updated to handle it.
1025*9880d681SAndroid Build Coastguard Worker assert((Seq == S_Retain || Seq == S_CanRelease || Seq == S_Use) &&
1026*9880d681SAndroid Build Coastguard Worker "Unknown top down sequence state.");
1027*9880d681SAndroid Build Coastguard Worker
1028*9880d681SAndroid Build Coastguard Worker const Value *Arg = I->first;
1029*9880d681SAndroid Build Coastguard Worker const TerminatorInst *TI = cast<TerminatorInst>(&BB->back());
1030*9880d681SAndroid Build Coastguard Worker bool SomeSuccHasSame = false;
1031*9880d681SAndroid Build Coastguard Worker bool AllSuccsHaveSame = true;
1032*9880d681SAndroid Build Coastguard Worker bool NotAllSeqEqualButKnownSafe = false;
1033*9880d681SAndroid Build Coastguard Worker
1034*9880d681SAndroid Build Coastguard Worker succ_const_iterator SI(TI), SE(TI, false);
1035*9880d681SAndroid Build Coastguard Worker
1036*9880d681SAndroid Build Coastguard Worker for (; SI != SE; ++SI) {
1037*9880d681SAndroid Build Coastguard Worker // If VisitBottomUp has pointer information for this successor, take
1038*9880d681SAndroid Build Coastguard Worker // what we know about it.
1039*9880d681SAndroid Build Coastguard Worker const DenseMap<const BasicBlock *, BBState>::iterator BBI =
1040*9880d681SAndroid Build Coastguard Worker BBStates.find(*SI);
1041*9880d681SAndroid Build Coastguard Worker assert(BBI != BBStates.end());
1042*9880d681SAndroid Build Coastguard Worker const BottomUpPtrState &SuccS = BBI->second.getPtrBottomUpState(Arg);
1043*9880d681SAndroid Build Coastguard Worker const Sequence SuccSSeq = SuccS.GetSeq();
1044*9880d681SAndroid Build Coastguard Worker
1045*9880d681SAndroid Build Coastguard Worker // If bottom up, the pointer is in an S_None state, clear the sequence
1046*9880d681SAndroid Build Coastguard Worker // progress since the sequence in the bottom up state finished
1047*9880d681SAndroid Build Coastguard Worker // suggesting a mismatch in between retains/releases. This is true for
1048*9880d681SAndroid Build Coastguard Worker // all three cases that we are handling here: S_Retain, S_Use, and
1049*9880d681SAndroid Build Coastguard Worker // S_CanRelease.
1050*9880d681SAndroid Build Coastguard Worker if (SuccSSeq == S_None) {
1051*9880d681SAndroid Build Coastguard Worker S.ClearSequenceProgress();
1052*9880d681SAndroid Build Coastguard Worker continue;
1053*9880d681SAndroid Build Coastguard Worker }
1054*9880d681SAndroid Build Coastguard Worker
1055*9880d681SAndroid Build Coastguard Worker // If we have S_Use or S_CanRelease, perform our check for cfg hazard
1056*9880d681SAndroid Build Coastguard Worker // checks.
1057*9880d681SAndroid Build Coastguard Worker const bool SuccSRRIKnownSafe = SuccS.IsKnownSafe();
1058*9880d681SAndroid Build Coastguard Worker
1059*9880d681SAndroid Build Coastguard Worker // *NOTE* We do not use Seq from above here since we are allowing for
1060*9880d681SAndroid Build Coastguard Worker // S.GetSeq() to change while we are visiting basic blocks.
1061*9880d681SAndroid Build Coastguard Worker switch(S.GetSeq()) {
1062*9880d681SAndroid Build Coastguard Worker case S_Use: {
1063*9880d681SAndroid Build Coastguard Worker bool ShouldContinue = false;
1064*9880d681SAndroid Build Coastguard Worker CheckForUseCFGHazard(SuccSSeq, SuccSRRIKnownSafe, S, SomeSuccHasSame,
1065*9880d681SAndroid Build Coastguard Worker AllSuccsHaveSame, NotAllSeqEqualButKnownSafe,
1066*9880d681SAndroid Build Coastguard Worker ShouldContinue);
1067*9880d681SAndroid Build Coastguard Worker if (ShouldContinue)
1068*9880d681SAndroid Build Coastguard Worker continue;
1069*9880d681SAndroid Build Coastguard Worker break;
1070*9880d681SAndroid Build Coastguard Worker }
1071*9880d681SAndroid Build Coastguard Worker case S_CanRelease: {
1072*9880d681SAndroid Build Coastguard Worker CheckForCanReleaseCFGHazard(SuccSSeq, SuccSRRIKnownSafe, S,
1073*9880d681SAndroid Build Coastguard Worker SomeSuccHasSame, AllSuccsHaveSame,
1074*9880d681SAndroid Build Coastguard Worker NotAllSeqEqualButKnownSafe);
1075*9880d681SAndroid Build Coastguard Worker break;
1076*9880d681SAndroid Build Coastguard Worker }
1077*9880d681SAndroid Build Coastguard Worker case S_Retain:
1078*9880d681SAndroid Build Coastguard Worker case S_None:
1079*9880d681SAndroid Build Coastguard Worker case S_Stop:
1080*9880d681SAndroid Build Coastguard Worker case S_Release:
1081*9880d681SAndroid Build Coastguard Worker case S_MovableRelease:
1082*9880d681SAndroid Build Coastguard Worker break;
1083*9880d681SAndroid Build Coastguard Worker }
1084*9880d681SAndroid Build Coastguard Worker }
1085*9880d681SAndroid Build Coastguard Worker
1086*9880d681SAndroid Build Coastguard Worker // If the state at the other end of any of the successor edges
1087*9880d681SAndroid Build Coastguard Worker // matches the current state, require all edges to match. This
1088*9880d681SAndroid Build Coastguard Worker // guards against loops in the middle of a sequence.
1089*9880d681SAndroid Build Coastguard Worker if (SomeSuccHasSame && !AllSuccsHaveSame) {
1090*9880d681SAndroid Build Coastguard Worker S.ClearSequenceProgress();
1091*9880d681SAndroid Build Coastguard Worker } else if (NotAllSeqEqualButKnownSafe) {
1092*9880d681SAndroid Build Coastguard Worker // If we would have cleared the state foregoing the fact that we are known
1093*9880d681SAndroid Build Coastguard Worker // safe, stop code motion. This is because whether or not it is safe to
1094*9880d681SAndroid Build Coastguard Worker // remove RR pairs via KnownSafe is an orthogonal concept to whether we
1095*9880d681SAndroid Build Coastguard Worker // are allowed to perform code motion.
1096*9880d681SAndroid Build Coastguard Worker S.SetCFGHazardAfflicted(true);
1097*9880d681SAndroid Build Coastguard Worker }
1098*9880d681SAndroid Build Coastguard Worker }
1099*9880d681SAndroid Build Coastguard Worker }
1100*9880d681SAndroid Build Coastguard Worker
VisitInstructionBottomUp(Instruction * Inst,BasicBlock * BB,BlotMapVector<Value *,RRInfo> & Retains,BBState & MyStates)1101*9880d681SAndroid Build Coastguard Worker bool ObjCARCOpt::VisitInstructionBottomUp(
1102*9880d681SAndroid Build Coastguard Worker Instruction *Inst, BasicBlock *BB, BlotMapVector<Value *, RRInfo> &Retains,
1103*9880d681SAndroid Build Coastguard Worker BBState &MyStates) {
1104*9880d681SAndroid Build Coastguard Worker bool NestingDetected = false;
1105*9880d681SAndroid Build Coastguard Worker ARCInstKind Class = GetARCInstKind(Inst);
1106*9880d681SAndroid Build Coastguard Worker const Value *Arg = nullptr;
1107*9880d681SAndroid Build Coastguard Worker
1108*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << " Class: " << Class << "\n");
1109*9880d681SAndroid Build Coastguard Worker
1110*9880d681SAndroid Build Coastguard Worker switch (Class) {
1111*9880d681SAndroid Build Coastguard Worker case ARCInstKind::Release: {
1112*9880d681SAndroid Build Coastguard Worker Arg = GetArgRCIdentityRoot(Inst);
1113*9880d681SAndroid Build Coastguard Worker
1114*9880d681SAndroid Build Coastguard Worker BottomUpPtrState &S = MyStates.getPtrBottomUpState(Arg);
1115*9880d681SAndroid Build Coastguard Worker NestingDetected |= S.InitBottomUp(MDKindCache, Inst);
1116*9880d681SAndroid Build Coastguard Worker break;
1117*9880d681SAndroid Build Coastguard Worker }
1118*9880d681SAndroid Build Coastguard Worker case ARCInstKind::RetainBlock:
1119*9880d681SAndroid Build Coastguard Worker // In OptimizeIndividualCalls, we have strength reduced all optimizable
1120*9880d681SAndroid Build Coastguard Worker // objc_retainBlocks to objc_retains. Thus at this point any
1121*9880d681SAndroid Build Coastguard Worker // objc_retainBlocks that we see are not optimizable.
1122*9880d681SAndroid Build Coastguard Worker break;
1123*9880d681SAndroid Build Coastguard Worker case ARCInstKind::Retain:
1124*9880d681SAndroid Build Coastguard Worker case ARCInstKind::RetainRV: {
1125*9880d681SAndroid Build Coastguard Worker Arg = GetArgRCIdentityRoot(Inst);
1126*9880d681SAndroid Build Coastguard Worker BottomUpPtrState &S = MyStates.getPtrBottomUpState(Arg);
1127*9880d681SAndroid Build Coastguard Worker if (S.MatchWithRetain()) {
1128*9880d681SAndroid Build Coastguard Worker // Don't do retain+release tracking for ARCInstKind::RetainRV, because
1129*9880d681SAndroid Build Coastguard Worker // it's better to let it remain as the first instruction after a call.
1130*9880d681SAndroid Build Coastguard Worker if (Class != ARCInstKind::RetainRV) {
1131*9880d681SAndroid Build Coastguard Worker DEBUG(llvm::dbgs() << " Matching with: " << *Inst << "\n");
1132*9880d681SAndroid Build Coastguard Worker Retains[Inst] = S.GetRRInfo();
1133*9880d681SAndroid Build Coastguard Worker }
1134*9880d681SAndroid Build Coastguard Worker S.ClearSequenceProgress();
1135*9880d681SAndroid Build Coastguard Worker }
1136*9880d681SAndroid Build Coastguard Worker // A retain moving bottom up can be a use.
1137*9880d681SAndroid Build Coastguard Worker break;
1138*9880d681SAndroid Build Coastguard Worker }
1139*9880d681SAndroid Build Coastguard Worker case ARCInstKind::AutoreleasepoolPop:
1140*9880d681SAndroid Build Coastguard Worker // Conservatively, clear MyStates for all known pointers.
1141*9880d681SAndroid Build Coastguard Worker MyStates.clearBottomUpPointers();
1142*9880d681SAndroid Build Coastguard Worker return NestingDetected;
1143*9880d681SAndroid Build Coastguard Worker case ARCInstKind::AutoreleasepoolPush:
1144*9880d681SAndroid Build Coastguard Worker case ARCInstKind::None:
1145*9880d681SAndroid Build Coastguard Worker // These are irrelevant.
1146*9880d681SAndroid Build Coastguard Worker return NestingDetected;
1147*9880d681SAndroid Build Coastguard Worker case ARCInstKind::User:
1148*9880d681SAndroid Build Coastguard Worker // If we have a store into an alloca of a pointer we are tracking, the
1149*9880d681SAndroid Build Coastguard Worker // pointer has multiple owners implying that we must be more conservative.
1150*9880d681SAndroid Build Coastguard Worker //
1151*9880d681SAndroid Build Coastguard Worker // This comes up in the context of a pointer being ``KnownSafe''. In the
1152*9880d681SAndroid Build Coastguard Worker // presence of a block being initialized, the frontend will emit the
1153*9880d681SAndroid Build Coastguard Worker // objc_retain on the original pointer and the release on the pointer loaded
1154*9880d681SAndroid Build Coastguard Worker // from the alloca. The optimizer will through the provenance analysis
1155*9880d681SAndroid Build Coastguard Worker // realize that the two are related, but since we only require KnownSafe in
1156*9880d681SAndroid Build Coastguard Worker // one direction, will match the inner retain on the original pointer with
1157*9880d681SAndroid Build Coastguard Worker // the guard release on the original pointer. This is fixed by ensuring that
1158*9880d681SAndroid Build Coastguard Worker // in the presence of allocas we only unconditionally remove pointers if
1159*9880d681SAndroid Build Coastguard Worker // both our retain and our release are KnownSafe.
1160*9880d681SAndroid Build Coastguard Worker if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) {
1161*9880d681SAndroid Build Coastguard Worker const DataLayout &DL = BB->getModule()->getDataLayout();
1162*9880d681SAndroid Build Coastguard Worker if (AreAnyUnderlyingObjectsAnAlloca(SI->getPointerOperand(), DL)) {
1163*9880d681SAndroid Build Coastguard Worker auto I = MyStates.findPtrBottomUpState(
1164*9880d681SAndroid Build Coastguard Worker GetRCIdentityRoot(SI->getValueOperand()));
1165*9880d681SAndroid Build Coastguard Worker if (I != MyStates.bottom_up_ptr_end())
1166*9880d681SAndroid Build Coastguard Worker MultiOwnersSet.insert(I->first);
1167*9880d681SAndroid Build Coastguard Worker }
1168*9880d681SAndroid Build Coastguard Worker }
1169*9880d681SAndroid Build Coastguard Worker break;
1170*9880d681SAndroid Build Coastguard Worker default:
1171*9880d681SAndroid Build Coastguard Worker break;
1172*9880d681SAndroid Build Coastguard Worker }
1173*9880d681SAndroid Build Coastguard Worker
1174*9880d681SAndroid Build Coastguard Worker // Consider any other possible effects of this instruction on each
1175*9880d681SAndroid Build Coastguard Worker // pointer being tracked.
1176*9880d681SAndroid Build Coastguard Worker for (auto MI = MyStates.bottom_up_ptr_begin(),
1177*9880d681SAndroid Build Coastguard Worker ME = MyStates.bottom_up_ptr_end();
1178*9880d681SAndroid Build Coastguard Worker MI != ME; ++MI) {
1179*9880d681SAndroid Build Coastguard Worker const Value *Ptr = MI->first;
1180*9880d681SAndroid Build Coastguard Worker if (Ptr == Arg)
1181*9880d681SAndroid Build Coastguard Worker continue; // Handled above.
1182*9880d681SAndroid Build Coastguard Worker BottomUpPtrState &S = MI->second;
1183*9880d681SAndroid Build Coastguard Worker
1184*9880d681SAndroid Build Coastguard Worker if (S.HandlePotentialAlterRefCount(Inst, Ptr, PA, Class))
1185*9880d681SAndroid Build Coastguard Worker continue;
1186*9880d681SAndroid Build Coastguard Worker
1187*9880d681SAndroid Build Coastguard Worker S.HandlePotentialUse(BB, Inst, Ptr, PA, Class);
1188*9880d681SAndroid Build Coastguard Worker }
1189*9880d681SAndroid Build Coastguard Worker
1190*9880d681SAndroid Build Coastguard Worker return NestingDetected;
1191*9880d681SAndroid Build Coastguard Worker }
1192*9880d681SAndroid Build Coastguard Worker
VisitBottomUp(BasicBlock * BB,DenseMap<const BasicBlock *,BBState> & BBStates,BlotMapVector<Value *,RRInfo> & Retains)1193*9880d681SAndroid Build Coastguard Worker bool ObjCARCOpt::VisitBottomUp(BasicBlock *BB,
1194*9880d681SAndroid Build Coastguard Worker DenseMap<const BasicBlock *, BBState> &BBStates,
1195*9880d681SAndroid Build Coastguard Worker BlotMapVector<Value *, RRInfo> &Retains) {
1196*9880d681SAndroid Build Coastguard Worker
1197*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "\n== ObjCARCOpt::VisitBottomUp ==\n");
1198*9880d681SAndroid Build Coastguard Worker
1199*9880d681SAndroid Build Coastguard Worker bool NestingDetected = false;
1200*9880d681SAndroid Build Coastguard Worker BBState &MyStates = BBStates[BB];
1201*9880d681SAndroid Build Coastguard Worker
1202*9880d681SAndroid Build Coastguard Worker // Merge the states from each successor to compute the initial state
1203*9880d681SAndroid Build Coastguard Worker // for the current block.
1204*9880d681SAndroid Build Coastguard Worker BBState::edge_iterator SI(MyStates.succ_begin()),
1205*9880d681SAndroid Build Coastguard Worker SE(MyStates.succ_end());
1206*9880d681SAndroid Build Coastguard Worker if (SI != SE) {
1207*9880d681SAndroid Build Coastguard Worker const BasicBlock *Succ = *SI;
1208*9880d681SAndroid Build Coastguard Worker DenseMap<const BasicBlock *, BBState>::iterator I = BBStates.find(Succ);
1209*9880d681SAndroid Build Coastguard Worker assert(I != BBStates.end());
1210*9880d681SAndroid Build Coastguard Worker MyStates.InitFromSucc(I->second);
1211*9880d681SAndroid Build Coastguard Worker ++SI;
1212*9880d681SAndroid Build Coastguard Worker for (; SI != SE; ++SI) {
1213*9880d681SAndroid Build Coastguard Worker Succ = *SI;
1214*9880d681SAndroid Build Coastguard Worker I = BBStates.find(Succ);
1215*9880d681SAndroid Build Coastguard Worker assert(I != BBStates.end());
1216*9880d681SAndroid Build Coastguard Worker MyStates.MergeSucc(I->second);
1217*9880d681SAndroid Build Coastguard Worker }
1218*9880d681SAndroid Build Coastguard Worker }
1219*9880d681SAndroid Build Coastguard Worker
1220*9880d681SAndroid Build Coastguard Worker DEBUG(llvm::dbgs() << "Before:\n" << BBStates[BB] << "\n"
1221*9880d681SAndroid Build Coastguard Worker << "Performing Dataflow:\n");
1222*9880d681SAndroid Build Coastguard Worker
1223*9880d681SAndroid Build Coastguard Worker // Visit all the instructions, bottom-up.
1224*9880d681SAndroid Build Coastguard Worker for (BasicBlock::iterator I = BB->end(), E = BB->begin(); I != E; --I) {
1225*9880d681SAndroid Build Coastguard Worker Instruction *Inst = &*std::prev(I);
1226*9880d681SAndroid Build Coastguard Worker
1227*9880d681SAndroid Build Coastguard Worker // Invoke instructions are visited as part of their successors (below).
1228*9880d681SAndroid Build Coastguard Worker if (isa<InvokeInst>(Inst))
1229*9880d681SAndroid Build Coastguard Worker continue;
1230*9880d681SAndroid Build Coastguard Worker
1231*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << " Visiting " << *Inst << "\n");
1232*9880d681SAndroid Build Coastguard Worker
1233*9880d681SAndroid Build Coastguard Worker NestingDetected |= VisitInstructionBottomUp(Inst, BB, Retains, MyStates);
1234*9880d681SAndroid Build Coastguard Worker }
1235*9880d681SAndroid Build Coastguard Worker
1236*9880d681SAndroid Build Coastguard Worker // If there's a predecessor with an invoke, visit the invoke as if it were
1237*9880d681SAndroid Build Coastguard Worker // part of this block, since we can't insert code after an invoke in its own
1238*9880d681SAndroid Build Coastguard Worker // block, and we don't want to split critical edges.
1239*9880d681SAndroid Build Coastguard Worker for (BBState::edge_iterator PI(MyStates.pred_begin()),
1240*9880d681SAndroid Build Coastguard Worker PE(MyStates.pred_end()); PI != PE; ++PI) {
1241*9880d681SAndroid Build Coastguard Worker BasicBlock *Pred = *PI;
1242*9880d681SAndroid Build Coastguard Worker if (InvokeInst *II = dyn_cast<InvokeInst>(&Pred->back()))
1243*9880d681SAndroid Build Coastguard Worker NestingDetected |= VisitInstructionBottomUp(II, BB, Retains, MyStates);
1244*9880d681SAndroid Build Coastguard Worker }
1245*9880d681SAndroid Build Coastguard Worker
1246*9880d681SAndroid Build Coastguard Worker DEBUG(llvm::dbgs() << "\nFinal State:\n" << BBStates[BB] << "\n");
1247*9880d681SAndroid Build Coastguard Worker
1248*9880d681SAndroid Build Coastguard Worker return NestingDetected;
1249*9880d681SAndroid Build Coastguard Worker }
1250*9880d681SAndroid Build Coastguard Worker
1251*9880d681SAndroid Build Coastguard Worker bool
VisitInstructionTopDown(Instruction * Inst,DenseMap<Value *,RRInfo> & Releases,BBState & MyStates)1252*9880d681SAndroid Build Coastguard Worker ObjCARCOpt::VisitInstructionTopDown(Instruction *Inst,
1253*9880d681SAndroid Build Coastguard Worker DenseMap<Value *, RRInfo> &Releases,
1254*9880d681SAndroid Build Coastguard Worker BBState &MyStates) {
1255*9880d681SAndroid Build Coastguard Worker bool NestingDetected = false;
1256*9880d681SAndroid Build Coastguard Worker ARCInstKind Class = GetARCInstKind(Inst);
1257*9880d681SAndroid Build Coastguard Worker const Value *Arg = nullptr;
1258*9880d681SAndroid Build Coastguard Worker
1259*9880d681SAndroid Build Coastguard Worker DEBUG(llvm::dbgs() << " Class: " << Class << "\n");
1260*9880d681SAndroid Build Coastguard Worker
1261*9880d681SAndroid Build Coastguard Worker switch (Class) {
1262*9880d681SAndroid Build Coastguard Worker case ARCInstKind::RetainBlock:
1263*9880d681SAndroid Build Coastguard Worker // In OptimizeIndividualCalls, we have strength reduced all optimizable
1264*9880d681SAndroid Build Coastguard Worker // objc_retainBlocks to objc_retains. Thus at this point any
1265*9880d681SAndroid Build Coastguard Worker // objc_retainBlocks that we see are not optimizable. We need to break since
1266*9880d681SAndroid Build Coastguard Worker // a retain can be a potential use.
1267*9880d681SAndroid Build Coastguard Worker break;
1268*9880d681SAndroid Build Coastguard Worker case ARCInstKind::Retain:
1269*9880d681SAndroid Build Coastguard Worker case ARCInstKind::RetainRV: {
1270*9880d681SAndroid Build Coastguard Worker Arg = GetArgRCIdentityRoot(Inst);
1271*9880d681SAndroid Build Coastguard Worker TopDownPtrState &S = MyStates.getPtrTopDownState(Arg);
1272*9880d681SAndroid Build Coastguard Worker NestingDetected |= S.InitTopDown(Class, Inst);
1273*9880d681SAndroid Build Coastguard Worker // A retain can be a potential use; proceed to the generic checking
1274*9880d681SAndroid Build Coastguard Worker // code below.
1275*9880d681SAndroid Build Coastguard Worker break;
1276*9880d681SAndroid Build Coastguard Worker }
1277*9880d681SAndroid Build Coastguard Worker case ARCInstKind::Release: {
1278*9880d681SAndroid Build Coastguard Worker Arg = GetArgRCIdentityRoot(Inst);
1279*9880d681SAndroid Build Coastguard Worker TopDownPtrState &S = MyStates.getPtrTopDownState(Arg);
1280*9880d681SAndroid Build Coastguard Worker // Try to form a tentative pair in between this release instruction and the
1281*9880d681SAndroid Build Coastguard Worker // top down pointers that we are tracking.
1282*9880d681SAndroid Build Coastguard Worker if (S.MatchWithRelease(MDKindCache, Inst)) {
1283*9880d681SAndroid Build Coastguard Worker // If we succeed, copy S's RRInfo into the Release -> {Retain Set
1284*9880d681SAndroid Build Coastguard Worker // Map}. Then we clear S.
1285*9880d681SAndroid Build Coastguard Worker DEBUG(llvm::dbgs() << " Matching with: " << *Inst << "\n");
1286*9880d681SAndroid Build Coastguard Worker Releases[Inst] = S.GetRRInfo();
1287*9880d681SAndroid Build Coastguard Worker S.ClearSequenceProgress();
1288*9880d681SAndroid Build Coastguard Worker }
1289*9880d681SAndroid Build Coastguard Worker break;
1290*9880d681SAndroid Build Coastguard Worker }
1291*9880d681SAndroid Build Coastguard Worker case ARCInstKind::AutoreleasepoolPop:
1292*9880d681SAndroid Build Coastguard Worker // Conservatively, clear MyStates for all known pointers.
1293*9880d681SAndroid Build Coastguard Worker MyStates.clearTopDownPointers();
1294*9880d681SAndroid Build Coastguard Worker return false;
1295*9880d681SAndroid Build Coastguard Worker case ARCInstKind::AutoreleasepoolPush:
1296*9880d681SAndroid Build Coastguard Worker case ARCInstKind::None:
1297*9880d681SAndroid Build Coastguard Worker // These can not be uses of
1298*9880d681SAndroid Build Coastguard Worker return false;
1299*9880d681SAndroid Build Coastguard Worker default:
1300*9880d681SAndroid Build Coastguard Worker break;
1301*9880d681SAndroid Build Coastguard Worker }
1302*9880d681SAndroid Build Coastguard Worker
1303*9880d681SAndroid Build Coastguard Worker // Consider any other possible effects of this instruction on each
1304*9880d681SAndroid Build Coastguard Worker // pointer being tracked.
1305*9880d681SAndroid Build Coastguard Worker for (auto MI = MyStates.top_down_ptr_begin(),
1306*9880d681SAndroid Build Coastguard Worker ME = MyStates.top_down_ptr_end();
1307*9880d681SAndroid Build Coastguard Worker MI != ME; ++MI) {
1308*9880d681SAndroid Build Coastguard Worker const Value *Ptr = MI->first;
1309*9880d681SAndroid Build Coastguard Worker if (Ptr == Arg)
1310*9880d681SAndroid Build Coastguard Worker continue; // Handled above.
1311*9880d681SAndroid Build Coastguard Worker TopDownPtrState &S = MI->second;
1312*9880d681SAndroid Build Coastguard Worker if (S.HandlePotentialAlterRefCount(Inst, Ptr, PA, Class))
1313*9880d681SAndroid Build Coastguard Worker continue;
1314*9880d681SAndroid Build Coastguard Worker
1315*9880d681SAndroid Build Coastguard Worker S.HandlePotentialUse(Inst, Ptr, PA, Class);
1316*9880d681SAndroid Build Coastguard Worker }
1317*9880d681SAndroid Build Coastguard Worker
1318*9880d681SAndroid Build Coastguard Worker return NestingDetected;
1319*9880d681SAndroid Build Coastguard Worker }
1320*9880d681SAndroid Build Coastguard Worker
1321*9880d681SAndroid Build Coastguard Worker bool
VisitTopDown(BasicBlock * BB,DenseMap<const BasicBlock *,BBState> & BBStates,DenseMap<Value *,RRInfo> & Releases)1322*9880d681SAndroid Build Coastguard Worker ObjCARCOpt::VisitTopDown(BasicBlock *BB,
1323*9880d681SAndroid Build Coastguard Worker DenseMap<const BasicBlock *, BBState> &BBStates,
1324*9880d681SAndroid Build Coastguard Worker DenseMap<Value *, RRInfo> &Releases) {
1325*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "\n== ObjCARCOpt::VisitTopDown ==\n");
1326*9880d681SAndroid Build Coastguard Worker bool NestingDetected = false;
1327*9880d681SAndroid Build Coastguard Worker BBState &MyStates = BBStates[BB];
1328*9880d681SAndroid Build Coastguard Worker
1329*9880d681SAndroid Build Coastguard Worker // Merge the states from each predecessor to compute the initial state
1330*9880d681SAndroid Build Coastguard Worker // for the current block.
1331*9880d681SAndroid Build Coastguard Worker BBState::edge_iterator PI(MyStates.pred_begin()),
1332*9880d681SAndroid Build Coastguard Worker PE(MyStates.pred_end());
1333*9880d681SAndroid Build Coastguard Worker if (PI != PE) {
1334*9880d681SAndroid Build Coastguard Worker const BasicBlock *Pred = *PI;
1335*9880d681SAndroid Build Coastguard Worker DenseMap<const BasicBlock *, BBState>::iterator I = BBStates.find(Pred);
1336*9880d681SAndroid Build Coastguard Worker assert(I != BBStates.end());
1337*9880d681SAndroid Build Coastguard Worker MyStates.InitFromPred(I->second);
1338*9880d681SAndroid Build Coastguard Worker ++PI;
1339*9880d681SAndroid Build Coastguard Worker for (; PI != PE; ++PI) {
1340*9880d681SAndroid Build Coastguard Worker Pred = *PI;
1341*9880d681SAndroid Build Coastguard Worker I = BBStates.find(Pred);
1342*9880d681SAndroid Build Coastguard Worker assert(I != BBStates.end());
1343*9880d681SAndroid Build Coastguard Worker MyStates.MergePred(I->second);
1344*9880d681SAndroid Build Coastguard Worker }
1345*9880d681SAndroid Build Coastguard Worker }
1346*9880d681SAndroid Build Coastguard Worker
1347*9880d681SAndroid Build Coastguard Worker DEBUG(llvm::dbgs() << "Before:\n" << BBStates[BB] << "\n"
1348*9880d681SAndroid Build Coastguard Worker << "Performing Dataflow:\n");
1349*9880d681SAndroid Build Coastguard Worker
1350*9880d681SAndroid Build Coastguard Worker // Visit all the instructions, top-down.
1351*9880d681SAndroid Build Coastguard Worker for (Instruction &Inst : *BB) {
1352*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << " Visiting " << Inst << "\n");
1353*9880d681SAndroid Build Coastguard Worker
1354*9880d681SAndroid Build Coastguard Worker NestingDetected |= VisitInstructionTopDown(&Inst, Releases, MyStates);
1355*9880d681SAndroid Build Coastguard Worker }
1356*9880d681SAndroid Build Coastguard Worker
1357*9880d681SAndroid Build Coastguard Worker DEBUG(llvm::dbgs() << "\nState Before Checking for CFG Hazards:\n"
1358*9880d681SAndroid Build Coastguard Worker << BBStates[BB] << "\n\n");
1359*9880d681SAndroid Build Coastguard Worker CheckForCFGHazards(BB, BBStates, MyStates);
1360*9880d681SAndroid Build Coastguard Worker DEBUG(llvm::dbgs() << "Final State:\n" << BBStates[BB] << "\n");
1361*9880d681SAndroid Build Coastguard Worker return NestingDetected;
1362*9880d681SAndroid Build Coastguard Worker }
1363*9880d681SAndroid Build Coastguard Worker
1364*9880d681SAndroid Build Coastguard Worker static void
ComputePostOrders(Function & F,SmallVectorImpl<BasicBlock * > & PostOrder,SmallVectorImpl<BasicBlock * > & ReverseCFGPostOrder,unsigned NoObjCARCExceptionsMDKind,DenseMap<const BasicBlock *,BBState> & BBStates)1365*9880d681SAndroid Build Coastguard Worker ComputePostOrders(Function &F,
1366*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<BasicBlock *> &PostOrder,
1367*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<BasicBlock *> &ReverseCFGPostOrder,
1368*9880d681SAndroid Build Coastguard Worker unsigned NoObjCARCExceptionsMDKind,
1369*9880d681SAndroid Build Coastguard Worker DenseMap<const BasicBlock *, BBState> &BBStates) {
1370*9880d681SAndroid Build Coastguard Worker /// The visited set, for doing DFS walks.
1371*9880d681SAndroid Build Coastguard Worker SmallPtrSet<BasicBlock *, 16> Visited;
1372*9880d681SAndroid Build Coastguard Worker
1373*9880d681SAndroid Build Coastguard Worker // Do DFS, computing the PostOrder.
1374*9880d681SAndroid Build Coastguard Worker SmallPtrSet<BasicBlock *, 16> OnStack;
1375*9880d681SAndroid Build Coastguard Worker SmallVector<std::pair<BasicBlock *, succ_iterator>, 16> SuccStack;
1376*9880d681SAndroid Build Coastguard Worker
1377*9880d681SAndroid Build Coastguard Worker // Functions always have exactly one entry block, and we don't have
1378*9880d681SAndroid Build Coastguard Worker // any other block that we treat like an entry block.
1379*9880d681SAndroid Build Coastguard Worker BasicBlock *EntryBB = &F.getEntryBlock();
1380*9880d681SAndroid Build Coastguard Worker BBState &MyStates = BBStates[EntryBB];
1381*9880d681SAndroid Build Coastguard Worker MyStates.SetAsEntry();
1382*9880d681SAndroid Build Coastguard Worker TerminatorInst *EntryTI = cast<TerminatorInst>(&EntryBB->back());
1383*9880d681SAndroid Build Coastguard Worker SuccStack.push_back(std::make_pair(EntryBB, succ_iterator(EntryTI)));
1384*9880d681SAndroid Build Coastguard Worker Visited.insert(EntryBB);
1385*9880d681SAndroid Build Coastguard Worker OnStack.insert(EntryBB);
1386*9880d681SAndroid Build Coastguard Worker do {
1387*9880d681SAndroid Build Coastguard Worker dfs_next_succ:
1388*9880d681SAndroid Build Coastguard Worker BasicBlock *CurrBB = SuccStack.back().first;
1389*9880d681SAndroid Build Coastguard Worker TerminatorInst *TI = cast<TerminatorInst>(&CurrBB->back());
1390*9880d681SAndroid Build Coastguard Worker succ_iterator SE(TI, false);
1391*9880d681SAndroid Build Coastguard Worker
1392*9880d681SAndroid Build Coastguard Worker while (SuccStack.back().second != SE) {
1393*9880d681SAndroid Build Coastguard Worker BasicBlock *SuccBB = *SuccStack.back().second++;
1394*9880d681SAndroid Build Coastguard Worker if (Visited.insert(SuccBB).second) {
1395*9880d681SAndroid Build Coastguard Worker TerminatorInst *TI = cast<TerminatorInst>(&SuccBB->back());
1396*9880d681SAndroid Build Coastguard Worker SuccStack.push_back(std::make_pair(SuccBB, succ_iterator(TI)));
1397*9880d681SAndroid Build Coastguard Worker BBStates[CurrBB].addSucc(SuccBB);
1398*9880d681SAndroid Build Coastguard Worker BBState &SuccStates = BBStates[SuccBB];
1399*9880d681SAndroid Build Coastguard Worker SuccStates.addPred(CurrBB);
1400*9880d681SAndroid Build Coastguard Worker OnStack.insert(SuccBB);
1401*9880d681SAndroid Build Coastguard Worker goto dfs_next_succ;
1402*9880d681SAndroid Build Coastguard Worker }
1403*9880d681SAndroid Build Coastguard Worker
1404*9880d681SAndroid Build Coastguard Worker if (!OnStack.count(SuccBB)) {
1405*9880d681SAndroid Build Coastguard Worker BBStates[CurrBB].addSucc(SuccBB);
1406*9880d681SAndroid Build Coastguard Worker BBStates[SuccBB].addPred(CurrBB);
1407*9880d681SAndroid Build Coastguard Worker }
1408*9880d681SAndroid Build Coastguard Worker }
1409*9880d681SAndroid Build Coastguard Worker OnStack.erase(CurrBB);
1410*9880d681SAndroid Build Coastguard Worker PostOrder.push_back(CurrBB);
1411*9880d681SAndroid Build Coastguard Worker SuccStack.pop_back();
1412*9880d681SAndroid Build Coastguard Worker } while (!SuccStack.empty());
1413*9880d681SAndroid Build Coastguard Worker
1414*9880d681SAndroid Build Coastguard Worker Visited.clear();
1415*9880d681SAndroid Build Coastguard Worker
1416*9880d681SAndroid Build Coastguard Worker // Do reverse-CFG DFS, computing the reverse-CFG PostOrder.
1417*9880d681SAndroid Build Coastguard Worker // Functions may have many exits, and there also blocks which we treat
1418*9880d681SAndroid Build Coastguard Worker // as exits due to ignored edges.
1419*9880d681SAndroid Build Coastguard Worker SmallVector<std::pair<BasicBlock *, BBState::edge_iterator>, 16> PredStack;
1420*9880d681SAndroid Build Coastguard Worker for (BasicBlock &ExitBB : F) {
1421*9880d681SAndroid Build Coastguard Worker BBState &MyStates = BBStates[&ExitBB];
1422*9880d681SAndroid Build Coastguard Worker if (!MyStates.isExit())
1423*9880d681SAndroid Build Coastguard Worker continue;
1424*9880d681SAndroid Build Coastguard Worker
1425*9880d681SAndroid Build Coastguard Worker MyStates.SetAsExit();
1426*9880d681SAndroid Build Coastguard Worker
1427*9880d681SAndroid Build Coastguard Worker PredStack.push_back(std::make_pair(&ExitBB, MyStates.pred_begin()));
1428*9880d681SAndroid Build Coastguard Worker Visited.insert(&ExitBB);
1429*9880d681SAndroid Build Coastguard Worker while (!PredStack.empty()) {
1430*9880d681SAndroid Build Coastguard Worker reverse_dfs_next_succ:
1431*9880d681SAndroid Build Coastguard Worker BBState::edge_iterator PE = BBStates[PredStack.back().first].pred_end();
1432*9880d681SAndroid Build Coastguard Worker while (PredStack.back().second != PE) {
1433*9880d681SAndroid Build Coastguard Worker BasicBlock *BB = *PredStack.back().second++;
1434*9880d681SAndroid Build Coastguard Worker if (Visited.insert(BB).second) {
1435*9880d681SAndroid Build Coastguard Worker PredStack.push_back(std::make_pair(BB, BBStates[BB].pred_begin()));
1436*9880d681SAndroid Build Coastguard Worker goto reverse_dfs_next_succ;
1437*9880d681SAndroid Build Coastguard Worker }
1438*9880d681SAndroid Build Coastguard Worker }
1439*9880d681SAndroid Build Coastguard Worker ReverseCFGPostOrder.push_back(PredStack.pop_back_val().first);
1440*9880d681SAndroid Build Coastguard Worker }
1441*9880d681SAndroid Build Coastguard Worker }
1442*9880d681SAndroid Build Coastguard Worker }
1443*9880d681SAndroid Build Coastguard Worker
1444*9880d681SAndroid Build Coastguard Worker // Visit the function both top-down and bottom-up.
Visit(Function & F,DenseMap<const BasicBlock *,BBState> & BBStates,BlotMapVector<Value *,RRInfo> & Retains,DenseMap<Value *,RRInfo> & Releases)1445*9880d681SAndroid Build Coastguard Worker bool ObjCARCOpt::Visit(Function &F,
1446*9880d681SAndroid Build Coastguard Worker DenseMap<const BasicBlock *, BBState> &BBStates,
1447*9880d681SAndroid Build Coastguard Worker BlotMapVector<Value *, RRInfo> &Retains,
1448*9880d681SAndroid Build Coastguard Worker DenseMap<Value *, RRInfo> &Releases) {
1449*9880d681SAndroid Build Coastguard Worker
1450*9880d681SAndroid Build Coastguard Worker // Use reverse-postorder traversals, because we magically know that loops
1451*9880d681SAndroid Build Coastguard Worker // will be well behaved, i.e. they won't repeatedly call retain on a single
1452*9880d681SAndroid Build Coastguard Worker // pointer without doing a release. We can't use the ReversePostOrderTraversal
1453*9880d681SAndroid Build Coastguard Worker // class here because we want the reverse-CFG postorder to consider each
1454*9880d681SAndroid Build Coastguard Worker // function exit point, and we want to ignore selected cycle edges.
1455*9880d681SAndroid Build Coastguard Worker SmallVector<BasicBlock *, 16> PostOrder;
1456*9880d681SAndroid Build Coastguard Worker SmallVector<BasicBlock *, 16> ReverseCFGPostOrder;
1457*9880d681SAndroid Build Coastguard Worker ComputePostOrders(F, PostOrder, ReverseCFGPostOrder,
1458*9880d681SAndroid Build Coastguard Worker MDKindCache.get(ARCMDKindID::NoObjCARCExceptions),
1459*9880d681SAndroid Build Coastguard Worker BBStates);
1460*9880d681SAndroid Build Coastguard Worker
1461*9880d681SAndroid Build Coastguard Worker // Use reverse-postorder on the reverse CFG for bottom-up.
1462*9880d681SAndroid Build Coastguard Worker bool BottomUpNestingDetected = false;
1463*9880d681SAndroid Build Coastguard Worker for (BasicBlock *BB : reverse(ReverseCFGPostOrder))
1464*9880d681SAndroid Build Coastguard Worker BottomUpNestingDetected |= VisitBottomUp(BB, BBStates, Retains);
1465*9880d681SAndroid Build Coastguard Worker
1466*9880d681SAndroid Build Coastguard Worker // Use reverse-postorder for top-down.
1467*9880d681SAndroid Build Coastguard Worker bool TopDownNestingDetected = false;
1468*9880d681SAndroid Build Coastguard Worker for (BasicBlock *BB : reverse(PostOrder))
1469*9880d681SAndroid Build Coastguard Worker TopDownNestingDetected |= VisitTopDown(BB, BBStates, Releases);
1470*9880d681SAndroid Build Coastguard Worker
1471*9880d681SAndroid Build Coastguard Worker return TopDownNestingDetected && BottomUpNestingDetected;
1472*9880d681SAndroid Build Coastguard Worker }
1473*9880d681SAndroid Build Coastguard Worker
1474*9880d681SAndroid Build Coastguard Worker /// Move the calls in RetainsToMove and ReleasesToMove.
MoveCalls(Value * Arg,RRInfo & RetainsToMove,RRInfo & ReleasesToMove,BlotMapVector<Value *,RRInfo> & Retains,DenseMap<Value *,RRInfo> & Releases,SmallVectorImpl<Instruction * > & DeadInsts,Module * M)1475*9880d681SAndroid Build Coastguard Worker void ObjCARCOpt::MoveCalls(Value *Arg, RRInfo &RetainsToMove,
1476*9880d681SAndroid Build Coastguard Worker RRInfo &ReleasesToMove,
1477*9880d681SAndroid Build Coastguard Worker BlotMapVector<Value *, RRInfo> &Retains,
1478*9880d681SAndroid Build Coastguard Worker DenseMap<Value *, RRInfo> &Releases,
1479*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<Instruction *> &DeadInsts,
1480*9880d681SAndroid Build Coastguard Worker Module *M) {
1481*9880d681SAndroid Build Coastguard Worker Type *ArgTy = Arg->getType();
1482*9880d681SAndroid Build Coastguard Worker Type *ParamTy = PointerType::getUnqual(Type::getInt8Ty(ArgTy->getContext()));
1483*9880d681SAndroid Build Coastguard Worker
1484*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "== ObjCARCOpt::MoveCalls ==\n");
1485*9880d681SAndroid Build Coastguard Worker
1486*9880d681SAndroid Build Coastguard Worker // Insert the new retain and release calls.
1487*9880d681SAndroid Build Coastguard Worker for (Instruction *InsertPt : ReleasesToMove.ReverseInsertPts) {
1488*9880d681SAndroid Build Coastguard Worker Value *MyArg = ArgTy == ParamTy ? Arg :
1489*9880d681SAndroid Build Coastguard Worker new BitCastInst(Arg, ParamTy, "", InsertPt);
1490*9880d681SAndroid Build Coastguard Worker Constant *Decl = EP.get(ARCRuntimeEntryPointKind::Retain);
1491*9880d681SAndroid Build Coastguard Worker CallInst *Call = CallInst::Create(Decl, MyArg, "", InsertPt);
1492*9880d681SAndroid Build Coastguard Worker Call->setDoesNotThrow();
1493*9880d681SAndroid Build Coastguard Worker Call->setTailCall();
1494*9880d681SAndroid Build Coastguard Worker
1495*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Inserting new Retain: " << *Call << "\n"
1496*9880d681SAndroid Build Coastguard Worker "At insertion point: " << *InsertPt << "\n");
1497*9880d681SAndroid Build Coastguard Worker }
1498*9880d681SAndroid Build Coastguard Worker for (Instruction *InsertPt : RetainsToMove.ReverseInsertPts) {
1499*9880d681SAndroid Build Coastguard Worker Value *MyArg = ArgTy == ParamTy ? Arg :
1500*9880d681SAndroid Build Coastguard Worker new BitCastInst(Arg, ParamTy, "", InsertPt);
1501*9880d681SAndroid Build Coastguard Worker Constant *Decl = EP.get(ARCRuntimeEntryPointKind::Release);
1502*9880d681SAndroid Build Coastguard Worker CallInst *Call = CallInst::Create(Decl, MyArg, "", InsertPt);
1503*9880d681SAndroid Build Coastguard Worker // Attach a clang.imprecise_release metadata tag, if appropriate.
1504*9880d681SAndroid Build Coastguard Worker if (MDNode *M = ReleasesToMove.ReleaseMetadata)
1505*9880d681SAndroid Build Coastguard Worker Call->setMetadata(MDKindCache.get(ARCMDKindID::ImpreciseRelease), M);
1506*9880d681SAndroid Build Coastguard Worker Call->setDoesNotThrow();
1507*9880d681SAndroid Build Coastguard Worker if (ReleasesToMove.IsTailCallRelease)
1508*9880d681SAndroid Build Coastguard Worker Call->setTailCall();
1509*9880d681SAndroid Build Coastguard Worker
1510*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Inserting new Release: " << *Call << "\n"
1511*9880d681SAndroid Build Coastguard Worker "At insertion point: " << *InsertPt << "\n");
1512*9880d681SAndroid Build Coastguard Worker }
1513*9880d681SAndroid Build Coastguard Worker
1514*9880d681SAndroid Build Coastguard Worker // Delete the original retain and release calls.
1515*9880d681SAndroid Build Coastguard Worker for (Instruction *OrigRetain : RetainsToMove.Calls) {
1516*9880d681SAndroid Build Coastguard Worker Retains.blot(OrigRetain);
1517*9880d681SAndroid Build Coastguard Worker DeadInsts.push_back(OrigRetain);
1518*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Deleting retain: " << *OrigRetain << "\n");
1519*9880d681SAndroid Build Coastguard Worker }
1520*9880d681SAndroid Build Coastguard Worker for (Instruction *OrigRelease : ReleasesToMove.Calls) {
1521*9880d681SAndroid Build Coastguard Worker Releases.erase(OrigRelease);
1522*9880d681SAndroid Build Coastguard Worker DeadInsts.push_back(OrigRelease);
1523*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Deleting release: " << *OrigRelease << "\n");
1524*9880d681SAndroid Build Coastguard Worker }
1525*9880d681SAndroid Build Coastguard Worker
1526*9880d681SAndroid Build Coastguard Worker }
1527*9880d681SAndroid Build Coastguard Worker
PairUpRetainsAndReleases(DenseMap<const BasicBlock *,BBState> & BBStates,BlotMapVector<Value *,RRInfo> & Retains,DenseMap<Value *,RRInfo> & Releases,Module * M,SmallVectorImpl<Instruction * > & NewRetains,SmallVectorImpl<Instruction * > & NewReleases,SmallVectorImpl<Instruction * > & DeadInsts,RRInfo & RetainsToMove,RRInfo & ReleasesToMove,Value * Arg,bool KnownSafe,bool & AnyPairsCompletelyEliminated)1528*9880d681SAndroid Build Coastguard Worker bool ObjCARCOpt::PairUpRetainsAndReleases(
1529*9880d681SAndroid Build Coastguard Worker DenseMap<const BasicBlock *, BBState> &BBStates,
1530*9880d681SAndroid Build Coastguard Worker BlotMapVector<Value *, RRInfo> &Retains,
1531*9880d681SAndroid Build Coastguard Worker DenseMap<Value *, RRInfo> &Releases, Module *M,
1532*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<Instruction *> &NewRetains,
1533*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<Instruction *> &NewReleases,
1534*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<Instruction *> &DeadInsts, RRInfo &RetainsToMove,
1535*9880d681SAndroid Build Coastguard Worker RRInfo &ReleasesToMove, Value *Arg, bool KnownSafe,
1536*9880d681SAndroid Build Coastguard Worker bool &AnyPairsCompletelyEliminated) {
1537*9880d681SAndroid Build Coastguard Worker // If a pair happens in a region where it is known that the reference count
1538*9880d681SAndroid Build Coastguard Worker // is already incremented, we can similarly ignore possible decrements unless
1539*9880d681SAndroid Build Coastguard Worker // we are dealing with a retainable object with multiple provenance sources.
1540*9880d681SAndroid Build Coastguard Worker bool KnownSafeTD = true, KnownSafeBU = true;
1541*9880d681SAndroid Build Coastguard Worker bool MultipleOwners = false;
1542*9880d681SAndroid Build Coastguard Worker bool CFGHazardAfflicted = false;
1543*9880d681SAndroid Build Coastguard Worker
1544*9880d681SAndroid Build Coastguard Worker // Connect the dots between the top-down-collected RetainsToMove and
1545*9880d681SAndroid Build Coastguard Worker // bottom-up-collected ReleasesToMove to form sets of related calls.
1546*9880d681SAndroid Build Coastguard Worker // This is an iterative process so that we connect multiple releases
1547*9880d681SAndroid Build Coastguard Worker // to multiple retains if needed.
1548*9880d681SAndroid Build Coastguard Worker unsigned OldDelta = 0;
1549*9880d681SAndroid Build Coastguard Worker unsigned NewDelta = 0;
1550*9880d681SAndroid Build Coastguard Worker unsigned OldCount = 0;
1551*9880d681SAndroid Build Coastguard Worker unsigned NewCount = 0;
1552*9880d681SAndroid Build Coastguard Worker bool FirstRelease = true;
1553*9880d681SAndroid Build Coastguard Worker for (;;) {
1554*9880d681SAndroid Build Coastguard Worker for (Instruction *NewRetain : NewRetains) {
1555*9880d681SAndroid Build Coastguard Worker auto It = Retains.find(NewRetain);
1556*9880d681SAndroid Build Coastguard Worker assert(It != Retains.end());
1557*9880d681SAndroid Build Coastguard Worker const RRInfo &NewRetainRRI = It->second;
1558*9880d681SAndroid Build Coastguard Worker KnownSafeTD &= NewRetainRRI.KnownSafe;
1559*9880d681SAndroid Build Coastguard Worker MultipleOwners =
1560*9880d681SAndroid Build Coastguard Worker MultipleOwners || MultiOwnersSet.count(GetArgRCIdentityRoot(NewRetain));
1561*9880d681SAndroid Build Coastguard Worker for (Instruction *NewRetainRelease : NewRetainRRI.Calls) {
1562*9880d681SAndroid Build Coastguard Worker auto Jt = Releases.find(NewRetainRelease);
1563*9880d681SAndroid Build Coastguard Worker if (Jt == Releases.end())
1564*9880d681SAndroid Build Coastguard Worker return false;
1565*9880d681SAndroid Build Coastguard Worker const RRInfo &NewRetainReleaseRRI = Jt->second;
1566*9880d681SAndroid Build Coastguard Worker
1567*9880d681SAndroid Build Coastguard Worker // If the release does not have a reference to the retain as well,
1568*9880d681SAndroid Build Coastguard Worker // something happened which is unaccounted for. Do not do anything.
1569*9880d681SAndroid Build Coastguard Worker //
1570*9880d681SAndroid Build Coastguard Worker // This can happen if we catch an additive overflow during path count
1571*9880d681SAndroid Build Coastguard Worker // merging.
1572*9880d681SAndroid Build Coastguard Worker if (!NewRetainReleaseRRI.Calls.count(NewRetain))
1573*9880d681SAndroid Build Coastguard Worker return false;
1574*9880d681SAndroid Build Coastguard Worker
1575*9880d681SAndroid Build Coastguard Worker if (ReleasesToMove.Calls.insert(NewRetainRelease).second) {
1576*9880d681SAndroid Build Coastguard Worker
1577*9880d681SAndroid Build Coastguard Worker // If we overflow when we compute the path count, don't remove/move
1578*9880d681SAndroid Build Coastguard Worker // anything.
1579*9880d681SAndroid Build Coastguard Worker const BBState &NRRBBState = BBStates[NewRetainRelease->getParent()];
1580*9880d681SAndroid Build Coastguard Worker unsigned PathCount = BBState::OverflowOccurredValue;
1581*9880d681SAndroid Build Coastguard Worker if (NRRBBState.GetAllPathCountWithOverflow(PathCount))
1582*9880d681SAndroid Build Coastguard Worker return false;
1583*9880d681SAndroid Build Coastguard Worker assert(PathCount != BBState::OverflowOccurredValue &&
1584*9880d681SAndroid Build Coastguard Worker "PathCount at this point can not be "
1585*9880d681SAndroid Build Coastguard Worker "OverflowOccurredValue.");
1586*9880d681SAndroid Build Coastguard Worker OldDelta -= PathCount;
1587*9880d681SAndroid Build Coastguard Worker
1588*9880d681SAndroid Build Coastguard Worker // Merge the ReleaseMetadata and IsTailCallRelease values.
1589*9880d681SAndroid Build Coastguard Worker if (FirstRelease) {
1590*9880d681SAndroid Build Coastguard Worker ReleasesToMove.ReleaseMetadata =
1591*9880d681SAndroid Build Coastguard Worker NewRetainReleaseRRI.ReleaseMetadata;
1592*9880d681SAndroid Build Coastguard Worker ReleasesToMove.IsTailCallRelease =
1593*9880d681SAndroid Build Coastguard Worker NewRetainReleaseRRI.IsTailCallRelease;
1594*9880d681SAndroid Build Coastguard Worker FirstRelease = false;
1595*9880d681SAndroid Build Coastguard Worker } else {
1596*9880d681SAndroid Build Coastguard Worker if (ReleasesToMove.ReleaseMetadata !=
1597*9880d681SAndroid Build Coastguard Worker NewRetainReleaseRRI.ReleaseMetadata)
1598*9880d681SAndroid Build Coastguard Worker ReleasesToMove.ReleaseMetadata = nullptr;
1599*9880d681SAndroid Build Coastguard Worker if (ReleasesToMove.IsTailCallRelease !=
1600*9880d681SAndroid Build Coastguard Worker NewRetainReleaseRRI.IsTailCallRelease)
1601*9880d681SAndroid Build Coastguard Worker ReleasesToMove.IsTailCallRelease = false;
1602*9880d681SAndroid Build Coastguard Worker }
1603*9880d681SAndroid Build Coastguard Worker
1604*9880d681SAndroid Build Coastguard Worker // Collect the optimal insertion points.
1605*9880d681SAndroid Build Coastguard Worker if (!KnownSafe)
1606*9880d681SAndroid Build Coastguard Worker for (Instruction *RIP : NewRetainReleaseRRI.ReverseInsertPts) {
1607*9880d681SAndroid Build Coastguard Worker if (ReleasesToMove.ReverseInsertPts.insert(RIP).second) {
1608*9880d681SAndroid Build Coastguard Worker // If we overflow when we compute the path count, don't
1609*9880d681SAndroid Build Coastguard Worker // remove/move anything.
1610*9880d681SAndroid Build Coastguard Worker const BBState &RIPBBState = BBStates[RIP->getParent()];
1611*9880d681SAndroid Build Coastguard Worker PathCount = BBState::OverflowOccurredValue;
1612*9880d681SAndroid Build Coastguard Worker if (RIPBBState.GetAllPathCountWithOverflow(PathCount))
1613*9880d681SAndroid Build Coastguard Worker return false;
1614*9880d681SAndroid Build Coastguard Worker assert(PathCount != BBState::OverflowOccurredValue &&
1615*9880d681SAndroid Build Coastguard Worker "PathCount at this point can not be "
1616*9880d681SAndroid Build Coastguard Worker "OverflowOccurredValue.");
1617*9880d681SAndroid Build Coastguard Worker NewDelta -= PathCount;
1618*9880d681SAndroid Build Coastguard Worker }
1619*9880d681SAndroid Build Coastguard Worker }
1620*9880d681SAndroid Build Coastguard Worker NewReleases.push_back(NewRetainRelease);
1621*9880d681SAndroid Build Coastguard Worker }
1622*9880d681SAndroid Build Coastguard Worker }
1623*9880d681SAndroid Build Coastguard Worker }
1624*9880d681SAndroid Build Coastguard Worker NewRetains.clear();
1625*9880d681SAndroid Build Coastguard Worker if (NewReleases.empty()) break;
1626*9880d681SAndroid Build Coastguard Worker
1627*9880d681SAndroid Build Coastguard Worker // Back the other way.
1628*9880d681SAndroid Build Coastguard Worker for (Instruction *NewRelease : NewReleases) {
1629*9880d681SAndroid Build Coastguard Worker auto It = Releases.find(NewRelease);
1630*9880d681SAndroid Build Coastguard Worker assert(It != Releases.end());
1631*9880d681SAndroid Build Coastguard Worker const RRInfo &NewReleaseRRI = It->second;
1632*9880d681SAndroid Build Coastguard Worker KnownSafeBU &= NewReleaseRRI.KnownSafe;
1633*9880d681SAndroid Build Coastguard Worker CFGHazardAfflicted |= NewReleaseRRI.CFGHazardAfflicted;
1634*9880d681SAndroid Build Coastguard Worker for (Instruction *NewReleaseRetain : NewReleaseRRI.Calls) {
1635*9880d681SAndroid Build Coastguard Worker auto Jt = Retains.find(NewReleaseRetain);
1636*9880d681SAndroid Build Coastguard Worker if (Jt == Retains.end())
1637*9880d681SAndroid Build Coastguard Worker return false;
1638*9880d681SAndroid Build Coastguard Worker const RRInfo &NewReleaseRetainRRI = Jt->second;
1639*9880d681SAndroid Build Coastguard Worker
1640*9880d681SAndroid Build Coastguard Worker // If the retain does not have a reference to the release as well,
1641*9880d681SAndroid Build Coastguard Worker // something happened which is unaccounted for. Do not do anything.
1642*9880d681SAndroid Build Coastguard Worker //
1643*9880d681SAndroid Build Coastguard Worker // This can happen if we catch an additive overflow during path count
1644*9880d681SAndroid Build Coastguard Worker // merging.
1645*9880d681SAndroid Build Coastguard Worker if (!NewReleaseRetainRRI.Calls.count(NewRelease))
1646*9880d681SAndroid Build Coastguard Worker return false;
1647*9880d681SAndroid Build Coastguard Worker
1648*9880d681SAndroid Build Coastguard Worker if (RetainsToMove.Calls.insert(NewReleaseRetain).second) {
1649*9880d681SAndroid Build Coastguard Worker // If we overflow when we compute the path count, don't remove/move
1650*9880d681SAndroid Build Coastguard Worker // anything.
1651*9880d681SAndroid Build Coastguard Worker const BBState &NRRBBState = BBStates[NewReleaseRetain->getParent()];
1652*9880d681SAndroid Build Coastguard Worker unsigned PathCount = BBState::OverflowOccurredValue;
1653*9880d681SAndroid Build Coastguard Worker if (NRRBBState.GetAllPathCountWithOverflow(PathCount))
1654*9880d681SAndroid Build Coastguard Worker return false;
1655*9880d681SAndroid Build Coastguard Worker assert(PathCount != BBState::OverflowOccurredValue &&
1656*9880d681SAndroid Build Coastguard Worker "PathCount at this point can not be "
1657*9880d681SAndroid Build Coastguard Worker "OverflowOccurredValue.");
1658*9880d681SAndroid Build Coastguard Worker OldDelta += PathCount;
1659*9880d681SAndroid Build Coastguard Worker OldCount += PathCount;
1660*9880d681SAndroid Build Coastguard Worker
1661*9880d681SAndroid Build Coastguard Worker // Collect the optimal insertion points.
1662*9880d681SAndroid Build Coastguard Worker if (!KnownSafe)
1663*9880d681SAndroid Build Coastguard Worker for (Instruction *RIP : NewReleaseRetainRRI.ReverseInsertPts) {
1664*9880d681SAndroid Build Coastguard Worker if (RetainsToMove.ReverseInsertPts.insert(RIP).second) {
1665*9880d681SAndroid Build Coastguard Worker // If we overflow when we compute the path count, don't
1666*9880d681SAndroid Build Coastguard Worker // remove/move anything.
1667*9880d681SAndroid Build Coastguard Worker const BBState &RIPBBState = BBStates[RIP->getParent()];
1668*9880d681SAndroid Build Coastguard Worker
1669*9880d681SAndroid Build Coastguard Worker PathCount = BBState::OverflowOccurredValue;
1670*9880d681SAndroid Build Coastguard Worker if (RIPBBState.GetAllPathCountWithOverflow(PathCount))
1671*9880d681SAndroid Build Coastguard Worker return false;
1672*9880d681SAndroid Build Coastguard Worker assert(PathCount != BBState::OverflowOccurredValue &&
1673*9880d681SAndroid Build Coastguard Worker "PathCount at this point can not be "
1674*9880d681SAndroid Build Coastguard Worker "OverflowOccurredValue.");
1675*9880d681SAndroid Build Coastguard Worker NewDelta += PathCount;
1676*9880d681SAndroid Build Coastguard Worker NewCount += PathCount;
1677*9880d681SAndroid Build Coastguard Worker }
1678*9880d681SAndroid Build Coastguard Worker }
1679*9880d681SAndroid Build Coastguard Worker NewRetains.push_back(NewReleaseRetain);
1680*9880d681SAndroid Build Coastguard Worker }
1681*9880d681SAndroid Build Coastguard Worker }
1682*9880d681SAndroid Build Coastguard Worker }
1683*9880d681SAndroid Build Coastguard Worker NewReleases.clear();
1684*9880d681SAndroid Build Coastguard Worker if (NewRetains.empty()) break;
1685*9880d681SAndroid Build Coastguard Worker }
1686*9880d681SAndroid Build Coastguard Worker
1687*9880d681SAndroid Build Coastguard Worker // We can only remove pointers if we are known safe in both directions.
1688*9880d681SAndroid Build Coastguard Worker bool UnconditionallySafe = KnownSafeTD && KnownSafeBU;
1689*9880d681SAndroid Build Coastguard Worker if (UnconditionallySafe) {
1690*9880d681SAndroid Build Coastguard Worker RetainsToMove.ReverseInsertPts.clear();
1691*9880d681SAndroid Build Coastguard Worker ReleasesToMove.ReverseInsertPts.clear();
1692*9880d681SAndroid Build Coastguard Worker NewCount = 0;
1693*9880d681SAndroid Build Coastguard Worker } else {
1694*9880d681SAndroid Build Coastguard Worker // Determine whether the new insertion points we computed preserve the
1695*9880d681SAndroid Build Coastguard Worker // balance of retain and release calls through the program.
1696*9880d681SAndroid Build Coastguard Worker // TODO: If the fully aggressive solution isn't valid, try to find a
1697*9880d681SAndroid Build Coastguard Worker // less aggressive solution which is.
1698*9880d681SAndroid Build Coastguard Worker if (NewDelta != 0)
1699*9880d681SAndroid Build Coastguard Worker return false;
1700*9880d681SAndroid Build Coastguard Worker
1701*9880d681SAndroid Build Coastguard Worker // At this point, we are not going to remove any RR pairs, but we still are
1702*9880d681SAndroid Build Coastguard Worker // able to move RR pairs. If one of our pointers is afflicted with
1703*9880d681SAndroid Build Coastguard Worker // CFGHazards, we cannot perform such code motion so exit early.
1704*9880d681SAndroid Build Coastguard Worker const bool WillPerformCodeMotion = RetainsToMove.ReverseInsertPts.size() ||
1705*9880d681SAndroid Build Coastguard Worker ReleasesToMove.ReverseInsertPts.size();
1706*9880d681SAndroid Build Coastguard Worker if (CFGHazardAfflicted && WillPerformCodeMotion)
1707*9880d681SAndroid Build Coastguard Worker return false;
1708*9880d681SAndroid Build Coastguard Worker }
1709*9880d681SAndroid Build Coastguard Worker
1710*9880d681SAndroid Build Coastguard Worker // Determine whether the original call points are balanced in the retain and
1711*9880d681SAndroid Build Coastguard Worker // release calls through the program. If not, conservatively don't touch
1712*9880d681SAndroid Build Coastguard Worker // them.
1713*9880d681SAndroid Build Coastguard Worker // TODO: It's theoretically possible to do code motion in this case, as
1714*9880d681SAndroid Build Coastguard Worker // long as the existing imbalances are maintained.
1715*9880d681SAndroid Build Coastguard Worker if (OldDelta != 0)
1716*9880d681SAndroid Build Coastguard Worker return false;
1717*9880d681SAndroid Build Coastguard Worker
1718*9880d681SAndroid Build Coastguard Worker Changed = true;
1719*9880d681SAndroid Build Coastguard Worker assert(OldCount != 0 && "Unreachable code?");
1720*9880d681SAndroid Build Coastguard Worker NumRRs += OldCount - NewCount;
1721*9880d681SAndroid Build Coastguard Worker // Set to true if we completely removed any RR pairs.
1722*9880d681SAndroid Build Coastguard Worker AnyPairsCompletelyEliminated = NewCount == 0;
1723*9880d681SAndroid Build Coastguard Worker
1724*9880d681SAndroid Build Coastguard Worker // We can move calls!
1725*9880d681SAndroid Build Coastguard Worker return true;
1726*9880d681SAndroid Build Coastguard Worker }
1727*9880d681SAndroid Build Coastguard Worker
1728*9880d681SAndroid Build Coastguard Worker /// Identify pairings between the retains and releases, and delete and/or move
1729*9880d681SAndroid Build Coastguard Worker /// them.
PerformCodePlacement(DenseMap<const BasicBlock *,BBState> & BBStates,BlotMapVector<Value *,RRInfo> & Retains,DenseMap<Value *,RRInfo> & Releases,Module * M)1730*9880d681SAndroid Build Coastguard Worker bool ObjCARCOpt::PerformCodePlacement(
1731*9880d681SAndroid Build Coastguard Worker DenseMap<const BasicBlock *, BBState> &BBStates,
1732*9880d681SAndroid Build Coastguard Worker BlotMapVector<Value *, RRInfo> &Retains,
1733*9880d681SAndroid Build Coastguard Worker DenseMap<Value *, RRInfo> &Releases, Module *M) {
1734*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "\n== ObjCARCOpt::PerformCodePlacement ==\n");
1735*9880d681SAndroid Build Coastguard Worker
1736*9880d681SAndroid Build Coastguard Worker bool AnyPairsCompletelyEliminated = false;
1737*9880d681SAndroid Build Coastguard Worker RRInfo RetainsToMove;
1738*9880d681SAndroid Build Coastguard Worker RRInfo ReleasesToMove;
1739*9880d681SAndroid Build Coastguard Worker SmallVector<Instruction *, 4> NewRetains;
1740*9880d681SAndroid Build Coastguard Worker SmallVector<Instruction *, 4> NewReleases;
1741*9880d681SAndroid Build Coastguard Worker SmallVector<Instruction *, 8> DeadInsts;
1742*9880d681SAndroid Build Coastguard Worker
1743*9880d681SAndroid Build Coastguard Worker // Visit each retain.
1744*9880d681SAndroid Build Coastguard Worker for (BlotMapVector<Value *, RRInfo>::const_iterator I = Retains.begin(),
1745*9880d681SAndroid Build Coastguard Worker E = Retains.end();
1746*9880d681SAndroid Build Coastguard Worker I != E; ++I) {
1747*9880d681SAndroid Build Coastguard Worker Value *V = I->first;
1748*9880d681SAndroid Build Coastguard Worker if (!V) continue; // blotted
1749*9880d681SAndroid Build Coastguard Worker
1750*9880d681SAndroid Build Coastguard Worker Instruction *Retain = cast<Instruction>(V);
1751*9880d681SAndroid Build Coastguard Worker
1752*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Visiting: " << *Retain << "\n");
1753*9880d681SAndroid Build Coastguard Worker
1754*9880d681SAndroid Build Coastguard Worker Value *Arg = GetArgRCIdentityRoot(Retain);
1755*9880d681SAndroid Build Coastguard Worker
1756*9880d681SAndroid Build Coastguard Worker // If the object being released is in static or stack storage, we know it's
1757*9880d681SAndroid Build Coastguard Worker // not being managed by ObjC reference counting, so we can delete pairs
1758*9880d681SAndroid Build Coastguard Worker // regardless of what possible decrements or uses lie between them.
1759*9880d681SAndroid Build Coastguard Worker bool KnownSafe = isa<Constant>(Arg) || isa<AllocaInst>(Arg);
1760*9880d681SAndroid Build Coastguard Worker
1761*9880d681SAndroid Build Coastguard Worker // A constant pointer can't be pointing to an object on the heap. It may
1762*9880d681SAndroid Build Coastguard Worker // be reference-counted, but it won't be deleted.
1763*9880d681SAndroid Build Coastguard Worker if (const LoadInst *LI = dyn_cast<LoadInst>(Arg))
1764*9880d681SAndroid Build Coastguard Worker if (const GlobalVariable *GV =
1765*9880d681SAndroid Build Coastguard Worker dyn_cast<GlobalVariable>(
1766*9880d681SAndroid Build Coastguard Worker GetRCIdentityRoot(LI->getPointerOperand())))
1767*9880d681SAndroid Build Coastguard Worker if (GV->isConstant())
1768*9880d681SAndroid Build Coastguard Worker KnownSafe = true;
1769*9880d681SAndroid Build Coastguard Worker
1770*9880d681SAndroid Build Coastguard Worker // Connect the dots between the top-down-collected RetainsToMove and
1771*9880d681SAndroid Build Coastguard Worker // bottom-up-collected ReleasesToMove to form sets of related calls.
1772*9880d681SAndroid Build Coastguard Worker NewRetains.push_back(Retain);
1773*9880d681SAndroid Build Coastguard Worker bool PerformMoveCalls = PairUpRetainsAndReleases(
1774*9880d681SAndroid Build Coastguard Worker BBStates, Retains, Releases, M, NewRetains, NewReleases, DeadInsts,
1775*9880d681SAndroid Build Coastguard Worker RetainsToMove, ReleasesToMove, Arg, KnownSafe,
1776*9880d681SAndroid Build Coastguard Worker AnyPairsCompletelyEliminated);
1777*9880d681SAndroid Build Coastguard Worker
1778*9880d681SAndroid Build Coastguard Worker if (PerformMoveCalls) {
1779*9880d681SAndroid Build Coastguard Worker // Ok, everything checks out and we're all set. Let's move/delete some
1780*9880d681SAndroid Build Coastguard Worker // code!
1781*9880d681SAndroid Build Coastguard Worker MoveCalls(Arg, RetainsToMove, ReleasesToMove,
1782*9880d681SAndroid Build Coastguard Worker Retains, Releases, DeadInsts, M);
1783*9880d681SAndroid Build Coastguard Worker }
1784*9880d681SAndroid Build Coastguard Worker
1785*9880d681SAndroid Build Coastguard Worker // Clean up state for next retain.
1786*9880d681SAndroid Build Coastguard Worker NewReleases.clear();
1787*9880d681SAndroid Build Coastguard Worker NewRetains.clear();
1788*9880d681SAndroid Build Coastguard Worker RetainsToMove.clear();
1789*9880d681SAndroid Build Coastguard Worker ReleasesToMove.clear();
1790*9880d681SAndroid Build Coastguard Worker }
1791*9880d681SAndroid Build Coastguard Worker
1792*9880d681SAndroid Build Coastguard Worker // Now that we're done moving everything, we can delete the newly dead
1793*9880d681SAndroid Build Coastguard Worker // instructions, as we no longer need them as insert points.
1794*9880d681SAndroid Build Coastguard Worker while (!DeadInsts.empty())
1795*9880d681SAndroid Build Coastguard Worker EraseInstruction(DeadInsts.pop_back_val());
1796*9880d681SAndroid Build Coastguard Worker
1797*9880d681SAndroid Build Coastguard Worker return AnyPairsCompletelyEliminated;
1798*9880d681SAndroid Build Coastguard Worker }
1799*9880d681SAndroid Build Coastguard Worker
1800*9880d681SAndroid Build Coastguard Worker /// Weak pointer optimizations.
OptimizeWeakCalls(Function & F)1801*9880d681SAndroid Build Coastguard Worker void ObjCARCOpt::OptimizeWeakCalls(Function &F) {
1802*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "\n== ObjCARCOpt::OptimizeWeakCalls ==\n");
1803*9880d681SAndroid Build Coastguard Worker
1804*9880d681SAndroid Build Coastguard Worker // First, do memdep-style RLE and S2L optimizations. We can't use memdep
1805*9880d681SAndroid Build Coastguard Worker // itself because it uses AliasAnalysis and we need to do provenance
1806*9880d681SAndroid Build Coastguard Worker // queries instead.
1807*9880d681SAndroid Build Coastguard Worker for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E; ) {
1808*9880d681SAndroid Build Coastguard Worker Instruction *Inst = &*I++;
1809*9880d681SAndroid Build Coastguard Worker
1810*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Visiting: " << *Inst << "\n");
1811*9880d681SAndroid Build Coastguard Worker
1812*9880d681SAndroid Build Coastguard Worker ARCInstKind Class = GetBasicARCInstKind(Inst);
1813*9880d681SAndroid Build Coastguard Worker if (Class != ARCInstKind::LoadWeak &&
1814*9880d681SAndroid Build Coastguard Worker Class != ARCInstKind::LoadWeakRetained)
1815*9880d681SAndroid Build Coastguard Worker continue;
1816*9880d681SAndroid Build Coastguard Worker
1817*9880d681SAndroid Build Coastguard Worker // Delete objc_loadWeak calls with no users.
1818*9880d681SAndroid Build Coastguard Worker if (Class == ARCInstKind::LoadWeak && Inst->use_empty()) {
1819*9880d681SAndroid Build Coastguard Worker Inst->eraseFromParent();
1820*9880d681SAndroid Build Coastguard Worker continue;
1821*9880d681SAndroid Build Coastguard Worker }
1822*9880d681SAndroid Build Coastguard Worker
1823*9880d681SAndroid Build Coastguard Worker // TODO: For now, just look for an earlier available version of this value
1824*9880d681SAndroid Build Coastguard Worker // within the same block. Theoretically, we could do memdep-style non-local
1825*9880d681SAndroid Build Coastguard Worker // analysis too, but that would want caching. A better approach would be to
1826*9880d681SAndroid Build Coastguard Worker // use the technique that EarlyCSE uses.
1827*9880d681SAndroid Build Coastguard Worker inst_iterator Current = std::prev(I);
1828*9880d681SAndroid Build Coastguard Worker BasicBlock *CurrentBB = &*Current.getBasicBlockIterator();
1829*9880d681SAndroid Build Coastguard Worker for (BasicBlock::iterator B = CurrentBB->begin(),
1830*9880d681SAndroid Build Coastguard Worker J = Current.getInstructionIterator();
1831*9880d681SAndroid Build Coastguard Worker J != B; --J) {
1832*9880d681SAndroid Build Coastguard Worker Instruction *EarlierInst = &*std::prev(J);
1833*9880d681SAndroid Build Coastguard Worker ARCInstKind EarlierClass = GetARCInstKind(EarlierInst);
1834*9880d681SAndroid Build Coastguard Worker switch (EarlierClass) {
1835*9880d681SAndroid Build Coastguard Worker case ARCInstKind::LoadWeak:
1836*9880d681SAndroid Build Coastguard Worker case ARCInstKind::LoadWeakRetained: {
1837*9880d681SAndroid Build Coastguard Worker // If this is loading from the same pointer, replace this load's value
1838*9880d681SAndroid Build Coastguard Worker // with that one.
1839*9880d681SAndroid Build Coastguard Worker CallInst *Call = cast<CallInst>(Inst);
1840*9880d681SAndroid Build Coastguard Worker CallInst *EarlierCall = cast<CallInst>(EarlierInst);
1841*9880d681SAndroid Build Coastguard Worker Value *Arg = Call->getArgOperand(0);
1842*9880d681SAndroid Build Coastguard Worker Value *EarlierArg = EarlierCall->getArgOperand(0);
1843*9880d681SAndroid Build Coastguard Worker switch (PA.getAA()->alias(Arg, EarlierArg)) {
1844*9880d681SAndroid Build Coastguard Worker case MustAlias:
1845*9880d681SAndroid Build Coastguard Worker Changed = true;
1846*9880d681SAndroid Build Coastguard Worker // If the load has a builtin retain, insert a plain retain for it.
1847*9880d681SAndroid Build Coastguard Worker if (Class == ARCInstKind::LoadWeakRetained) {
1848*9880d681SAndroid Build Coastguard Worker Constant *Decl = EP.get(ARCRuntimeEntryPointKind::Retain);
1849*9880d681SAndroid Build Coastguard Worker CallInst *CI = CallInst::Create(Decl, EarlierCall, "", Call);
1850*9880d681SAndroid Build Coastguard Worker CI->setTailCall();
1851*9880d681SAndroid Build Coastguard Worker }
1852*9880d681SAndroid Build Coastguard Worker // Zap the fully redundant load.
1853*9880d681SAndroid Build Coastguard Worker Call->replaceAllUsesWith(EarlierCall);
1854*9880d681SAndroid Build Coastguard Worker Call->eraseFromParent();
1855*9880d681SAndroid Build Coastguard Worker goto clobbered;
1856*9880d681SAndroid Build Coastguard Worker case MayAlias:
1857*9880d681SAndroid Build Coastguard Worker case PartialAlias:
1858*9880d681SAndroid Build Coastguard Worker goto clobbered;
1859*9880d681SAndroid Build Coastguard Worker case NoAlias:
1860*9880d681SAndroid Build Coastguard Worker break;
1861*9880d681SAndroid Build Coastguard Worker }
1862*9880d681SAndroid Build Coastguard Worker break;
1863*9880d681SAndroid Build Coastguard Worker }
1864*9880d681SAndroid Build Coastguard Worker case ARCInstKind::StoreWeak:
1865*9880d681SAndroid Build Coastguard Worker case ARCInstKind::InitWeak: {
1866*9880d681SAndroid Build Coastguard Worker // If this is storing to the same pointer and has the same size etc.
1867*9880d681SAndroid Build Coastguard Worker // replace this load's value with the stored value.
1868*9880d681SAndroid Build Coastguard Worker CallInst *Call = cast<CallInst>(Inst);
1869*9880d681SAndroid Build Coastguard Worker CallInst *EarlierCall = cast<CallInst>(EarlierInst);
1870*9880d681SAndroid Build Coastguard Worker Value *Arg = Call->getArgOperand(0);
1871*9880d681SAndroid Build Coastguard Worker Value *EarlierArg = EarlierCall->getArgOperand(0);
1872*9880d681SAndroid Build Coastguard Worker switch (PA.getAA()->alias(Arg, EarlierArg)) {
1873*9880d681SAndroid Build Coastguard Worker case MustAlias:
1874*9880d681SAndroid Build Coastguard Worker Changed = true;
1875*9880d681SAndroid Build Coastguard Worker // If the load has a builtin retain, insert a plain retain for it.
1876*9880d681SAndroid Build Coastguard Worker if (Class == ARCInstKind::LoadWeakRetained) {
1877*9880d681SAndroid Build Coastguard Worker Constant *Decl = EP.get(ARCRuntimeEntryPointKind::Retain);
1878*9880d681SAndroid Build Coastguard Worker CallInst *CI = CallInst::Create(Decl, EarlierCall, "", Call);
1879*9880d681SAndroid Build Coastguard Worker CI->setTailCall();
1880*9880d681SAndroid Build Coastguard Worker }
1881*9880d681SAndroid Build Coastguard Worker // Zap the fully redundant load.
1882*9880d681SAndroid Build Coastguard Worker Call->replaceAllUsesWith(EarlierCall->getArgOperand(1));
1883*9880d681SAndroid Build Coastguard Worker Call->eraseFromParent();
1884*9880d681SAndroid Build Coastguard Worker goto clobbered;
1885*9880d681SAndroid Build Coastguard Worker case MayAlias:
1886*9880d681SAndroid Build Coastguard Worker case PartialAlias:
1887*9880d681SAndroid Build Coastguard Worker goto clobbered;
1888*9880d681SAndroid Build Coastguard Worker case NoAlias:
1889*9880d681SAndroid Build Coastguard Worker break;
1890*9880d681SAndroid Build Coastguard Worker }
1891*9880d681SAndroid Build Coastguard Worker break;
1892*9880d681SAndroid Build Coastguard Worker }
1893*9880d681SAndroid Build Coastguard Worker case ARCInstKind::MoveWeak:
1894*9880d681SAndroid Build Coastguard Worker case ARCInstKind::CopyWeak:
1895*9880d681SAndroid Build Coastguard Worker // TOOD: Grab the copied value.
1896*9880d681SAndroid Build Coastguard Worker goto clobbered;
1897*9880d681SAndroid Build Coastguard Worker case ARCInstKind::AutoreleasepoolPush:
1898*9880d681SAndroid Build Coastguard Worker case ARCInstKind::None:
1899*9880d681SAndroid Build Coastguard Worker case ARCInstKind::IntrinsicUser:
1900*9880d681SAndroid Build Coastguard Worker case ARCInstKind::User:
1901*9880d681SAndroid Build Coastguard Worker // Weak pointers are only modified through the weak entry points
1902*9880d681SAndroid Build Coastguard Worker // (and arbitrary calls, which could call the weak entry points).
1903*9880d681SAndroid Build Coastguard Worker break;
1904*9880d681SAndroid Build Coastguard Worker default:
1905*9880d681SAndroid Build Coastguard Worker // Anything else could modify the weak pointer.
1906*9880d681SAndroid Build Coastguard Worker goto clobbered;
1907*9880d681SAndroid Build Coastguard Worker }
1908*9880d681SAndroid Build Coastguard Worker }
1909*9880d681SAndroid Build Coastguard Worker clobbered:;
1910*9880d681SAndroid Build Coastguard Worker }
1911*9880d681SAndroid Build Coastguard Worker
1912*9880d681SAndroid Build Coastguard Worker // Then, for each destroyWeak with an alloca operand, check to see if
1913*9880d681SAndroid Build Coastguard Worker // the alloca and all its users can be zapped.
1914*9880d681SAndroid Build Coastguard Worker for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E; ) {
1915*9880d681SAndroid Build Coastguard Worker Instruction *Inst = &*I++;
1916*9880d681SAndroid Build Coastguard Worker ARCInstKind Class = GetBasicARCInstKind(Inst);
1917*9880d681SAndroid Build Coastguard Worker if (Class != ARCInstKind::DestroyWeak)
1918*9880d681SAndroid Build Coastguard Worker continue;
1919*9880d681SAndroid Build Coastguard Worker
1920*9880d681SAndroid Build Coastguard Worker CallInst *Call = cast<CallInst>(Inst);
1921*9880d681SAndroid Build Coastguard Worker Value *Arg = Call->getArgOperand(0);
1922*9880d681SAndroid Build Coastguard Worker if (AllocaInst *Alloca = dyn_cast<AllocaInst>(Arg)) {
1923*9880d681SAndroid Build Coastguard Worker for (User *U : Alloca->users()) {
1924*9880d681SAndroid Build Coastguard Worker const Instruction *UserInst = cast<Instruction>(U);
1925*9880d681SAndroid Build Coastguard Worker switch (GetBasicARCInstKind(UserInst)) {
1926*9880d681SAndroid Build Coastguard Worker case ARCInstKind::InitWeak:
1927*9880d681SAndroid Build Coastguard Worker case ARCInstKind::StoreWeak:
1928*9880d681SAndroid Build Coastguard Worker case ARCInstKind::DestroyWeak:
1929*9880d681SAndroid Build Coastguard Worker continue;
1930*9880d681SAndroid Build Coastguard Worker default:
1931*9880d681SAndroid Build Coastguard Worker goto done;
1932*9880d681SAndroid Build Coastguard Worker }
1933*9880d681SAndroid Build Coastguard Worker }
1934*9880d681SAndroid Build Coastguard Worker Changed = true;
1935*9880d681SAndroid Build Coastguard Worker for (auto UI = Alloca->user_begin(), UE = Alloca->user_end(); UI != UE;) {
1936*9880d681SAndroid Build Coastguard Worker CallInst *UserInst = cast<CallInst>(*UI++);
1937*9880d681SAndroid Build Coastguard Worker switch (GetBasicARCInstKind(UserInst)) {
1938*9880d681SAndroid Build Coastguard Worker case ARCInstKind::InitWeak:
1939*9880d681SAndroid Build Coastguard Worker case ARCInstKind::StoreWeak:
1940*9880d681SAndroid Build Coastguard Worker // These functions return their second argument.
1941*9880d681SAndroid Build Coastguard Worker UserInst->replaceAllUsesWith(UserInst->getArgOperand(1));
1942*9880d681SAndroid Build Coastguard Worker break;
1943*9880d681SAndroid Build Coastguard Worker case ARCInstKind::DestroyWeak:
1944*9880d681SAndroid Build Coastguard Worker // No return value.
1945*9880d681SAndroid Build Coastguard Worker break;
1946*9880d681SAndroid Build Coastguard Worker default:
1947*9880d681SAndroid Build Coastguard Worker llvm_unreachable("alloca really is used!");
1948*9880d681SAndroid Build Coastguard Worker }
1949*9880d681SAndroid Build Coastguard Worker UserInst->eraseFromParent();
1950*9880d681SAndroid Build Coastguard Worker }
1951*9880d681SAndroid Build Coastguard Worker Alloca->eraseFromParent();
1952*9880d681SAndroid Build Coastguard Worker done:;
1953*9880d681SAndroid Build Coastguard Worker }
1954*9880d681SAndroid Build Coastguard Worker }
1955*9880d681SAndroid Build Coastguard Worker }
1956*9880d681SAndroid Build Coastguard Worker
1957*9880d681SAndroid Build Coastguard Worker /// Identify program paths which execute sequences of retains and releases which
1958*9880d681SAndroid Build Coastguard Worker /// can be eliminated.
OptimizeSequences(Function & F)1959*9880d681SAndroid Build Coastguard Worker bool ObjCARCOpt::OptimizeSequences(Function &F) {
1960*9880d681SAndroid Build Coastguard Worker // Releases, Retains - These are used to store the results of the main flow
1961*9880d681SAndroid Build Coastguard Worker // analysis. These use Value* as the key instead of Instruction* so that the
1962*9880d681SAndroid Build Coastguard Worker // map stays valid when we get around to rewriting code and calls get
1963*9880d681SAndroid Build Coastguard Worker // replaced by arguments.
1964*9880d681SAndroid Build Coastguard Worker DenseMap<Value *, RRInfo> Releases;
1965*9880d681SAndroid Build Coastguard Worker BlotMapVector<Value *, RRInfo> Retains;
1966*9880d681SAndroid Build Coastguard Worker
1967*9880d681SAndroid Build Coastguard Worker // This is used during the traversal of the function to track the
1968*9880d681SAndroid Build Coastguard Worker // states for each identified object at each block.
1969*9880d681SAndroid Build Coastguard Worker DenseMap<const BasicBlock *, BBState> BBStates;
1970*9880d681SAndroid Build Coastguard Worker
1971*9880d681SAndroid Build Coastguard Worker // Analyze the CFG of the function, and all instructions.
1972*9880d681SAndroid Build Coastguard Worker bool NestingDetected = Visit(F, BBStates, Retains, Releases);
1973*9880d681SAndroid Build Coastguard Worker
1974*9880d681SAndroid Build Coastguard Worker // Transform.
1975*9880d681SAndroid Build Coastguard Worker bool AnyPairsCompletelyEliminated = PerformCodePlacement(BBStates, Retains,
1976*9880d681SAndroid Build Coastguard Worker Releases,
1977*9880d681SAndroid Build Coastguard Worker F.getParent());
1978*9880d681SAndroid Build Coastguard Worker
1979*9880d681SAndroid Build Coastguard Worker // Cleanup.
1980*9880d681SAndroid Build Coastguard Worker MultiOwnersSet.clear();
1981*9880d681SAndroid Build Coastguard Worker
1982*9880d681SAndroid Build Coastguard Worker return AnyPairsCompletelyEliminated && NestingDetected;
1983*9880d681SAndroid Build Coastguard Worker }
1984*9880d681SAndroid Build Coastguard Worker
1985*9880d681SAndroid Build Coastguard Worker /// Check if there is a dependent call earlier that does not have anything in
1986*9880d681SAndroid Build Coastguard Worker /// between the Retain and the call that can affect the reference count of their
1987*9880d681SAndroid Build Coastguard Worker /// shared pointer argument. Note that Retain need not be in BB.
1988*9880d681SAndroid Build Coastguard Worker static bool
HasSafePathToPredecessorCall(const Value * Arg,Instruction * Retain,SmallPtrSetImpl<Instruction * > & DepInsts,SmallPtrSetImpl<const BasicBlock * > & Visited,ProvenanceAnalysis & PA)1989*9880d681SAndroid Build Coastguard Worker HasSafePathToPredecessorCall(const Value *Arg, Instruction *Retain,
1990*9880d681SAndroid Build Coastguard Worker SmallPtrSetImpl<Instruction *> &DepInsts,
1991*9880d681SAndroid Build Coastguard Worker SmallPtrSetImpl<const BasicBlock *> &Visited,
1992*9880d681SAndroid Build Coastguard Worker ProvenanceAnalysis &PA) {
1993*9880d681SAndroid Build Coastguard Worker FindDependencies(CanChangeRetainCount, Arg, Retain->getParent(), Retain,
1994*9880d681SAndroid Build Coastguard Worker DepInsts, Visited, PA);
1995*9880d681SAndroid Build Coastguard Worker if (DepInsts.size() != 1)
1996*9880d681SAndroid Build Coastguard Worker return false;
1997*9880d681SAndroid Build Coastguard Worker
1998*9880d681SAndroid Build Coastguard Worker auto *Call = dyn_cast_or_null<CallInst>(*DepInsts.begin());
1999*9880d681SAndroid Build Coastguard Worker
2000*9880d681SAndroid Build Coastguard Worker // Check that the pointer is the return value of the call.
2001*9880d681SAndroid Build Coastguard Worker if (!Call || Arg != Call)
2002*9880d681SAndroid Build Coastguard Worker return false;
2003*9880d681SAndroid Build Coastguard Worker
2004*9880d681SAndroid Build Coastguard Worker // Check that the call is a regular call.
2005*9880d681SAndroid Build Coastguard Worker ARCInstKind Class = GetBasicARCInstKind(Call);
2006*9880d681SAndroid Build Coastguard Worker return Class == ARCInstKind::CallOrUser || Class == ARCInstKind::Call;
2007*9880d681SAndroid Build Coastguard Worker }
2008*9880d681SAndroid Build Coastguard Worker
2009*9880d681SAndroid Build Coastguard Worker /// Find a dependent retain that precedes the given autorelease for which there
2010*9880d681SAndroid Build Coastguard Worker /// is nothing in between the two instructions that can affect the ref count of
2011*9880d681SAndroid Build Coastguard Worker /// Arg.
2012*9880d681SAndroid Build Coastguard Worker static CallInst *
FindPredecessorRetainWithSafePath(const Value * Arg,BasicBlock * BB,Instruction * Autorelease,SmallPtrSetImpl<Instruction * > & DepInsts,SmallPtrSetImpl<const BasicBlock * > & Visited,ProvenanceAnalysis & PA)2013*9880d681SAndroid Build Coastguard Worker FindPredecessorRetainWithSafePath(const Value *Arg, BasicBlock *BB,
2014*9880d681SAndroid Build Coastguard Worker Instruction *Autorelease,
2015*9880d681SAndroid Build Coastguard Worker SmallPtrSetImpl<Instruction *> &DepInsts,
2016*9880d681SAndroid Build Coastguard Worker SmallPtrSetImpl<const BasicBlock *> &Visited,
2017*9880d681SAndroid Build Coastguard Worker ProvenanceAnalysis &PA) {
2018*9880d681SAndroid Build Coastguard Worker FindDependencies(CanChangeRetainCount, Arg,
2019*9880d681SAndroid Build Coastguard Worker BB, Autorelease, DepInsts, Visited, PA);
2020*9880d681SAndroid Build Coastguard Worker if (DepInsts.size() != 1)
2021*9880d681SAndroid Build Coastguard Worker return nullptr;
2022*9880d681SAndroid Build Coastguard Worker
2023*9880d681SAndroid Build Coastguard Worker auto *Retain = dyn_cast_or_null<CallInst>(*DepInsts.begin());
2024*9880d681SAndroid Build Coastguard Worker
2025*9880d681SAndroid Build Coastguard Worker // Check that we found a retain with the same argument.
2026*9880d681SAndroid Build Coastguard Worker if (!Retain || !IsRetain(GetBasicARCInstKind(Retain)) ||
2027*9880d681SAndroid Build Coastguard Worker GetArgRCIdentityRoot(Retain) != Arg) {
2028*9880d681SAndroid Build Coastguard Worker return nullptr;
2029*9880d681SAndroid Build Coastguard Worker }
2030*9880d681SAndroid Build Coastguard Worker
2031*9880d681SAndroid Build Coastguard Worker return Retain;
2032*9880d681SAndroid Build Coastguard Worker }
2033*9880d681SAndroid Build Coastguard Worker
2034*9880d681SAndroid Build Coastguard Worker /// Look for an ``autorelease'' instruction dependent on Arg such that there are
2035*9880d681SAndroid Build Coastguard Worker /// no instructions dependent on Arg that need a positive ref count in between
2036*9880d681SAndroid Build Coastguard Worker /// the autorelease and the ret.
2037*9880d681SAndroid Build Coastguard Worker static CallInst *
FindPredecessorAutoreleaseWithSafePath(const Value * Arg,BasicBlock * BB,ReturnInst * Ret,SmallPtrSetImpl<Instruction * > & DepInsts,SmallPtrSetImpl<const BasicBlock * > & V,ProvenanceAnalysis & PA)2038*9880d681SAndroid Build Coastguard Worker FindPredecessorAutoreleaseWithSafePath(const Value *Arg, BasicBlock *BB,
2039*9880d681SAndroid Build Coastguard Worker ReturnInst *Ret,
2040*9880d681SAndroid Build Coastguard Worker SmallPtrSetImpl<Instruction *> &DepInsts,
2041*9880d681SAndroid Build Coastguard Worker SmallPtrSetImpl<const BasicBlock *> &V,
2042*9880d681SAndroid Build Coastguard Worker ProvenanceAnalysis &PA) {
2043*9880d681SAndroid Build Coastguard Worker FindDependencies(NeedsPositiveRetainCount, Arg,
2044*9880d681SAndroid Build Coastguard Worker BB, Ret, DepInsts, V, PA);
2045*9880d681SAndroid Build Coastguard Worker if (DepInsts.size() != 1)
2046*9880d681SAndroid Build Coastguard Worker return nullptr;
2047*9880d681SAndroid Build Coastguard Worker
2048*9880d681SAndroid Build Coastguard Worker auto *Autorelease = dyn_cast_or_null<CallInst>(*DepInsts.begin());
2049*9880d681SAndroid Build Coastguard Worker if (!Autorelease)
2050*9880d681SAndroid Build Coastguard Worker return nullptr;
2051*9880d681SAndroid Build Coastguard Worker ARCInstKind AutoreleaseClass = GetBasicARCInstKind(Autorelease);
2052*9880d681SAndroid Build Coastguard Worker if (!IsAutorelease(AutoreleaseClass))
2053*9880d681SAndroid Build Coastguard Worker return nullptr;
2054*9880d681SAndroid Build Coastguard Worker if (GetArgRCIdentityRoot(Autorelease) != Arg)
2055*9880d681SAndroid Build Coastguard Worker return nullptr;
2056*9880d681SAndroid Build Coastguard Worker
2057*9880d681SAndroid Build Coastguard Worker return Autorelease;
2058*9880d681SAndroid Build Coastguard Worker }
2059*9880d681SAndroid Build Coastguard Worker
2060*9880d681SAndroid Build Coastguard Worker /// Look for this pattern:
2061*9880d681SAndroid Build Coastguard Worker /// \code
2062*9880d681SAndroid Build Coastguard Worker /// %call = call i8* @something(...)
2063*9880d681SAndroid Build Coastguard Worker /// %2 = call i8* @objc_retain(i8* %call)
2064*9880d681SAndroid Build Coastguard Worker /// %3 = call i8* @objc_autorelease(i8* %2)
2065*9880d681SAndroid Build Coastguard Worker /// ret i8* %3
2066*9880d681SAndroid Build Coastguard Worker /// \endcode
2067*9880d681SAndroid Build Coastguard Worker /// And delete the retain and autorelease.
OptimizeReturns(Function & F)2068*9880d681SAndroid Build Coastguard Worker void ObjCARCOpt::OptimizeReturns(Function &F) {
2069*9880d681SAndroid Build Coastguard Worker if (!F.getReturnType()->isPointerTy())
2070*9880d681SAndroid Build Coastguard Worker return;
2071*9880d681SAndroid Build Coastguard Worker
2072*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "\n== ObjCARCOpt::OptimizeReturns ==\n");
2073*9880d681SAndroid Build Coastguard Worker
2074*9880d681SAndroid Build Coastguard Worker SmallPtrSet<Instruction *, 4> DependingInstructions;
2075*9880d681SAndroid Build Coastguard Worker SmallPtrSet<const BasicBlock *, 4> Visited;
2076*9880d681SAndroid Build Coastguard Worker for (BasicBlock &BB: F) {
2077*9880d681SAndroid Build Coastguard Worker ReturnInst *Ret = dyn_cast<ReturnInst>(&BB.back());
2078*9880d681SAndroid Build Coastguard Worker
2079*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Visiting: " << *Ret << "\n");
2080*9880d681SAndroid Build Coastguard Worker
2081*9880d681SAndroid Build Coastguard Worker if (!Ret)
2082*9880d681SAndroid Build Coastguard Worker continue;
2083*9880d681SAndroid Build Coastguard Worker
2084*9880d681SAndroid Build Coastguard Worker const Value *Arg = GetRCIdentityRoot(Ret->getOperand(0));
2085*9880d681SAndroid Build Coastguard Worker
2086*9880d681SAndroid Build Coastguard Worker // Look for an ``autorelease'' instruction that is a predecessor of Ret and
2087*9880d681SAndroid Build Coastguard Worker // dependent on Arg such that there are no instructions dependent on Arg
2088*9880d681SAndroid Build Coastguard Worker // that need a positive ref count in between the autorelease and Ret.
2089*9880d681SAndroid Build Coastguard Worker CallInst *Autorelease = FindPredecessorAutoreleaseWithSafePath(
2090*9880d681SAndroid Build Coastguard Worker Arg, &BB, Ret, DependingInstructions, Visited, PA);
2091*9880d681SAndroid Build Coastguard Worker DependingInstructions.clear();
2092*9880d681SAndroid Build Coastguard Worker Visited.clear();
2093*9880d681SAndroid Build Coastguard Worker
2094*9880d681SAndroid Build Coastguard Worker if (!Autorelease)
2095*9880d681SAndroid Build Coastguard Worker continue;
2096*9880d681SAndroid Build Coastguard Worker
2097*9880d681SAndroid Build Coastguard Worker CallInst *Retain = FindPredecessorRetainWithSafePath(
2098*9880d681SAndroid Build Coastguard Worker Arg, &BB, Autorelease, DependingInstructions, Visited, PA);
2099*9880d681SAndroid Build Coastguard Worker DependingInstructions.clear();
2100*9880d681SAndroid Build Coastguard Worker Visited.clear();
2101*9880d681SAndroid Build Coastguard Worker
2102*9880d681SAndroid Build Coastguard Worker if (!Retain)
2103*9880d681SAndroid Build Coastguard Worker continue;
2104*9880d681SAndroid Build Coastguard Worker
2105*9880d681SAndroid Build Coastguard Worker // Check that there is nothing that can affect the reference count
2106*9880d681SAndroid Build Coastguard Worker // between the retain and the call. Note that Retain need not be in BB.
2107*9880d681SAndroid Build Coastguard Worker bool HasSafePathToCall = HasSafePathToPredecessorCall(Arg, Retain,
2108*9880d681SAndroid Build Coastguard Worker DependingInstructions,
2109*9880d681SAndroid Build Coastguard Worker Visited, PA);
2110*9880d681SAndroid Build Coastguard Worker DependingInstructions.clear();
2111*9880d681SAndroid Build Coastguard Worker Visited.clear();
2112*9880d681SAndroid Build Coastguard Worker
2113*9880d681SAndroid Build Coastguard Worker if (!HasSafePathToCall)
2114*9880d681SAndroid Build Coastguard Worker continue;
2115*9880d681SAndroid Build Coastguard Worker
2116*9880d681SAndroid Build Coastguard Worker // If so, we can zap the retain and autorelease.
2117*9880d681SAndroid Build Coastguard Worker Changed = true;
2118*9880d681SAndroid Build Coastguard Worker ++NumRets;
2119*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Erasing: " << *Retain << "\nErasing: "
2120*9880d681SAndroid Build Coastguard Worker << *Autorelease << "\n");
2121*9880d681SAndroid Build Coastguard Worker EraseInstruction(Retain);
2122*9880d681SAndroid Build Coastguard Worker EraseInstruction(Autorelease);
2123*9880d681SAndroid Build Coastguard Worker }
2124*9880d681SAndroid Build Coastguard Worker }
2125*9880d681SAndroid Build Coastguard Worker
2126*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
2127*9880d681SAndroid Build Coastguard Worker void
GatherStatistics(Function & F,bool AfterOptimization)2128*9880d681SAndroid Build Coastguard Worker ObjCARCOpt::GatherStatistics(Function &F, bool AfterOptimization) {
2129*9880d681SAndroid Build Coastguard Worker llvm::Statistic &NumRetains =
2130*9880d681SAndroid Build Coastguard Worker AfterOptimization? NumRetainsAfterOpt : NumRetainsBeforeOpt;
2131*9880d681SAndroid Build Coastguard Worker llvm::Statistic &NumReleases =
2132*9880d681SAndroid Build Coastguard Worker AfterOptimization? NumReleasesAfterOpt : NumReleasesBeforeOpt;
2133*9880d681SAndroid Build Coastguard Worker
2134*9880d681SAndroid Build Coastguard Worker for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E; ) {
2135*9880d681SAndroid Build Coastguard Worker Instruction *Inst = &*I++;
2136*9880d681SAndroid Build Coastguard Worker switch (GetBasicARCInstKind(Inst)) {
2137*9880d681SAndroid Build Coastguard Worker default:
2138*9880d681SAndroid Build Coastguard Worker break;
2139*9880d681SAndroid Build Coastguard Worker case ARCInstKind::Retain:
2140*9880d681SAndroid Build Coastguard Worker ++NumRetains;
2141*9880d681SAndroid Build Coastguard Worker break;
2142*9880d681SAndroid Build Coastguard Worker case ARCInstKind::Release:
2143*9880d681SAndroid Build Coastguard Worker ++NumReleases;
2144*9880d681SAndroid Build Coastguard Worker break;
2145*9880d681SAndroid Build Coastguard Worker }
2146*9880d681SAndroid Build Coastguard Worker }
2147*9880d681SAndroid Build Coastguard Worker }
2148*9880d681SAndroid Build Coastguard Worker #endif
2149*9880d681SAndroid Build Coastguard Worker
doInitialization(Module & M)2150*9880d681SAndroid Build Coastguard Worker bool ObjCARCOpt::doInitialization(Module &M) {
2151*9880d681SAndroid Build Coastguard Worker if (!EnableARCOpts)
2152*9880d681SAndroid Build Coastguard Worker return false;
2153*9880d681SAndroid Build Coastguard Worker
2154*9880d681SAndroid Build Coastguard Worker // If nothing in the Module uses ARC, don't do anything.
2155*9880d681SAndroid Build Coastguard Worker Run = ModuleHasARC(M);
2156*9880d681SAndroid Build Coastguard Worker if (!Run)
2157*9880d681SAndroid Build Coastguard Worker return false;
2158*9880d681SAndroid Build Coastguard Worker
2159*9880d681SAndroid Build Coastguard Worker // Intuitively, objc_retain and others are nocapture, however in practice
2160*9880d681SAndroid Build Coastguard Worker // they are not, because they return their argument value. And objc_release
2161*9880d681SAndroid Build Coastguard Worker // calls finalizers which can have arbitrary side effects.
2162*9880d681SAndroid Build Coastguard Worker MDKindCache.init(&M);
2163*9880d681SAndroid Build Coastguard Worker
2164*9880d681SAndroid Build Coastguard Worker // Initialize our runtime entry point cache.
2165*9880d681SAndroid Build Coastguard Worker EP.init(&M);
2166*9880d681SAndroid Build Coastguard Worker
2167*9880d681SAndroid Build Coastguard Worker return false;
2168*9880d681SAndroid Build Coastguard Worker }
2169*9880d681SAndroid Build Coastguard Worker
runOnFunction(Function & F)2170*9880d681SAndroid Build Coastguard Worker bool ObjCARCOpt::runOnFunction(Function &F) {
2171*9880d681SAndroid Build Coastguard Worker if (!EnableARCOpts)
2172*9880d681SAndroid Build Coastguard Worker return false;
2173*9880d681SAndroid Build Coastguard Worker
2174*9880d681SAndroid Build Coastguard Worker // If nothing in the Module uses ARC, don't do anything.
2175*9880d681SAndroid Build Coastguard Worker if (!Run)
2176*9880d681SAndroid Build Coastguard Worker return false;
2177*9880d681SAndroid Build Coastguard Worker
2178*9880d681SAndroid Build Coastguard Worker Changed = false;
2179*9880d681SAndroid Build Coastguard Worker
2180*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "<<< ObjCARCOpt: Visiting Function: " << F.getName() << " >>>"
2181*9880d681SAndroid Build Coastguard Worker "\n");
2182*9880d681SAndroid Build Coastguard Worker
2183*9880d681SAndroid Build Coastguard Worker PA.setAA(&getAnalysis<AAResultsWrapperPass>().getAAResults());
2184*9880d681SAndroid Build Coastguard Worker
2185*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
2186*9880d681SAndroid Build Coastguard Worker if (AreStatisticsEnabled()) {
2187*9880d681SAndroid Build Coastguard Worker GatherStatistics(F, false);
2188*9880d681SAndroid Build Coastguard Worker }
2189*9880d681SAndroid Build Coastguard Worker #endif
2190*9880d681SAndroid Build Coastguard Worker
2191*9880d681SAndroid Build Coastguard Worker // This pass performs several distinct transformations. As a compile-time aid
2192*9880d681SAndroid Build Coastguard Worker // when compiling code that isn't ObjC, skip these if the relevant ObjC
2193*9880d681SAndroid Build Coastguard Worker // library functions aren't declared.
2194*9880d681SAndroid Build Coastguard Worker
2195*9880d681SAndroid Build Coastguard Worker // Preliminary optimizations. This also computes UsedInThisFunction.
2196*9880d681SAndroid Build Coastguard Worker OptimizeIndividualCalls(F);
2197*9880d681SAndroid Build Coastguard Worker
2198*9880d681SAndroid Build Coastguard Worker // Optimizations for weak pointers.
2199*9880d681SAndroid Build Coastguard Worker if (UsedInThisFunction & ((1 << unsigned(ARCInstKind::LoadWeak)) |
2200*9880d681SAndroid Build Coastguard Worker (1 << unsigned(ARCInstKind::LoadWeakRetained)) |
2201*9880d681SAndroid Build Coastguard Worker (1 << unsigned(ARCInstKind::StoreWeak)) |
2202*9880d681SAndroid Build Coastguard Worker (1 << unsigned(ARCInstKind::InitWeak)) |
2203*9880d681SAndroid Build Coastguard Worker (1 << unsigned(ARCInstKind::CopyWeak)) |
2204*9880d681SAndroid Build Coastguard Worker (1 << unsigned(ARCInstKind::MoveWeak)) |
2205*9880d681SAndroid Build Coastguard Worker (1 << unsigned(ARCInstKind::DestroyWeak))))
2206*9880d681SAndroid Build Coastguard Worker OptimizeWeakCalls(F);
2207*9880d681SAndroid Build Coastguard Worker
2208*9880d681SAndroid Build Coastguard Worker // Optimizations for retain+release pairs.
2209*9880d681SAndroid Build Coastguard Worker if (UsedInThisFunction & ((1 << unsigned(ARCInstKind::Retain)) |
2210*9880d681SAndroid Build Coastguard Worker (1 << unsigned(ARCInstKind::RetainRV)) |
2211*9880d681SAndroid Build Coastguard Worker (1 << unsigned(ARCInstKind::RetainBlock))))
2212*9880d681SAndroid Build Coastguard Worker if (UsedInThisFunction & (1 << unsigned(ARCInstKind::Release)))
2213*9880d681SAndroid Build Coastguard Worker // Run OptimizeSequences until it either stops making changes or
2214*9880d681SAndroid Build Coastguard Worker // no retain+release pair nesting is detected.
2215*9880d681SAndroid Build Coastguard Worker while (OptimizeSequences(F)) {}
2216*9880d681SAndroid Build Coastguard Worker
2217*9880d681SAndroid Build Coastguard Worker // Optimizations if objc_autorelease is used.
2218*9880d681SAndroid Build Coastguard Worker if (UsedInThisFunction & ((1 << unsigned(ARCInstKind::Autorelease)) |
2219*9880d681SAndroid Build Coastguard Worker (1 << unsigned(ARCInstKind::AutoreleaseRV))))
2220*9880d681SAndroid Build Coastguard Worker OptimizeReturns(F);
2221*9880d681SAndroid Build Coastguard Worker
2222*9880d681SAndroid Build Coastguard Worker // Gather statistics after optimization.
2223*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
2224*9880d681SAndroid Build Coastguard Worker if (AreStatisticsEnabled()) {
2225*9880d681SAndroid Build Coastguard Worker GatherStatistics(F, true);
2226*9880d681SAndroid Build Coastguard Worker }
2227*9880d681SAndroid Build Coastguard Worker #endif
2228*9880d681SAndroid Build Coastguard Worker
2229*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "\n");
2230*9880d681SAndroid Build Coastguard Worker
2231*9880d681SAndroid Build Coastguard Worker return Changed;
2232*9880d681SAndroid Build Coastguard Worker }
2233*9880d681SAndroid Build Coastguard Worker
releaseMemory()2234*9880d681SAndroid Build Coastguard Worker void ObjCARCOpt::releaseMemory() {
2235*9880d681SAndroid Build Coastguard Worker PA.clear();
2236*9880d681SAndroid Build Coastguard Worker }
2237*9880d681SAndroid Build Coastguard Worker
2238*9880d681SAndroid Build Coastguard Worker /// @}
2239*9880d681SAndroid Build Coastguard Worker ///
2240