mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[g-arc-opts] Move any non-trivial non-templated code from RefCountState.h => RefCountState.cpp. NFC.
Swift SVN r27005
This commit is contained in:
@@ -74,57 +74,151 @@ MergeTopDownLatticeStates(TopDownRefCountState::LatticeState L1,
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Reference Count State Implementation
|
||||
// Bottom Up Ref Count State
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
bool TopDownRefCountState::merge(const TopDownRefCountState &Other) {
|
||||
auto NewState = MergeTopDownLatticeStates(LatState, Other.LatState);
|
||||
DEBUG(llvm::dbgs() << " Performing TopDown Merge.\n");
|
||||
DEBUG(llvm::dbgs() << " Left: " << LatState << "; Right: "
|
||||
<< Other.LatState << "; Result: " << NewState << "\n");
|
||||
DEBUG(llvm::dbgs() << " V: ";
|
||||
if (hasRCRoot())
|
||||
getRCRoot()->dump();
|
||||
else
|
||||
llvm::dbgs() << "\n";
|
||||
llvm::dbgs() << " OtherV: ";
|
||||
if (Other.hasRCRoot())
|
||||
Other.getRCRoot()->dump();
|
||||
else
|
||||
llvm::dbgs() << "\n");
|
||||
/// Initializes/reinitialized the state for I. If we reinitialize we return
|
||||
/// true.
|
||||
bool BottomUpRefCountState::initWithMutatorInst(SILInstruction *I) {
|
||||
assert((isa<StrongReleaseInst>(I) || isa<ReleaseValueInst>(I)) &&
|
||||
"strong_release and release_value are only supported.");
|
||||
|
||||
LatState = NewState;
|
||||
KnownSafe &= Other.KnownSafe;
|
||||
bool NestingDetected = SuperTy::initWithMutatorInst(I);
|
||||
|
||||
// If we're doing a merge on a path that's previously seen a partial merge,
|
||||
// conservatively drop the sequence, to avoid doing partial RR elimination. If
|
||||
// the branch predicates for the two merge differ, mixing them is unsafe since
|
||||
// they are not control dependent.
|
||||
//
|
||||
// TODO: Add support for determining control dependence.
|
||||
if (LatState == TopDownRefCountState::LatticeState::None) {
|
||||
clear();
|
||||
DEBUG(llvm::dbgs() << " Found LatticeState::None. "
|
||||
"Clearing State!\n");
|
||||
// If we know that there is another decrement on the same pointer that has
|
||||
// not been matched up to an increment, then the pointer must have a
|
||||
// reference count of at least 2 before this decrement. This implies it is
|
||||
// known safe.
|
||||
KnownSafe = NestingDetected;
|
||||
|
||||
// Set our lattice state to be incremented.
|
||||
LatState = LatticeState::Decremented;
|
||||
|
||||
return NestingDetected;
|
||||
}
|
||||
|
||||
/// Return true if we *might* remove this instruction.
|
||||
///
|
||||
/// This is a conservative query given the information we know, so as we
|
||||
/// perform the dataflow it may change value.
|
||||
bool BottomUpRefCountState::mightRemoveMutators() {
|
||||
if (LatState == LatticeState::None)
|
||||
return false;
|
||||
|
||||
// We will not remove mutators if we have a might be decremented value that
|
||||
// is not known safe.
|
||||
return LatState != LatticeState::MightBeDecremented || isKnownSafe();
|
||||
}
|
||||
|
||||
/// Uninitialize the current state.
|
||||
void BottomUpRefCountState::clear() {
|
||||
// If we can not conservatively prove that the given RefCountState will not
|
||||
// be removed, be conservative and clear the transition state, so we do not
|
||||
// propagate KnownSafety forward.
|
||||
if (mightRemoveMutators())
|
||||
Transition = None;
|
||||
LatState = LatticeState::None;
|
||||
SuperTy::clear();
|
||||
}
|
||||
|
||||
/// If advance the state's sequence appropriately for a decrement. If we do
|
||||
/// advance return true. Otherwise return false.
|
||||
bool BottomUpRefCountState::
|
||||
handleDecrement(SILInstruction *PotentialDecrement) {
|
||||
switch (LatState) {
|
||||
case LatticeState::MightBeUsed:
|
||||
LatState = LatticeState::MightBeDecremented;
|
||||
return true;
|
||||
case LatticeState::None:
|
||||
case LatticeState::MightBeDecremented:
|
||||
case LatticeState::Decremented:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Transition.hasValue() || !Other.Transition.hasValue() ||
|
||||
!Transition->merge(Other.Transition.getValue())) {
|
||||
DEBUG(llvm::dbgs() << " Failed merge!\n");
|
||||
clear();
|
||||
/// Given the current lattice state, if we have seen a use, advance the
|
||||
/// lattice state. Return true if we do so and false otherwise.
|
||||
bool
|
||||
BottomUpRefCountState::handleUser(SILInstruction *PotentialUser) {
|
||||
assert(valueCanBeUsedGivenLatticeState() &&
|
||||
"Must be able to be used at this point of the lattice.");
|
||||
// Advance the sequence...
|
||||
switch (LatState) {
|
||||
case LatticeState::Decremented:
|
||||
LatState = LatticeState::MightBeUsed;
|
||||
assert(InsertPts.empty() && "If we are decremented, we should have no "
|
||||
"insertion points.");
|
||||
InsertPts.insert(std::next(SILBasicBlock::iterator(PotentialUser)));
|
||||
return true;
|
||||
case LatticeState::MightBeUsed:
|
||||
case LatticeState::MightBeDecremented:
|
||||
case LatticeState::None:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Partial |= Other.Partial;
|
||||
Partial |= InsertPts.size() != Other.InsertPts.size();
|
||||
for (auto *SI : Other.InsertPts)
|
||||
Partial |= InsertPts.insert(SI).second;
|
||||
/// Returns true if given the current lattice state, do we care if the value
|
||||
/// we are tracking is used.
|
||||
bool BottomUpRefCountState::
|
||||
valueCanBeGuaranteedUsedGivenLatticeState() const {
|
||||
switch (LatState) {
|
||||
case LatticeState::None:
|
||||
case LatticeState::MightBeDecremented:
|
||||
return false;
|
||||
case LatticeState::Decremented:
|
||||
case LatticeState::MightBeUsed:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG(llvm::dbgs() << " Partial: " << (Partial ? "yes" : "no")
|
||||
<< "\n");
|
||||
/// Given the current lattice state, if we have seen a use, advance the
|
||||
/// lattice state. Return true if we do so and false otherwise.
|
||||
bool
|
||||
BottomUpRefCountState::
|
||||
handleGuaranteedUser(SILInstruction *PotentialGuaranteedUser) {
|
||||
assert(valueCanBeGuaranteedUsedGivenLatticeState() &&
|
||||
"Must be able to be used at this point of the lattice.");
|
||||
// Advance the sequence...
|
||||
switch (LatState) {
|
||||
// If were decremented, insert the insertion point.
|
||||
case LatticeState::Decremented: {
|
||||
assert(InsertPts.empty() && "If we are decremented, we should have no "
|
||||
"insertion points.");
|
||||
auto Iter = SILBasicBlock::iterator(PotentialGuaranteedUser);
|
||||
InsertPts.insert(std::next(Iter));
|
||||
LatState = LatticeState::MightBeDecremented;
|
||||
return true;
|
||||
}
|
||||
case LatticeState::MightBeUsed:
|
||||
// If we have a might be used, we already created an insertion point
|
||||
// earlier. Just move to MightBeDecremented.
|
||||
LatState = LatticeState::MightBeDecremented;
|
||||
return true;
|
||||
case LatticeState::MightBeDecremented:
|
||||
case LatticeState::None:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
/// We have a matching ref count inst. Return true if we advance the sequence
|
||||
/// and false otherwise.
|
||||
bool
|
||||
BottomUpRefCountState::
|
||||
handleRefCountInstMatch(SILInstruction *RefCountInst) {
|
||||
// Otherwise modify the state appropriately in preparation for removing the
|
||||
// increment, decrement pair.
|
||||
switch (LatState) {
|
||||
case LatticeState::None:
|
||||
return false;
|
||||
case LatticeState::Decremented:
|
||||
case LatticeState::MightBeUsed:
|
||||
// Unset InsertPt so we remove retain release pairs instead of
|
||||
// performing code motion.
|
||||
InsertPts.clear();
|
||||
SWIFT_FALLTHROUGH;
|
||||
case LatticeState::MightBeDecremented:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool BottomUpRefCountState::merge(const BottomUpRefCountState &Other) {
|
||||
@@ -177,6 +271,204 @@ bool BottomUpRefCountState::merge(const BottomUpRefCountState &Other) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Top Down Ref Count State
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// Initializes/reinitialized the state for I. If we reinitialize we return
|
||||
/// true.
|
||||
bool TopDownRefCountState::initWithMutatorInst(SILInstruction *I) {
|
||||
assert((isa<StrongRetainInst>(I) || isa<RetainValueInst>(I)) &&
|
||||
"strong_retain and retain_value are only supported.");
|
||||
|
||||
bool NestingDetected = SuperTy::initWithMutatorInst(I);
|
||||
|
||||
// Set our lattice state to be incremented.
|
||||
LatState = LatticeState::Incremented;
|
||||
|
||||
return NestingDetected;
|
||||
}
|
||||
|
||||
/// Initialize this ref count state with the @owned Arg at +1.
|
||||
void TopDownRefCountState::initWithArg(SILArgument *Arg) {
|
||||
LatState = LatticeState::Incremented;
|
||||
Transition = RCStateTransition(Arg);
|
||||
assert((*Transition).getKind() == RCStateTransitionKind::StrongEntrance &&
|
||||
"Expected a strong entrance here");
|
||||
RCRoot = Arg;
|
||||
KnownSafe = false;
|
||||
InsertPts.clear();
|
||||
}
|
||||
|
||||
/// Initiailize this RefCountState with an instruction which introduces a new
|
||||
/// ref count at +1.
|
||||
void
|
||||
TopDownRefCountState::initWithEntranceInst(SILInstruction *I) {
|
||||
assert(I->getNumTypes() == 1 &&
|
||||
"Expected an instruction with one return value");
|
||||
LatState = LatticeState::Incremented;
|
||||
Transition = RCStateTransition(I);
|
||||
assert((*Transition).getKind() == RCStateTransitionKind::StrongEntrance &&
|
||||
"Expected a strong entrance here");
|
||||
RCRoot = I;
|
||||
KnownSafe = false;
|
||||
InsertPts.clear();
|
||||
}
|
||||
|
||||
/// Uninitialize the current state.
|
||||
void TopDownRefCountState::clear() {
|
||||
Transition = None;
|
||||
LatState = LatticeState::None;
|
||||
SuperTy::clear();
|
||||
}
|
||||
|
||||
/// If advance the state's sequence appropriately for a decrement. If we do
|
||||
/// advance return true. Otherwise return false.
|
||||
bool TopDownRefCountState::handleDecrement(SILInstruction *PotentialDecrement) {
|
||||
switch (LatState) {
|
||||
case LatticeState::Incremented:
|
||||
LatState = LatticeState::MightBeDecremented;
|
||||
InsertPts.insert(PotentialDecrement);
|
||||
return true;
|
||||
case LatticeState::None:
|
||||
case LatticeState::MightBeDecremented:
|
||||
case LatticeState::MightBeUsed:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Given the current lattice state, if we have seen a use, advance the
|
||||
/// lattice state. Return true if we do so and false otherwise.
|
||||
bool TopDownRefCountState::handleUser(SILInstruction *PotentialUser) {
|
||||
assert(valueCanBeUsedGivenLatticeState() &&
|
||||
"Must be able to be used at this point of the lattice.");
|
||||
|
||||
// Otherwise advance the sequence...
|
||||
switch (LatState) {
|
||||
case LatticeState::MightBeDecremented:
|
||||
LatState = LatticeState::MightBeUsed;
|
||||
return true;
|
||||
case LatticeState::Incremented:
|
||||
case LatticeState::None:
|
||||
case LatticeState::MightBeUsed:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if given the current lattice state, do we care if the value
|
||||
/// we are tracking is used.
|
||||
bool
|
||||
TopDownRefCountState::
|
||||
valueCanBeGuaranteedUsedGivenLatticeState() const {
|
||||
switch (LatState) {
|
||||
case LatticeState::None:
|
||||
case LatticeState::MightBeUsed:
|
||||
return false;
|
||||
case LatticeState::Incremented:
|
||||
case LatticeState::MightBeDecremented:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// Given the current lattice state, if we have seen a use, advance the
|
||||
/// lattice state. Return true if we do so and false otherwise.
|
||||
bool
|
||||
TopDownRefCountState::
|
||||
handleGuaranteedUser(SILInstruction *PotentialGuaranteedUser) {
|
||||
assert(valueCanBeGuaranteedUsedGivenLatticeState() &&
|
||||
"Must be able to be used at this point of the lattice.");
|
||||
// Advance the sequence...
|
||||
switch (LatState) {
|
||||
// If were decremented, insert the insertion point.
|
||||
case LatticeState::Incremented: {
|
||||
assert(InsertPts.empty() && "If we are decremented, we should have no "
|
||||
"insertion points.");
|
||||
LatState = LatticeState::MightBeUsed;
|
||||
InsertPts.insert(PotentialGuaranteedUser);
|
||||
return true;
|
||||
}
|
||||
case LatticeState::MightBeDecremented:
|
||||
// If we have a might be used, we already created an insertion point
|
||||
// earlier. Just move to MightBeDecremented.
|
||||
LatState = LatticeState::MightBeUsed;
|
||||
return true;
|
||||
case LatticeState::MightBeUsed:
|
||||
case LatticeState::None:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// We have a matching ref count inst. Return true if we advance the sequence
|
||||
/// and false otherwise.
|
||||
bool TopDownRefCountState::
|
||||
handleRefCountInstMatch(SILInstruction *RefCountInst) {
|
||||
// Otherwise modify the state appropriately in preparation for removing the
|
||||
// increment, decrement pair.
|
||||
switch (LatState) {
|
||||
case LatticeState::None:
|
||||
return false;
|
||||
case LatticeState::Incremented:
|
||||
case LatticeState::MightBeDecremented:
|
||||
// Unset InsertPt so we remove retain release pairs instead of performing
|
||||
// code motion.
|
||||
InsertPts.clear();
|
||||
SWIFT_FALLTHROUGH;
|
||||
case LatticeState::MightBeUsed:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool TopDownRefCountState::merge(const TopDownRefCountState &Other) {
|
||||
auto NewState = MergeTopDownLatticeStates(LatState, Other.LatState);
|
||||
DEBUG(llvm::dbgs() << " Performing TopDown Merge.\n");
|
||||
DEBUG(llvm::dbgs() << " Left: " << LatState << "; Right: "
|
||||
<< Other.LatState << "; Result: " << NewState << "\n");
|
||||
DEBUG(llvm::dbgs() << " V: ";
|
||||
if (hasRCRoot())
|
||||
getRCRoot()->dump();
|
||||
else
|
||||
llvm::dbgs() << "\n";
|
||||
llvm::dbgs() << " OtherV: ";
|
||||
if (Other.hasRCRoot())
|
||||
Other.getRCRoot()->dump();
|
||||
else
|
||||
llvm::dbgs() << "\n");
|
||||
|
||||
LatState = NewState;
|
||||
KnownSafe &= Other.KnownSafe;
|
||||
|
||||
// If we're doing a merge on a path that's previously seen a partial merge,
|
||||
// conservatively drop the sequence, to avoid doing partial RR elimination. If
|
||||
// the branch predicates for the two merge differ, mixing them is unsafe since
|
||||
// they are not control dependent.
|
||||
//
|
||||
// TODO: Add support for determining control dependence.
|
||||
if (LatState == TopDownRefCountState::LatticeState::None) {
|
||||
clear();
|
||||
DEBUG(llvm::dbgs() << " Found LatticeState::None. "
|
||||
"Clearing State!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Transition.hasValue() || !Other.Transition.hasValue() ||
|
||||
!Transition->merge(Other.Transition.getValue())) {
|
||||
DEBUG(llvm::dbgs() << " Failed merge!\n");
|
||||
clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
Partial |= Other.Partial;
|
||||
Partial |= InsertPts.size() != Other.InsertPts.size();
|
||||
for (auto *SI : Other.InsertPts)
|
||||
Partial |= InsertPts.insert(SI).second;
|
||||
|
||||
DEBUG(llvm::dbgs() << " Partial: " << (Partial ? "yes" : "no")
|
||||
<< "\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Printing Utilities
|
||||
//===----------------------------------------------------------------------===//
|
||||
@@ -214,4 +506,3 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
|
||||
}
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
|
||||
Reference in New Issue
Block a user