[K/N] Fixed a corner case in escape analysis

#KT-61409 Fixed
This commit is contained in:
Igor Chevdar
2023-08-27 12:51:00 +03:00
committed by Space Team
parent e80988d98c
commit 2e02ee4ec8
@@ -1353,7 +1353,7 @@ internal object EscapeAnalysis {
// (picking a leaf drain with only one incoming edge at a time). // (picking a leaf drain with only one incoming edge at a time).
// They can be removed because they don't add any relations between the parameters. // They can be removed because they don't add any relations between the parameters.
val reversedEdges = interestingDrains.associateWith { val reversedEdges = interestingDrains.associateWith {
mutableListOf<Pair<PointsToGraphNode, PointsToGraphEdge>>() mutableListOf<PointsToGraphNode>()
} }
val edgesCount = mutableMapOf<PointsToGraphNode, Int>() val edgesCount = mutableMapOf<PointsToGraphNode, Int>()
val leaves = mutableListOf<PointsToGraphNode>() val leaves = mutableListOf<PointsToGraphNode>()
@@ -1361,7 +1361,7 @@ internal object EscapeAnalysis {
var count = 0 var count = 0
for (edge in drain.edges) { for (edge in drain.edges) {
val nextDrain = edge.node.drain val nextDrain = edge.node.drain
reversedEdges[nextDrain]!! += drain to edge reversedEdges[nextDrain]!! += drain
if (nextDrain in interestingDrains) if (nextDrain in interestingDrains)
++count ++count
} }
@@ -1383,10 +1383,10 @@ internal object EscapeAnalysis {
if (drain in parameterDrains) if (drain in parameterDrains)
continue continue
if (incomingEdges.size == 1 if (incomingEdges.size == 1
&& incomingEdges[0].let { (node, edge) -> escapes(node) || !escapes(edge.node) } && (escapes(incomingEdges[0]) || !escapes(drain))
) { ) {
interestingDrains.remove(drain) interestingDrains.remove(drain)
val prevDrain = incomingEdges[0].first val prevDrain = incomingEdges[0]
val count = edgesCount[prevDrain]!! - 1 val count = edgesCount[prevDrain]!! - 1
edgesCount[prevDrain] = count edgesCount[prevDrain] = count
if (count == 0) if (count == 0)
@@ -1523,19 +1523,24 @@ internal object EscapeAnalysis {
.filter { nodeIds[it] == null } // Was optimized away. .filter { nodeIds[it] == null } // Was optimized away.
.forEach { drain -> .forEach { drain ->
val referencingNodes = findReferencing(drain).filter { nodeIds[it] != null } val referencingNodes = findReferencing(drain).filter { nodeIds[it] != null }
var needDrain = false if (escapes(drain) && referencingNodes.all { !escapes(it) }) {
outerLoop@ for (i in referencingNodes.indices)
for (j in i + 1 until referencingNodes.size) {
val firstNode = referencingNodes[i]
val secondNode = referencingNodes[j]
val pair = Pair(firstNode, secondNode)
if (pair !in connectedNodes) {
needDrain = true
break@outerLoop
}
}
if (needDrain)
nodeIds[drain] = drainFactory() nodeIds[drain] = drainFactory()
escapeOrigins += drain
} else {
var needDrain = false
outerLoop@ for (i in referencingNodes.indices)
for (j in i + 1 until referencingNodes.size) {
val firstNode = referencingNodes[i]
val secondNode = referencingNodes[j]
val pair = Pair(firstNode, secondNode)
if (pair !in connectedNodes) {
needDrain = true
break@outerLoop
}
}
if (needDrain)
nodeIds[drain] = drainFactory()
}
} }
} }