diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index d959288e6a1..ab9c191e2f3 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -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 { diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBytecodeTextTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBytecodeTextTestGenerated.java index 012ed8eb5ef..91e194203cf 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBytecodeTextTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBytecodeTextTestGenerated.java @@ -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") diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/RangeToHandler.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/RangeToHandler.kt index 73ef9c5a636..02ad8c56066 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/RangeToHandler.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/RangeToHandler.kt @@ -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.", + "kotlin.CharArray.", + "kotlin.String.", + "kotlin.ShortArray.", + "kotlin.IntArray.", + "kotlin.LongArray.", + "kotlin.FloatArray.", + "kotlin.DoubleArray.", + "kotlin.BooleanArray.", + "kotlin.collections.List.", + "kotlin.collections.MutableList.", + "kotlin.CharSequence.", + "kotlin.collections.Set.", + "kotlin.collections.MutableSet.", + "kotlin.collections.Map.", + "kotlin.collections.MutableMap.", + ) + + 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 } } - - } \ No newline at end of file diff --git a/compiler/testData/codegen/box/ranges/forInRangeWithUpperBoundMinus1.kt b/compiler/testData/codegen/box/ranges/forInRangeWithUpperBoundMinus1.kt new file mode 100644 index 00000000000..b85377a279f --- /dev/null +++ b/compiler/testData/codegen/box/ranges/forInRangeWithUpperBoundMinus1.kt @@ -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() + 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() + 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() + 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" } +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInRangeSpecializedToUntil.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeSpecializedToUntil.kt index d53813ffa00..1b734f5f2b1 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/forInRangeSpecializedToUntil.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeSpecializedToUntil.kt @@ -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 diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/booleanArray.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/booleanArray.kt new file mode 100644 index 00000000000..1854591b110 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/booleanArray.kt @@ -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 \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/byteArray.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/byteArray.kt new file mode 100644 index 00000000000..dd0d3169a32 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/byteArray.kt @@ -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 diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/charArray.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/charArray.kt new file mode 100644 index 00000000000..e4d36610048 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/charArray.kt @@ -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 \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/charSequence.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/charSequence.kt new file mode 100644 index 00000000000..231f8c62fba --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/charSequence.kt @@ -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 \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/doubleArray.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/doubleArray.kt new file mode 100644 index 00000000000..744e157743b --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/doubleArray.kt @@ -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 \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/emptyList.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/emptyList.kt new file mode 100644 index 00000000000..9132b2242c7 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/emptyList.kt @@ -0,0 +1,15 @@ +// TARGET_BACKEND: JVM_IR + +fun test() { + val list = emptyList() + 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 diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/emptyMap.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/emptyMap.kt new file mode 100644 index 00000000000..3bb6d6e3d81 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/emptyMap.kt @@ -0,0 +1,15 @@ +// TARGET_BACKEND: JVM_IR + +fun test() { + val map = emptyMap() + 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 \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/emptySet.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/emptySet.kt new file mode 100644 index 00000000000..9b0202844fc --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/emptySet.kt @@ -0,0 +1,15 @@ +// TARGET_BACKEND: JVM_IR + +fun test() { + val set = emptySet() + 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 \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/floatArray.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/floatArray.kt new file mode 100644 index 00000000000..4831241786d --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/floatArray.kt @@ -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 \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/intArray.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/intArray.kt new file mode 100644 index 00000000000..1a29cf02cc8 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/intArray.kt @@ -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 \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/list.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/list.kt new file mode 100644 index 00000000000..a198c0834db --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/list.kt @@ -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 \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/longArray.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/longArray.kt new file mode 100644 index 00000000000..1fe6455ebee --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/longArray.kt @@ -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 \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/map.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/map.kt new file mode 100644 index 00000000000..468434b53a6 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/map.kt @@ -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 \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/mutableList.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/mutableList.kt new file mode 100644 index 00000000000..7619767b3ef --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/mutableList.kt @@ -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 diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/mutableMap.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/mutableMap.kt new file mode 100644 index 00000000000..5b51cdd72f0 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/mutableMap.kt @@ -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 \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/mutableSet.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/mutableSet.kt new file mode 100644 index 00000000000..f721ac9f5b5 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/mutableSet.kt @@ -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 \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/set.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/set.kt new file mode 100644 index 00000000000..3c9ef67c2f0 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/set.kt @@ -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 \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/shortArray.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/shortArray.kt new file mode 100644 index 00000000000..f1d2560e628 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/shortArray.kt @@ -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 diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/string.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/string.kt new file mode 100644 index 00000000000..62e46e70139 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeWithUpperBoundMinus1/string.kt @@ -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 \ No newline at end of file diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeTextTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeTextTestGenerated.java index eaf8965092b..0fadcc37e47 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BytecodeTextTestGenerated.java @@ -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") diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index 548f815511f..ddd34d1108b 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -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 { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeTextTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeTextTestGenerated.java index 69bf549f6e5..9fc2223c142 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeTextTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBytecodeTextTestGenerated.java @@ -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")