[K/N][optmz] Better escape analysis divergence handling
This commit is contained in:
+46
-30
@@ -558,7 +558,6 @@ internal object EscapeAnalysis {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val nonTrivialComponent = nodes.size > 1
|
|
||||||
val pointsToGraphs = mutableMapOf<DataFlowIR.FunctionSymbol.Declared, PointsToGraph>()
|
val pointsToGraphs = mutableMapOf<DataFlowIR.FunctionSymbol.Declared, PointsToGraph>()
|
||||||
val toAnalyze = mutableSetOf<DataFlowIR.FunctionSymbol.Declared>()
|
val toAnalyze = mutableSetOf<DataFlowIR.FunctionSymbol.Declared>()
|
||||||
toAnalyze.addAll(nodes)
|
toAnalyze.addAll(nodes)
|
||||||
@@ -574,33 +573,40 @@ internal object EscapeAnalysis {
|
|||||||
|
|
||||||
val pointsToGraph = PointsToGraph(function)
|
val pointsToGraph = PointsToGraph(function)
|
||||||
pointsToGraphs[function] = pointsToGraph
|
pointsToGraphs[function] = pointsToGraph
|
||||||
analyze(callGraph, pointsToGraph, function)
|
|
||||||
val endResult = escapeAnalysisResults[function]!!
|
|
||||||
|
|
||||||
if (startResult == endResult) {
|
val maxAllowedGraphSize = with(DivergenceResolutionParams) {
|
||||||
context.log { "Escape analysis is not changed" }
|
// A heuristic: the majority of functions have their points-to graph size linear in number of IR (or DFG) nodes,
|
||||||
} else {
|
// there are exceptions but it's a trade-off we have to make.
|
||||||
context.log { "Escape analysis was refined:\n$endResult" }
|
// The trick with [NegligibleSize] handles functions that basically delegate their work to other functions.
|
||||||
if (with(DivergenceResolutionParams) {
|
val numberOfNodes = intraproceduralAnalysisResults[function]!!.function.body.allScopes.sumOf { it.nodes.size }
|
||||||
// A heuristic: the majority of functions have their points-to graph size linear in number of IR (or DFG) nodes,
|
NegligibleSize + numberOfNodes * SwellingFactor
|
||||||
// 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
|
var analyzedSuccessfully = analyze(callGraph, pointsToGraph, function, maxAllowedGraphSize)
|
||||||
|| (nonTrivialComponent && pointsToGraph.allNodes.size > maxAllowedGraphSize)
|
var processCallers = true
|
||||||
}
|
if (analyzedSuccessfully) {
|
||||||
) {
|
val endResult = escapeAnalysisResults[function]!!
|
||||||
// TODO: suboptimal. May be it is possible somehow handle the entire component at once?
|
if (startResult == endResult) {
|
||||||
context.log {
|
context.log { "Escape analysis is not changed" }
|
||||||
"WARNING: Escape analysis for $function seems not to be converging." +
|
processCallers = false
|
||||||
" Assuming conservative results."
|
} else {
|
||||||
}
|
context.log { "Escape analysis was refined:\n$endResult" }
|
||||||
escapeAnalysisResults[function] = FunctionEscapeAnalysisResult.pessimistic(function.parameters.size)
|
if (numberOfRuns[function]!! > DivergenceResolutionParams.MaxAttempts)
|
||||||
nodes.remove(function)
|
analyzedSuccessfully = false
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!analyzedSuccessfully) {
|
||||||
|
// 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." +
|
||||||
|
" Assuming conservative results."
|
||||||
|
}
|
||||||
|
escapeAnalysisResults[function] = FunctionEscapeAnalysisResult.pessimistic(function.parameters.size)
|
||||||
|
nodes.remove(function)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (processCallers) {
|
||||||
callGraph.reversedEdges[function]?.forEach {
|
callGraph.reversedEdges[function]?.forEach {
|
||||||
if (nodes.contains(it))
|
if (nodes.contains(it))
|
||||||
toAnalyze.add(it)
|
toAnalyze.add(it)
|
||||||
@@ -659,19 +665,27 @@ internal object EscapeAnalysis {
|
|||||||
private fun arraySize(itemSize: Int, length: Int): Long =
|
private fun arraySize(itemSize: Int, length: Int): Long =
|
||||||
pointerSize /* typeinfo */ + 4 /* size */ + itemSize * length.toLong()
|
pointerSize /* typeinfo */ + 4 /* size */ + itemSize * length.toLong()
|
||||||
|
|
||||||
private fun analyze(callGraph: CallGraph, pointsToGraph: PointsToGraph, function: DataFlowIR.FunctionSymbol.Declared) {
|
private fun analyze(
|
||||||
context.log {"Before calls analysis" }
|
callGraph: CallGraph,
|
||||||
|
pointsToGraph: PointsToGraph,
|
||||||
|
function: DataFlowIR.FunctionSymbol.Declared,
|
||||||
|
maxAllowedGraphSize: Int
|
||||||
|
): Boolean {
|
||||||
|
context.log { "Before calls analysis" }
|
||||||
pointsToGraph.log()
|
pointsToGraph.log()
|
||||||
pointsToGraph.logDigraph(false)
|
pointsToGraph.logDigraph(false)
|
||||||
|
|
||||||
callGraph.directEdges[function]!!.callSites.forEach {
|
callGraph.directEdges[function]!!.callSites.forEach {
|
||||||
val callee = it.actualCallee
|
val callee = it.actualCallee
|
||||||
val calleeEAResult = if (it.isVirtual)
|
val calleeEAResult = if (it.isVirtual)
|
||||||
getExternalFunctionEAResult(it)
|
getExternalFunctionEAResult(it)
|
||||||
else
|
else
|
||||||
callGraph.directEdges[callee]?.let { escapeAnalysisResults[it.symbol]!! }
|
callGraph.directEdges[callee]?.let { escapeAnalysisResults[it.symbol]!! }
|
||||||
?: getExternalFunctionEAResult(it)
|
?: getExternalFunctionEAResult(it)
|
||||||
pointsToGraph.processCall(it, calleeEAResult)
|
pointsToGraph.processCall(it, calleeEAResult)
|
||||||
|
|
||||||
|
if (pointsToGraph.allNodes.size > maxAllowedGraphSize)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
context.log { "After calls analysis" }
|
context.log { "After calls analysis" }
|
||||||
@@ -686,6 +700,8 @@ internal object EscapeAnalysis {
|
|||||||
pointsToGraph.logDigraph(true)
|
pointsToGraph.logDigraph(true)
|
||||||
|
|
||||||
escapeAnalysisResults[function] = eaResult
|
escapeAnalysisResults[function] = eaResult
|
||||||
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun DataFlowIR.FunctionSymbol.resolved(): DataFlowIR.FunctionSymbol {
|
private fun DataFlowIR.FunctionSymbol.resolved(): DataFlowIR.FunctionSymbol {
|
||||||
|
|||||||
Reference in New Issue
Block a user