JVM_IR generate less bytecode for for-loops if possible(KT-22334).

This commit is contained in:
Xin Wang
2021-12-28 10:54:01 +08:00
committed by Dmitry Petrov
parent 3b928e1780
commit 9ae452e489
27 changed files with 830 additions and 12 deletions
@@ -34261,6 +34261,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/ranges/forInRangeWithImplicitReceiver.kt");
}
@Test
@TestMetadata("forInRangeWithUpperBoundMinus1.kt")
public void testForInRangeWithUpperBoundMinus1() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInRangeWithUpperBoundMinus1.kt");
}
@Test
@TestMetadata("forInStringVarUpdatedInLoopBody.kt")
public void testForInStringVarUpdatedInLoopBody() throws Exception {
@@ -2794,6 +2794,130 @@ public class FirBytecodeTextTestGenerated extends AbstractFirBytecodeTextTest {
}
}
@Nested
@TestMetadata("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1")
@TestDataPath("$PROJECT_ROOT")
public class ForInRangeWithUpperBoundMinus1 {
@Test
public void testAllFilesPresentInForInRangeWithUpperBoundMinus1() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("booleanArray.kt")
public void testBooleanArray() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/booleanArray.kt");
}
@Test
@TestMetadata("byteArray.kt")
public void testByteArray() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/byteArray.kt");
}
@Test
@TestMetadata("charArray.kt")
public void testCharArray() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/charArray.kt");
}
@Test
@TestMetadata("charSequence.kt")
public void testCharSequence() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/charSequence.kt");
}
@Test
@TestMetadata("doubleArray.kt")
public void testDoubleArray() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/doubleArray.kt");
}
@Test
@TestMetadata("emptyList.kt")
public void testEmptyList() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/emptyList.kt");
}
@Test
@TestMetadata("emptyMap.kt")
public void testEmptyMap() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/emptyMap.kt");
}
@Test
@TestMetadata("emptySet.kt")
public void testEmptySet() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/emptySet.kt");
}
@Test
@TestMetadata("floatArray.kt")
public void testFloatArray() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/floatArray.kt");
}
@Test
@TestMetadata("intArray.kt")
public void testIntArray() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/intArray.kt");
}
@Test
@TestMetadata("list.kt")
public void testList() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/list.kt");
}
@Test
@TestMetadata("longArray.kt")
public void testLongArray() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/longArray.kt");
}
@Test
@TestMetadata("map.kt")
public void testMap() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/map.kt");
}
@Test
@TestMetadata("mutableList.kt")
public void testMutableList() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/mutableList.kt");
}
@Test
@TestMetadata("mutableMap.kt")
public void testMutableMap() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/mutableMap.kt");
}
@Test
@TestMetadata("mutableSet.kt")
public void testMutableSet() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/mutableSet.kt");
}
@Test
@TestMetadata("set.kt")
public void testSet() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/set.kt");
}
@Test
@TestMetadata("shortArray.kt")
public void testShortArray() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/shortArray.kt");
}
@Test
@TestMetadata("string.kt")
public void testString() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/string.kt");
}
}
@Nested
@TestMetadata("compiler/testData/codegen/bytecodeText/forLoop/forInReversed")
@TestDataPath("$PROJECT_ROOT")
@@ -10,12 +10,10 @@ import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.lower.loops.*
import org.jetbrains.kotlin.backend.common.lower.matchers.SimpleCalleeMatcher
import org.jetbrains.kotlin.ir.builders.irInt
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrConst
import org.jetbrains.kotlin.ir.expressions.IrConstKind
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.util.OperatorNameConventions
/** Builds a [HeaderInfo] for progressions built using the `rangeTo` function. */
@@ -67,7 +65,46 @@ internal class RangeToHandler(private val context: CommonBackendContext) :
if (preferJavaLikeCounterLoop || this.constLongValue == -1L) return null
}
val irConst = this as? IrConst<*> ?: return null
return when (this) {
is IrConst<*> -> convertIrConst(this)
is IrCall -> convertIrCall(this)
else -> null
}
}
private val allowedMethods = listOf(
"kotlin.ByteArray.<get-size>",
"kotlin.CharArray.<get-size>",
"kotlin.String.<get-length>",
"kotlin.ShortArray.<get-size>",
"kotlin.IntArray.<get-size>",
"kotlin.LongArray.<get-size>",
"kotlin.FloatArray.<get-size>",
"kotlin.DoubleArray.<get-size>",
"kotlin.BooleanArray.<get-size>",
"kotlin.collections.List.<get-size>",
"kotlin.collections.MutableList.<get-size>",
"kotlin.CharSequence.<get-length>",
"kotlin.collections.Set.<get-size>",
"kotlin.collections.MutableSet.<get-size>",
"kotlin.collections.Map.<get-size>",
"kotlin.collections.MutableMap.<get-size>",
)
private fun convertIrCall(irCall: IrCall): IrExpression? {
fun IrCall.dispatchReceiverName() = (dispatchReceiver as? IrCall)?.symbol?.owner?.fqNameWhenAvailable.toString()
return if (irCall.origin == IrStatementOrigin.MINUS
&& (irCall.getValueArgument(0) as? IrConst<*>)?.value == 1
&& irCall.dispatchReceiverName() in allowedMethods // to avoid possible underflow
) irCall.dispatchReceiver
else null
}
private fun convertIrConst(irConst: IrConst<*>): IrExpression? {
val startOffset = irConst.startOffset
val endOffset = irConst.endOffset
val type = irConst.type
return when (irConst.kind) {
IrConstKind.Char -> {
val charValue = IrConstKind.Char.valueOf(irConst)
@@ -108,6 +145,4 @@ internal class RangeToHandler(private val context: CommonBackendContext) :
null
}
}
}
@@ -0,0 +1,227 @@
// TARGET_BACKEND: JVM_IR
// WITH_STDLIB
fun box(): String {
noUnderflow()
testByteArray()
testCharArray()
testShortArray()
testIntArray()
testLongArray()
testFloatArray()
testDoubleArray()
testBooleanArray()
testEmptyList()
testList()
testMutableList()
testCharSequence()
testString()
testEmptySet()
testSet()
testMutableSet()
testEmptyMap()
testMap()
testMutableMap()
return "OK"
}
fun noUnderflow() {
val M1 = Int.MAX_VALUE - 2
val M2 = Int.MIN_VALUE
var t = 0
for (x in M1..M2 - 1) {
++t
assert(t <= 3) { "Failed: too many iterations" }
}
assert(t == 3) { "Failed: t=$t" }
}
fun testByteArray() {
val array = byteArrayOf(1, 2, 3)
val range = array.size - 1
var optimized = 0
var nonOptimized = 0
for (i in 0..array.size - 1) optimized += array[i]
for (i in 0..range) nonOptimized += array[i]
assert(optimized == nonOptimized) { "optimized($optimized) and nonOptimized($nonOptimized) should be equal" }
}
fun testCharArray() {
val array = charArrayOf('1', '2', '3')
val range = array.size - 1
var optimized = ""
var nonOptimized = ""
for (i in 0..array.size - 1) optimized += array[i]
for (i in 0..range) nonOptimized += array[i]
assert(optimized == nonOptimized) { "optimized($optimized) and nonOptimized($nonOptimized) should be equal" }
}
fun testShortArray() {
val array = shortArrayOf(1, 2, 3)
val range = array.size - 1
var optimized = 0
var nonOptimized = 0
for (i in 0..array.size - 1) optimized += array[i]
for (i in 0..range) nonOptimized += array[i]
assert(optimized == nonOptimized) { "optimized($optimized) and nonOptimized($nonOptimized) should be equal" }
}
fun testIntArray() {
val array = intArrayOf(1, 2, 3)
val range = array.size - 1
var optimized = 0
var nonOptimized = 0
for (i in 0..array.size - 1) optimized += array[i]
for (i in 0..range) nonOptimized += array[i]
assert(optimized == nonOptimized) { "optimized($optimized) and nonOptimized($nonOptimized) should be equal" }
}
fun testLongArray() {
val array = longArrayOf(1, 2, 3)
val range = array.size - 1
var optimized = 0L
var nonOptimized = 0L
for (i in 0..array.size - 1) optimized += array[i]
for (i in 0..range) nonOptimized += array[i]
assert(optimized == nonOptimized) { "optimized($optimized) and nonOptimized($nonOptimized) should be equal" }
}
fun testFloatArray() {
val array = floatArrayOf(1f, 2f, 3f)
val range = array.size - 1
var optimized = 0f
var nonOptimized = 0f
for (i in 0..array.size - 1) optimized += array[i]
for (i in 0..range) nonOptimized += array[i]
assert(optimized == nonOptimized) { "optimized($optimized) and nonOptimized($nonOptimized) should be equal" }
}
fun testDoubleArray() {
val array = doubleArrayOf(1.0, 2.0, 3.0)
val range = array.size - 1
var optimized = 0.0
var nonOptimized = 0.0
for (i in 0..array.size - 1) optimized += array[i]
for (i in 0..range) nonOptimized += array[i]
assert(optimized == nonOptimized) { "optimized($optimized) and nonOptimized($nonOptimized) should be equal" }
}
fun testBooleanArray() {
val array = booleanArrayOf(true, false, true)
val range = array.size - 1
var optimized = ""
var nonOptimized = ""
for (i in 0..array.size - 1) optimized += array[i]
for (i in 0..range) nonOptimized += array[i]
assert(optimized == nonOptimized) { "optimized($optimized) and nonOptimized($nonOptimized) should be equal" }
}
fun testEmptyList() {
val list = emptyList<Int>()
val range = list.size - 1
var optimized = 0
var nonOptimized = 0
for (i in 0..list.size - 1) optimized += list[i]
for (i in 0..range) nonOptimized += list[i]
assert(optimized == nonOptimized) { "optimized($optimized) and nonOptimized($nonOptimized) should be equal" }
}
fun testList() {
val list = listOf(1, 2, 3)
val range = list.size - 1
var optimized = 0
var nonOptimized = 0
for (i in 0..list.size - 1) optimized += list[i]
for (i in 0..range) nonOptimized += list[i]
assert(optimized == nonOptimized) { "optimized($optimized) and nonOptimized($nonOptimized) should be equal" }
}
fun testMutableList() {
val list = mutableListOf(1, 2, 3)
val range = list.size - 1
var optimized = 0
var nonOptimized = 0
for (i in 0..list.size - 1) optimized += list[i]
for (i in 0..range) nonOptimized += list[i]
assert(optimized == nonOptimized) { "optimized($optimized) and nonOptimized($nonOptimized) should be equal" }
}
fun testCharSequence() {
val chars: CharSequence = "123"
val range = chars.length - 1
var optimized = ""
var nonOptimized = ""
for (i in 0..chars.length - 1) optimized += chars[i]
for (i in 0..range) nonOptimized += chars[i]
assert(optimized == nonOptimized) { "optimized($optimized) and nonOptimized($nonOptimized) should be equal" }
}
fun testString() {
val str = "123"
val range = str.length - 1
var optimized = ""
var nonOptimized = ""
for (i in 0..str.length - 1) optimized += str[i]
for (i in 0..range) nonOptimized += str[i]
assert(optimized == nonOptimized) { "optimized($optimized) and nonOptimized($nonOptimized) should be equal" }
}
fun testEmptySet() {
val set = emptySet<Int>()
val range = set.size - 1
var optimized = ""
var nonOptimized = ""
for (i in 0..set.size - 1) optimized += set.elementAt(i)
for (i in 0..range) nonOptimized += set.elementAt(i)
assert(optimized == nonOptimized) { "optimized($optimized) and nonOptimized($nonOptimized) should be equal" }
}
fun testSet() {
val set = setOf(1, 2, 3)
val range = set.size - 1
var optimized = ""
var nonOptimized = ""
for (i in 0..set.size - 1) optimized += set.elementAt(i)
for (i in 0..range) nonOptimized += set.elementAt(i)
assert(optimized == nonOptimized) { "optimized($optimized) and nonOptimized($nonOptimized) should be equal" }
}
fun testMutableSet() {
val set = mutableSetOf(1, 2, 3)
val range = set.size - 1
var optimized = ""
var nonOptimized = ""
for (i in 0..set.size - 1) optimized += set.elementAt(i)
for (i in 0..range) nonOptimized += set.elementAt(i)
assert(optimized == nonOptimized) { "optimized($optimized) and nonOptimized($nonOptimized) should be equal" }
}
fun testEmptyMap() {
val map = emptyMap<Int, Int>()
val range = map.size - 1
var optimized = ""
var nonOptimized = ""
for (i in 0..map.size - 1) optimized += map[i]
for (i in 0..range) nonOptimized += map[i]
assert(optimized == nonOptimized) { "optimized($optimized) and nonOptimized($nonOptimized) should be equal" }
}
fun testMap() {
val map = mapOf(1 to 1, 2 to 2, 3 to 3)
val range = map.size - 1
var optimized = ""
var nonOptimized = ""
for (i in 0..map.size - 1) optimized += map[i]
for (i in 0..range) nonOptimized += map[i]
assert(optimized == nonOptimized) { "optimized($optimized) and nonOptimized($nonOptimized) should be equal" }
}
fun testMutableMap() {
val map = mutableMapOf(1 to 1, 2 to 2, 3 to 3)
val range = map.size - 1
var optimized = ""
var nonOptimized = ""
for (i in 0..map.size - 1) optimized += map[i]
for (i in 0..range) nonOptimized += map[i]
assert(optimized == nonOptimized) { "optimized($optimized) and nonOptimized($nonOptimized) should be equal" }
}
@@ -22,11 +22,12 @@ fun test(): Int {
// 1 IF
// JVM_IR_TEMPLATES
// 1 IF_ICMPGT
// 1 IF_ICMPEQ
// 2 IF
// 7 ILOAD
// 0 IF_ICMPGT
// 1 IF_ICMPGE
// 0 IF_ICMPEQ
// 1 IF
// 5 ILOAD
// 4 ISTORE
// 1 IINC
// 1 IADD
// 1 ISUB
// 0 ISUB
@@ -0,0 +1,15 @@
// TARGET_BACKEND: JVM_IR
fun test() {
val array = booleanArrayOf(true, false, true)
var optimized = ""
for (i in 0..array.size - 1) optimized += array[i]
}
// 0 IF_ICMPGT
// 1 IF_ICMPGE
// 0 IADD
// 0 ISUB
// 3 ILOAD
// 2 ISTORE
// 1 IINC
@@ -0,0 +1,15 @@
// TARGET_BACKEND: JVM_IR
fun test() {
val array = byteArrayOf(1, 2, 3)
var optimized = 0
for (i in 0..array.size - 1) optimized += array[i]
}
// 0 IF_ICMPGT
// 1 IF_ICMPGE
// 1 IADD
// 0 ISUB
// 4 ILOAD
// 4 ISTORE
// 1 IINC
@@ -0,0 +1,15 @@
// TARGET_BACKEND: JVM_IR
fun test() {
val array = charArrayOf('1', '2', '3')
var optimized = ""
for (i in 0..array.size - 1) optimized += array[i]
}
// 0 IF_ICMPGT
// 1 IF_ICMPGE
// 0 IADD
// 0 ISUB
// 3 ILOAD
// 2 ISTORE
// 1 IINC
@@ -0,0 +1,15 @@
// TARGET_BACKEND: JVM_IR
fun test() {
val chars: CharSequence = "123"
var optimized = ""
for (i in 0..chars.length - 1) optimized += chars[i]
}
// 0 IF_ICMPGT
// 1 IF_ICMPGE
// 0 IADD
// 0 ISUB
// 3 ILOAD
// 2 ISTORE
// 1 IINC
@@ -0,0 +1,15 @@
// TARGET_BACKEND: JVM_IR
fun test() {
val array = doubleArrayOf(1.0, 2.0, 3.0)
var optimized = 0.0
for (i in 0..array.size - 1) optimized += array[i]
}
// 0 IF_ICMPGT
// 1 IF_ICMPGE
// 0 IADD
// 0 ISUB
// 3 ILOAD
// 2 ISTORE
// 1 IINC
@@ -0,0 +1,15 @@
// TARGET_BACKEND: JVM_IR
fun test() {
val list = emptyList<Int>()
var optimized = 0
for (i in 0..list.size - 1) optimized += list[i]
}
// 0 IF_ICMPGT
// 1 IF_ICMPGE
// 1 IADD
// 0 ISUB
// 4 ILOAD
// 4 ISTORE
// 1 IINC
@@ -0,0 +1,15 @@
// TARGET_BACKEND: JVM_IR
fun test() {
val map = emptyMap<Int, Int>()
var optimized = ""
for (i in 0..map.size - 1) optimized += map[i]
}
// 0 IF_ICMPGT
// 1 IF_ICMPGE
// 0 IADD
// 0 ISUB
// 3 ILOAD
// 2 ISTORE
// 1 IINC
@@ -0,0 +1,15 @@
// TARGET_BACKEND: JVM_IR
fun test() {
val set = emptySet<Int>()
var optimized = ""
for (i in 0..set.size - 1) optimized += set.elementAt(i)
}
// 0 IF_ICMPGT
// 1 IF_ICMPGE
// 0 IADD
// 0 ISUB
// 3 ILOAD
// 2 ISTORE
// 1 IINC
@@ -0,0 +1,15 @@
// TARGET_BACKEND: JVM_IR
fun test() {
val array = floatArrayOf(1f, 2f, 3f)
var optimized = 0f
for (i in 0..array.size - 1) optimized += array[i]
}
// 0 IF_ICMPGT
// 1 IF_ICMPGE
// 0 IADD
// 0 ISUB
// 3 ILOAD
// 2 ISTORE
// 1 IINC
@@ -0,0 +1,15 @@
// TARGET_BACKEND: JVM_IR
fun test() {
val array = intArrayOf(1, 2, 3)
var optimized = 0
for (i in 0..array.size - 1) optimized += array[i]
}
// 0 IF_ICMPGT
// 1 IF_ICMPGE
// 1 IADD
// 0 ISUB
// 4 ILOAD
// 4 ISTORE
// 1 IINC
@@ -0,0 +1,15 @@
// TARGET_BACKEND: JVM_IR
fun test() {
val list = listOf(1, 2, 3)
var optimized = 0
for (i in 0..list.size - 1) optimized += list[i]
}
// 0 IF_ICMPGT
// 1 IF_ICMPGE
// 1 IADD
// 0 ISUB
// 4 ILOAD
// 4 ISTORE
// 1 IINC
@@ -0,0 +1,15 @@
// TARGET_BACKEND: JVM_IR
fun test() {
val array = longArrayOf(1, 2, 3)
var optimized = 0L
for (i in 0..array.size - 1) optimized += array[i]
}
// 0 IF_ICMPGT
// 1 IF_ICMPGE
// 0 IADD
// 0 ISUB
// 3 ILOAD
// 2 ISTORE
// 1 IINC
@@ -0,0 +1,15 @@
// TARGET_BACKEND: JVM_IR
fun test() {
val map = mapOf(1 to 1, 2 to 2, 3 to 3)
var optimized = ""
for (i in 0..map.size - 1) optimized += map[i]
}
// 0 IF_ICMPGT
// 1 IF_ICMPGE
// 0 IADD
// 0 ISUB
// 3 ILOAD
// 2 ISTORE
// 1 IINC
@@ -0,0 +1,15 @@
// TARGET_BACKEND: JVM_IR
fun test() {
val list = mutableListOf(1, 2, 3)
var optimized = 0
for (i in 0..list.size - 1) optimized += list[i]
}
// 0 IF_ICMPGT
// 1 IF_ICMPGE
// 1 IADD
// 0 ISUB
// 4 ILOAD
// 4 ISTORE
// 1 IINC
@@ -0,0 +1,15 @@
// TARGET_BACKEND: JVM_IR
fun test() {
val map = mutableMapOf(1 to 1, 2 to 2, 3 to 3)
var optimized = ""
for (i in 0..map.size - 1) optimized += map[i]
}
// 0 IF_ICMPGT
// 1 IF_ICMPGE
// 0 IADD
// 0 ISUB
// 3 ILOAD
// 2 ISTORE
// 1 IINC
@@ -0,0 +1,15 @@
// TARGET_BACKEND: JVM_IR
fun test() {
val set = mutableSetOf(1, 2, 3)
var optimized = ""
for (i in 0..set.size - 1) optimized += set.elementAt(i)
}
// 0 IF_ICMPGT
// 1 IF_ICMPGE
// 0 IADD
// 0 ISUB
// 3 ILOAD
// 2 ISTORE
// 1 IINC
@@ -0,0 +1,15 @@
// TARGET_BACKEND: JVM_IR
fun test() {
val set = setOf(1, 2, 3)
var optimized = ""
for (i in 0..set.size - 1) optimized += set.elementAt(i)
}
// 0 IF_ICMPGT
// 1 IF_ICMPGE
// 0 IADD
// 0 ISUB
// 3 ILOAD
// 2 ISTORE
// 1 IINC
@@ -0,0 +1,15 @@
// TARGET_BACKEND: JVM_IR
fun test() {
val array = shortArrayOf(1, 2, 3)
var optimized = 0
for (i in 0..array.size - 1) optimized += array[i]
}
// 0 IF_ICMPGT
// 1 IF_ICMPGE
// 1 IADD
// 0 ISUB
// 4 ILOAD
// 4 ISTORE
// 1 IINC
@@ -0,0 +1,15 @@
// TARGET_BACKEND: JVM_IR
fun test() {
val str = "123"
var optimized = ""
for (i in 0..str.length - 1) optimized += str[i]
}
// 0 IF_ICMPGT
// 1 IF_ICMPGE
// 0 IADD
// 0 ISUB
// 3 ILOAD
// 2 ISTORE
// 1 IINC
@@ -2764,6 +2764,16 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
}
}
@Nested
@TestMetadata("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1")
@TestDataPath("$PROJECT_ROOT")
public class ForInRangeWithUpperBoundMinus1 {
@Test
public void testAllFilesPresentInForInRangeWithUpperBoundMinus1() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
}
@Nested
@TestMetadata("compiler/testData/codegen/bytecodeText/forLoop/forInReversed")
@TestDataPath("$PROJECT_ROOT")
@@ -34261,6 +34261,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/ranges/forInRangeWithImplicitReceiver.kt");
}
@Test
@TestMetadata("forInRangeWithUpperBoundMinus1.kt")
public void testForInRangeWithUpperBoundMinus1() throws Exception {
runTest("compiler/testData/codegen/box/ranges/forInRangeWithUpperBoundMinus1.kt");
}
@Test
@TestMetadata("forInStringVarUpdatedInLoopBody.kt")
public void testForInStringVarUpdatedInLoopBody() throws Exception {
@@ -2794,6 +2794,130 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
}
}
@Nested
@TestMetadata("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1")
@TestDataPath("$PROJECT_ROOT")
public class ForInRangeWithUpperBoundMinus1 {
@Test
public void testAllFilesPresentInForInRangeWithUpperBoundMinus1() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("booleanArray.kt")
public void testBooleanArray() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/booleanArray.kt");
}
@Test
@TestMetadata("byteArray.kt")
public void testByteArray() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/byteArray.kt");
}
@Test
@TestMetadata("charArray.kt")
public void testCharArray() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/charArray.kt");
}
@Test
@TestMetadata("charSequence.kt")
public void testCharSequence() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/charSequence.kt");
}
@Test
@TestMetadata("doubleArray.kt")
public void testDoubleArray() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/doubleArray.kt");
}
@Test
@TestMetadata("emptyList.kt")
public void testEmptyList() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/emptyList.kt");
}
@Test
@TestMetadata("emptyMap.kt")
public void testEmptyMap() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/emptyMap.kt");
}
@Test
@TestMetadata("emptySet.kt")
public void testEmptySet() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/emptySet.kt");
}
@Test
@TestMetadata("floatArray.kt")
public void testFloatArray() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/floatArray.kt");
}
@Test
@TestMetadata("intArray.kt")
public void testIntArray() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/intArray.kt");
}
@Test
@TestMetadata("list.kt")
public void testList() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/list.kt");
}
@Test
@TestMetadata("longArray.kt")
public void testLongArray() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/longArray.kt");
}
@Test
@TestMetadata("map.kt")
public void testMap() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/map.kt");
}
@Test
@TestMetadata("mutableList.kt")
public void testMutableList() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/mutableList.kt");
}
@Test
@TestMetadata("mutableMap.kt")
public void testMutableMap() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/mutableMap.kt");
}
@Test
@TestMetadata("mutableSet.kt")
public void testMutableSet() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/mutableSet.kt");
}
@Test
@TestMetadata("set.kt")
public void testSet() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/set.kt");
}
@Test
@TestMetadata("shortArray.kt")
public void testShortArray() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/shortArray.kt");
}
@Test
@TestMetadata("string.kt")
public void testString() throws Exception {
runTest("compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/string.kt");
}
}
@Nested
@TestMetadata("compiler/testData/codegen/bytecodeText/forLoop/forInReversed")
@TestDataPath("$PROJECT_ROOT")