@@ -544,20 +544,23 @@ namespace {
544544// / and the compiler emits assigns when it reinitializes vars this early in the
545545// / pipeline.
546546struct ClosureArgDataflowState {
547+ ASTContext &C;
547548 SmallVector<SILInstruction *, 32 > livenessWorklist;
548549 SmallVector<SILInstruction *, 32 > consumingWorklist;
549550 MultiDefPrunedLiveness livenessForConsumes;
550551 UseState &useState;
551552
552553public:
553554 ClosureArgDataflowState (SILFunction *function, UseState &useState)
554- : livenessForConsumes(function), useState(useState) {}
555+ : C(function->getASTContext ()),
556+ livenessForConsumes(function), useState(useState) {}
555557
556558 bool process (
557559 SILArgument *arg, ClosureOperandState &state,
558560 SmallBlotSetVector<SILInstruction *, 8 > &postDominatingConsumingUsers);
559561
560562private:
563+
561564 // / Perform our liveness dataflow. Returns true if we found any liveness uses
562565 // / at all. These we will need to error upon.
563566 bool performLivenessDataflow (const BasicBlockSet &initBlocks,
@@ -719,15 +722,15 @@ void ClosureArgDataflowState::classifyUses(BasicBlockSet &initBlocks,
719722
720723 for (auto *user : useState.inits ) {
721724 if (upwardScanForInit (user, useState)) {
722- LLVM_DEBUG (llvm::dbgs () << " Found init block at: " << *user);
725+ LLVM_DEBUG (llvm::dbgs () << " Found init block during classifyUses at: " << *user);
723726 livenessForConsumes.initializeDef (user);
724727 initBlocks.insert (user->getParent ());
725728 }
726729 }
727730
728731 for (auto *user : useState.livenessUses ) {
729732 if (upwardScanForUseOut (user, useState)) {
730- LLVM_DEBUG (llvm::dbgs () << " Found use block at: " << *user);
733+ LLVM_DEBUG (llvm::dbgs () << " Found use block during classifyUses at: " << *user);
731734 livenessBlocks.insert (user->getParent ());
732735 livenessWorklist.push_back (user);
733736 }
@@ -742,7 +745,7 @@ void ClosureArgDataflowState::classifyUses(BasicBlockSet &initBlocks,
742745 assert (iter != useState.destroyToIndexMap .end ());
743746
744747 if (upwardScanForDestroys (destroy, useState)) {
745- LLVM_DEBUG (llvm::dbgs () << " Found destroy block at: " << *destroy);
748+ LLVM_DEBUG (llvm::dbgs () << " Found destroy block during classifyUses at: " << *destroy);
746749 consumingBlocks.insert (destroy->getParent ());
747750 consumingWorklist.push_back (destroy);
748751 }
@@ -755,8 +758,17 @@ void ClosureArgDataflowState::classifyUses(BasicBlockSet &initBlocks,
755758 auto iter = useState.reinitToIndexMap .find (reinit);
756759 assert (iter != useState.reinitToIndexMap .end ());
757760
761+ // TODO: Reinitialization analysis is currently incomplete and leads
762+ // to miscompiles. Treat reinitializations as regular uses for now.
763+ if (!C.LangOpts .hasFeature (Feature::ReinitializeConsumeInMultiBlockDefer)) {
764+ LLVM_DEBUG (llvm::dbgs () << " Treating reinit as use block during classifyUses at: " << *reinit);
765+ livenessBlocks.insert (reinit->getParent ());
766+ livenessWorklist.push_back (reinit);
767+ continue ;
768+ }
769+
758770 if (upwardScanForDestroys (reinit, useState)) {
759- LLVM_DEBUG (llvm::dbgs () << " Found reinit block at: " << *reinit);
771+ LLVM_DEBUG (llvm::dbgs () << " Found reinit block during classifyUses at: " << *reinit);
760772 consumingBlocks.insert (reinit->getParent ());
761773 consumingWorklist.push_back (reinit);
762774 }
@@ -823,31 +835,38 @@ bool ClosureArgDataflowState::process(
823835 // parameter. We are going to change it to be an out parameter and eliminate
824836 // these when we clone the closure.
825837 if (performConsumingDataflow (initBlocks, consumingBlocks)) {
838+ LLVM_DEBUG (llvm::dbgs () << " found single consuming use!\n " );
839+
826840 // Before we do anything, make sure our argument has at least one single
827841 // debug_value user. If we have many we can't handle it since something in
828842 // SILGen is emitting weird code. Our tests will ensure that SILGen does not
829843 // diverge by mistake. So we are really just being careful.
830844 if (hasMoreThanOneDebugUse (address)) {
831845 // Failing b/c more than one debug use!
846+ LLVM_DEBUG (llvm::dbgs () << " ...but argument has more than one debug use!\n " );
832847 return false ;
833848 }
834849
835850 // !!! FIXME: Why?
836- // auto *frontBlock = &*fn->begin();
837- // livenessForConsumes.initializeDefBlock(frontBlock );
851+ // auto *frontBlock = &*fn->begin();
852+ // livenessForConsumes.initializeDef(address );
838853
839- for (unsigned i : indices (livenessWorklist)) {
840- if (auto *ptr = livenessWorklist[i]) {
854+ for (unsigned i : indices (consumingWorklist)) {
855+ if (auto *ptr = consumingWorklist[i]) {
856+ LLVM_DEBUG (llvm::dbgs () << " liveness for consume: " << *ptr);
841857 state.pairedConsumingInsts .push_back (ptr);
842- livenessForConsumes.updateForUse (ptr, true /* is lifetime ending*/ );
858+ // livenessForConsumes.updateForUse(ptr, true /*is lifetime ending*/);
843859 }
844860 }
845861
846862 // If our consumes do not have a linear lifetime, bail. We will error on the
847863 // move being unknown.
848864 for (auto *ptr : state.pairedConsumingInsts ) {
849- if (livenessForConsumes.isWithinBoundary (ptr))
865+ /* if (livenessForConsumes.isWithinBoundary(ptr)) {
866+ LLVM_DEBUG(llvm::dbgs() << "consuming inst within boundary; bailing: "
867+ << *ptr);
850868 return false;
869+ }*/
851870 postDominatingConsumingUsers.insert (ptr);
852871 }
853872 state.result = DownwardScanResult::ClosureConsume;
@@ -1835,15 +1854,15 @@ void DataflowState::init() {
18351854 // mark this as an "init block".
18361855 for (auto *init : useState.inits ) {
18371856 if (upwardScanForInit (init, useState)) {
1838- LLVM_DEBUG (llvm::dbgs () << " Found use block at: " << *init);
1857+ LLVM_DEBUG (llvm::dbgs () << " Found use block during DataflowState::init at: " << *init);
18391858 initBlocks.insert (init->getParent ());
18401859 }
18411860 }
18421861
18431862 // Then go through all normal uses and do upwardScanForUseOut.
18441863 for (auto *user : useState.livenessUses ) {
18451864 if (upwardScanForUseOut (user, useState)) {
1846- LLVM_DEBUG (llvm::dbgs () << " Found liveness block at: " << *user);
1865+ LLVM_DEBUG (llvm::dbgs () << " Found liveness block during DataflowState::init at: " << *user);
18471866 useBlocks[user->getParent ()] = user;
18481867 }
18491868 }
@@ -1860,7 +1879,7 @@ void DataflowState::init() {
18601879 assert (iter != useState.destroyToIndexMap .end ());
18611880
18621881 if (upwardScanForDestroys (destroy, useState)) {
1863- LLVM_DEBUG (llvm::dbgs () << " Found destroy block at: " << *destroy);
1882+ LLVM_DEBUG (llvm::dbgs () << " Found destroy block during DataflowState::init at: " << *destroy);
18641883 destroyBlocks[destroy->getParent ()] = destroy;
18651884 }
18661885 }
@@ -1876,7 +1895,7 @@ void DataflowState::init() {
18761895 assert (iter != useState.reinitToIndexMap .end ());
18771896
18781897 if (upwardScanForDestroys (reinit, useState)) {
1879- LLVM_DEBUG (llvm::dbgs () << " Found reinit block at: " << *reinit);
1898+ LLVM_DEBUG (llvm::dbgs () << " Found reinit block during DataflowState::init at: " << *reinit);
18801899 reinitBlocks[reinit->getParent ()] = reinit;
18811900 }
18821901 }
@@ -1896,14 +1915,14 @@ void DataflowState::init() {
18961915 case DownwardScanResult::ClosureUse:
18971916 if (upwardScanForUseOut (user, useState)) {
18981917 LLVM_DEBUG (llvm::dbgs ()
1899- << " Found closure liveness block at: " << *user);
1918+ << " Found closure liveness block during DataflowState::init at: " << *user);
19001919 closureUseBlocks[user->getParent ()] = &state;
19011920 }
19021921 break ;
19031922 case DownwardScanResult::ClosureConsume:
19041923 if (upwardScanForDestroys (user, useState)) {
19051924 LLVM_DEBUG (llvm::dbgs ()
1906- << " Found closure consuming block at: " << *user);
1925+ << " Found closure consuming block during DataflowState::init at: " << *user);
19071926 closureConsumeBlocks[user->getParent ()] = use;
19081927 }
19091928 break ;
@@ -2019,20 +2038,20 @@ void ConsumeOperatorCopyableAddressesChecker::cloneDeferCalleeAndRewriteUses(
20192038bool ConsumeOperatorCopyableAddressesChecker::performClosureDataflow (
20202039 Operand *callerOperand, ClosureOperandState &calleeOperandState) {
20212040 auto fas = FullApplySite::isa (callerOperand->getUser ());
2022- auto *func = fas.getCalleeFunction ();
2041+ auto *callee = fas.getCalleeFunction ();
20232042 auto *address =
2024- func ->begin ()->getArgument (fas.getCalleeArgIndex (*callerOperand));
2043+ callee ->begin ()->getArgument (fas.getCalleeArgIndex (*callerOperand));
20252044
20262045 LLVM_DEBUG (llvm::dbgs () << " Performing closure dataflow on caller use: "
20272046 << *callerOperand->getUser ());
2028- LLVM_DEBUG (llvm::dbgs () << " Callee: " << func ->getName () << ' \n ' );
2047+ LLVM_DEBUG (llvm::dbgs () << " Callee: " << callee ->getName () << ' \n ' );
20292048 LLVM_DEBUG (llvm::dbgs () << " Callee Argument: " << *address);
20302049 // We emit an end closure dataflow to make it easier when reading debug output
20312050 // to make it easy to see when we have returned to analyzing the caller.
20322051 SWIFT_DEFER {
20332052 LLVM_DEBUG (llvm::dbgs ()
20342053 << " Finished performing closure dataflow on Callee: "
2035- << func ->getName () << ' \n ' ;);
2054+ << callee ->getName () << ' \n ' ;);
20362055 };
20372056 auto accessPathWithBase = AccessPathWithBase::compute (address);
20382057 auto accessPath = accessPathWithBase.accessPath ;
@@ -2053,10 +2072,10 @@ bool ConsumeOperatorCopyableAddressesChecker::performClosureDataflow(
20532072 GatherClosureUseVisitor visitor (closureUseState);
20542073 SWIFT_DEFER { visitor.clear (); };
20552074 visitor.reset (address);
2056- if (!visitAccessPathUses (visitor, accessPath, fn ))
2075+ if (!visitAccessPathUses (visitor, accessPath, callee ))
20572076 return false ;
20582077
2059- ClosureArgDataflowState closureUseDataflowState (fn , closureUseState);
2078+ ClosureArgDataflowState closureUseDataflowState (callee , closureUseState);
20602079 return closureUseDataflowState.process (address, calleeOperandState,
20612080 closureConsumes);
20622081}
0 commit comments