[objc-arc] Move the checking of whether or not we can match onto PtrStates and out of the main dataflow.

These refactored computations check whether or not we are at a stage
of the sequence where we can perform a match. This patch moves the
computation out of the main dataflow and into
{BottomUp,TopDown}PtrState.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@231439 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Michael Gottesman 2015-03-06 00:34:42 +00:00
parent f111a2a5f1
commit b207e98e20
3 changed files with 76 additions and 51 deletions

View File

@ -1059,33 +1059,13 @@ bool ObjCARCOpt::VisitInstructionBottomUp(
case ARCInstKind::Retain: case ARCInstKind::Retain:
case ARCInstKind::RetainRV: { case ARCInstKind::RetainRV: {
Arg = GetArgRCIdentityRoot(Inst); Arg = GetArgRCIdentityRoot(Inst);
BottomUpPtrState &S = MyStates.getPtrBottomUpState(Arg); BottomUpPtrState &S = MyStates.getPtrBottomUpState(Arg);
S.SetKnownPositiveRefCount(); if (S.MatchWithRetain()) {
// Don't do retain+release tracking for ARCInstKind::RetainRV, because
Sequence OldSeq = S.GetSeq(); // it's better to let it remain as the first instruction after a call.
switch (OldSeq) {
case S_Stop:
case S_Release:
case S_MovableRelease:
case S_Use:
// If OldSeq is not S_Use or OldSeq is S_Use and we are tracking an
// imprecise release, clear our reverse insertion points.
if (OldSeq != S_Use || S.IsTrackingImpreciseReleases())
S.ClearReverseInsertPts();
// FALL THROUGH
case S_CanRelease:
// Don't do retain+release tracking for ARCInstKind::RetainRV,
// because it's
// better to let it remain as the first instruction after a call.
if (Class != ARCInstKind::RetainRV) if (Class != ARCInstKind::RetainRV)
Retains[Inst] = S.GetRRInfo(); Retains[Inst] = S.GetRRInfo();
S.ClearSequenceProgress(); S.ClearSequenceProgress();
break;
case S_None:
break;
case S_Retain:
llvm_unreachable("bottom-up pointer in retain state!");
} }
// A retain moving bottom up can be a use. // A retain moving bottom up can be a use.
break; break;
@ -1268,7 +1248,8 @@ ObjCARCOpt::VisitInstructionTopDown(Instruction *Inst,
case ARCInstKind::RetainBlock: case ARCInstKind::RetainBlock:
// In OptimizeIndividualCalls, we have strength reduced all optimizable // In OptimizeIndividualCalls, we have strength reduced all optimizable
// objc_retainBlocks to objc_retains. Thus at this point any // objc_retainBlocks to objc_retains. Thus at this point any
// objc_retainBlocks that we see are not optimizable. // objc_retainBlocks that we see are not optimizable. We need to break since
// a retain can be a potential use.
break; break;
case ARCInstKind::Retain: case ARCInstKind::Retain:
case ARCInstKind::RetainRV: { case ARCInstKind::RetainRV: {
@ -1281,44 +1262,25 @@ ObjCARCOpt::VisitInstructionTopDown(Instruction *Inst,
} }
case ARCInstKind::Release: { case ARCInstKind::Release: {
Arg = GetArgRCIdentityRoot(Inst); Arg = GetArgRCIdentityRoot(Inst);
TopDownPtrState &S = MyStates.getPtrTopDownState(Arg); TopDownPtrState &S = MyStates.getPtrTopDownState(Arg);
S.ClearKnownPositiveRefCount(); // Try to form a tentative pair in between this release instruction and the
// top down pointers that we are tracking.
Sequence OldSeq = S.GetSeq(); if (S.MatchWithRelease(MDKindCache, Inst)) {
// If we succeed, copy S's RRInfo into the Release -> {Retain Set
MDNode *ReleaseMetadata = // Map}. Then we clear S.
Inst->getMetadata(MDKindCache.ImpreciseReleaseMDKind);
switch (OldSeq) {
case S_Retain:
case S_CanRelease:
if (OldSeq == S_Retain || ReleaseMetadata != nullptr)
S.ClearReverseInsertPts();
// FALL THROUGH
case S_Use:
S.SetReleaseMetadata(ReleaseMetadata);
S.SetTailCallRelease(cast<CallInst>(Inst)->isTailCall());
Releases[Inst] = S.GetRRInfo(); Releases[Inst] = S.GetRRInfo();
S.ClearSequenceProgress(); S.ClearSequenceProgress();
break;
case S_None:
break;
case S_Stop:
case S_Release:
case S_MovableRelease:
llvm_unreachable("top-down pointer in release state!");
} }
break; break;
} }
case ARCInstKind::AutoreleasepoolPop: case ARCInstKind::AutoreleasepoolPop:
// Conservatively, clear MyStates for all known pointers. // Conservatively, clear MyStates for all known pointers.
MyStates.clearTopDownPointers(); MyStates.clearTopDownPointers();
return NestingDetected; return false;
case ARCInstKind::AutoreleasepoolPush: case ARCInstKind::AutoreleasepoolPush:
case ARCInstKind::None: case ARCInstKind::None:
// These are irrelevant. // These can not be uses of
return NestingDetected; return false;
default: default:
break; break;
} }

View File

@ -164,6 +164,29 @@ bool BottomUpPtrState::InitBottomUp(ARCMDKindCache &Cache, Instruction *I) {
return NestingDetected; return NestingDetected;
} }
bool BottomUpPtrState::MatchWithRetain() {
SetKnownPositiveRefCount();
Sequence OldSeq = GetSeq();
switch (OldSeq) {
case S_Stop:
case S_Release:
case S_MovableRelease:
case S_Use:
// If OldSeq is not S_Use or OldSeq is S_Use and we are tracking an
// imprecise release, clear our reverse insertion points.
if (OldSeq != S_Use || IsTrackingImpreciseReleases())
ClearReverseInsertPts();
// FALL THROUGH
case S_CanRelease:
return true;
case S_None:
return false;
case S_Retain:
llvm_unreachable("bottom-up pointer in retain state!");
}
}
bool TopDownPtrState::InitTopDown(ARCInstKind Kind, Instruction *I) { bool TopDownPtrState::InitTopDown(ARCInstKind Kind, Instruction *I) {
bool NestingDetected = false; bool NestingDetected = false;
// Don't do retain+release tracking for ARCInstKind::RetainRV, because // Don't do retain+release tracking for ARCInstKind::RetainRV, because
@ -188,3 +211,30 @@ bool TopDownPtrState::InitTopDown(ARCInstKind Kind, Instruction *I) {
SetKnownPositiveRefCount(); SetKnownPositiveRefCount();
return NestingDetected; return NestingDetected;
} }
bool TopDownPtrState::MatchWithRelease(ARCMDKindCache &Cache,
Instruction *Release) {
ClearKnownPositiveRefCount();
Sequence OldSeq = GetSeq();
MDNode *ReleaseMetadata = Release->getMetadata(Cache.ImpreciseReleaseMDKind);
switch (OldSeq) {
case S_Retain:
case S_CanRelease:
if (OldSeq == S_Retain || ReleaseMetadata != nullptr)
ClearReverseInsertPts();
// FALL THROUGH
case S_Use:
SetReleaseMetadata(ReleaseMetadata);
SetTailCallRelease(cast<CallInst>(Release)->isTailCall());
return true;
case S_None:
return false;
case S_Stop:
case S_Release:
case S_MovableRelease:
llvm_unreachable("top-down pointer in bottom up state!");
}
}

View File

@ -169,6 +169,14 @@ struct BottomUpPtrState : PtrState {
/// (Re-)Initialize this bottom up pointer returning true if we detected a /// (Re-)Initialize this bottom up pointer returning true if we detected a
/// pointer with nested releases. /// pointer with nested releases.
bool InitBottomUp(ARCMDKindCache &Cache, Instruction *I); bool InitBottomUp(ARCMDKindCache &Cache, Instruction *I);
/// Return true if this set of releases can be paired with a release. Modifies
/// state appropriately to reflect that the matching occured if it is
/// successful.
///
/// 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();
}; };
struct TopDownPtrState : PtrState { struct TopDownPtrState : PtrState {
@ -177,6 +185,11 @@ struct TopDownPtrState : PtrState {
/// (Re-)Initialize this bottom up pointer returning true if we detected a /// (Re-)Initialize this bottom up pointer returning true if we detected a
/// pointer with nested releases. /// pointer with nested releases.
bool InitTopDown(ARCInstKind Kind, Instruction *I); bool InitTopDown(ARCInstKind Kind, Instruction *I);
/// Return true if this set of retains can be paired with the given
/// release. Modifies state appropriately to reflect that the matching
/// occured.
bool MatchWithRelease(ARCMDKindCache &Cache, Instruction *Release);
}; };
} // end namespace objcarc } // end namespace objcarc