@@ -466,12 +466,35 @@ class PartitionOpTranslator {
466
466
: function(function),
467
467
sendableProtocol (
468
468
function->getASTContext ().getProtocol(KnownProtocolKind::Sendable)),
469
- builder() {
469
+ functionArgPartition(), builder() {
470
470
assert (sendableProtocol && " PartitionOpTranslators should only be created "
471
471
" in contexts in which the availability of the "
472
472
" Sendable protocol has already been checked." );
473
473
builder.translater = this ;
474
474
initCapturedUniquelyIdentifiedValues ();
475
+
476
+ LLVM_DEBUG (llvm::dbgs () << " Initializing Function Args:\n " );
477
+ auto functionArguments = function->getArguments ();
478
+ if (functionArguments.empty ()) {
479
+ LLVM_DEBUG (llvm::dbgs () << " None.\n " );
480
+ functionArgPartition = Partition::singleRegion ({});
481
+ return ;
482
+ }
483
+
484
+ llvm::SmallVector<Element, 8 > nonSendableIndices;
485
+ for (SILArgument *arg : functionArguments) {
486
+ if (auto state = tryToTrackValue (arg)) {
487
+ // If we have an arg that is an actor, we allow for it to be
488
+ // consumed... value ids derived from it though cannot be consumed.
489
+ LLVM_DEBUG (llvm::dbgs () << " %%" << state->getID ());
490
+ neverTransferredValueIDs.push_back (state->getID ());
491
+ nonSendableIndices.push_back (state->getID ());
492
+ LLVM_DEBUG (llvm::dbgs () << *arg);
493
+ }
494
+ }
495
+
496
+ // All non actor values are in the same partition.
497
+ functionArgPartition = Partition::singleRegion (nonSendableIndices);
475
498
}
476
499
477
500
std::optional<TrackableValue> getValueForId (TrackableValueID id) const {
@@ -528,35 +551,7 @@ class PartitionOpTranslator {
528
551
// including self if available, into the same region, ensuring those
529
552
// arguments get IDs in doing so. This Partition will be used as the
530
553
// entry point for the full partition analysis.
531
- Partition getEntryPartition () const {
532
- if (!functionArgPartition) {
533
- LLVM_DEBUG (llvm::dbgs () << " Initializing Function Args:\n " );
534
- auto *self = const_cast <PartitionOpTranslator *>(this );
535
- auto functionArguments = function->getArguments ();
536
- if (functionArguments.empty ()) {
537
- LLVM_DEBUG (llvm::dbgs () << " None.\n " );
538
- self->functionArgPartition = Partition::singleRegion ({});
539
- } else {
540
- llvm::SmallVector<Element, 8 > nonSendableIndices;
541
- for (SILArgument *arg : functionArguments) {
542
- if (auto state = tryToTrackValue (arg)) {
543
- // If we have an arg that is an actor, we allow for it to be
544
- // consumed... value ids derived from it though cannot be consumed.
545
- LLVM_DEBUG (llvm::dbgs () << " %%" << state->getID ());
546
- self->neverTransferredValueIDs .push_back (state->getID ());
547
- nonSendableIndices.push_back (state->getID ());
548
- LLVM_DEBUG (llvm::dbgs () << *arg);
549
- }
550
- }
551
-
552
- // All non actor values are in the same partition.
553
- self->functionArgPartition =
554
- Partition::singleRegion (nonSendableIndices);
555
- }
556
- }
557
-
558
- return *functionArgPartition;
559
- }
554
+ Partition getEntryPartition () const { return *functionArgPartition; }
560
555
561
556
// Get the vector of IDs that cannot be legally transferred at any point in
562
557
// this function. Since we place all args and self in a single region right
@@ -589,6 +584,21 @@ class PartitionOpTranslator {
589
584
llvm::report_fatal_error (" all apply instructions should be covered" );
590
585
}
591
586
587
+ #ifndef NDEBUG
588
+ void dumpValues () const {
589
+ // Since this is just used for debug output, be inefficient to make nicer
590
+ // output.
591
+ std::vector<std::pair<unsigned , SILValue>> temp;
592
+ for (auto p : stateIndexToEquivalenceClass) {
593
+ temp.emplace_back (p.first , p.second );
594
+ }
595
+ std::sort (temp.begin (), temp.end ());
596
+ for (auto p : temp) {
597
+ LLVM_DEBUG (llvm::dbgs () << " %%" << p.first << " : " << p.second );
598
+ }
599
+ }
600
+ #endif
601
+
592
602
// ===========================================================================
593
603
// The following section of functions wrap the more primitive Assign, Require,
594
604
// Merge, etc functions that generate PartitionOps with more logic common to
@@ -1102,21 +1112,21 @@ class PartitionOpTranslator {
1102
1112
// translateSILBasicBlock reduces a SIL basic block to the vector of
1103
1113
// transformations to the non-Sendable partition that it induces.
1104
1114
// it accomplished this by sequentially calling translateSILInstruction
1105
- std::vector<PartitionOp> translateSILBasicBlock (SILBasicBlock *basicBlock) {
1115
+ void translateSILBasicBlock (SILBasicBlock *basicBlock,
1116
+ std::vector<PartitionOp> &foundPartitionOps) {
1106
1117
LLVM_DEBUG (llvm::dbgs () << SEP_STR << " Compiling basic block for function "
1107
1118
<< basicBlock->getFunction ()->getName () << " : " ;
1108
1119
basicBlock->dumpID (); llvm::dbgs () << SEP_STR;
1109
1120
basicBlock->print (llvm::dbgs ());
1110
1121
llvm::dbgs () << SEP_STR << " Results:\n " ;);
1111
- // translate each SIL instruction to a PartitionOp, if necessary
1112
- std::vector<PartitionOp> partitionOps;
1122
+ // Translate each SIL instruction to the PartitionOps that it represents if
1123
+ // any.
1113
1124
for (auto &instruction : *basicBlock) {
1114
1125
LLVM_DEBUG (llvm::dbgs () << " Visiting: " << instruction);
1115
1126
translateSILInstruction (&instruction);
1116
- copy (builder.currentInstPartitionOps , std::back_inserter (partitionOps));
1127
+ copy (builder.currentInstPartitionOps ,
1128
+ std::back_inserter (foundPartitionOps));
1117
1129
}
1118
-
1119
- return partitionOps;
1120
1130
}
1121
1131
};
1122
1132
@@ -1199,25 +1209,18 @@ class BlockPartitionState {
1199
1209
SILBasicBlock *basicBlock;
1200
1210
PartitionOpTranslator &translator;
1201
1211
1202
- bool blockPartitionOpsPopulated = false ;
1203
1212
std::vector<PartitionOp> blockPartitionOps = {};
1204
1213
1205
1214
BlockPartitionState (SILBasicBlock *basicBlock,
1206
1215
PartitionOpTranslator &translator)
1207
- : basicBlock(basicBlock), translator(translator) {}
1208
-
1209
- void ensureBlockPartitionOpsPopulated () {
1210
- if (blockPartitionOpsPopulated) return ;
1211
- blockPartitionOpsPopulated = true ;
1212
- blockPartitionOps = translator.translateSILBasicBlock (basicBlock);
1216
+ : basicBlock(basicBlock), translator(translator) {
1217
+ translator.translateSILBasicBlock (basicBlock, blockPartitionOps);
1213
1218
}
1214
1219
1215
1220
// recomputes the exit partition from the entry partition,
1216
1221
// and returns whether this changed the exit partition.
1217
1222
// Note that this method ignored errors that arise.
1218
1223
bool recomputeExitFromEntry () {
1219
- ensureBlockPartitionOpsPopulated ();
1220
-
1221
1224
Partition workingPartition = entryPartition;
1222
1225
for (auto partitionOp : blockPartitionOps) {
1223
1226
// by calling apply without providing a `handleFailure` closure,
@@ -1782,7 +1785,7 @@ class PartitionAnalysis {
1782
1785
return BlockPartitionState (block, translator);
1783
1786
}),
1784
1787
raceTracer (fn, blockStates), function(fn), solved(false ) {
1785
- // initialize the entry block as needing an update, and having a partition
1788
+ // Initialize the entry block as needing an update, and having a partition
1786
1789
// that places all its non-sendable args in a single region
1787
1790
blockStates[fn->getEntryBlock ()].needsUpdate = true ;
1788
1791
blockStates[fn->getEntryBlock ()].entryPartition =
@@ -1793,12 +1796,20 @@ class PartitionAnalysis {
1793
1796
assert (!solved && " solve should only be called once" );
1794
1797
solved = true ;
1795
1798
1799
+ LLVM_DEBUG (llvm::dbgs () << SEP_STR << " Performing Dataflow!\n " << SEP_STR);
1800
+ LLVM_DEBUG (llvm::dbgs () << " Values!\n " ; translator.dumpValues ());
1801
+
1796
1802
bool anyNeedUpdate = true ;
1797
1803
while (anyNeedUpdate) {
1798
1804
anyNeedUpdate = false ;
1799
1805
1800
1806
for (auto [block, blockState] : blockStates) {
1801
- if (!blockState.needsUpdate ) continue ;
1807
+
1808
+ LLVM_DEBUG (llvm::dbgs () << " Block: bb" << block.getDebugID () << " \n " );
1809
+ if (!blockState.needsUpdate ) {
1810
+ LLVM_DEBUG (llvm::dbgs () << " Doesn't need update! Skipping!\n " );
1811
+ continue ;
1812
+ }
1802
1813
1803
1814
// mark this block as no longer needing an update
1804
1815
blockState.needsUpdate = false ;
@@ -1810,31 +1821,45 @@ class PartitionAnalysis {
1810
1821
Partition newEntryPartition;
1811
1822
bool firstPred = true ;
1812
1823
1813
- // this loop computes the join of the exit partitions of all
1824
+ LLVM_DEBUG (llvm::dbgs () << " Visiting Preds!\n " );
1825
+
1826
+ // This loop computes the join of the exit partitions of all
1814
1827
// predecessors of this block
1815
1828
for (SILBasicBlock *predBlock : block.getPredecessorBlocks ()) {
1816
1829
BlockPartitionState &predState = blockStates[predBlock];
1817
1830
// ignore predecessors that haven't been reached by the analysis yet
1818
- if (!predState.reached ) continue ;
1831
+ if (!predState.reached )
1832
+ continue ;
1819
1833
1820
1834
if (firstPred) {
1821
1835
firstPred = false ;
1822
1836
newEntryPartition = predState.exitPartition ;
1837
+ LLVM_DEBUG (llvm::dbgs () << " First Pred. bb"
1838
+ << predBlock->getDebugID () << " : " ;
1839
+ newEntryPartition.print (llvm::dbgs ()));
1823
1840
continue ;
1824
1841
}
1825
1842
1826
- newEntryPartition = Partition::join (
1827
- newEntryPartition, predState.exitPartition );
1843
+ LLVM_DEBUG (llvm::dbgs ()
1844
+ << " Pred. bb" << predBlock->getDebugID () << " : " ;
1845
+ predState.exitPartition .print (llvm::dbgs ()));
1846
+ newEntryPartition =
1847
+ Partition::join (newEntryPartition, predState.exitPartition );
1848
+ LLVM_DEBUG (llvm::dbgs () << " Join: " ;
1849
+ newEntryPartition.print (llvm::dbgs ()));
1828
1850
}
1829
1851
1830
- // if we found predecessor blocks, then attempt to use them to
1831
- // update the entry partition for this block, and abort this block's
1832
- // update if the entry partition was not updated
1852
+ // If we found predecessor blocks, then attempt to use them to update
1853
+ // the entry partition for this block, and abort this block's update if
1854
+ // the entry partition was not updated.
1833
1855
if (!firstPred) {
1834
1856
// if the recomputed entry partition is the same as the current one,
1835
1857
// perform no update
1836
- if (Partition::equals (newEntryPartition, blockState.entryPartition ))
1858
+ if (Partition::equals (newEntryPartition, blockState.entryPartition )) {
1859
+ LLVM_DEBUG (llvm::dbgs ()
1860
+ << " Entry partition is the same... skipping!\n " );
1837
1861
continue ;
1862
+ }
1838
1863
1839
1864
// otherwise update the entry partition
1840
1865
blockState.entryPartition = newEntryPartition;
@@ -1882,7 +1907,9 @@ class PartitionAnalysis {
1882
1907
<< function->getName () << " \n " );
1883
1908
RaceTracer tracer (function, blockStates);
1884
1909
1885
- for (auto [_, blockState] : blockStates) {
1910
+ for (auto [block, blockState] : blockStates) {
1911
+ LLVM_DEBUG (llvm::dbgs () << " Block bb" << block.getDebugID () << " \n " );
1912
+
1886
1913
// populate the raceTracer with all requires of transferred valued found
1887
1914
// throughout the CFG
1888
1915
blockState.diagnoseFailures (
0 commit comments