@@ -456,24 +456,18 @@ void EscapeAnalysis::ConnectionGraph::initializePointsTo(CGNode *initialNode,
456
456
CGNode *newPointsTo,
457
457
bool createEdge) {
458
458
// Track nodes that require pointsTo edges.
459
- llvm::SmallVector<CGNode *, 4 > pointsToEdges;
459
+ llvm::SmallVector<CGNode *, 4 > pointsToEdgeNodes;
460
+ if (createEdge)
461
+ pointsToEdgeNodes.push_back (initialNode);
460
462
461
463
// Step 1: Visit each node that reaches or is reachable via defer edges until
462
464
// reaching a node with the newPointsTo or with a proper pointsTo edge.
463
465
464
466
// A worklist to gather updated nodes in the defer web.
465
467
CGNodeWorklist updatedNodes (this );
466
- updatedNodes.push (initialNode);
467
- if (createEdge)
468
- pointsToEdges.push_back (initialNode);
469
- unsigned updateCount = 1 ;
470
- assert (updateCount == updatedNodes.size ());
471
- // Augment the worlist with the nodes that were reached via backward
472
- // traversal. It's not as precise as DFS, but helps avoid redundant pointsTo
473
- // edges in most cases.
474
- llvm::SmallPtrSet<CGNode *, 8 > backwardReachable;
475
-
476
- auto visitDeferTarget = [&](CGNode *node, bool isSuccessor) {
468
+ unsigned updateCount = 0 ;
469
+
470
+ auto visitDeferTarget = [&](CGNode *node, bool /* isSuccessor*/ ) {
477
471
if (updatedNodes.contains (node))
478
472
return true ;
479
473
@@ -484,7 +478,7 @@ void EscapeAnalysis::ConnectionGraph::initializePointsTo(CGNode *initialNode,
484
478
// nodes are initialized one at a time, each time a new defer edge is
485
479
// created. If this were not complete, then the backward traversal below
486
480
// in Step 2 could reach uninitialized nodes not seen here in Step 1.
487
- pointsToEdges .push_back (node);
481
+ pointsToEdgeNodes .push_back (node);
488
482
return true ;
489
483
}
490
484
++updateCount;
@@ -493,31 +487,29 @@ void EscapeAnalysis::ConnectionGraph::initializePointsTo(CGNode *initialNode,
493
487
// edge. Create a "fake" pointsTo edge to maintain the graph invariant
494
488
// (this changes the structure of the graph but adding this edge has no
495
489
// effect on the process of merging nodes or creating new defer edges).
496
- pointsToEdges .push_back (node);
490
+ pointsToEdgeNodes .push_back (node);
497
491
}
498
492
updatedNodes.push (node);
499
- if (!isSuccessor)
500
- backwardReachable.insert (node);
501
-
502
493
return true ;
503
494
};
495
+ // Seed updatedNodes with initialNode.
496
+ visitDeferTarget (initialNode, true );
504
497
// updatedNodes may grow during this loop.
505
- unsigned nextUpdatedNodeIdx = 0 ;
506
- for (; nextUpdatedNodeIdx < updatedNodes.size (); ++nextUpdatedNodeIdx)
507
- updatedNodes[nextUpdatedNodeIdx]->visitDefers (visitDeferTarget);
498
+ for (unsigned idx = 0 ; idx < updatedNodes.size (); ++idx)
499
+ updatedNodes[idx]->visitDefers (visitDeferTarget);
508
500
// Reset this worklist so others can be used, but updateNode.nodeVector still
509
501
// holds all the nodes found by step 1.
510
502
updatedNodes.reset ();
511
503
512
504
// Step 2: Update pointsTo fields by propagating backward from nodes that
513
505
// already have a pointsTo edge.
514
- assert (nextUpdatedNodeIdx == updatedNodes.size ());
515
- --nextUpdatedNodeIdx;
516
- bool processBackwardReachable = false ;
517
506
do {
518
- while (!pointsToEdges .empty ()) {
519
- CGNode *edgeNode = pointsToEdges .pop_back_val ();
507
+ while (!pointsToEdgeNodes .empty ()) {
508
+ CGNode *edgeNode = pointsToEdgeNodes .pop_back_val ();
520
509
if (!edgeNode->pointsTo ) {
510
+ // This node is either (1) a leaf node in the defer web (identified in
511
+ // step 1) or (2) an arbitrary node in a defer-cycle (identified in a
512
+ // previous iteration of the outer loop).
521
513
edgeNode->setPointsToEdge (newPointsTo);
522
514
newPointsTo->mergeUsePoints (edgeNode);
523
515
assert (updateCount--);
@@ -542,35 +534,19 @@ void EscapeAnalysis::ConnectionGraph::initializePointsTo(CGNode *initialNode,
542
534
return Traversal::Follow;
543
535
});
544
536
}
545
- // For all nodes visited in step 1, if any node was not backward-reachable
546
- // from a pointsTo edge, create an edge for it and restart traversal.
547
- //
548
- // First process all forward-reachable nodes in backward order, then process
549
- // all backwardReachable nodes in forward order.
550
- while (nextUpdatedNodeIdx != updatedNodes.size ()) {
551
- CGNode *node = updatedNodes[nextUpdatedNodeIdx];
552
- // When processBackwardReachable == true, the backwardReachable set is
553
- // empty and all forward reachable nodes already have a pointsTo edge.
554
- if (!backwardReachable.count (node)) {
555
- if (!node->pointsTo ) {
556
- pointsToEdges.push_back (node);
557
- break ;
558
- }
559
- }
560
- if (processBackwardReachable) {
561
- ++nextUpdatedNodeIdx;
562
- continue ;
563
- }
564
- if (nextUpdatedNodeIdx > 0 ) {
565
- --nextUpdatedNodeIdx;
566
- continue ;
537
+ // For all nodes visited in step 1, pick a single node that was not
538
+ // backward-reachable from a pointsTo edge, create an edge for it and
539
+ // restart traversal. This only happens when step 1 fails to find leaves in
540
+ // the defer web because of defer edge cycles.
541
+ while (!updatedNodes.empty ()) {
542
+ CGNode *node = updatedNodes.nodeVector .pop_back_val ();
543
+ if (!node->pointsTo ) {
544
+ pointsToEdgeNodes.push_back (node);
545
+ break ;
567
546
}
568
- // reverse direction
569
- backwardReachable.clear ();
570
- processBackwardReachable = true ;
571
547
}
572
548
// This outer loop is exceedingly unlikely to execute more than twice.
573
- } while (!pointsToEdges .empty ());
549
+ } while (!pointsToEdgeNodes .empty ());
574
550
assert (updateCount == 0 );
575
551
}
576
552
0 commit comments