[K/N][codegen] Removed square graph swelling during escape analysis
Helps with https://youtrack.jetbrains.com/issue/KT-44148
This commit is contained in:
+18
-18
@@ -1359,14 +1359,17 @@ internal object EscapeAnalysis {
|
|||||||
drainFactory: () -> CompressedPointsToGraph.Node
|
drainFactory: () -> CompressedPointsToGraph.Node
|
||||||
) {
|
) {
|
||||||
// Here we try to find this subgraph within one component: [v -> d; w -> d; v !-> w; w !-> v].
|
// Here we try to find this subgraph within one component: [v -> d; w -> d; v !-> w; w !-> v].
|
||||||
// In most cases such a node [d] is just the drain of the component,
|
|
||||||
// but it may have been optimized away.
|
|
||||||
// This is needed because components are built with edges being considered undirected, so
|
// This is needed because components are built with edges being considered undirected, so
|
||||||
// this implicit connection between [v] and [w] may be needed. Note, however, that the
|
// this implicit connection between [v] and [w] may be needed. Note, however, that the
|
||||||
// opposite subgraph: [d -> v; d -> w; v !-> w; w !-> v] is not interesting, because [d]
|
// opposite subgraph: [d -> v; d -> w; v !-> w; w !-> v] is not interesting, because [d]
|
||||||
// can't hold both values simultaneously, but two references can hold the same value
|
// can't hold both values simultaneously, but two references can hold the same value
|
||||||
// at the same time, that's the difference.
|
// at the same time, that's the difference.
|
||||||
// For concrete example see [codegen/escapeAnalysis/test10.kt].
|
// For concrete example see [codegen/escapeAnalysis/test10.kt].
|
||||||
|
// Note: it is possible to search not for all such nodes, but for drains only, here's why:
|
||||||
|
// Assume a node [v] which is referenced from the two fixed nodes is found, then consider
|
||||||
|
// the [v]'s drain, by construction all drains are reachable from all nodes within the corresponding
|
||||||
|
// component, including [v]; this implies that the drain also is referenced from these two nodes,
|
||||||
|
// and therefore it is possible to check only drains rather than all nodes.
|
||||||
val connectedNodes = mutableSetOf<Pair<PointsToGraphNode, PointsToGraphNode>>()
|
val connectedNodes = mutableSetOf<Pair<PointsToGraphNode, PointsToGraphNode>>()
|
||||||
allNodes.filter { nodeIds[it] != null && nodeIds[it.drain] == null /* The drain has been optimized away */ }
|
allNodes.filter { nodeIds[it] != null && nodeIds[it.drain] == null /* The drain has been optimized away */ }
|
||||||
.forEach { node ->
|
.forEach { node ->
|
||||||
@@ -1379,27 +1382,24 @@ internal object EscapeAnalysis {
|
|||||||
connectedNodes.add(Pair(secondNode, firstNode))
|
connectedNodes.add(Pair(secondNode, firstNode))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
allNodes.filter { nodeIds[it] == null && it.drain in interestingDrains && nodeIds[it.drain] == null }
|
|
||||||
.forEach { node ->
|
interestingDrains
|
||||||
val referencingNodes = findReferencing(node).filter { nodeIds[it] != null }
|
.filter { nodeIds[it] == null } // Was optimized away.
|
||||||
for (i in referencingNodes.indices)
|
.forEach { drain ->
|
||||||
|
val referencingNodes = findReferencing(drain).filter { nodeIds[it] != null }
|
||||||
|
var needDrain = false
|
||||||
|
outerLoop@ for (i in referencingNodes.indices)
|
||||||
for (j in i + 1 until referencingNodes.size) {
|
for (j in i + 1 until referencingNodes.size) {
|
||||||
val firstNode = referencingNodes[i]
|
val firstNode = referencingNodes[i]
|
||||||
val secondNode = referencingNodes[j]
|
val secondNode = referencingNodes[j]
|
||||||
val pair = Pair(firstNode, secondNode)
|
val pair = Pair(firstNode, secondNode)
|
||||||
if (pair in connectedNodes) continue
|
if (pair !in connectedNodes) {
|
||||||
|
needDrain = true
|
||||||
// It is not an actual drain, but a temporary node to reflect the found constraint.
|
break@outerLoop
|
||||||
val additionalDrain = newDrain()
|
}
|
||||||
// For consistency.
|
|
||||||
additionalDrain.depth = min(firstNode.depth, secondNode.depth)
|
|
||||||
|
|
||||||
firstNode.addAssignmentEdge(additionalDrain)
|
|
||||||
secondNode.addAssignmentEdge(additionalDrain)
|
|
||||||
nodeIds[additionalDrain] = drainFactory()
|
|
||||||
connectedNodes.add(pair)
|
|
||||||
connectedNodes.add(Pair(secondNode, firstNode))
|
|
||||||
}
|
}
|
||||||
|
if (needDrain)
|
||||||
|
nodeIds[drain] = drainFactory()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user