[objc-arc] Move the detection of potential uses or altering of a ref count onto PtrState.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@231446 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Michael Gottesman 2015-03-06 02:07:12 +00:00
parent 6023ad2d37
commit 18b755804f
3 changed files with 171 additions and 108 deletions

View File

@ -1113,71 +1113,11 @@ bool ObjCARCOpt::VisitInstructionBottomUp(
if (Ptr == Arg)
continue; // Handled above.
BottomUpPtrState &S = MI->second;
Sequence Seq = S.GetSeq();
// Check for possible releases.
if (CanAlterRefCount(Inst, Ptr, PA, Class)) {
DEBUG(dbgs() << "CanAlterRefCount: Seq: " << Seq << "; " << *Ptr
<< "\n");
S.ClearKnownPositiveRefCount();
switch (Seq) {
case S_Use:
S.SetSeq(S_CanRelease);
if (S.HandlePotentialAlterRefCount(Inst, Ptr, PA, Class))
continue;
case S_CanRelease:
case S_Release:
case S_MovableRelease:
case S_Stop:
case S_None:
break;
case S_Retain:
llvm_unreachable("bottom-up pointer in retain state!");
}
}
// Check for possible direct uses.
switch (Seq) {
case S_Release:
case S_MovableRelease:
if (CanUse(Inst, Ptr, PA, Class)) {
DEBUG(dbgs() << "CanUse: Seq: " << Seq << "; " << *Ptr
<< "\n");
assert(!S.HasReverseInsertPts());
// If this is an invoke instruction, we're scanning it as part of
// one of its successor blocks, since we can't insert code after it
// in its own block, and we don't want to split critical edges.
if (isa<InvokeInst>(Inst))
S.InsertReverseInsertPt(BB->getFirstInsertionPt());
else
S.InsertReverseInsertPt(std::next(BasicBlock::iterator(Inst)));
S.SetSeq(S_Use);
} else if (Seq == S_Release && IsUser(Class)) {
DEBUG(dbgs() << "PreciseReleaseUse: Seq: " << Seq << "; " << *Ptr
<< "\n");
// Non-movable releases depend on any possible objc pointer use.
S.SetSeq(S_Stop);
assert(!S.HasReverseInsertPts());
// As above; handle invoke specially.
if (isa<InvokeInst>(Inst))
S.InsertReverseInsertPt(BB->getFirstInsertionPt());
else
S.InsertReverseInsertPt(std::next(BasicBlock::iterator(Inst)));
}
break;
case S_Stop:
if (CanUse(Inst, Ptr, PA, Class)) {
DEBUG(dbgs() << "PreciseStopUse: Seq: " << Seq << "; " << *Ptr
<< "\n");
S.SetSeq(S_Use);
}
break;
case S_CanRelease:
case S_Use:
case S_None:
break;
case S_Retain:
llvm_unreachable("bottom-up pointer in retain state!");
}
S.HandlePotentialUse(BB, Inst, Ptr, PA, Class);
}
return NestingDetected;
@ -1294,52 +1234,10 @@ ObjCARCOpt::VisitInstructionTopDown(Instruction *Inst,
if (Ptr == Arg)
continue; // Handled above.
TopDownPtrState &S = MI->second;
Sequence Seq = S.GetSeq();
// Check for possible releases.
if (CanAlterRefCount(Inst, Ptr, PA, Class)) {
DEBUG(dbgs() << "CanAlterRefCount: Seq: " << Seq << "; " << *Ptr
<< "\n");
S.ClearKnownPositiveRefCount();
switch (Seq) {
case S_Retain:
S.SetSeq(S_CanRelease);
assert(!S.HasReverseInsertPts());
S.InsertReverseInsertPt(Inst);
// One call can't cause a transition from S_Retain to S_CanRelease
// and S_CanRelease to S_Use. If we've made the first transition,
// we're done.
if (S.HandlePotentialAlterRefCount(Inst, Ptr, PA, Class))
continue;
case S_Use:
case S_CanRelease:
case S_None:
break;
case S_Stop:
case S_Release:
case S_MovableRelease:
llvm_unreachable("top-down pointer in release state!");
}
}
// Check for possible direct uses.
switch (Seq) {
case S_CanRelease:
if (CanUse(Inst, Ptr, PA, Class)) {
DEBUG(dbgs() << "CanUse: Seq: " << Seq << "; " << *Ptr
<< "\n");
S.SetSeq(S_Use);
}
break;
case S_Retain:
case S_Use:
case S_None:
break;
case S_Stop:
case S_Release:
case S_MovableRelease:
llvm_unreachable("top-down pointer in release state!");
}
S.HandlePotentialUse(Inst, Ptr, PA, Class);
}
return NestingDetected;

View File

@ -11,10 +11,15 @@
#include "llvm/Support/Debug.h"
#include "PtrState.h"
#include "ObjCARC.h"
#include "DependencyAnalysis.h"
using namespace llvm;
using namespace llvm::objcarc;
//===----------------------------------------------------------------------===//
// Utility
//===----------------------------------------------------------------------===//
raw_ostream &llvm::objcarc::operator<<(raw_ostream &OS, const Sequence S) {
switch (S) {
case S_None:
@ -35,6 +40,10 @@ raw_ostream &llvm::objcarc::operator<<(raw_ostream &OS, const Sequence S) {
llvm_unreachable("Unknown sequence type.");
}
//===----------------------------------------------------------------------===//
// Sequence
//===----------------------------------------------------------------------===//
static Sequence MergeSeqs(Sequence A, Sequence B, bool TopDown) {
// The easy cases.
if (A == B)
@ -64,6 +73,10 @@ static Sequence MergeSeqs(Sequence A, Sequence B, bool TopDown) {
return S_None;
}
//===----------------------------------------------------------------------===//
// RRInfo
//===----------------------------------------------------------------------===//
void RRInfo::clear() {
KnownSafe = false;
IsTailCallRelease = false;
@ -94,6 +107,10 @@ bool RRInfo::Merge(const RRInfo &Other) {
return Partial;
}
//===----------------------------------------------------------------------===//
// PtrState
//===----------------------------------------------------------------------===//
void PtrState::SetKnownPositiveRefCount() {
DEBUG(dbgs() << "Setting Known Positive.\n");
KnownPositiveRefCount = true;
@ -139,6 +156,10 @@ void PtrState::Merge(const PtrState &Other, bool TopDown) {
}
}
//===----------------------------------------------------------------------===//
// BottomUpPtrState
//===----------------------------------------------------------------------===//
bool BottomUpPtrState::InitBottomUp(ARCMDKindCache &Cache, Instruction *I) {
// If we see two releases in a row on the same pointer. If so, make
// a note, and we'll cicle back to revisit it after we've
@ -187,6 +208,84 @@ bool BottomUpPtrState::MatchWithRetain() {
}
}
bool BottomUpPtrState::HandlePotentialAlterRefCount(Instruction *Inst,
const Value *Ptr,
ProvenanceAnalysis &PA,
ARCInstKind Class) {
Sequence Seq = GetSeq();
// Check for possible releases.
if (!CanAlterRefCount(Inst, Ptr, PA, Class))
return false;
DEBUG(dbgs() << "CanAlterRefCount: Seq: " << Seq << "; " << *Ptr << "\n");
ClearKnownPositiveRefCount();
switch (Seq) {
case S_Use:
SetSeq(S_CanRelease);
return true;
case S_CanRelease:
case S_Release:
case S_MovableRelease:
case S_Stop:
case S_None:
return false;
case S_Retain:
llvm_unreachable("bottom-up pointer in retain state!");
}
}
void BottomUpPtrState::HandlePotentialUse(BasicBlock *BB, Instruction *Inst,
const Value *Ptr,
ProvenanceAnalysis &PA,
ARCInstKind Class) {
// Check for possible direct uses.
switch (GetSeq()) {
case S_Release:
case S_MovableRelease:
if (CanUse(Inst, Ptr, PA, Class)) {
DEBUG(dbgs() << "CanUse: Seq: " << Seq << "; " << *Ptr << "\n");
assert(!HasReverseInsertPts());
// If this is an invoke instruction, we're scanning it as part of
// one of its successor blocks, since we can't insert code after it
// in its own block, and we don't want to split critical edges.
if (isa<InvokeInst>(Inst))
InsertReverseInsertPt(BB->getFirstInsertionPt());
else
InsertReverseInsertPt(std::next(BasicBlock::iterator(Inst)));
SetSeq(S_Use);
} else if (Seq == S_Release && IsUser(Class)) {
DEBUG(dbgs() << "PreciseReleaseUse: Seq: " << Seq << "; " << *Ptr
<< "\n");
// Non-movable releases depend on any possible objc pointer use.
SetSeq(S_Stop);
assert(!HasReverseInsertPts());
// As above; handle invoke specially.
if (isa<InvokeInst>(Inst))
InsertReverseInsertPt(BB->getFirstInsertionPt());
else
InsertReverseInsertPt(std::next(BasicBlock::iterator(Inst)));
}
break;
case S_Stop:
if (CanUse(Inst, Ptr, PA, Class)) {
DEBUG(dbgs() << "PreciseStopUse: Seq: " << Seq << "; " << *Ptr << "\n");
SetSeq(S_Use);
}
break;
case S_CanRelease:
case S_Use:
case S_None:
break;
case S_Retain:
llvm_unreachable("bottom-up pointer in retain state!");
}
}
//===----------------------------------------------------------------------===//
// TopDownPtrState
//===----------------------------------------------------------------------===//
bool TopDownPtrState::InitTopDown(ARCInstKind Kind, Instruction *I) {
bool NestingDetected = false;
// Don't do retain+release tracking for ARCInstKind::RetainRV, because
@ -238,3 +337,57 @@ bool TopDownPtrState::MatchWithRelease(ARCMDKindCache &Cache,
llvm_unreachable("top-down pointer in bottom up state!");
}
}
bool TopDownPtrState::HandlePotentialAlterRefCount(Instruction *Inst,
const Value *Ptr,
ProvenanceAnalysis &PA,
ARCInstKind Class) {
// Check for possible releases.
if (!CanAlterRefCount(Inst, Ptr, PA, Class))
return false;
DEBUG(dbgs() << "CanAlterRefCount: Seq: " << Seq << "; " << *Ptr << "\n");
ClearKnownPositiveRefCount();
switch (Seq) {
case S_Retain:
SetSeq(S_CanRelease);
assert(!HasReverseInsertPts());
InsertReverseInsertPt(Inst);
// One call can't cause a transition from S_Retain to S_CanRelease
// and S_CanRelease to S_Use. If we've made the first transition,
// we're done.
return true;
case S_Use:
case S_CanRelease:
case S_None:
return false;
case S_Stop:
case S_Release:
case S_MovableRelease:
llvm_unreachable("top-down pointer in release state!");
}
llvm_unreachable("covered switch is not covered!?");
}
void TopDownPtrState::HandlePotentialUse(Instruction *Inst, const Value *Ptr,
ProvenanceAnalysis &PA,
ARCInstKind Class) {
// Check for possible direct uses.
switch (GetSeq()) {
case S_CanRelease:
if (!CanUse(Inst, Ptr, PA, Class))
return;
DEBUG(dbgs() << "CanUse: Seq: " << Seq << "; " << *Ptr << "\n");
SetSeq(S_Use);
return;
case S_Retain:
case S_Use:
case S_None:
return;
case S_Stop:
case S_Release:
case S_MovableRelease:
llvm_unreachable("top-down pointer in release state!");
}
}

View File

@ -28,6 +28,7 @@ namespace llvm {
namespace objcarc {
struct ARCMDKindCache;
class ProvenanceAnalysis;
/// \enum Sequence
///
@ -177,6 +178,11 @@ struct BottomUpPtrState : PtrState {
/// It is assumed that one has already checked that the RCIdentity of the
/// retain and the RCIdentity of this ptr state are the same.
bool MatchWithRetain();
void HandlePotentialUse(BasicBlock *BB, Instruction *Inst, const Value *Ptr,
ProvenanceAnalysis &PA, ARCInstKind Class);
bool HandlePotentialAlterRefCount(Instruction *Inst, const Value *Ptr,
ProvenanceAnalysis &PA, ARCInstKind Class);
};
struct TopDownPtrState : PtrState {
@ -190,6 +196,12 @@ struct TopDownPtrState : PtrState {
/// release. Modifies state appropriately to reflect that the matching
/// occured.
bool MatchWithRelease(ARCMDKindCache &Cache, Instruction *Release);
void HandlePotentialUse(Instruction *Inst, const Value *Ptr,
ProvenanceAnalysis &PA, ARCInstKind Class);
bool HandlePotentialAlterRefCount(Instruction *Inst, const Value *Ptr,
ProvenanceAnalysis &PA, ARCInstKind Class);
};
} // end namespace objcarc