Simplify the known retain count tracking; use a boolean state instead

of a precise count. Also, move RRInfo's Partial field into PtrState,
now that it won't increase the size.

llvm-svn: 155513
This commit is contained in:
Dan Gohman 2012-04-25 00:50:46 +00:00
parent 3a24d34041
commit 64171a0b3b

View File

@ -1361,12 +1361,6 @@ namespace {
/// with the "tail" keyword. /// with the "tail" keyword.
bool IsTailCallRelease; bool IsTailCallRelease;
/// Partial - True of we've seen an opportunity for partial RR elimination,
/// such as pushing calls into a CFG triangle or into one side of a
/// CFG diamond.
/// TODO: Consider moving this to PtrState.
bool Partial;
/// ReleaseMetadata - If the Calls are objc_release calls and they all have /// ReleaseMetadata - If the Calls are objc_release calls and they all have
/// a clang.imprecise_release tag, this is the metadata tag. /// a clang.imprecise_release tag, this is the metadata tag.
MDNode *ReleaseMetadata; MDNode *ReleaseMetadata;
@ -1381,7 +1375,7 @@ namespace {
RRInfo() : RRInfo() :
KnownSafe(false), IsRetainBlock(false), KnownSafe(false), IsRetainBlock(false),
IsTailCallRelease(false), Partial(false), IsTailCallRelease(false),
ReleaseMetadata(0) {} ReleaseMetadata(0) {}
void clear(); void clear();
@ -1392,7 +1386,6 @@ void RRInfo::clear() {
KnownSafe = false; KnownSafe = false;
IsRetainBlock = false; IsRetainBlock = false;
IsTailCallRelease = false; IsTailCallRelease = false;
Partial = false;
ReleaseMetadata = 0; ReleaseMetadata = 0;
Calls.clear(); Calls.clear();
ReverseInsertPts.clear(); ReverseInsertPts.clear();
@ -1402,8 +1395,14 @@ namespace {
/// PtrState - This class summarizes several per-pointer runtime properties /// PtrState - This class summarizes several per-pointer runtime properties
/// which are propogated through the flow graph. /// which are propogated through the flow graph.
class PtrState { class PtrState {
/// RefCount - The known minimum number of reference count increments. /// KnownPositiveRefCount - True if the reference count is known to
unsigned RefCount; /// be incremented.
bool KnownPositiveRefCount;
/// Partial - True of we've seen an opportunity for partial RR elimination,
/// such as pushing calls into a CFG triangle or into one side of a
/// CFG diamond.
bool Partial;
/// NestCount - The known minimum level of retain+release nesting. /// NestCount - The known minimum level of retain+release nesting.
unsigned NestCount; unsigned NestCount;
@ -1416,22 +1415,19 @@ namespace {
/// TODO: Encapsulate this better. /// TODO: Encapsulate this better.
RRInfo RRI; RRInfo RRI;
PtrState() : RefCount(0), NestCount(0), Seq(S_None) {} PtrState() : KnownPositiveRefCount(false), Partial(false),
NestCount(0), Seq(S_None) {}
void SetAtLeastOneRefCount() { void SetKnownPositiveRefCount() {
if (RefCount == 0) RefCount = 1; KnownPositiveRefCount = true;
} }
void IncrementRefCount() { void ClearRefCount() {
if (RefCount != UINT_MAX) ++RefCount; KnownPositiveRefCount = false;
}
void DecrementRefCount() {
if (RefCount != 0) --RefCount;
} }
bool IsKnownIncremented() const { bool IsKnownIncremented() const {
return RefCount > 0; return KnownPositiveRefCount;
} }
void IncrementNestCount() { void IncrementNestCount() {
@ -1455,7 +1451,12 @@ namespace {
} }
void ClearSequenceProgress() { void ClearSequenceProgress() {
Seq = S_None; ResetSequenceProgress(S_None);
}
void ResetSequenceProgress(Sequence NewSeq) {
Seq = NewSeq;
Partial = false;
RRI.clear(); RRI.clear();
} }
@ -1466,7 +1467,7 @@ namespace {
void void
PtrState::Merge(const PtrState &Other, bool TopDown) { PtrState::Merge(const PtrState &Other, bool TopDown) {
Seq = MergeSeqs(Seq, Other.Seq, TopDown); Seq = MergeSeqs(Seq, Other.Seq, TopDown);
RefCount = std::min(RefCount, Other.RefCount); KnownPositiveRefCount = KnownPositiveRefCount && Other.KnownPositiveRefCount;
NestCount = std::min(NestCount, Other.NestCount); NestCount = std::min(NestCount, Other.NestCount);
// We can't merge a plain objc_retain with an objc_retainBlock. // We can't merge a plain objc_retain with an objc_retainBlock.
@ -1475,14 +1476,14 @@ PtrState::Merge(const PtrState &Other, bool TopDown) {
// If we're not in a sequence (anymore), drop all associated state. // If we're not in a sequence (anymore), drop all associated state.
if (Seq == S_None) { if (Seq == S_None) {
Partial = false;
RRI.clear(); RRI.clear();
} else if (RRI.Partial || Other.RRI.Partial) { } else if (Partial || Other.Partial) {
// If we're doing a merge on a path that's previously seen a partial // If we're doing a merge on a path that's previously seen a partial
// merge, conservatively drop the sequence, to avoid doing partial // merge, conservatively drop the sequence, to avoid doing partial
// RR elimination. If the branch predicates for the two merge differ, // RR elimination. If the branch predicates for the two merge differ,
// mixing them is unsafe. // mixing them is unsafe.
Seq = S_None; ClearSequenceProgress();
RRI.clear();
} else { } else {
// Conservatively merge the ReleaseMetadata information. // Conservatively merge the ReleaseMetadata information.
if (RRI.ReleaseMetadata != Other.RRI.ReleaseMetadata) if (RRI.ReleaseMetadata != Other.RRI.ReleaseMetadata)
@ -1494,12 +1495,12 @@ PtrState::Merge(const PtrState &Other, bool TopDown) {
// Merge the insert point sets. If there are any differences, // Merge the insert point sets. If there are any differences,
// that makes this a partial merge. // that makes this a partial merge.
RRI.Partial = RRI.ReverseInsertPts.size() != Partial = RRI.ReverseInsertPts.size() !=
Other.RRI.ReverseInsertPts.size(); Other.RRI.ReverseInsertPts.size();
for (SmallPtrSet<Instruction *, 2>::const_iterator for (SmallPtrSet<Instruction *, 2>::const_iterator
I = Other.RRI.ReverseInsertPts.begin(), I = Other.RRI.ReverseInsertPts.begin(),
E = Other.RRI.ReverseInsertPts.end(); I != E; ++I) E = Other.RRI.ReverseInsertPts.end(); I != E; ++I)
RRI.Partial |= RRI.ReverseInsertPts.insert(*I); Partial |= RRI.ReverseInsertPts.insert(*I);
} }
} }
@ -2634,16 +2635,13 @@ ObjCARCOpt::VisitInstructionBottomUp(Instruction *Inst,
if (S.GetSeq() == S_Release || S.GetSeq() == S_MovableRelease) if (S.GetSeq() == S_Release || S.GetSeq() == S_MovableRelease)
NestingDetected = true; NestingDetected = true;
S.RRI.clear();
MDNode *ReleaseMetadata = Inst->getMetadata(ImpreciseReleaseMDKind); MDNode *ReleaseMetadata = Inst->getMetadata(ImpreciseReleaseMDKind);
S.SetSeq(ReleaseMetadata ? S_MovableRelease : S_Release); S.ResetSequenceProgress(ReleaseMetadata ? S_MovableRelease : S_Release);
S.RRI.ReleaseMetadata = ReleaseMetadata; S.RRI.ReleaseMetadata = ReleaseMetadata;
S.RRI.KnownSafe = S.IsKnownNested() || S.IsKnownIncremented(); S.RRI.KnownSafe = S.IsKnownNested() || S.IsKnownIncremented();
S.RRI.IsTailCallRelease = cast<CallInst>(Inst)->isTailCall(); S.RRI.IsTailCallRelease = cast<CallInst>(Inst)->isTailCall();
S.RRI.Calls.insert(Inst); S.RRI.Calls.insert(Inst);
S.IncrementRefCount();
S.IncrementNestCount(); S.IncrementNestCount();
break; break;
} }
@ -2658,8 +2656,7 @@ ObjCARCOpt::VisitInstructionBottomUp(Instruction *Inst,
Arg = GetObjCArg(Inst); Arg = GetObjCArg(Inst);
PtrState &S = MyStates.getPtrBottomUpState(Arg); PtrState &S = MyStates.getPtrBottomUpState(Arg);
S.DecrementRefCount(); S.SetKnownPositiveRefCount();
S.SetAtLeastOneRefCount();
S.DecrementNestCount(); S.DecrementNestCount();
switch (S.GetSeq()) { switch (S.GetSeq()) {
@ -2709,7 +2706,7 @@ ObjCARCOpt::VisitInstructionBottomUp(Instruction *Inst,
// Check for possible releases. // Check for possible releases.
if (CanAlterRefCount(Inst, Ptr, PA, Class)) { if (CanAlterRefCount(Inst, Ptr, PA, Class)) {
S.DecrementRefCount(); S.ClearRefCount();
switch (Seq) { switch (Seq) {
case S_Use: case S_Use:
S.SetSeq(S_CanRelease); S.SetSeq(S_CanRelease);
@ -2852,8 +2849,7 @@ ObjCARCOpt::VisitInstructionTopDown(Instruction *Inst,
if (S.GetSeq() == S_Retain) if (S.GetSeq() == S_Retain)
NestingDetected = true; NestingDetected = true;
S.SetSeq(S_Retain); S.ResetSequenceProgress(S_Retain);
S.RRI.clear();
S.RRI.IsRetainBlock = Class == IC_RetainBlock; S.RRI.IsRetainBlock = Class == IC_RetainBlock;
// Don't check S.IsKnownIncremented() here because it's not // Don't check S.IsKnownIncremented() here because it's not
// sufficient. // sufficient.
@ -2861,8 +2857,6 @@ ObjCARCOpt::VisitInstructionTopDown(Instruction *Inst,
S.RRI.Calls.insert(Inst); S.RRI.Calls.insert(Inst);
} }
S.SetAtLeastOneRefCount();
S.IncrementRefCount();
S.IncrementNestCount(); S.IncrementNestCount();
return NestingDetected; return NestingDetected;
} }
@ -2870,7 +2864,6 @@ ObjCARCOpt::VisitInstructionTopDown(Instruction *Inst,
Arg = GetObjCArg(Inst); Arg = GetObjCArg(Inst);
PtrState &S = MyStates.getPtrTopDownState(Arg); PtrState &S = MyStates.getPtrTopDownState(Arg);
S.DecrementRefCount();
S.DecrementNestCount(); S.DecrementNestCount();
switch (S.GetSeq()) { switch (S.GetSeq()) {
@ -2917,7 +2910,7 @@ ObjCARCOpt::VisitInstructionTopDown(Instruction *Inst,
// Check for possible releases. // Check for possible releases.
if (CanAlterRefCount(Inst, Ptr, PA, Class)) { if (CanAlterRefCount(Inst, Ptr, PA, Class)) {
S.DecrementRefCount(); S.ClearRefCount();
switch (Seq) { switch (Seq) {
case S_Retain: case S_Retain:
S.SetSeq(S_CanRelease); S.SetSeq(S_CanRelease);