mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 11:13:28 +01:00
[objc-arc] Move the detection of potential uses or altering of a ref count onto PtrState.
llvm-svn: 231446
This commit is contained in:
parent
b7a87300a2
commit
beba035edd
@ -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);
|
||||
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!");
|
||||
}
|
||||
}
|
||||
if (S.HandlePotentialAlterRefCount(Inst, Ptr, PA, Class))
|
||||
continue;
|
||||
|
||||
// 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();
|
||||
if (S.HandlePotentialAlterRefCount(Inst, Ptr, PA, Class))
|
||||
continue;
|
||||
|
||||
// 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.
|
||||
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;
|
||||
|
@ -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!");
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user