@@ -544,20 +544,23 @@ namespace {
544
544
// / and the compiler emits assigns when it reinitializes vars this early in the
545
545
// / pipeline.
546
546
struct ClosureArgDataflowState {
547
+ ASTContext &C;
547
548
SmallVector<SILInstruction *, 32 > livenessWorklist;
548
549
SmallVector<SILInstruction *, 32 > consumingWorklist;
549
550
MultiDefPrunedLiveness livenessForConsumes;
550
551
UseState &useState;
551
552
552
553
public:
553
554
ClosureArgDataflowState (SILFunction *function, UseState &useState)
554
- : livenessForConsumes(function), useState(useState) {}
555
+ : C(function->getASTContext ()),
556
+ livenessForConsumes(function), useState(useState) {}
555
557
556
558
bool process (
557
559
SILArgument *arg, ClosureOperandState &state,
558
560
SmallBlotSetVector<SILInstruction *, 8 > &postDominatingConsumingUsers);
559
561
560
562
private:
563
+
561
564
// / Perform our liveness dataflow. Returns true if we found any liveness uses
562
565
// / at all. These we will need to error upon.
563
566
bool performLivenessDataflow (const BasicBlockSet &initBlocks,
@@ -719,15 +722,15 @@ void ClosureArgDataflowState::classifyUses(BasicBlockSet &initBlocks,
719
722
720
723
for (auto *user : useState.inits ) {
721
724
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);
723
726
livenessForConsumes.initializeDef (user);
724
727
initBlocks.insert (user->getParent ());
725
728
}
726
729
}
727
730
728
731
for (auto *user : useState.livenessUses ) {
729
732
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);
731
734
livenessBlocks.insert (user->getParent ());
732
735
livenessWorklist.push_back (user);
733
736
}
@@ -742,7 +745,7 @@ void ClosureArgDataflowState::classifyUses(BasicBlockSet &initBlocks,
742
745
assert (iter != useState.destroyToIndexMap .end ());
743
746
744
747
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);
746
749
consumingBlocks.insert (destroy->getParent ());
747
750
consumingWorklist.push_back (destroy);
748
751
}
@@ -755,8 +758,17 @@ void ClosureArgDataflowState::classifyUses(BasicBlockSet &initBlocks,
755
758
auto iter = useState.reinitToIndexMap .find (reinit);
756
759
assert (iter != useState.reinitToIndexMap .end ());
757
760
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
+
758
770
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);
760
772
consumingBlocks.insert (reinit->getParent ());
761
773
consumingWorklist.push_back (reinit);
762
774
}
@@ -823,31 +835,38 @@ bool ClosureArgDataflowState::process(
823
835
// parameter. We are going to change it to be an out parameter and eliminate
824
836
// these when we clone the closure.
825
837
if (performConsumingDataflow (initBlocks, consumingBlocks)) {
838
+ LLVM_DEBUG (llvm::dbgs () << " found single consuming use!\n " );
839
+
826
840
// Before we do anything, make sure our argument has at least one single
827
841
// debug_value user. If we have many we can't handle it since something in
828
842
// SILGen is emitting weird code. Our tests will ensure that SILGen does not
829
843
// diverge by mistake. So we are really just being careful.
830
844
if (hasMoreThanOneDebugUse (address)) {
831
845
// Failing b/c more than one debug use!
846
+ LLVM_DEBUG (llvm::dbgs () << " ...but argument has more than one debug use!\n " );
832
847
return false ;
833
848
}
834
849
835
850
// !!! FIXME: Why?
836
- // auto *frontBlock = &*fn->begin();
837
- // livenessForConsumes.initializeDefBlock(frontBlock );
851
+ // auto *frontBlock = &*fn->begin();
852
+ // livenessForConsumes.initializeDef(address );
838
853
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);
841
857
state.pairedConsumingInsts .push_back (ptr);
842
- livenessForConsumes.updateForUse (ptr, true /* is lifetime ending*/ );
858
+ // livenessForConsumes.updateForUse(ptr, true /*is lifetime ending*/);
843
859
}
844
860
}
845
861
846
862
// If our consumes do not have a linear lifetime, bail. We will error on the
847
863
// move being unknown.
848
864
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);
850
868
return false;
869
+ }*/
851
870
postDominatingConsumingUsers.insert (ptr);
852
871
}
853
872
state.result = DownwardScanResult::ClosureConsume;
@@ -1835,15 +1854,15 @@ void DataflowState::init() {
1835
1854
// mark this as an "init block".
1836
1855
for (auto *init : useState.inits ) {
1837
1856
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);
1839
1858
initBlocks.insert (init->getParent ());
1840
1859
}
1841
1860
}
1842
1861
1843
1862
// Then go through all normal uses and do upwardScanForUseOut.
1844
1863
for (auto *user : useState.livenessUses ) {
1845
1864
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);
1847
1866
useBlocks[user->getParent ()] = user;
1848
1867
}
1849
1868
}
@@ -1860,7 +1879,7 @@ void DataflowState::init() {
1860
1879
assert (iter != useState.destroyToIndexMap .end ());
1861
1880
1862
1881
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);
1864
1883
destroyBlocks[destroy->getParent ()] = destroy;
1865
1884
}
1866
1885
}
@@ -1876,7 +1895,7 @@ void DataflowState::init() {
1876
1895
assert (iter != useState.reinitToIndexMap .end ());
1877
1896
1878
1897
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);
1880
1899
reinitBlocks[reinit->getParent ()] = reinit;
1881
1900
}
1882
1901
}
@@ -1896,14 +1915,14 @@ void DataflowState::init() {
1896
1915
case DownwardScanResult::ClosureUse:
1897
1916
if (upwardScanForUseOut (user, useState)) {
1898
1917
LLVM_DEBUG (llvm::dbgs ()
1899
- << " Found closure liveness block at: " << *user);
1918
+ << " Found closure liveness block during DataflowState::init at: " << *user);
1900
1919
closureUseBlocks[user->getParent ()] = &state;
1901
1920
}
1902
1921
break ;
1903
1922
case DownwardScanResult::ClosureConsume:
1904
1923
if (upwardScanForDestroys (user, useState)) {
1905
1924
LLVM_DEBUG (llvm::dbgs ()
1906
- << " Found closure consuming block at: " << *user);
1925
+ << " Found closure consuming block during DataflowState::init at: " << *user);
1907
1926
closureConsumeBlocks[user->getParent ()] = use;
1908
1927
}
1909
1928
break ;
@@ -2019,20 +2038,20 @@ void ConsumeOperatorCopyableAddressesChecker::cloneDeferCalleeAndRewriteUses(
2019
2038
bool ConsumeOperatorCopyableAddressesChecker::performClosureDataflow (
2020
2039
Operand *callerOperand, ClosureOperandState &calleeOperandState) {
2021
2040
auto fas = FullApplySite::isa (callerOperand->getUser ());
2022
- auto *func = fas.getCalleeFunction ();
2041
+ auto *callee = fas.getCalleeFunction ();
2023
2042
auto *address =
2024
- func ->begin ()->getArgument (fas.getCalleeArgIndex (*callerOperand));
2043
+ callee ->begin ()->getArgument (fas.getCalleeArgIndex (*callerOperand));
2025
2044
2026
2045
LLVM_DEBUG (llvm::dbgs () << " Performing closure dataflow on caller use: "
2027
2046
<< *callerOperand->getUser ());
2028
- LLVM_DEBUG (llvm::dbgs () << " Callee: " << func ->getName () << ' \n ' );
2047
+ LLVM_DEBUG (llvm::dbgs () << " Callee: " << callee ->getName () << ' \n ' );
2029
2048
LLVM_DEBUG (llvm::dbgs () << " Callee Argument: " << *address);
2030
2049
// We emit an end closure dataflow to make it easier when reading debug output
2031
2050
// to make it easy to see when we have returned to analyzing the caller.
2032
2051
SWIFT_DEFER {
2033
2052
LLVM_DEBUG (llvm::dbgs ()
2034
2053
<< " Finished performing closure dataflow on Callee: "
2035
- << func ->getName () << ' \n ' ;);
2054
+ << callee ->getName () << ' \n ' ;);
2036
2055
};
2037
2056
auto accessPathWithBase = AccessPathWithBase::compute (address);
2038
2057
auto accessPath = accessPathWithBase.accessPath ;
@@ -2053,10 +2072,10 @@ bool ConsumeOperatorCopyableAddressesChecker::performClosureDataflow(
2053
2072
GatherClosureUseVisitor visitor (closureUseState);
2054
2073
SWIFT_DEFER { visitor.clear (); };
2055
2074
visitor.reset (address);
2056
- if (!visitAccessPathUses (visitor, accessPath, fn ))
2075
+ if (!visitAccessPathUses (visitor, accessPath, callee ))
2057
2076
return false ;
2058
2077
2059
- ClosureArgDataflowState closureUseDataflowState (fn , closureUseState);
2078
+ ClosureArgDataflowState closureUseDataflowState (callee , closureUseState);
2060
2079
return closureUseDataflowState.process (address, calleeOperandState,
2061
2080
closureConsumes);
2062
2081
}
0 commit comments