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
@@ -0,0 +1,54 @@
fun main(args: Array<String>) {
// Simple loops
for (i in 0..4) {
print(i)
}
println()
for (i in 0 until 4) {
print(i)
}
println()
for (i in 4 downTo 0) {
print(i)
}
println()
println()
// Steps
for (i in 0..4 step 2) {
print(i)
}
println()
for (i in 0 until 4 step 2) {
print(i)
}
println()
for (i in 4 downTo 0 step 2) {
print(i)
}
println()
println()
// Two steps
for (i in 0..6 step 2 step 3) {
print(i)
}
println()
for (i in 0 until 6 step 2 step 3) {
print(i)
}
println()
for (i in 6 downTo 0 step 2 step 3) {
print(i)
}
println()
println()
}
@@ -0,0 +1,51 @@
fun main(args: Array<String>) {
// Negative step.
try {
for (i in 0 .. 4 step -2) print(i); println()
throw AssertionError()
} catch (e: IllegalArgumentException) {}
try {
for (i in 0 until 4 step -2) print(i); println()
throw AssertionError()
} catch (e: IllegalArgumentException) {}
try {
for (i in 4 downTo 0 step -2) print(i); println()
throw AssertionError()
} catch (e: IllegalArgumentException) {}
// Zero step.
try {
for (i in 0 .. 4 step 0) print(i); println()
throw AssertionError()
} catch (e: IllegalArgumentException) {}
try {
for (i in 0 until 4 step 0) print(i); println()
throw AssertionError()
} catch (e: IllegalArgumentException) {}
try {
for (i in 4 downTo 0 step 0) print(i); println()
throw AssertionError()
} catch (e: IllegalArgumentException) {}
// Two steps, one is negative.
try {
for (i in 0 .. 4 step -2 step 3) print(i); println()
throw AssertionError()
} catch (e: IllegalArgumentException) {}
try {
for (i in 0 until 4 step -2 step 3) print(i); println()
throw AssertionError()
} catch (e: IllegalArgumentException) {}
try {
for (i in 4 downTo 0 step -2 step 3) print(i); println()
throw AssertionError()
} catch (e: IllegalArgumentException) {}
println("OK")
}
@@ -0,0 +1,8 @@
fun main(args: Array<String>) {
for (i in Int.MAX_VALUE - 1 .. Int.MAX_VALUE) { print(i); print(' ') }; println()
for (i in Int.MAX_VALUE - 1 until Int.MAX_VALUE) { print(i); print(' ') }; println()
for (i in Int.MIN_VALUE + 1 downTo Int.MIN_VALUE) { print(i); print(' ') }; println()
val M = Int.MAX_VALUE / 2
for (i in M + 4..M + 10 step M) { print(i); print(' ') }; println()
}
@@ -0,0 +1,55 @@
fun main(args: Array<String>) {
for (i in 0.toByte() .. 4.toByte()) print(i); println()
for (i in 0.toByte() .. 4.toShort()) print(i); println()
for (i in 0.toByte() .. 4.toInt()) print(i); println()
for (i in 0.toByte() .. 4.toLong()) print(i); println()
for (i in 0.toShort() .. 4.toByte()) print(i); println()
for (i in 0.toShort() .. 4.toShort()) print(i); println()
for (i in 0.toShort() .. 4.toInt()) print(i); println()
for (i in 0.toShort() .. 4.toLong()) print(i); println()
for (i in 0.toInt() .. 4.toByte()) print(i); println()
for (i in 0.toInt() .. 4.toShort()) print(i); println()
for (i in 0.toInt() .. 4.toInt()) print(i); println()
for (i in 0.toInt() .. 4.toLong()) print(i); println()
for (i in 0.toLong() .. 4.toByte()) print(i); println()
for (i in 0.toLong() .. 4.toShort()) print(i); println()
for (i in 0.toLong() .. 4.toInt()) print(i); println()
for (i in 0.toLong() .. 4.toLong()) print(i); println()
for (i in 0.toByte() until 4.toByte()) print(i); println()
for (i in 0.toByte() until 4.toShort()) print(i); println()
for (i in 0.toByte() until 4.toInt()) print(i); println()
for (i in 0.toByte() until 4.toLong()) print(i); println()
for (i in 0.toShort() until 4.toByte()) print(i); println()
for (i in 0.toShort() until 4.toShort()) print(i); println()
for (i in 0.toShort() until 4.toInt()) print(i); println()
for (i in 0.toShort() until 4.toLong()) print(i); println()
for (i in 0.toInt() until 4.toByte()) print(i); println()
for (i in 0.toInt() until 4.toShort()) print(i); println()
for (i in 0.toInt() until 4.toInt()) print(i); println()
for (i in 0.toInt() until 4.toLong()) print(i); println()
for (i in 0.toLong() until 4.toByte()) print(i); println()
for (i in 0.toLong() until 4.toShort()) print(i); println()
for (i in 0.toLong() until 4.toInt()) print(i); println()
for (i in 0.toLong() until 4.toLong()) print(i); println()
for (i in 4.toByte() downTo 0.toByte()) print(i); println()
for (i in 4.toByte() downTo 0.toShort()) print(i); println()
for (i in 4.toByte() downTo 0.toInt()) print(i); println()
for (i in 4.toByte() downTo 0.toLong()) print(i); println()
for (i in 4.toShort() downTo 0.toByte()) print(i); println()
for (i in 4.toShort() downTo 0.toShort()) print(i); println()
for (i in 4.toShort() downTo 0.toInt()) print(i); println()
for (i in 4.toShort() downTo 0.toLong()) print(i); println()
for (i in 4.toInt() downTo 0.toByte()) print(i); println()
for (i in 4.toInt() downTo 0.toShort()) print(i); println()
for (i in 4.toInt() downTo 0.toInt()) print(i); println()
for (i in 4.toInt() downTo 0.toLong()) print(i); println()
for (i in 4.toLong() downTo 0.toByte()) print(i); println()
for (i in 4.toLong() downTo 0.toShort()) print(i); println()
for (i in 4.toLong() downTo 0.toInt()) print(i); println()
for (i in 4.toLong() downTo 0.toLong()) print(i); println()
for (i in 'a' .. 'd') print(i); println()
for (i in 'a' until 'd') print(i); println()
for (i in 'd' downTo 'a') print(i); println()
// TODO: Add step tests.
}