[objc-arc] Track if we encountered an additive overflow while computing {TopDown,BottomUp}PathCounts and do nothing if it occurred.

I fixed the aforementioned problems that came up on some of the linux boxes.
Major thanks to Nick Lewycky for his help debugging!

rdar://14590914

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@188122 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Michael Gottesman 2013-08-09 23:22:27 +00:00
parent 835738ce54
commit 3ed7576a3b
2 changed files with 1116 additions and 11 deletions

View File

@ -674,7 +674,9 @@ namespace {
SmallVector<BasicBlock *, 2> Succs; SmallVector<BasicBlock *, 2> Succs;
public: public:
BBState() : TopDownPathCount(0), BottomUpPathCount(0) {} static const unsigned OverflowOccurredValue;
BBState() : TopDownPathCount(0), BottomUpPathCount(0) { }
typedef MapTy::iterator ptr_iterator; typedef MapTy::iterator ptr_iterator;
typedef MapTy::const_iterator ptr_const_iterator; typedef MapTy::const_iterator ptr_const_iterator;
@ -745,13 +747,15 @@ namespace {
/// Returns true if overflow occured. Returns false if overflow did not /// Returns true if overflow occured. Returns false if overflow did not
/// occur. /// occur.
bool GetAllPathCountWithOverflow(unsigned &PathCount) const { bool GetAllPathCountWithOverflow(unsigned &PathCount) const {
assert(TopDownPathCount != 0); if (TopDownPathCount == OverflowOccurredValue ||
assert(BottomUpPathCount != 0); BottomUpPathCount == OverflowOccurredValue)
return true;
unsigned long long Product = unsigned long long Product =
(unsigned long long)TopDownPathCount*BottomUpPathCount; (unsigned long long)TopDownPathCount*BottomUpPathCount;
PathCount = Product; // Overflow occured if any of the upper bits of Product are set or if all
// Overflow occured if any of the upper bits of Product are set. // the lower bits of Product are all set.
return Product >> 32; return (Product >> 32) ||
((PathCount = Product) == OverflowOccurredValue);
} }
// Specialized CFG utilities. // Specialized CFG utilities.
@ -766,6 +770,8 @@ namespace {
bool isExit() const { return Succs.empty(); } bool isExit() const { return Succs.empty(); }
}; };
const unsigned BBState::OverflowOccurredValue = 0xffffffff;
} }
void BBState::InitFromPred(const BBState &Other) { void BBState::InitFromPred(const BBState &Other) {
@ -781,13 +787,25 @@ void BBState::InitFromSucc(const BBState &Other) {
/// The top-down traversal uses this to merge information about predecessors to /// The top-down traversal uses this to merge information about predecessors to
/// form the initial state for a new block. /// form the initial state for a new block.
void BBState::MergePred(const BBState &Other) { void BBState::MergePred(const BBState &Other) {
if (TopDownPathCount == OverflowOccurredValue)
return;
// Other.TopDownPathCount can be 0, in which case it is either dead or a // Other.TopDownPathCount can be 0, in which case it is either dead or a
// loop backedge. Loop backedges are special. // loop backedge. Loop backedges are special.
TopDownPathCount += Other.TopDownPathCount; TopDownPathCount += Other.TopDownPathCount;
// In order to be consistent, we clear the top down pointers when by adding
// TopDownPathCount becomes OverflowOccurredValue even though "true" overflow
// has not occured.
if (TopDownPathCount == OverflowOccurredValue) {
clearTopDownPointers();
return;
}
// Check for overflow. If we have overflow, fall back to conservative // Check for overflow. If we have overflow, fall back to conservative
// behavior. // behavior.
if (TopDownPathCount < Other.TopDownPathCount) { if (TopDownPathCount < Other.TopDownPathCount) {
TopDownPathCount = OverflowOccurredValue;
clearTopDownPointers(); clearTopDownPointers();
return; return;
} }
@ -813,13 +831,25 @@ void BBState::MergePred(const BBState &Other) {
/// The bottom-up traversal uses this to merge information about successors to /// The bottom-up traversal uses this to merge information about successors to
/// form the initial state for a new block. /// form the initial state for a new block.
void BBState::MergeSucc(const BBState &Other) { void BBState::MergeSucc(const BBState &Other) {
if (BottomUpPathCount == OverflowOccurredValue)
return;
// Other.BottomUpPathCount can be 0, in which case it is either dead or a // Other.BottomUpPathCount can be 0, in which case it is either dead or a
// loop backedge. Loop backedges are special. // loop backedge. Loop backedges are special.
BottomUpPathCount += Other.BottomUpPathCount; BottomUpPathCount += Other.BottomUpPathCount;
// In order to be consistent, we clear the top down pointers when by adding
// BottomUpPathCount becomes OverflowOccurredValue even though "true" overflow
// has not occured.
if (BottomUpPathCount == OverflowOccurredValue) {
clearBottomUpPointers();
return;
}
// Check for overflow. If we have overflow, fall back to conservative // Check for overflow. If we have overflow, fall back to conservative
// behavior. // behavior.
if (BottomUpPathCount < Other.BottomUpPathCount) { if (BottomUpPathCount < Other.BottomUpPathCount) {
BottomUpPathCount = OverflowOccurredValue;
clearBottomUpPointers(); clearBottomUpPointers();
return; return;
} }
@ -2526,9 +2556,12 @@ ObjCARCOpt::ConnectTDBUTraversals(DenseMap<const BasicBlock *, BBState>
// If we overflow when we compute the path count, don't remove/move // If we overflow when we compute the path count, don't remove/move
// anything. // anything.
const BBState &NRRBBState = BBStates[NewRetainRelease->getParent()]; const BBState &NRRBBState = BBStates[NewRetainRelease->getParent()];
unsigned PathCount; unsigned PathCount = BBState::OverflowOccurredValue;
if (NRRBBState.GetAllPathCountWithOverflow(PathCount)) if (NRRBBState.GetAllPathCountWithOverflow(PathCount))
return false; return false;
assert(PathCount != BBState::OverflowOccurredValue &&
"PathCount at this point can not be "
"OverflowOccurredValue.");
OldDelta -= PathCount; OldDelta -= PathCount;
// Merge the ReleaseMetadata and IsTailCallRelease values. // Merge the ReleaseMetadata and IsTailCallRelease values.
@ -2558,8 +2591,12 @@ ObjCARCOpt::ConnectTDBUTraversals(DenseMap<const BasicBlock *, BBState>
// If we overflow when we compute the path count, don't // If we overflow when we compute the path count, don't
// remove/move anything. // remove/move anything.
const BBState &RIPBBState = BBStates[RIP->getParent()]; const BBState &RIPBBState = BBStates[RIP->getParent()];
PathCount = BBState::OverflowOccurredValue;
if (RIPBBState.GetAllPathCountWithOverflow(PathCount)) if (RIPBBState.GetAllPathCountWithOverflow(PathCount))
return false; return false;
assert(PathCount != BBState::OverflowOccurredValue &&
"PathCount at this point can not be "
"OverflowOccurredValue.");
NewDelta -= PathCount; NewDelta -= PathCount;
} }
} }
@ -2595,9 +2632,12 @@ ObjCARCOpt::ConnectTDBUTraversals(DenseMap<const BasicBlock *, BBState>
// If we overflow when we compute the path count, don't remove/move // If we overflow when we compute the path count, don't remove/move
// anything. // anything.
const BBState &NRRBBState = BBStates[NewReleaseRetain->getParent()]; const BBState &NRRBBState = BBStates[NewReleaseRetain->getParent()];
unsigned PathCount; unsigned PathCount = BBState::OverflowOccurredValue;
if (NRRBBState.GetAllPathCountWithOverflow(PathCount)) if (NRRBBState.GetAllPathCountWithOverflow(PathCount))
return false; return false;
assert(PathCount != BBState::OverflowOccurredValue &&
"PathCount at this point can not be "
"OverflowOccurredValue.");
OldDelta += PathCount; OldDelta += PathCount;
OldCount += PathCount; OldCount += PathCount;
@ -2612,8 +2652,13 @@ ObjCARCOpt::ConnectTDBUTraversals(DenseMap<const BasicBlock *, BBState>
// If we overflow when we compute the path count, don't // If we overflow when we compute the path count, don't
// remove/move anything. // remove/move anything.
const BBState &RIPBBState = BBStates[RIP->getParent()]; const BBState &RIPBBState = BBStates[RIP->getParent()];
PathCount = BBState::OverflowOccurredValue;
if (RIPBBState.GetAllPathCountWithOverflow(PathCount)) if (RIPBBState.GetAllPathCountWithOverflow(PathCount))
return false; return false;
assert(PathCount != BBState::OverflowOccurredValue &&
"PathCount at this point can not be "
"OverflowOccurredValue.");
NewDelta += PathCount; NewDelta += PathCount;
NewCount += PathCount; NewCount += PathCount;
} }

File diff suppressed because it is too large Load Diff