From e057e5ffac75ea9b46fb35e91d6df27c8ee53111 Mon Sep 17 00:00:00 2001 From: Igor Chevdar Date: Tue, 7 Sep 2021 11:33:31 +0500 Subject: [PATCH] [K/N][optmz] New strategy for resolving divergence of escape analysis --- .../konan/optimizations/EscapeAnalysis.kt | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/EscapeAnalysis.kt b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/EscapeAnalysis.kt index 8688ccc37d2..fb2bfbef59e 100644 --- a/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/EscapeAnalysis.kt +++ b/kotlin-native/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/EscapeAnalysis.kt @@ -133,6 +133,12 @@ internal object EscapeAnalysis { val PARAMETER = -2 } + object DivergenceResolutionParams { + const val MaxAttempts = 3 + const val NegligibleSize = 100 + const val SwellingFactor = 25 + } + private class RoleInfoEntry(val node: DataFlowIR.Node? = null, val field: DataFlowIR.Field?) private open class RoleInfo { @@ -553,7 +559,8 @@ internal object EscapeAnalysis { } } - val pointsToGraphs = nodes.associateBy({ it }, { PointsToGraph(it) }) + val nonTrivialComponent = nodes.size > 1 + val pointsToGraphs = mutableMapOf() val toAnalyze = mutableSetOf() toAnalyze.addAll(nodes) val numberOfRuns = nodes.associateWith { 0 }.toMutableMap() @@ -566,14 +573,26 @@ internal object EscapeAnalysis { val startResult = escapeAnalysisResults[function]!! context.log { "Start escape analysis result:\n$startResult" } - analyze(callGraph, pointsToGraphs[function]!!, function) + val pointsToGraph = PointsToGraph(function) + pointsToGraphs[function] = pointsToGraph + analyze(callGraph, pointsToGraph, function) val endResult = escapeAnalysisResults[function]!! if (startResult == endResult) { context.log { "Escape analysis is not changed" } } else { context.log { "Escape analysis was refined:\n$endResult" } - if (numberOfRuns[function]!! > 2) { + if (with(DivergenceResolutionParams) { + // A heuristic: the majority of functions have their points-to graph size linear in number of IR (or DFG) nodes, + // there are exceptions but it's a trade-off we have to make. + // The trick with [NegligibleSize] handles functions that basically delegate their work to other functions. + val numberOfNodes = intraproceduralAnalysisResults[function]!!.function.body.allScopes.sumOf { it.nodes.size } + val maxAllowedGraphSize = NegligibleSize + numberOfNodes * SwellingFactor + + numberOfRuns[function]!! > MaxAttempts + || (nonTrivialComponent && pointsToGraph.allNodes.size > maxAllowedGraphSize) + } + ) { // TODO: suboptimal. May be it is possible somehow handle the entire component at once? context.log { "WARNING: Escape analysis for $function seems not to be converging." +