[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::RetainRV: {
Arg = GetArgRCIdentityRoot(Inst);
BottomUpPtrState &S = MyStates.getPtrBottomUpState(Arg);
S.SetKnownPositiveRefCount();
Sequence OldSeq = S.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 || 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 (S.MatchWithRetain()) {
// 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)
Retains[Inst] = S.GetRRInfo();
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.
break;
@ -1268,7 +1248,8 @@ ObjCARCOpt::VisitInstructionTopDown(Instruction *Inst,
case ARCInstKind::RetainBlock:
// In OptimizeIndividualCalls, we have strength reduced all optimizable
// 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;
case ARCInstKind::Retain:
case ARCInstKind::RetainRV: {
@ -1281,44 +1262,25 @@ ObjCARCOpt::VisitInstructionTopDown(Instruction *Inst,
}
case ARCInstKind::Release: {
Arg = GetArgRCIdentityRoot(Inst);
TopDownPtrState &S = MyStates.getPtrTopDownState(Arg);
S.ClearKnownPositiveRefCount();
Sequence OldSeq = S.GetSeq();
MDNode *ReleaseMetadata =
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());
// Try to form a tentative pair in between this release instruction and the
// top down pointers that we are tracking.
if (S.MatchWithRelease(MDKindCache, Inst)) {
// If we succeed, copy S's RRInfo into the Release -> {Retain Set
// Map}. Then we clear S.
Releases[Inst] = S.GetRRInfo();
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;
}
case ARCInstKind::AutoreleasepoolPop:
// Conservatively, clear MyStates for all known pointers.
MyStates.clearTopDownPointers();
return NestingDetected;
return false;
case ARCInstKind::AutoreleasepoolPush:
case ARCInstKind::None:
// These are irrelevant.
return NestingDetected;
// These can not be uses of
return false;
default:
break;
}

View File

@ -164,6 +164,29 @@ bool BottomUpPtrState::InitBottomUp(ARCMDKindCache &Cache, Instruction *I) {
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 NestingDetected = false;
// Don't do retain+release tracking for ARCInstKind::RetainRV, because
@ -188,3 +211,30 @@ bool TopDownPtrState::InitTopDown(ARCInstKind Kind, Instruction *I) {
SetKnownPositiveRefCount();
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
/// pointer with nested releases.
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 {
@ -177,6 +185,11 @@ struct TopDownPtrState : PtrState {
/// (Re-)Initialize this bottom up pointer returning true if we detected a
/// pointer with nested releases.
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