@@ -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;
@@ -2018,20 +2037,20 @@ void ConsumeOperatorCopyableAddressesChecker::cloneDeferCalleeAndRewriteUses(
2018
2037
bool ConsumeOperatorCopyableAddressesChecker::performClosureDataflow(
2019
2038
Operand *callerOperand, ClosureOperandState &calleeOperandState) {
2020
2039
auto fas = FullApplySite::isa(callerOperand->getUser());
2021
- auto *func = fas.getCalleeFunction();
2040
+ auto *callee = fas.getCalleeFunction();
2022
2041
auto *address =
2023
- func ->begin()->getArgument(fas.getCalleeArgIndex(*callerOperand));
2042
+ callee ->begin()->getArgument(fas.getCalleeArgIndex(*callerOperand));
2024
2043
2025
2044
LLVM_DEBUG(llvm::dbgs() << "Performing closure dataflow on caller use: "
2026
2045
<< *callerOperand->getUser());
2027
- LLVM_DEBUG(llvm::dbgs() << " Callee: " << func ->getName() << '\n');
2046
+ LLVM_DEBUG(llvm::dbgs() << " Callee: " << callee ->getName() << '\n');
2028
2047
LLVM_DEBUG(llvm::dbgs() << " Callee Argument: " << *address);
2029
2048
// We emit an end closure dataflow to make it easier when reading debug output
2030
2049
// to make it easy to see when we have returned to analyzing the caller.
2031
2050
SWIFT_DEFER {
2032
2051
LLVM_DEBUG(llvm::dbgs()
2033
2052
<< "Finished performing closure dataflow on Callee: "
2034
- << func ->getName() << '\n';);
2053
+ << callee ->getName() << '\n';);
2035
2054
};
2036
2055
auto accessPathWithBase = AccessPathWithBase::compute(address);
2037
2056
auto accessPath = accessPathWithBase.accessPath;
@@ -2052,10 +2071,10 @@ bool ConsumeOperatorCopyableAddressesChecker::performClosureDataflow(
2052
2071
GatherClosureUseVisitor visitor(closureUseState);
2053
2072
SWIFT_DEFER { visitor.clear(); };
2054
2073
visitor.reset(address);
2055
- if (!visitAccessPathUses(visitor, accessPath, fn ))
2074
+ if (!visitAccessPathUses(visitor, accessPath, callee ))
2056
2075
return false;
2057
2076
2058
- ClosureArgDataflowState closureUseDataflowState(fn , closureUseState);
2077
+ ClosureArgDataflowState closureUseDataflowState(callee , closureUseState);
2059
2078
return closureUseDataflowState.process(address, calleeOperandState,
2060
2079
closureConsumes);
2061
2080
}
0 commit comments