@@ -558,7 +558,8 @@ void EscapeAnalysis::ConnectionGraph::initializePointsTo(CGNode *initialNode,
558
558
559
559
CGNode *predNode = pred.getPredNode ();
560
560
if (predNode->pointsTo ) {
561
- assert (predNode->pointsTo ->getMergeTarget () == newPointsTo);
561
+ assert (predNode->pointsTo ->getMergeTarget ()
562
+ == newPointsTo->getMergeTarget ());
562
563
return Traversal::Backtrack;
563
564
}
564
565
predNode->pointsTo = newPointsTo;
@@ -761,6 +762,11 @@ void EscapeAnalysis::ConnectionGraph::mergePointsTo(CGNode *initialNode,
761
762
CGNode *newPointsTo) {
762
763
CGNode *oldPointsTo = initialNode->pointsTo ;
763
764
assert (oldPointsTo && " merging content should not initialize any pointsTo" );
765
+
766
+ // newPointsTo may already be scheduled for a merge. Only create new edges to
767
+ // unmerged nodes. This may create a temporary pointsTo mismatch in the defer
768
+ // web, but Graph verification takes merged nodes into consideration.
769
+ newPointsTo = newPointsTo->getMergeTarget ();
764
770
if (oldPointsTo == newPointsTo)
765
771
return ;
766
772
@@ -870,8 +876,6 @@ CGNode *EscapeAnalysis::ConnectionGraph::createContentNode(
870
876
CGNode *newContent =
871
877
allocNode (nullptr , NodeType::Content, isInterior, hasReferenceOnly);
872
878
initializePointsToEdge (addrNode, newContent);
873
- assert (ToMerge.empty ()
874
- && " Initially setting pointsTo should not require any node merges" );
875
879
return newContent;
876
880
}
877
881
@@ -1002,57 +1006,58 @@ bool EscapeAnalysis::ConnectionGraph::mergeFrom(ConnectionGraph *SourceGraph,
1002
1006
CGNodeMap &Mapping) {
1003
1007
// The main point of the merging algorithm is to map each content node in the
1004
1008
// source graph to a content node in this (destination) graph. This may
1005
- // require to create new nodes or to merge existing nodes in this graph.
1009
+ // require creating new nodes or merging existing nodes in this graph.
1006
1010
1007
1011
// First step: replicate the points-to edges and the content nodes of the
1008
1012
// source graph in this graph.
1009
1013
bool Changed = false ;
1010
- bool NodesMerged;
1011
- do {
1012
- NodesMerged = false ;
1013
- for (unsigned Idx = 0 ; Idx < Mapping.getMappedNodes ().size (); ++Idx) {
1014
- CGNode *SourceNd = Mapping.getMappedNodes ()[Idx];
1015
- CGNode *DestNd = Mapping.get (SourceNd);
1016
- assert (DestNd);
1017
-
1018
- if (SourceNd->getEscapeState () >= EscapeState::Global) {
1019
- // We don't need to merge the source subgraph of nodes which have the
1020
- // global escaping state set.
1021
- // Just set global escaping in the caller node and that's it.
1022
- Changed |= DestNd->mergeEscapeState (EscapeState::Global);
1023
- // If DestNd is an interior node, its content still needs to be created.
1024
- if (!DestNd->isInterior ())
1025
- continue ;
1026
- }
1027
-
1028
- CGNode *SourcePT = SourceNd->pointsTo ;
1029
- if (!SourcePT)
1014
+ for (unsigned Idx = 0 ; Idx < Mapping.getMappedNodes ().size (); ++Idx) {
1015
+ CGNode *SourceNd = Mapping.getMappedNodes ()[Idx];
1016
+ CGNode *DestNd = Mapping.get (SourceNd);
1017
+ assert (DestNd);
1018
+
1019
+ if (SourceNd->getEscapeState () >= EscapeState::Global) {
1020
+ // We don't need to merge the source subgraph of nodes which have the
1021
+ // global escaping state set.
1022
+ // Just set global escaping in the caller node and that's it.
1023
+ Changed |= DestNd->mergeEscapeState (EscapeState::Global);
1024
+ // If DestNd is an interior node, its content still needs to be created.
1025
+ if (!DestNd->isInterior ())
1030
1026
continue ;
1027
+ }
1028
+
1029
+ CGNode *SourcePT = SourceNd->pointsTo ;
1030
+ if (!SourcePT)
1031
+ continue ;
1031
1032
1032
- CGNode *DestPT = DestNd->pointsTo ;
1033
+ CGNode *MappedDestPT = Mapping.get (SourcePT);
1034
+ CGNode *DestPT = DestNd->pointsTo ;
1035
+ if (!MappedDestPT) {
1033
1036
if (!DestPT) {
1034
1037
DestPT = createMergedContent (DestNd, SourcePT);
1035
1038
Changed = true ;
1036
1039
}
1037
- CGNode *MappedDestPT = Mapping.get (SourcePT);
1038
- if (!MappedDestPT) {
1039
- // This is the first time the dest node is seen; just add the mapping.
1040
- Mapping.add (SourcePT, DestPT);
1041
- continue ;
1042
- }
1043
- // We already found the destination node through another path.
1044
- assert (Mapping.getMappedNodes ().contains (SourcePT));
1045
- if (DestPT == MappedDestPT)
1046
- continue ;
1040
+ // This is the first time the dest node is seen; just add the mapping.
1041
+ Mapping.add (SourcePT, DestPT);
1042
+ continue ;
1043
+ }
1044
+ if (DestPT == MappedDestPT)
1045
+ continue ;
1047
1046
1048
- // There are two content nodes in this graph which map to the same
1049
- // content node in the source graph -> we have to merge them.
1050
- scheduleToMerge (DestPT, MappedDestPT) ;
1051
- mergeAllScheduledNodes ();
1052
- Changed = true ;
1053
- NodesMerged = true ;
1047
+ // We already found the destination node through another path.
1048
+ assert (Mapping. getMappedNodes (). contains (SourcePT));
1049
+ Changed = true ;
1050
+ if (!DestPT) {
1051
+ initializePointsToEdge (DestNd, MappedDestPT) ;
1052
+ continue ;
1054
1053
}
1055
- } while (NodesMerged);
1054
+ // There are two content nodes in this graph which map to the same
1055
+ // content node in the source graph -> we have to merge them.
1056
+ // Defer merging the nodes until all mapped nodes are created so that the
1057
+ // graph is structurally valid before merging.
1058
+ scheduleToMerge (DestPT, MappedDestPT);
1059
+ }
1060
+ mergeAllScheduledNodes ();
1056
1061
Mapping.getMappedNodes ().reset (); // Make way for a different worklist.
1057
1062
1058
1063
// Second step: add the source graph's defer edges to this graph.
0 commit comments