[objc-arc] Create two subclasses of PtrState in preparation for moving per ptr state change behavior onto a PtrState class.

This will enable the main ObjCARCOpts dataflow to work with higher
level concepts such as "can this ptr state be modified by this ref
count" and not need to understand the nitty gritty details of how that
is determined. This makes the dataflow cleaner.

llvm-svn: 231437
This commit is contained in:
Michael Gottesman 2015-03-06 00:34:36 +00:00
parent 41c01005ed
commit feb138e211
2 changed files with 60 additions and 43 deletions

View File

@ -185,20 +185,18 @@ namespace {
/// The number of unique control paths to exits from this block. /// The number of unique control paths to exits from this block.
unsigned BottomUpPathCount; unsigned BottomUpPathCount;
/// A type for PerPtrTopDown and PerPtrBottomUp.
typedef BlotMapVector<const Value *, PtrState> MapTy;
/// The top-down traversal uses this to record information known about a /// The top-down traversal uses this to record information known about a
/// pointer at the bottom of each block. /// pointer at the bottom of each block.
MapTy PerPtrTopDown; BlotMapVector<const Value *, TopDownPtrState> PerPtrTopDown;
/// The bottom-up traversal uses this to record information known about a /// The bottom-up traversal uses this to record information known about a
/// pointer at the top of each block. /// pointer at the top of each block.
MapTy PerPtrBottomUp; BlotMapVector<const Value *, BottomUpPtrState> PerPtrBottomUp;
/// Effective predecessors of the current block ignoring ignorable edges and /// Effective predecessors of the current block ignoring ignorable edges and
/// ignored backedges. /// ignored backedges.
SmallVector<BasicBlock *, 2> Preds; SmallVector<BasicBlock *, 2> Preds;
/// Effective successors of the current block ignoring ignorable edges and /// Effective successors of the current block ignoring ignorable edges and
/// ignored backedges. /// ignored backedges.
SmallVector<BasicBlock *, 2> Succs; SmallVector<BasicBlock *, 2> Succs;
@ -208,24 +206,30 @@ namespace {
BBState() : TopDownPathCount(0), BottomUpPathCount(0) { } BBState() : TopDownPathCount(0), BottomUpPathCount(0) { }
typedef MapTy::iterator ptr_iterator; typedef decltype(PerPtrTopDown)::iterator top_down_ptr_iterator;
typedef MapTy::const_iterator ptr_const_iterator; typedef decltype(PerPtrTopDown)::const_iterator const_top_down_ptr_iterator;
ptr_iterator top_down_ptr_begin() { return PerPtrTopDown.begin(); } top_down_ptr_iterator top_down_ptr_begin() { return PerPtrTopDown.begin(); }
ptr_iterator top_down_ptr_end() { return PerPtrTopDown.end(); } top_down_ptr_iterator top_down_ptr_end() { return PerPtrTopDown.end(); }
ptr_const_iterator top_down_ptr_begin() const { const_top_down_ptr_iterator top_down_ptr_begin() const {
return PerPtrTopDown.begin(); return PerPtrTopDown.begin();
} }
ptr_const_iterator top_down_ptr_end() const { const_top_down_ptr_iterator top_down_ptr_end() const {
return PerPtrTopDown.end(); return PerPtrTopDown.end();
} }
ptr_iterator bottom_up_ptr_begin() { return PerPtrBottomUp.begin(); } typedef decltype(PerPtrBottomUp)::iterator bottom_up_ptr_iterator;
ptr_iterator bottom_up_ptr_end() { return PerPtrBottomUp.end(); } typedef decltype(
ptr_const_iterator bottom_up_ptr_begin() const { PerPtrBottomUp)::const_iterator const_bottom_up_ptr_iterator;
bottom_up_ptr_iterator bottom_up_ptr_begin() {
return PerPtrBottomUp.begin(); return PerPtrBottomUp.begin();
} }
ptr_const_iterator bottom_up_ptr_end() const { bottom_up_ptr_iterator bottom_up_ptr_end() { return PerPtrBottomUp.end(); }
const_bottom_up_ptr_iterator bottom_up_ptr_begin() const {
return PerPtrBottomUp.begin();
}
const_bottom_up_ptr_iterator bottom_up_ptr_end() const {
return PerPtrBottomUp.end(); return PerPtrBottomUp.end();
} }
@ -240,20 +244,20 @@ namespace {
/// Attempt to find the PtrState object describing the top down state for /// Attempt to find the PtrState object describing the top down state for
/// pointer Arg. Return a new initialized PtrState describing the top down /// pointer Arg. Return a new initialized PtrState describing the top down
/// state for Arg if we do not find one. /// state for Arg if we do not find one.
PtrState &getPtrTopDownState(const Value *Arg) { TopDownPtrState &getPtrTopDownState(const Value *Arg) {
return PerPtrTopDown[Arg]; return PerPtrTopDown[Arg];
} }
/// Attempt to find the PtrState object describing the bottom up state for /// Attempt to find the PtrState object describing the bottom up state for
/// pointer Arg. Return a new initialized PtrState describing the bottom up /// pointer Arg. Return a new initialized PtrState describing the bottom up
/// state for Arg if we do not find one. /// state for Arg if we do not find one.
PtrState &getPtrBottomUpState(const Value *Arg) { BottomUpPtrState &getPtrBottomUpState(const Value *Arg) {
return PerPtrBottomUp[Arg]; return PerPtrBottomUp[Arg];
} }
/// Attempt to find the PtrState object describing the bottom up state for /// Attempt to find the PtrState object describing the bottom up state for
/// pointer Arg. /// pointer Arg.
ptr_iterator findPtrBottomUpState(const Value *Arg) { bottom_up_ptr_iterator findPtrBottomUpState(const Value *Arg) {
return PerPtrBottomUp.find(Arg); return PerPtrBottomUp.find(Arg);
} }
@ -345,8 +349,8 @@ void BBState::MergePred(const BBState &Other) {
// entry. // entry.
for (auto MI = Other.top_down_ptr_begin(), ME = Other.top_down_ptr_end(); for (auto MI = Other.top_down_ptr_begin(), ME = Other.top_down_ptr_end();
MI != ME; ++MI) { MI != ME; ++MI) {
std::pair<ptr_iterator, bool> Pair = PerPtrTopDown.insert(*MI); auto Pair = PerPtrTopDown.insert(*MI);
Pair.first->second.Merge(Pair.second ? PtrState() : MI->second, Pair.first->second.Merge(Pair.second ? TopDownPtrState() : MI->second,
/*TopDown=*/true); /*TopDown=*/true);
} }
@ -354,7 +358,7 @@ void BBState::MergePred(const BBState &Other) {
// same key, force it to merge with an empty entry. // same key, force it to merge with an empty entry.
for (auto MI = top_down_ptr_begin(), ME = top_down_ptr_end(); MI != ME; ++MI) for (auto MI = top_down_ptr_begin(), ME = top_down_ptr_end(); MI != ME; ++MI)
if (Other.PerPtrTopDown.find(MI->first) == Other.PerPtrTopDown.end()) if (Other.PerPtrTopDown.find(MI->first) == Other.PerPtrTopDown.end())
MI->second.Merge(PtrState(), /*TopDown=*/true); MI->second.Merge(TopDownPtrState(), /*TopDown=*/true);
} }
/// The bottom-up traversal uses this to merge information about successors to /// The bottom-up traversal uses this to merge information about successors to
@ -388,8 +392,8 @@ void BBState::MergeSucc(const BBState &Other) {
// it with an empty entry. // it with an empty entry.
for (auto MI = Other.bottom_up_ptr_begin(), ME = Other.bottom_up_ptr_end(); for (auto MI = Other.bottom_up_ptr_begin(), ME = Other.bottom_up_ptr_end();
MI != ME; ++MI) { MI != ME; ++MI) {
std::pair<ptr_iterator, bool> Pair = PerPtrBottomUp.insert(*MI); auto Pair = PerPtrBottomUp.insert(*MI);
Pair.first->second.Merge(Pair.second ? PtrState() : MI->second, Pair.first->second.Merge(Pair.second ? BottomUpPtrState() : MI->second,
/*TopDown=*/false); /*TopDown=*/false);
} }
@ -398,7 +402,7 @@ void BBState::MergeSucc(const BBState &Other) {
for (auto MI = bottom_up_ptr_begin(), ME = bottom_up_ptr_end(); MI != ME; for (auto MI = bottom_up_ptr_begin(), ME = bottom_up_ptr_end(); MI != ME;
++MI) ++MI)
if (Other.PerPtrBottomUp.find(MI->first) == Other.PerPtrBottomUp.end()) if (Other.PerPtrBottomUp.find(MI->first) == Other.PerPtrBottomUp.end())
MI->second.Merge(PtrState(), /*TopDown=*/false); MI->second.Merge(BottomUpPtrState(), /*TopDown=*/false);
} }
namespace { namespace {
@ -872,7 +876,7 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) {
/// no CFG hazards by checking the states of various bottom up pointers. /// no CFG hazards by checking the states of various bottom up pointers.
static void CheckForUseCFGHazard(const Sequence SuccSSeq, static void CheckForUseCFGHazard(const Sequence SuccSSeq,
const bool SuccSRRIKnownSafe, const bool SuccSRRIKnownSafe,
PtrState &S, TopDownPtrState &S,
bool &SomeSuccHasSame, bool &SomeSuccHasSame,
bool &AllSuccsHaveSame, bool &AllSuccsHaveSame,
bool &NotAllSeqEqualButKnownSafe, bool &NotAllSeqEqualButKnownSafe,
@ -910,7 +914,7 @@ static void CheckForUseCFGHazard(const Sequence SuccSSeq,
/// pointers. /// pointers.
static void CheckForCanReleaseCFGHazard(const Sequence SuccSSeq, static void CheckForCanReleaseCFGHazard(const Sequence SuccSSeq,
const bool SuccSRRIKnownSafe, const bool SuccSRRIKnownSafe,
PtrState &S, TopDownPtrState &S,
bool &SomeSuccHasSame, bool &SomeSuccHasSame,
bool &AllSuccsHaveSame, bool &AllSuccsHaveSame,
bool &NotAllSeqEqualButKnownSafe) { bool &NotAllSeqEqualButKnownSafe) {
@ -943,9 +947,9 @@ ObjCARCOpt::CheckForCFGHazards(const BasicBlock *BB,
BBState &MyStates) const { BBState &MyStates) const {
// If any top-down local-use or possible-dec has a succ which is earlier in // If any top-down local-use or possible-dec has a succ which is earlier in
// the sequence, forget it. // the sequence, forget it.
for (BBState::ptr_iterator I = MyStates.top_down_ptr_begin(), for (auto I = MyStates.top_down_ptr_begin(), E = MyStates.top_down_ptr_end();
E = MyStates.top_down_ptr_end(); I != E; ++I) { I != E; ++I) {
PtrState &S = I->second; TopDownPtrState &S = I->second;
const Sequence Seq = I->second.GetSeq(); const Sequence Seq = I->second.GetSeq();
// We only care about S_Retain, S_CanRelease, and S_Use. // We only care about S_Retain, S_CanRelease, and S_Use.
@ -971,7 +975,7 @@ ObjCARCOpt::CheckForCFGHazards(const BasicBlock *BB,
const DenseMap<const BasicBlock *, BBState>::iterator BBI = const DenseMap<const BasicBlock *, BBState>::iterator BBI =
BBStates.find(*SI); BBStates.find(*SI);
assert(BBI != BBStates.end()); assert(BBI != BBStates.end());
const PtrState &SuccS = BBI->second.getPtrBottomUpState(Arg); const BottomUpPtrState &SuccS = BBI->second.getPtrBottomUpState(Arg);
const Sequence SuccSSeq = SuccS.GetSeq(); const Sequence SuccSSeq = SuccS.GetSeq();
// If bottom up, the pointer is in an S_None state, clear the sequence // If bottom up, the pointer is in an S_None state, clear the sequence
@ -1043,7 +1047,7 @@ bool ObjCARCOpt::VisitInstructionBottomUp(
case ARCInstKind::Release: { case ARCInstKind::Release: {
Arg = GetArgRCIdentityRoot(Inst); Arg = GetArgRCIdentityRoot(Inst);
PtrState &S = MyStates.getPtrBottomUpState(Arg); BottomUpPtrState &S = MyStates.getPtrBottomUpState(Arg);
// If we see two releases in a row on the same pointer. If so, make // 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 // a note, and we'll cicle back to revisit it after we've
@ -1077,7 +1081,7 @@ bool ObjCARCOpt::VisitInstructionBottomUp(
case ARCInstKind::RetainRV: { case ARCInstKind::RetainRV: {
Arg = GetArgRCIdentityRoot(Inst); Arg = GetArgRCIdentityRoot(Inst);
PtrState &S = MyStates.getPtrBottomUpState(Arg); BottomUpPtrState &S = MyStates.getPtrBottomUpState(Arg);
S.SetKnownPositiveRefCount(); S.SetKnownPositiveRefCount();
Sequence OldSeq = S.GetSeq(); Sequence OldSeq = S.GetSeq();
@ -1130,8 +1134,8 @@ bool ObjCARCOpt::VisitInstructionBottomUp(
// both our retain and our release are KnownSafe. // both our retain and our release are KnownSafe.
if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) { if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) {
if (AreAnyUnderlyingObjectsAnAlloca(SI->getPointerOperand())) { if (AreAnyUnderlyingObjectsAnAlloca(SI->getPointerOperand())) {
BBState::ptr_iterator I = MyStates.findPtrBottomUpState( auto I = MyStates.findPtrBottomUpState(
GetRCIdentityRoot(SI->getValueOperand())); GetRCIdentityRoot(SI->getValueOperand()));
if (I != MyStates.bottom_up_ptr_end()) if (I != MyStates.bottom_up_ptr_end())
MultiOwnersSet.insert(I->first); MultiOwnersSet.insert(I->first);
} }
@ -1143,12 +1147,13 @@ bool ObjCARCOpt::VisitInstructionBottomUp(
// Consider any other possible effects of this instruction on each // Consider any other possible effects of this instruction on each
// pointer being tracked. // pointer being tracked.
for (BBState::ptr_iterator MI = MyStates.bottom_up_ptr_begin(), for (auto MI = MyStates.bottom_up_ptr_begin(),
ME = MyStates.bottom_up_ptr_end(); MI != ME; ++MI) { ME = MyStates.bottom_up_ptr_end();
MI != ME; ++MI) {
const Value *Ptr = MI->first; const Value *Ptr = MI->first;
if (Ptr == Arg) if (Ptr == Arg)
continue; // Handled above. continue; // Handled above.
PtrState &S = MI->second; BottomUpPtrState &S = MI->second;
Sequence Seq = S.GetSeq(); Sequence Seq = S.GetSeq();
// Check for possible releases. // Check for possible releases.
@ -1290,7 +1295,7 @@ ObjCARCOpt::VisitInstructionTopDown(Instruction *Inst,
case ARCInstKind::RetainRV: { case ARCInstKind::RetainRV: {
Arg = GetArgRCIdentityRoot(Inst); Arg = GetArgRCIdentityRoot(Inst);
PtrState &S = MyStates.getPtrTopDownState(Arg); TopDownPtrState &S = MyStates.getPtrTopDownState(Arg);
// Don't do retain+release tracking for ARCInstKind::RetainRV, because // Don't do retain+release tracking for ARCInstKind::RetainRV, because
// it's // it's
@ -1320,7 +1325,7 @@ ObjCARCOpt::VisitInstructionTopDown(Instruction *Inst,
case ARCInstKind::Release: { case ARCInstKind::Release: {
Arg = GetArgRCIdentityRoot(Inst); Arg = GetArgRCIdentityRoot(Inst);
PtrState &S = MyStates.getPtrTopDownState(Arg); TopDownPtrState &S = MyStates.getPtrTopDownState(Arg);
S.ClearKnownPositiveRefCount(); S.ClearKnownPositiveRefCount();
Sequence OldSeq = S.GetSeq(); Sequence OldSeq = S.GetSeq();
@ -1363,12 +1368,13 @@ ObjCARCOpt::VisitInstructionTopDown(Instruction *Inst,
// Consider any other possible effects of this instruction on each // Consider any other possible effects of this instruction on each
// pointer being tracked. // pointer being tracked.
for (BBState::ptr_iterator MI = MyStates.top_down_ptr_begin(), for (auto MI = MyStates.top_down_ptr_begin(),
ME = MyStates.top_down_ptr_end(); MI != ME; ++MI) { ME = MyStates.top_down_ptr_end();
MI != ME; ++MI) {
const Value *Ptr = MI->first; const Value *Ptr = MI->first;
if (Ptr == Arg) if (Ptr == Arg)
continue; // Handled above. continue; // Handled above.
PtrState &S = MI->second; TopDownPtrState &S = MI->second;
Sequence Seq = S.GetSeq(); Sequence Seq = S.GetSeq();
// Check for possible releases. // Check for possible releases.

View File

@ -94,6 +94,7 @@ struct RRInfo {
/// \brief This class summarizes several per-pointer runtime properties which /// \brief This class summarizes several per-pointer runtime properties which
/// are propogated through the flow graph. /// are propogated through the flow graph.
class PtrState { class PtrState {
protected:
/// True if the reference count is known to be incremented. /// True if the reference count is known to be incremented.
bool KnownPositiveRefCount; bool KnownPositiveRefCount;
@ -107,9 +108,9 @@ class PtrState {
/// Unidirectional information about the current sequence. /// Unidirectional information about the current sequence.
RRInfo RRI; RRInfo RRI;
public:
PtrState() : KnownPositiveRefCount(false), Partial(false), Seq(S_None) {} PtrState() : KnownPositiveRefCount(false), Partial(false), Seq(S_None) {}
public:
bool IsKnownSafe() const { return RRI.KnownSafe; } bool IsKnownSafe() const { return RRI.KnownSafe; }
void SetKnownSafe(const bool NewValue) { RRI.KnownSafe = NewValue; } void SetKnownSafe(const bool NewValue) { RRI.KnownSafe = NewValue; }
@ -159,6 +160,16 @@ public:
const RRInfo &GetRRInfo() const { return RRI; } const RRInfo &GetRRInfo() const { return RRI; }
}; };
/// This is currently a stub.
struct BottomUpPtrState : PtrState {
BottomUpPtrState() : PtrState() {}
};
/// This is currently a stub.
struct TopDownPtrState : PtrState {
TopDownPtrState() : PtrState() {}
};
} // end namespace objcarc } // end namespace objcarc
} // end namespace llvm } // end namespace llvm