Skip to content

Commit

Permalink
[IR] Correct handling of loops in liveness analysis
Browse files Browse the repository at this point in the history
 #KT-64139 Fixed
  • Loading branch information
homuroll authored and qodana-bot committed Dec 19, 2023
1 parent 204cecd commit cfbb957
Showing 1 changed file with 24 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,31 @@ object LivenessAnalysis {
}
}

// May be used for debug purposes.
@Suppress("unused")
private fun BitSet.format() = buildString {
append('[')
var first = true
forEachBit {
if (!first) append(", ")
first = false
append(variables[it].name)
}
append(']')
}

private fun getVariableId(variable: IrVariable) = variableIds.getOrPut(variable) {
variables.add(variable)
variables.lastIndex
}

private inline fun <T : IrElement> saveAndCompute(element: T, liveVariables: BitSet, compute: () -> BitSet): BitSet {
if (filter(element))
filteredElementEndsLV[element] = liveVariables.copy().also { it.or(catchesLV) }
if (filter(element)) {
// Merge with the previous because of the loops (see the comment there).
val elementLV = filteredElementEndsLV.getOrPut(element) { BitSet() }
elementLV.or(liveVariables)
elementLV.or(catchesLV)
}
return compute()
}

Expand Down Expand Up @@ -217,13 +234,15 @@ object LivenessAnalysis {
loopEndsLV[loop] = data
var bodyEndLV = loop.condition.accept(this, data)
val body = loop.body ?: return bodyEndLV
var bodyStartLV: BitSet
val bodyStartLV = BitSet()
// In practice, only one or two iterations seem to be enough, but the classic algorithm
// loops until "saturation" (when nothing changes anymore).
do {
loopStartsLV[loop] = bodyEndLV
bodyStartLV = body.accept(this, bodyEndLV)
val nextBodyEndLV = loop.condition.accept(this, bodyStartLV)
val curBodyStartLV = body.accept(this, bodyEndLV)
// Since it's unknown how many iterations the loop will execute, merge the live variables at each iteration.
bodyStartLV.or(curBodyStartLV)
val nextBodyEndLV = loop.condition.accept(this, curBodyStartLV)
val lvHaveChanged = nextBodyEndLV != bodyEndLV
bodyEndLV = nextBodyEndLV
} while (lvHaveChanged)
Expand Down

0 comments on commit cfbb957

Please sign in to comment.