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
This commit is contained in:
@@ -64,14 +64,13 @@ fun <I : ControlFlowInfo<*, *>> Pseudocode.collectData(
|
||||
val edgesMap = LinkedHashMap<Instruction, Edges<I>>()
|
||||
edgesMap.put(getStartInstruction(traversalOrder), Edges(initialInfo, initialInfo))
|
||||
|
||||
val changed = BooleanArray(1)
|
||||
changed[0] = true
|
||||
while (changed[0]) {
|
||||
changed[0] = false
|
||||
val changed = mutableMapOf<Instruction, Boolean>()
|
||||
do {
|
||||
collectDataFromSubgraph(
|
||||
traversalOrder, edgesMap,
|
||||
mergeEdges, updateEdge, Collections.emptyList<Instruction>(), changed, false)
|
||||
}
|
||||
} while (changed.any { it.value })
|
||||
|
||||
return edgesMap
|
||||
}
|
||||
|
||||
@@ -81,7 +80,7 @@ private fun <I : ControlFlowInfo<*, *>> Pseudocode.collectDataFromSubgraph(
|
||||
mergeEdges: (Instruction, Collection<I>) -> Edges<I>,
|
||||
updateEdge: (Instruction, Instruction, I) -> I,
|
||||
previousSubGraphInstructions: Collection<Instruction>,
|
||||
changed: BooleanArray,
|
||||
changed: MutableMap<Instruction, Boolean>,
|
||||
isLocal: Boolean
|
||||
) {
|
||||
val instructions = getInstructions(traversalOrder)
|
||||
@@ -107,7 +106,13 @@ private fun <I : ControlFlowInfo<*, *>> 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<I>()
|
||||
|
||||
@@ -139,11 +144,19 @@ private fun getPreviousIncludingSubGraphInstructions(
|
||||
}
|
||||
|
||||
private fun <I : ControlFlowInfo<*, *>> updateEdgeDataForInstruction(
|
||||
instruction: Instruction, previousValue: Edges<I>?, newValue: Edges<I>?, edgesMap: MutableMap<Instruction, Edges<I>>, changed: BooleanArray) {
|
||||
instruction: Instruction,
|
||||
previousValue: Edges<I>?,
|
||||
newValue: Edges<I>?,
|
||||
edgesMap: MutableMap<Instruction, Edges<I>>,
|
||||
changed: MutableMap<Instruction, Boolean>
|
||||
) {
|
||||
if (previousValue != newValue && newValue != null) {
|
||||
changed[0] = true
|
||||
changed[instruction] = true
|
||||
edgesMap.put(instruction, newValue)
|
||||
}
|
||||
else {
|
||||
changed[instruction] = false
|
||||
}
|
||||
}
|
||||
|
||||
data class Edges<out T>(val incoming: T, val outgoing: T)
|
||||
|
||||
Reference in New Issue
Block a user