diff --git a/lib/SILOptimizer/ARC/ARCRegionState.cpp b/lib/SILOptimizer/ARC/ARCRegionState.cpp index c076b0ec198b2..f30d0049ff500 100644 --- a/lib/SILOptimizer/ARC/ARCRegionState.cpp +++ b/lib/SILOptimizer/ARC/ARCRegionState.cpp @@ -18,10 +18,15 @@ #include "swift/SILOptimizer/Analysis/LoopRegionAnalysis.h" #include "swift/SILOptimizer/Analysis/AliasAnalysis.h" #include "swift/SILOptimizer/Analysis/RCIdentityAnalysis.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" using namespace swift; +llvm::cl::opt verifyARCLoopSummary( + "verify-arc-loop-summary", llvm::cl::init(false), + llvm::cl::desc("Verify if loop summary is correct in ARCLoopsOpts")); + //===----------------------------------------------------------------------===// // ARCRegionState //===----------------------------------------------------------------------===// @@ -282,6 +287,18 @@ bool ARCRegionState::processLoopBottomUp( OtherState->second.checkAndResetKnownSafety( I, OtherState->first, checkIfRefCountInstIsMatched, RCIA, AA); } +#ifndef NDEBUG + // Verify updateForDifferentLoopInst is conservative enough that the flow + // sensitive native of the loop summarized instructions does not matter. + if (verifyARCLoopSummary) { + auto NewRefCountState = OtherState->second; + for (auto *I : State->getSummarizedInterestingInsts()) { + NewRefCountState.updateForDifferentLoopInst(I, AA); + } + assert(NewRefCountState.getLatticeState() == + OtherState->second.getLatticeState()); + } +#endif } return false; @@ -420,6 +437,18 @@ bool ARCRegionState::processLoopTopDown( OtherState->second.checkAndResetKnownSafety( I, OtherState->first, checkIfRefCountInstIsMatched, RCIA, AA); } +#ifndef NDEBUG + // Verify updateForDifferentLoopInst is conservative enough that the flow + // sensitive native of the loop summarized instructions does not matter. + if (verifyARCLoopSummary) { + auto NewRefCountState = OtherState->second; + for (auto *I : State->getSummarizedInterestingInsts()) { + NewRefCountState.updateForDifferentLoopInst(I, AA); + } + assert(NewRefCountState.getLatticeState() == + OtherState->second.getLatticeState()); + } +#endif } return false; diff --git a/lib/SILOptimizer/ARC/RefCountState.cpp b/lib/SILOptimizer/ARC/RefCountState.cpp index 1ffba9f5a38a2..6b2e7495cc6c7 100644 --- a/lib/SILOptimizer/ARC/RefCountState.cpp +++ b/lib/SILOptimizer/ARC/RefCountState.cpp @@ -493,6 +493,8 @@ void BottomUpRefCountState::checkAndResetKnownSafety( clearKnownSafe(); } +// This function is conservative enough that the flow sensitive nature of +// loop summarized instructions does not matter. void BottomUpRefCountState::updateForDifferentLoopInst(SILInstruction *I, AliasAnalysis *AA) { // If we are not tracking anything, bail. @@ -500,6 +502,8 @@ void BottomUpRefCountState::updateForDifferentLoopInst(SILInstruction *I, return; if (valueCanBeGuaranteedUsedGivenLatticeState()) { + // Any instruction that may need guaranteed use or may decrement the + // refcount will turn off CodeMotionSafety if (mayGuaranteedUseValue(I, getRCRoot(), AA) || mayDecrementRefCount(I, getRCRoot(), AA)) { LLVM_DEBUG(llvm::dbgs() << " Found potential guaranteed use:\n " @@ -917,12 +921,16 @@ void TopDownRefCountState::checkAndResetKnownSafety( clearKnownSafe(); } +// This function is conservative enough that the flow sensitive nature of +// loop summarized instructions does not matter. void TopDownRefCountState::updateForDifferentLoopInst(SILInstruction *I, AliasAnalysis *AA) { // If we are not tracking anything, bail. if (!isTrackingRefCount()) return; + // Any instruction that may need guaranteed use or may decrement the + // refcount will turn off CodeMotionSafety if (valueCanBeGuaranteedUsedGivenLatticeState()) { if (mayGuaranteedUseValue(I, getRCRoot(), AA) || mayDecrementRefCount(I, getRCRoot(), AA)) { diff --git a/lib/SILOptimizer/ARC/RefCountState.h b/lib/SILOptimizer/ARC/RefCountState.h index bc9e2e46e81cc..f0304bf681f52 100644 --- a/lib/SILOptimizer/ARC/RefCountState.h +++ b/lib/SILOptimizer/ARC/RefCountState.h @@ -178,6 +178,9 @@ class BottomUpRefCountState : public RefCountState { BottomUpRefCountState(BottomUpRefCountState &&) = default; BottomUpRefCountState &operator=(BottomUpRefCountState &&) = default; + /// Getter for LatticeState + LatticeState getLatticeState() const {return LatState;} + /// Return true if the release can be moved to the retain. bool isCodeMotionSafe() const { return LatState != LatticeState::MightBeDecremented; @@ -205,6 +208,8 @@ class BottomUpRefCountState : public RefCountState { /// The main difference in between this routine and update for same loop inst /// is that if we see any decrements on a value, we treat it as being /// guaranteed used. We treat any uses as regular uses. + /// This function is conservative enough that the flow sensitive nature of + /// loop summarized instructions does not matter. void updateForDifferentLoopInst( SILInstruction *I, AliasAnalysis *AA); @@ -312,6 +317,9 @@ class TopDownRefCountState : public RefCountState { TopDownRefCountState(TopDownRefCountState &&) = default; TopDownRefCountState &operator=(TopDownRefCountState &&) = default; + /// Getter for LatticeState + LatticeState getLatticeState() const {return LatState;} + /// Return true if the retain can be moved to the release. bool isCodeMotionSafe() const { return LatState != LatticeState::MightBeUsed; @@ -350,6 +358,8 @@ class TopDownRefCountState : public RefCountState { /// The main difference in between this routine and update for same loop inst /// is that if we see any decrements on a value, we treat it as being /// guaranteed used. We treat any uses as regular uses. + /// This function is conservative enough that the flow sensitive nature of + /// loop summarized instructions does not matter. void updateForDifferentLoopInst( SILInstruction *I, AliasAnalysis *AA);