Optimize range operations for 'until' extension from stdlib (KT-9900)

NB: for-in-until loop is generated as precondition loop, because the
corresponding range is right-exclusive (and thus we have no problems
with integer overflows).
This commit is contained in:
Dmitry Petrov
2017-05-02 15:00:14 +03:00
parent b83620fdb9
commit 506941e7e0
27 changed files with 533 additions and 8 deletions
@@ -0,0 +1,28 @@
// IGNORE_BACKEND: JS
// see KT-17700
// WITH_RUNTIME
import kotlin.test.assertEquals
fun box(): String {
testChar()
testNullableChar()
return "OK"
}
private fun testChar() {
var sum = ""
for (ch in '1' until '5') {
sum = sum + ch
}
assertEquals("1234", sum)
}
private fun testNullableChar() {
var sum = ""
for (ch: Char? in '1' until '5') {
sum = sum + (ch ?: break)
}
assertEquals("1234", sum)
}
@@ -0,0 +1,10 @@
// WITH_RUNTIME
import kotlin.test.assertEquals
fun box(): String {
for (ch in (-10).toChar() until '\u0000') {
throw AssertionError("This loop shoud not be executed")
}
return "OK"
}
@@ -0,0 +1,25 @@
// WITH_RUNTIME
import kotlin.test.assertEquals
fun box(): String {
testIntInIntUntilInt()
testNullableIntInIntUntilInt()
return "OK"
}
private fun testIntInIntUntilInt() {
var sum = 0
for (i in 1 until 5) {
sum = sum * 10 + i
}
assertEquals(1234, sum)
}
private fun testNullableIntInIntUntilInt() {
var sum = 0
for (i: Int? in 1 until 5) {
sum = sum * 10 + (i?.toInt() ?: break)
}
assertEquals(1234, sum)
}
@@ -0,0 +1,10 @@
// WITH_RUNTIME
import kotlin.test.assertEquals
fun box(): String {
for (i in 10 until 0) {
throw AssertionError("This loop should not be executed")
}
return "OK"
}
@@ -0,0 +1,43 @@
// WITH_RUNTIME
import kotlin.test.assertEquals
fun testLongInLongUntilLong() {
var sum = 0
for (i in 1L until 5L) {
sum = sum * 10 + i.toInt()
}
assertEquals(1234, sum)
}
fun testLongInLongUntilInt() {
var sum = 0
for (i in 1L until 5.toInt()) {
sum = sum * 10 + i.toInt()
}
assertEquals(1234, sum)
}
fun testLongInIntUntilLong() {
var sum = 0
for (i in 1.toInt() until 5L) {
sum = sum * 10 + i.toInt()
}
assertEquals(1234, sum)
}
fun testNullableLongInIntUntilLong() {
var sum = 0
for (i: Long? in 1.toInt() until 5L) {
sum = sum * 10 + (i?.toInt() ?: break)
}
assertEquals(1234, sum)
}
fun box(): String {
testLongInLongUntilLong()
testLongInIntUntilLong()
testLongInLongUntilInt()
testNullableLongInIntUntilLong()
return "OK"
}
@@ -0,0 +1,10 @@
// WITH_RUNTIME
import kotlin.test.assertEquals
fun box(): String {
for (i in Int.MAX_VALUE until Int.MAX_VALUE) {
throw AssertionError("This loop shoud not be executed")
}
return "OK"
}
@@ -0,0 +1,10 @@
// WITH_RUNTIME
import kotlin.test.assertEquals
fun box(): String {
for (i in 0 until Int.MIN_VALUE) {
throw AssertionError("This loop shoud not be executed")
}
return "OK"
}
@@ -0,0 +1,10 @@
// WITH_RUNTIME
import kotlin.test.assertEquals
fun box(): String {
for (i in 0 until Long.MIN_VALUE) {
throw AssertionError("This loop shoud not be executed")
}
return "OK"
}
@@ -0,0 +1,21 @@
// WITH_RUNTIME
import kotlin.test.assertEquals
fun box(): String {
testIntInIntUntilSmartcastInt()
return "OK"
}
private fun testIntInIntUntilSmartcastInt() {
var sum = 0
val a: Any = 5
if (a is Int) {
for (i: Int in 1 until a) {
sum = sum * 10 + i
}
}
assertEquals(1234, sum)
}
@@ -0,0 +1,16 @@
// WITH_RUNTIME
fun test(): Int {
var sum = 0
for (i in 1 until 6) {
sum = sum * 10 + i
}
return sum
}
// 0 iterator
// 0 getStart
// 0 getEnd
// 0 getFirst
// 0 getLast
// 1 IF
+2 -1
View File
@@ -1,6 +1,7 @@
fun Int.until(other: Int) = this..other - 1
fun foo() {
for (i in 1 until 2) {
val range = 1 until 2
for (i in range) {
}
for (i in 1..2 step 4) {}