1//===- PtrState.cpp -------------------------------------------------------===//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//===----------------------------------------------------------------------===//
31 #define DEBUG_TYPE "objc-arc-ptr-state"
33//===----------------------------------------------------------------------===//
35//===----------------------------------------------------------------------===//
40 return OS <<
"S_None";
42 return OS <<
"S_Retain";
44 return OS <<
"S_CanRelease";
48 return OS <<
"S_MovableRelease";
50 return OS <<
"S_Stop";
55//===----------------------------------------------------------------------===//
57//===----------------------------------------------------------------------===//
69 // Choose the side which is further along in the sequence.
74 // Choose the side which is further along in the sequence.
78 // If both sides are releases, choose the more conservative one.
86//===----------------------------------------------------------------------===//
88//===----------------------------------------------------------------------===//
100 // Conservatively merge the ReleaseMetadata information.
104 // Conservatively merge the boolean state.
109 // Merge the call sets.
112 // Merge the insert point sets. If there are any differences,
113 // that makes this a partial merge.
120//===----------------------------------------------------------------------===//
122//===----------------------------------------------------------------------===//
151 // If we're not in a sequence (anymore), drop all associated state.
156 // If we're doing a merge on a path that's previously seen a partial
157 // merge, conservatively drop the sequence, to avoid doing partial
158 // RR elimination. If the branch predicates for the two merge differ,
159 // mixing them is unsafe.
162 // Otherwise merge the other PtrState's RRInfo into our RRInfo. At this
163 // point, we know that currently we are not partial. Stash whether or not
164 // the merge operation caused us to undergo a partial merging of reverse
170//===----------------------------------------------------------------------===//
172//===----------------------------------------------------------------------===//
175 // If we see two releases in a row on the same pointer. If so, make
176 // a note, and we'll cicle back to revisit it after we've
177 // hopefully eliminated the second release, which may allow us to
178 // eliminate the first release too.
179 // Theoretically we could implement removal of nested retain+release
180 // pairs by making PtrState hold a stack of states, but this is
181 // simple and avoids adding overhead for the non-nested case.
182 bool NestingDetected =
false;
185 dbgs() <<
" Found nested releases (i.e. a release pair)\n");
186 NestingDetected =
true;
200 return NestingDetected;
211 // If OldSeq is not S_Use or OldSeq is S_Use and we are tracking an
212 // imprecise release, clear our reverse insertion points.
232 // Check for possible releases.
257 auto SetSeqAndInsertReverseInsertPt = [&](
Sequence NewSeq){
260 // If this is an invoke instruction, we're scanning it as part of
261 // one of its successor blocks, since we can't insert code after it
262 // in its own block, and we don't want to split critical edges.
266 InsertAfter = IP == BB->
end() ? std::prev(BB->
end()) : IP;
268 // A catchswitch must be the only non-phi instruction in its basic
269 // block, so attempting to insert an instruction into such a block would
270 // produce invalid IR.
276 if (InsertAfter != BB->
end())
281 // Don't insert anything between a call/invoke with operand bundle
282 // "clang.arc.attachedcall" and the retainRV/claimRV call that uses the call
289 // Check for possible direct uses.
295 SetSeqAndInsertReverseInsertPt(
S_Use);
300 SetSeqAndInsertReverseInsertPt(
S_Stop);
307 <<
"; " << *
Ptr <<
"\n");
320//===----------------------------------------------------------------------===//
322//===----------------------------------------------------------------------===//
325 bool NestingDetected =
false;
326 // Don't do retain+release tracking for ARCInstKind::RetainRV, because
328 // better to let it remain as the first instruction after a call.
330 // If we see two retains in a row on the same pointer. If so, make
331 // a note, and we'll cicle back to revisit it after we've
332 // hopefully eliminated the second retain, which may allow us to
333 // eliminate the first retain too.
334 // Theoretically we could implement removal of nested retain+release
335 // pairs by making PtrState hold a stack of states, but this is
336 // simple and avoids adding overhead for the non-nested case.
338 NestingDetected =
true;
346 return NestingDetected;
361 if (OldSeq ==
S_Retain || ReleaseMetadata !=
nullptr)
380 // Check for possible releases. Treat clang.arc.use as a releasing instruction
381 // to prevent sinking a retain past it.
395 // Don't insert anything between a call/invoke with operand bundle
396 // "clang.arc.attachedcall" and the retainRV/claimRV call that uses the call
401 // One call can't cause a transition from S_Retain to S_CanRelease
402 // and S_CanRelease to S_Use. If we've made the first transition,
419 // Check for possible direct uses.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file declares special dependency analysis routines used in Objective C ARC Optimizations.
This file defines common analysis utilities used by the ObjC ARC Optimizer.
This file defines ARC utility functions which are used by various parts of the compiler.
static Sequence MergeSeqs(Sequence A, Sequence B, bool TopDown)
LLVM Basic Block Representation.
LLVM_ABI const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
InstListType::iterator iterator
Instruction iterators...
LLVM Value Representation.
self_iterator getIterator()
A cache of MDKinds used by various ARC optimizations.
bool contains(const Instruction *I) const
See if an instruction is a bundled retainRV/claimRV call.
bool KnownPositiveRefCount
True if the reference count is known to be incremented.
unsigned char Seq
The current position in the sequence.
void SetCFGHazardAfflicted(const bool NewValue)
RRInfo RRI
Unidirectional information about the current sequence.
void ClearReverseInsertPts()
void SetKnownPositiveRefCount()
bool HasKnownPositiveRefCount() const
void InsertReverseInsertPt(Instruction *I)
bool HasReverseInsertPts() const
void SetTailCallRelease(const bool NewValue)
void ClearKnownPositiveRefCount()
void SetReleaseMetadata(MDNode *NewValue)
void InsertCall(Instruction *I)
void ResetSequenceProgress(Sequence NewSeq)
void SetSeq(Sequence NewSeq)
void SetKnownSafe(const bool NewValue)
void Merge(const PtrState &Other, bool TopDown)
void ClearSequenceProgress()
bool Partial
True if we've seen an opportunity for partial RR elimination, such as pushing calls into a CFG triang...
bool IsTrackingImpreciseReleases() const
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static const Instruction * getreturnRVOperand(const Instruction &Inst, ARCInstKind Class)
If Inst is a ReturnRV and its operand is a call or invoke, return the operand.
raw_ostream & operator<<(raw_ostream &OS, const ARCInstKind Class)
ARCInstKind
Equivalence classes of instructions in the ARC Model.
@ RetainRV
objc_retainAutoreleasedReturnValue
@ Call
could call objc_release
@ IntrinsicUser
llvm.objc.clang.arc.use
Sequence
A sequence of states that a pointer may go through in which an objc_retain and objc_release are actua...
@ S_CanRelease
foo(x) – x could possibly see a ref count decrement.
@ S_Retain
objc_retain(x).
@ S_Stop
code motion is stopped.
@ S_MovableRelease
objc_release(x), !clang.imprecise_release.
ARCInstKind GetBasicARCInstKind(const Value *V)
Determine which objc runtime call instruction class V belongs to.
bool CanDecrementRefCount(ARCInstKind Kind)
Returns false if conservatively we can prove that any instruction mapped to this kind can not decreme...
bool hasAttachedCallOpBundle(const CallBase *CB)
bool CanUse(const Instruction *Inst, const Value *Ptr, ProvenanceAnalysis &PA, ARCInstKind Class)
Test whether the given instruction can "use" the given pointer's object in a way that requires the re...
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI BasicBlock::iterator skipDebugIntrinsics(BasicBlock::iterator It)
Advance It while it points to a debug instruction and return the result.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
bool HandlePotentialAlterRefCount(Instruction *Inst, const Value *Ptr, ProvenanceAnalysis &PA, ARCInstKind Class)
bool InitBottomUp(ARCMDKindCache &Cache, Instruction *I)
(Re-)Initialize this bottom up pointer returning true if we detected a pointer with nested releases.
bool MatchWithRetain()
Return true if this set of releases can be paired with a release.
void HandlePotentialUse(BasicBlock *BB, Instruction *Inst, const Value *Ptr, ProvenanceAnalysis &PA, ARCInstKind Class)
bool Merge(const RRInfo &Other)
Conservatively merge the two RRInfo.
bool KnownSafe
After an objc_retain, the reference count of the referenced object is known to be positive.
SmallPtrSet< Instruction *, 2 > Calls
For a top-down sequence, the set of objc_retains or objc_retainBlocks.
MDNode * ReleaseMetadata
If the Calls are objc_release calls and they all have a clang.imprecise_release tag,...
bool CFGHazardAfflicted
If this is true, we cannot perform code motion but can still remove retain/release pairs.
bool IsTailCallRelease
True of the objc_release calls are all marked with the "tail" keyword.
SmallPtrSet< Instruction *, 2 > ReverseInsertPts
The set of optimal insert positions for moving calls in the opposite sequence.
bool MatchWithRelease(ARCMDKindCache &Cache, Instruction *Release)
Return true if this set of retains can be paired with the given release.
bool InitTopDown(ARCInstKind Kind, Instruction *I)
(Re-)Initialize this bottom up pointer returning true if we detected a pointer with nested releases.
bool HandlePotentialAlterRefCount(Instruction *Inst, const Value *Ptr, ProvenanceAnalysis &PA, ARCInstKind Class, const BundledRetainClaimRVs &BundledRVs)
void HandlePotentialUse(Instruction *Inst, const Value *Ptr, ProvenanceAnalysis &PA, ARCInstKind Class)