@@ -1266,6 +1266,12 @@ struct BlockSummaries {
1266
1266
}
1267
1267
1268
1268
void summarize (SILBasicBlock &block);
1269
+
1270
+ // / After we have summarized all of our blocks, initialize the given pruned
1271
+ // / liveness with the information needed from our summaries to perform
1272
+ // / multi-block liveness dataflow.
1273
+ void initializeLiveness (FieldSensitiveAddressPrunedLiveness &liveness,
1274
+ SmallPtrSetImpl<SILInstruction *> &inoutTermUsers);
1269
1275
};
1270
1276
1271
1277
} // anonymous namespace
@@ -1433,6 +1439,48 @@ void BlockSummaries::summarize(SILBasicBlock &block) {
1433
1439
}
1434
1440
}
1435
1441
1442
+ void BlockSummaries::initializeLiveness (
1443
+ FieldSensitiveAddressPrunedLiveness &liveness,
1444
+ SmallPtrSetImpl<SILInstruction *> &inoutTermUsers) {
1445
+ // At this point, we have handled all of the single block cases and have
1446
+ // simplified the remaining cases to global cases that we compute using
1447
+ // liveness. We begin by using all of our init down blocks as def blocks.
1448
+ for (auto initInstAndValue : initDownInsts)
1449
+ liveness.initializeDefBlock (initInstAndValue.first ->getParent (),
1450
+ initInstAndValue.second );
1451
+
1452
+ // Then add all of the takes that we saw propagated up to the top of our
1453
+ // block. Since we have done this for all of our defs
1454
+ for (auto takeInstAndValue : takeUpInsts)
1455
+ liveness.updateForUse (takeInstAndValue.first , takeInstAndValue.second ,
1456
+ true /* lifetime ending*/ );
1457
+ // Do the same for our borrow and liveness insts.
1458
+ for (auto livenessInstAndValue : livenessUpInsts)
1459
+ liveness.updateForUse (livenessInstAndValue.first ,
1460
+ livenessInstAndValue.second ,
1461
+ false /* lifetime ending*/ );
1462
+
1463
+ // Finally, if we have an inout argument, add a liveness use of the entire
1464
+ // value on terminators in blocks that are exits from the function. This
1465
+ // ensures that along all paths, if our inout is not reinitialized before we
1466
+ // exit the function, we will get an error. We also stash these users into
1467
+ // inoutTermUser so we can quickly recognize them later and emit a better
1468
+ // error msg.
1469
+ if (auto *fArg = dyn_cast<SILFunctionArgument>(markedAddress->getOperand ())) {
1470
+ if (fArg ->getArgumentConvention () ==
1471
+ SILArgumentConvention::Indirect_Inout) {
1472
+ SmallVector<SILBasicBlock *, 8 > exitBlocks;
1473
+ markedAddress->getFunction ()->findExitingBlocks (exitBlocks);
1474
+ for (auto *block : exitBlocks) {
1475
+ inoutTermUsers.insert (block->getTerminator ());
1476
+ liveness.updateForUse (block->getTerminator (),
1477
+ TypeTreeLeafTypeRange (markedAddress),
1478
+ false /* lifetime ending*/ );
1479
+ }
1480
+ }
1481
+ }
1482
+ }
1483
+
1436
1484
// ===----------------------------------------------------------------------===//
1437
1485
// MARK: Main Pass Implementation
1438
1486
// ===----------------------------------------------------------------------===//
@@ -1607,66 +1655,23 @@ bool MoveOnlyChecker::performSingleCheck(MarkMustCheckInst *markedAddress) {
1607
1655
// Multi-Block Liveness Dataflow
1608
1656
//
1609
1657
1610
- SmallVectorImpl<InstLeafTypePair> &initDownInsts = summaries.initDownInsts ;
1611
- SmallVectorImpl<InstLeafTypePair> &takeDownInsts = summaries.takeDownInsts ;
1612
- SmallVectorImpl<InstLeafTypePair> &takeUpInsts = summaries.takeUpInsts ;
1613
- SmallVectorImpl<InstLeafTypePair> &livenessUpInsts =
1614
- summaries.livenessUpInsts ;
1615
- BlockState::Map &blockToState = summaries.blockToState ;
1616
-
1617
1658
SmallVector<SILBasicBlock *, 32 > discoveredBlocks;
1618
1659
FieldSensitiveAddressPrunedLiveness liveness (fn, markedAddress,
1619
1660
&discoveredBlocks);
1661
+ SmallPtrSet<SILInstruction *, 8 > inoutTermUsers;
1620
1662
1621
- // At this point, we have handled all of the single block cases and have
1622
- // simplified the remaining cases to global cases that we compute using
1623
- // liveness. We begin by using all of our init down blocks as def blocks.
1624
- for (auto initInstAndValue : initDownInsts)
1625
- liveness.initializeDefBlock (initInstAndValue.first ->getParent (),
1626
- initInstAndValue.second );
1627
-
1628
- // Then add all of the takes that we saw propagated up to the top of our
1629
- // block. Since we have done this for all of our defs
1630
- for (auto takeInstAndValue : takeUpInsts)
1631
- liveness.updateForUse (takeInstAndValue.first , takeInstAndValue.second ,
1632
- true /* lifetime ending*/ );
1633
- // Do the same for our borrow and liveness insts.
1634
- for (auto livenessInstAndValue : livenessUpInsts)
1635
- liveness.updateForUse (livenessInstAndValue.first ,
1636
- livenessInstAndValue.second ,
1637
- false /* lifetime ending*/ );
1638
-
1639
- // Finally, if we have an inout argument, add a liveness use of the entire
1640
- // value on terminators in blocks that are exits from the function. This
1641
- // ensures that along all paths, if our inout is not reinitialized before we
1642
- // exit the function, we will get an error. We also stash these users into
1643
- // inoutTermUser so we can quickly recognize them later and emit a better
1644
- // error msg.
1645
- SmallPtrSet<SILInstruction *, 8 > inoutTermUser;
1646
- if (auto *fArg = dyn_cast<SILFunctionArgument>(markedAddress->getOperand ())) {
1647
- if (fArg ->getArgumentConvention () ==
1648
- SILArgumentConvention::Indirect_Inout) {
1649
- SmallVector<SILBasicBlock *, 8 > exitBlocks;
1650
- markedAddress->getFunction ()->findExitingBlocks (exitBlocks);
1651
- for (auto *block : exitBlocks) {
1652
- inoutTermUser.insert (block->getTerminator ());
1653
- liveness.updateForUse (block->getTerminator (),
1654
- TypeTreeLeafTypeRange (markedAddress),
1655
- false /* lifetime ending*/ );
1656
- }
1657
- }
1658
- }
1663
+ summaries.initializeLiveness (liveness, inoutTermUsers);
1659
1664
1660
1665
// If we have multiple blocks in the function, now run the global pruned
1661
1666
// liveness dataflow.
1662
1667
if (std::next (fn->begin ()) != fn->end ()) {
1663
1668
// Then compute the takes that are within the cumulative boundary of
1664
1669
// liveness that we have computed. If we find any, they are the errors ones.
1665
- LivenessChecker emitter (markedAddress, liveness, inoutTermUser ,
1666
- blockToState, diagnosticEmitter);
1670
+ LivenessChecker emitter (markedAddress, liveness, inoutTermUsers ,
1671
+ summaries. blockToState , diagnosticEmitter);
1667
1672
1668
1673
// If we had any errors, we do not want to modify the SIL... just bail.
1669
- if (emitter.compute (takeUpInsts, takeDownInsts)) {
1674
+ if (emitter.compute (summaries. takeUpInsts , summaries. takeDownInsts )) {
1670
1675
// TODO: Remove next line.
1671
1676
valuesWithDiagnostics.insert (markedAddress);
1672
1677
return true ;
0 commit comments