@@ -609,7 +609,7 @@ void EscapeAnalysis::ConnectionGraph::mergeAllScheduledNodes() {
609
609
// To pointsTo-> NodeB (but still has a pointsTo edge to NodeB)
610
610
while (!ToMerge.empty ()) {
611
611
if (EnableInternalVerify)
612
- verify ( /* allowMerge= */ true );
612
+ verifyStructure ( true /* allowMerge*/ );
613
613
614
614
CGNode *From = ToMerge.pop_back_val ();
615
615
CGNode *To = From->getMergeTarget ();
@@ -745,7 +745,6 @@ void EscapeAnalysis::ConnectionGraph::mergeAllScheduledNodes() {
745
745
From->isMerged = true ;
746
746
747
747
if (From->mappedValue ) {
748
- // If possible, transfer 'From's mappedValue to 'To' for clarity. Any
749
748
// values previously mapped to 'From' but not transferred to 'To's
750
749
// mappedValue must remain mapped to 'From'. Lookups on those values will
751
750
// find 'To' via the mergeTarget. Dropping a value's mapping is illegal
@@ -762,7 +761,7 @@ void EscapeAnalysis::ConnectionGraph::mergeAllScheduledNodes() {
762
761
From->pointsTo = nullptr ;
763
762
}
764
763
if (EnableInternalVerify)
765
- verify ( /* allowMerge= */ true );
764
+ verifyStructure ( true /* allowMerge*/ );
766
765
}
767
766
768
767
// As a result of a merge, update the pointsTo field of initialNode and
@@ -1574,21 +1573,40 @@ bool CGNode::matchPointToOfDefers(bool allowMerge) const {
1574
1573
return true ;
1575
1574
}
1576
1575
1577
- void EscapeAnalysis::ConnectionGraph::verify (bool allowMerge ) const {
1576
+ void EscapeAnalysis::ConnectionGraph::verify () const {
1578
1577
#ifndef NDEBUG
1579
- verifyStructure (allowMerge);
1578
+ // Invalidating EscapeAnalysis clears the connection graph.
1579
+ if (isEmpty ())
1580
+ return ;
1580
1581
1581
- // Check graph invariants
1582
- for (CGNode *Nd : Nodes) {
1583
- // ConnectionGraph invariant #4: For any node N, all paths starting at N
1584
- // which consist of only defer-edges and a single trailing points-to edge
1585
- // must lead to the same
1586
- assert (Nd->matchPointToOfDefers (allowMerge));
1587
- if (Nd->mappedValue && !(allowMerge && Nd->isMerged )) {
1588
- assert (Nd == Values2Nodes.lookup (Nd->mappedValue ));
1589
- assert (EA->isPointer (Nd->mappedValue ));
1590
- // Nodes must always be mapped from the pointer root value.
1591
- assert (Nd->mappedValue == EA->getPointerRoot (Nd->mappedValue ));
1582
+ verifyStructure ();
1583
+
1584
+ // Verify that all pointer nodes are still mapped, otherwise the process of
1585
+ // merging nodes may have lost information.
1586
+ for (SILBasicBlock &BB : *F) {
1587
+ for (auto &I : BB) {
1588
+ if (isNonWritableMemoryAddress (&I))
1589
+ continue ;
1590
+
1591
+ if (auto ai = dyn_cast<ApplyInst>(&I)) {
1592
+ if (EA->canOptimizeArrayUninitializedCall (ai, this ).isValid ())
1593
+ continue ;
1594
+ }
1595
+ for (auto result : I.getResults ()) {
1596
+ if (EA->getPointerBase (result))
1597
+ continue ;
1598
+
1599
+ if (!EA->isPointer (result))
1600
+ continue ;
1601
+
1602
+ if (!Values2Nodes.lookup (result)) {
1603
+ llvm::dbgs () << " No CG mapping for " ;
1604
+ result->dumpInContext ();
1605
+ llvm::dbgs () << " in:\n " ;
1606
+ F->dump ();
1607
+ llvm_unreachable (" Missing escape connection graph mapping" );
1608
+ }
1609
+ }
1592
1610
}
1593
1611
}
1594
1612
#endif
@@ -1597,6 +1615,7 @@ void EscapeAnalysis::ConnectionGraph::verify(bool allowMerge) const {
1597
1615
void EscapeAnalysis::ConnectionGraph::verifyStructure (bool allowMerge) const {
1598
1616
#ifndef NDEBUG
1599
1617
for (CGNode *Nd : Nodes) {
1618
+ // Verify the graph structure...
1600
1619
if (Nd->isMerged ) {
1601
1620
assert (Nd->mergeTo );
1602
1621
assert (!Nd->pointsTo );
@@ -1625,6 +1644,19 @@ void EscapeAnalysis::ConnectionGraph::verifyStructure(bool allowMerge) const {
1625
1644
}
1626
1645
if (Nd->isInterior ())
1627
1646
assert (Nd->pointsTo && " Interior content node requires a pointsTo node" );
1647
+
1648
+ // ConnectionGraph invariant #4: For any node N, all paths starting at N
1649
+ // which consist of only defer-edges and a single trailing points-to edge
1650
+ // must lead to the same
1651
+ assert (Nd->matchPointToOfDefers (allowMerge));
1652
+
1653
+ // Verify the node to value mapping...
1654
+ if (Nd->mappedValue && !(allowMerge && Nd->isMerged )) {
1655
+ assert (Nd == Values2Nodes.lookup (Nd->mappedValue ));
1656
+ assert (EA->isPointer (Nd->mappedValue ));
1657
+ // Nodes must always be mapped from the pointer root value.
1658
+ assert (Nd->mappedValue == EA->getPointerRoot (Nd->mappedValue ));
1659
+ }
1628
1660
}
1629
1661
#endif
1630
1662
}
@@ -1780,8 +1812,8 @@ bool EscapeAnalysis::buildConnectionGraphForDestructor(
1780
1812
}
1781
1813
1782
1814
EscapeAnalysis::ArrayUninitCall
1783
- EscapeAnalysis::canOptimizeArrayUninitializedCall (ApplyInst *ai,
1784
- ConnectionGraph *conGraph) {
1815
+ EscapeAnalysis::canOptimizeArrayUninitializedCall (
1816
+ ApplyInst *ai, const ConnectionGraph *conGraph) {
1785
1817
ArrayUninitCall call;
1786
1818
// This must be an exact match so we don't accidentally optimize
1787
1819
// "array.uninitialized_intrinsic".
@@ -2425,7 +2457,7 @@ void EscapeAnalysis::recompute(FunctionInfo *Initial) {
2425
2457
if (BottomUpOrder.wasRecomputedWithCurrentUpdateID (FInfo)) {
2426
2458
FInfo->Graph .computeUsePoints ();
2427
2459
FInfo->Graph .verify ();
2428
- FInfo->SummaryGraph .verify ();
2460
+ FInfo->SummaryGraph .verifyStructure ();
2429
2461
}
2430
2462
}
2431
2463
}
@@ -2766,6 +2798,25 @@ void EscapeAnalysis::handleDeleteNotification(SILNode *node) {
2766
2798
}
2767
2799
}
2768
2800
2801
+ void EscapeAnalysis::verify () const {
2802
+ #ifndef NDEBUG
2803
+ for (auto Iter : Function2Info) {
2804
+ FunctionInfo *FInfo = Iter.second ;
2805
+ FInfo->Graph .verify ();
2806
+ FInfo->SummaryGraph .verifyStructure ();
2807
+ }
2808
+ #endif
2809
+ }
2810
+
2811
+ void EscapeAnalysis::verify (SILFunction *F) const {
2812
+ #ifndef NDEBUG
2813
+ if (FunctionInfo *FInfo = Function2Info.lookup (F)) {
2814
+ FInfo->Graph .verify ();
2815
+ FInfo->SummaryGraph .verifyStructure ();
2816
+ }
2817
+ #endif
2818
+ }
2819
+
2769
2820
SILAnalysis *swift::createEscapeAnalysis (SILModule *M) {
2770
2821
return new EscapeAnalysis (M);
2771
2822
}
0 commit comments