@@ -1364,7 +1364,7 @@ struct DataflowState {
1364
1364
bool handleSingleBlockClosure (SILArgument *address,
1365
1365
ClosureOperandState &state);
1366
1366
bool cleanupAllDestroyAddr (
1367
- SILFunction *fn, SmallBitVector &destroyIndices,
1367
+ SILValue address, SILFunction *fn, SmallBitVector &destroyIndices,
1368
1368
SmallBitVector &reinitIndices, SmallBitVector &consumingClosureIndices,
1369
1369
BasicBlockSet &blocksVisitedWhenProcessingNewTakes,
1370
1370
BasicBlockSet &blocksWithMovesThatAreNowTakes,
@@ -1383,14 +1383,14 @@ struct DataflowState {
1383
1383
} // namespace
1384
1384
1385
1385
bool DataflowState::cleanupAllDestroyAddr (
1386
- SILFunction *fn, SmallBitVector &destroyIndices,
1386
+ SILValue address, SILFunction *fn, SmallBitVector &destroyIndices,
1387
1387
SmallBitVector &reinitIndices, SmallBitVector &consumingClosureIndices,
1388
1388
BasicBlockSet &blocksVisitedWhenProcessingNewTakes,
1389
1389
BasicBlockSet &blocksWithMovesThatAreNowTakes,
1390
1390
SmallBlotSetVector<SILInstruction *, 8 > &postDominatingConsumingUsers) {
1391
1391
bool madeChange = false ;
1392
1392
BasicBlockWorklist worklist (fn);
1393
- SILValue daiOperand;
1393
+
1394
1394
LLVM_DEBUG (llvm::dbgs () << " Cleanup up destroy addr!\n " );
1395
1395
LLVM_DEBUG (llvm::dbgs () << " Visiting destroys!\n " );
1396
1396
LLVM_DEBUG (llvm::dbgs () << " Destroy Indices: " << destroyIndices << " \n " );
@@ -1401,9 +1401,6 @@ bool DataflowState::cleanupAllDestroyAddr(
1401
1401
if (!dai)
1402
1402
continue ;
1403
1403
LLVM_DEBUG (llvm::dbgs () << " Destroy: " << *dai);
1404
- SILValue op = (*dai)->getOperand ();
1405
- assert (daiOperand == SILValue () || op == daiOperand);
1406
- daiOperand = op;
1407
1404
for (auto *predBlock : (*dai)->getParent ()->getPredecessorBlocks ()) {
1408
1405
worklist.pushIfNotVisited (predBlock);
1409
1406
}
@@ -1415,7 +1412,7 @@ bool DataflowState::cleanupAllDestroyAddr(
1415
1412
auto reinit = useState.reinits [index];
1416
1413
if (!reinit)
1417
1414
continue ;
1418
- LLVM_DEBUG (llvm::dbgs () << " Reinit: " << *reinit);
1415
+ LLVM_DEBUG (llvm::dbgs () << " Reinit: " << ** reinit);
1419
1416
for (auto *predBlock : (*reinit)->getParent ()->getPredecessorBlocks ()) {
1420
1417
worklist.pushIfNotVisited (predBlock);
1421
1418
}
@@ -1436,16 +1433,33 @@ bool DataflowState::cleanupAllDestroyAddr(
1436
1433
while (auto *next = worklist.pop ()) {
1437
1434
LLVM_DEBUG (llvm::dbgs ()
1438
1435
<< " Looking at block: bb" << next->getDebugID () << " \n " );
1436
+
1439
1437
// Any blocks that contained processed moves are stop points.
1440
- if (blocksWithMovesThatAreNowTakes.contains (next))
1438
+ if (blocksWithMovesThatAreNowTakes.contains (next)) {
1439
+ LLVM_DEBUG (llvm::dbgs ()
1440
+ << " Block contained a move that is now a true take.\n " );
1441
1441
continue ;
1442
+ }
1442
1443
1444
+ // Then if we find that we have a block that was never visited when we
1445
+ // walked along successor edges from the move, then we know that we need to
1446
+ // insert a destroy_addr.
1447
+ //
1448
+ // This is safe to do since this block lives along the dominance frontier
1449
+ // and we do not allow for critical edges, so as we walk along predecessors,
1450
+ // given that any such block must also have a successor that was reachable
1451
+ // from our move, we know that this unprocessed block must only have one
1452
+ // successor, a block reachable from our move and thus must not have any
1453
+ // unhandled uses.
1443
1454
if (!blocksVisitedWhenProcessingNewTakes.contains (next)) {
1455
+ LLVM_DEBUG (llvm::dbgs () << " Found a block that was not visited when "
1456
+ " we processed takes of the given move.\n " );
1444
1457
// Insert a destroy_addr here since the block isn't reachable from any of
1445
1458
// our moves.
1446
- SILBuilderWithScope builder (next->getTerminator ());
1459
+ SILBuilderWithScope builder (
1460
+ std::prev (next->getTerminator ()->getIterator ()));
1447
1461
auto *dvi = builder.createDestroyAddr (
1448
- RegularLocation::getAutoGeneratedLocation (), daiOperand );
1462
+ RegularLocation::getAutoGeneratedLocation (), address );
1449
1463
useState.destroys .insert (dvi);
1450
1464
continue ;
1451
1465
}
@@ -1538,7 +1552,7 @@ bool DataflowState::process(
1538
1552
return indicesOfPairedConsumingClosureUses;
1539
1553
};
1540
1554
1541
- BasicBlockSet visitedByNewMove (fn);
1555
+ BasicBlockSet blocksVisitedWhenProcessingNewTakes (fn);
1542
1556
BasicBlockSet blocksWithMovesThatAreNowTakes (fn);
1543
1557
bool convertedMarkMoveToTake = false ;
1544
1558
for (auto *mvi : markMovesThatPropagateDownwards) {
@@ -1547,12 +1561,12 @@ bool DataflowState::process(
1547
1561
LLVM_DEBUG (llvm::dbgs () << " Checking Multi Block Dataflow for: " << *mvi);
1548
1562
1549
1563
BasicBlockWorklist worklist (fn);
1550
- BasicBlockSetVector setVector (fn);
1564
+ BasicBlockSetVector visitedBlocks (fn);
1551
1565
for (auto *succBlock : mvi->getParent ()->getSuccessorBlocks ()) {
1552
1566
LLVM_DEBUG (llvm::dbgs ()
1553
1567
<< " SuccBlocks: " << succBlock->getDebugID () << " \n " );
1554
1568
worklist.pushIfNotVisited (succBlock);
1555
- setVector .insert (succBlock);
1569
+ visitedBlocks .insert (succBlock);
1556
1570
}
1557
1571
1558
1572
while (auto *next = worklist.pop ()) {
@@ -1684,7 +1698,7 @@ bool DataflowState::process(
1684
1698
// Otherwise, add successors if we haven't visited them to the worklist.
1685
1699
for (auto *succBlock : next->getSuccessorBlocks ()) {
1686
1700
worklist.pushIfNotVisited (succBlock);
1687
- setVector .insert (succBlock);
1701
+ visitedBlocks .insert (succBlock);
1688
1702
}
1689
1703
}
1690
1704
@@ -1701,8 +1715,8 @@ bool DataflowState::process(
1701
1715
builder.createCopyAddr (mvi->getLoc (), mvi->getSrc (), mvi->getDest (),
1702
1716
IsTake, IsInitialization);
1703
1717
// Flush our SetVector into the visitedByNewMove.
1704
- for (auto *block : setVector ) {
1705
- visitedByNewMove .insert (block);
1718
+ for (auto *block : visitedBlocks ) {
1719
+ blocksVisitedWhenProcessingNewTakes .insert (block);
1706
1720
}
1707
1721
convertedMarkMoveToTake = true ;
1708
1722
}
@@ -1716,9 +1730,10 @@ bool DataflowState::process(
1716
1730
// Now that we have processed all of our mark_moves, eliminate all of the
1717
1731
// destroy_addr.
1718
1732
madeChange |= cleanupAllDestroyAddr (
1719
- fn, getIndicesOfPairedDestroys (), getIndicesOfPairedReinits (),
1720
- getIndicesOfPairedConsumingClosureUses (), visitedByNewMove,
1721
- blocksWithMovesThatAreNowTakes, postDominatingConsumingUsers);
1733
+ address, fn, getIndicesOfPairedDestroys (), getIndicesOfPairedReinits (),
1734
+ getIndicesOfPairedConsumingClosureUses (),
1735
+ blocksVisitedWhenProcessingNewTakes, blocksWithMovesThatAreNowTakes,
1736
+ postDominatingConsumingUsers);
1722
1737
1723
1738
return madeChange;
1724
1739
}
0 commit comments