From aaddc34b54616a7981d7259d25e792a1237e6388 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Mon, 10 Apr 2017 16:24:41 +0300 Subject: [PATCH] Optimize control-flow analysis algorithm There's no need to recalculate results if all of the previous instructions' results remain unchanged. It's a crucial optimizations because otherwise algorithm can degrate to O(n * m) [n - instructions number, m - variables number] even in a linear code like this: var a_1 = 1 var a_2 = 1 ... var a_m = 1 We perform analysis iteration once, then we repeat it to be sure that no changes happened and here for each instruction we're starting to check if recomputed value is the same, that basically compares maps of all the variables, so it works O(n * m) After this change on the second iteration we won't recompute new values as none of predecessor has been changed --- .../kotlin/cfg/PseudocodeTraverser.kt | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/PseudocodeTraverser.kt b/compiler/frontend/src/org/jetbrains/kotlin/cfg/PseudocodeTraverser.kt index 69804c1b0c0..66be8d77789 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/PseudocodeTraverser.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/PseudocodeTraverser.kt @@ -64,14 +64,13 @@ fun > Pseudocode.collectData( val edgesMap = LinkedHashMap>() edgesMap.put(getStartInstruction(traversalOrder), Edges(initialInfo, initialInfo)) - val changed = BooleanArray(1) - changed[0] = true - while (changed[0]) { - changed[0] = false + val changed = mutableMapOf() + do { collectDataFromSubgraph( traversalOrder, edgesMap, mergeEdges, updateEdge, Collections.emptyList(), changed, false) - } + } while (changed.any { it.value }) + return edgesMap } @@ -81,7 +80,7 @@ private fun > Pseudocode.collectDataFromSubgraph( mergeEdges: (Instruction, Collection) -> Edges, updateEdge: (Instruction, Instruction, I) -> I, previousSubGraphInstructions: Collection, - changed: BooleanArray, + changed: MutableMap, isLocal: Boolean ) { val instructions = getInstructions(traversalOrder) @@ -107,7 +106,13 @@ private fun > Pseudocode.collectDataFromSubgraph( updateEdgeDataForInstruction(instruction, previousValue, updatedValue, edgesMap, changed) continue } + + val previousDataValue = edgesMap[instruction] + if (previousDataValue != null && previousInstructions.all { changed[it] == false }) { + changed[instruction] = false + continue + } val incomingEdgesData = HashSet() @@ -139,11 +144,19 @@ private fun getPreviousIncludingSubGraphInstructions( } private fun > updateEdgeDataForInstruction( - instruction: Instruction, previousValue: Edges?, newValue: Edges?, edgesMap: MutableMap>, changed: BooleanArray) { + instruction: Instruction, + previousValue: Edges?, + newValue: Edges?, + edgesMap: MutableMap>, + changed: MutableMap +) { if (previousValue != newValue && newValue != null) { - changed[0] = true + changed[instruction] = true edgesMap.put(instruction, newValue) } + else { + changed[instruction] = false + } } data class Edges(val incoming: T, val outgoing: T)