backend: Don't create a Progression objects in 'for' loops

This patch optimizes the following pattern:

for (i in first..last step st) { ... }

In this case we need to create a Progression object and then call its
iterator() method causing at least 2 allocation per loop. This change
replaces such loops with the following constuction:

var inductionVar = first
checkProgressionStep(step)  // check if step > 0
last = getProgressionLastElement(first, last, step)
if (first <= last) {
    do {
        i = inductionVar
        inductionVar += step
        ...
    } while(i != last)
}
This commit is contained in:
Ilya Matveev
2017-06-29 13:25:48 +07:00
committed by ilmat192
parent 06e31939dd
commit d474f207e3
10 changed files with 668 additions and 3 deletions
@@ -16,6 +16,8 @@
package konan.internal
import kotlin.internal.getProgressionLastElement
@ExportForCppRuntime
fun ThrowNullPointerException(): Nothing {
throw NullPointerException()
@@ -84,4 +86,13 @@ fun <T: Enum<T>> valuesForEnum(values: Array<T>): Array<T>
result[value.ordinal] = value
@Suppress("UNCHECKED_CAST")
return result as Array<T>
}
}
fun checkProgressionStep(step: Int) = if (step > 0) step else throw IllegalArgumentException("Step must be positive, was: $step.")
fun checkProgressionStep(step: Long) = if (step > 0) step else throw IllegalArgumentException("Step must be positive, was: $step.")
fun getProgressionBound(start: Char, end: Char, step: Int): Char =
getProgressionBound(start.toInt(), end.toInt(), step).toChar()
fun getProgressionBound(start: Int, end: Int, step: Int): Int = getProgressionLastElement(start, end, step)
fun getProgressionBound(start: Long, end: Long, step: Long): Long = getProgressionLastElement(start, end, step)