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 83f567db000..6c985134bee 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 @@ -31271,6 +31271,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/ranges/forInDownTo"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } + @Test + @TestMetadata("forInDownToWithPossibleUnderflow.kt") + public void testForInDownToWithPossibleUnderflow() throws Exception { + runTest("compiler/testData/codegen/box/ranges/forInDownTo/forInDownToWithPossibleUnderflow.kt"); + } + @Test @TestMetadata("forIntInDownTo.kt") public void testForIntInDownTo() 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 5deb87aaac3..5cc80a1dace 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 @@ -2366,6 +2366,12 @@ public class FirBytecodeTextTestGenerated extends AbstractFirBytecodeTextTest { runTest("compiler/testData/codegen/bytecodeText/forLoop/forInDownToIntMinValue.kt"); } + @Test + @TestMetadata("forInDownToLongConstNoUnderflow.kt") + public void testForInDownToLongConstNoUnderflow() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/forLoop/forInDownToLongConstNoUnderflow.kt"); + } + @Test @TestMetadata("forInDownToLongMinValue.kt") public void testForInDownToLongMinValue() throws Exception { diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/DownToHandler.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/DownToHandler.kt index b7ad80d0323..a975a20e31d 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/DownToHandler.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/DownToHandler.kt @@ -12,14 +12,19 @@ import org.jetbrains.kotlin.backend.common.lower.matchers.SimpleCalleeMatcher import org.jetbrains.kotlin.backend.common.lower.matchers.singleArgumentExtension 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.impl.IrConstImpl import org.jetbrains.kotlin.ir.symbols.IrSymbol -import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.name.FqName /** Builds a [HeaderInfo] for progressions built using the `downTo` extension function. */ internal class DownToHandler(private val context: CommonBackendContext) : ProgressionHandler { + private val preferJavaLikeCounterLoop = context.preferJavaLikeCounterLoop + private val progressionElementTypes = context.ir.symbols.progressionElementTypes override val matcher = SimpleCalleeMatcher { @@ -28,14 +33,78 @@ internal class DownToHandler(private val context: CommonBackendContext) : parameter(0) { it.type in progressionElementTypes } } - override fun build(expression: IrCall, data: ProgressionType, scopeOwner: IrSymbol): HeaderInfo? = + override fun build(expression: IrCall, data: ProgressionType, scopeOwner: IrSymbol) = with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) { - ProgressionHeaderInfo( - data, - first = expression.extensionReceiver!!, - last = expression.getValueArgument(0)!!, - step = irInt(-1), - direction = ProgressionDirection.DECREASING - ) + val first = expression.extensionReceiver!! + val last = expression.getValueArgument(0)!! + val step = irInt(-1) + val direction = ProgressionDirection.DECREASING + + if (preferJavaLikeCounterLoop) { + // Convert range with inclusive lower bound to exclusive lower bound if possible. + // This affects loop code performance on JVM. + val lastExclusive = last.convertToExclusiveLowerBound(data) + if (lastExclusive != null) { + return@with ProgressionHeaderInfo( + data, + first = first, + last = lastExclusive, + step = step, + direction = direction, + isLastInclusive = false, + canOverflow = false, + originalLastInclusive = last + ) + } + } + + ProgressionHeaderInfo(data, first = first, last = last, step = step, direction = direction) } + + private fun IrExpression.convertToExclusiveLowerBound(progressionType: ProgressionType): IrExpression? { + if (progressionType is UnsignedProgressionType) { + if (this.constLongValue == 0L) return null + } + + val irConst = this as? IrConst<*> ?: return null + return when (irConst.kind) { + IrConstKind.Char -> { + val charValue = IrConstKind.Char.valueOf(irConst) + if (charValue != Char.MIN_VALUE) + IrConstImpl.char(startOffset, endOffset, type, charValue.dec()) + else + null + } + IrConstKind.Byte -> { + val byteValue = IrConstKind.Byte.valueOf(irConst) + if (byteValue != Byte.MIN_VALUE) + IrConstImpl.byte(startOffset, endOffset, type, byteValue.dec()) + else + null + } + IrConstKind.Short -> { + val shortValue = IrConstKind.Short.valueOf(irConst) + if (shortValue != Short.MIN_VALUE) + IrConstImpl.short(startOffset, endOffset, type, shortValue.dec()) + else + null + } + IrConstKind.Int -> { + val intValue = IrConstKind.Int.valueOf(irConst) + if (intValue != Int.MIN_VALUE) + IrConstImpl.int(startOffset, endOffset, type, intValue.dec()) + else + null + } + IrConstKind.Long -> { + val longValue = IrConstKind.Long.valueOf(irConst) + if (longValue != Long.MIN_VALUE) + IrConstImpl.long(startOffset, endOffset, type, longValue.dec()) + else + null + } + else -> + null + } + } } \ No newline at end of file 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 0b9376aa85d..8aabbdc12a0 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 @@ -35,45 +35,37 @@ internal class RangeToHandler(private val context: CommonBackendContext) : override fun build(expression: IrCall, data: ProgressionType, scopeOwner: IrSymbol) = with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) { + val first = expression.dispatchReceiver!! val last = expression.getValueArgument(0)!! + val step = irInt(1) + val direction = ProgressionDirection.INCREASING - if (preferJavaLikeCounterLoop && canUseExclusiveUpperBound(last, data)) { + if (preferJavaLikeCounterLoop) { // Convert range with inclusive upper bound to exclusive upper bound if possible. // This affects loop code performance on JVM. - val lastExclusive = last.convertToExclusiveUpperBound() + val lastExclusive = last.convertToExclusiveUpperBound(data) if (lastExclusive != null) { return@with ProgressionHeaderInfo( data, - first = expression.dispatchReceiver!!, + first = first, last = lastExclusive, - step = irInt(1), - direction = ProgressionDirection.INCREASING, + step = step, + direction = direction, isLastInclusive = false, + canOverflow = false, originalLastInclusive = last ) } } - ProgressionHeaderInfo( - data, - first = expression.dispatchReceiver!!, - last = last, - step = irInt(1), - direction = ProgressionDirection.INCREASING - ) + ProgressionHeaderInfo(data, first = first, last = last, step = step, direction = direction) } - private fun canUseExclusiveUpperBound(last: IrExpression, progressionType: ProgressionType): Boolean { - val lastLongValue = last.constLongValue - ?: return false - return if (progressionType is UnsignedProgressionType) { - lastLongValue != -1L - } else { - lastLongValue != progressionType.maxValueAsLong + private fun IrExpression.convertToExclusiveUpperBound(progressionType: ProgressionType): IrExpression? { + if (progressionType is UnsignedProgressionType) { + if (this.constLongValue == -1L) return null } - } - private fun IrExpression.convertToExclusiveUpperBound(): IrConstImpl? { val irConst = this as? IrConst<*> ?: return null return when (irConst.kind) { IrConstKind.Char -> { diff --git a/compiler/testData/codegen/box/ranges/forInDownTo/forInDownToWithPossibleUnderflow.kt b/compiler/testData/codegen/box/ranges/forInDownTo/forInDownToWithPossibleUnderflow.kt new file mode 100644 index 00000000000..e9215e52112 --- /dev/null +++ b/compiler/testData/codegen/box/ranges/forInDownTo/forInDownToWithPossibleUnderflow.kt @@ -0,0 +1,72 @@ +// WITH_RUNTIME + +const val MB = Byte.MIN_VALUE +const val MS = Short.MIN_VALUE +const val MI = Int.MIN_VALUE +const val ML = Long.MIN_VALUE +const val MC = Char.MIN_VALUE + +fun testByte() { + var s = "" + var t = 0 + for (i in MB + 1 downTo MB) { + ++t + s += i + if (t > 2) throw Exception("too many iterations: $t") + } + if (s != "-127-128") throw Exception(s) +} + +fun testShort() { + var s = "" + var t = 0 + for (i in MS + 1 downTo MS) { + ++t + s += i + if (t > 2) throw Exception("too many iterations: $t") + } + if (s != "-32767-32768") throw Exception(s) +} + +fun testInt() { + var s = "" + var t = 0 + for (i in MI + 1 downTo MI) { + ++t + s += i + if (t > 2) throw Exception("too many iterations: $t") + } + if (s != "-2147483647-2147483648") throw Exception(s) +} + +fun testLong() { + var s = "" + var t = 0 + for (i in ML + 1L downTo ML) { + ++t + s += i + if (t > 2) throw Exception("too many iterations: $t") + } + if (s != "-9223372036854775807-9223372036854775808") throw Exception(s) +} + +fun testChar() { + var s = "" + var t = 0 + for (i in (MC.toInt() + 1).toChar() downTo MC) { + ++t + s += i.toInt() + if (t > 2) throw Exception("too many iterations: $t") + } + if (s != "10") throw Exception(s) +} + +fun box(): String { + testByte() + testShort() + testInt() + testLong() + testChar() + + return "OK" +} diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInDownToLongConstNoUnderflow.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInDownToLongConstNoUnderflow.kt new file mode 100644 index 00000000000..d6834e478b5 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInDownToLongConstNoUnderflow.kt @@ -0,0 +1,36 @@ +// IGNORE_BACKEND_FIR: JVM_IR + +// IMPORTANT! +// Please, when your changes cause failures in bytecodeText tests for 'for' loops, +// examine the resulting bytecode shape carefully. +// Range and progression-based loops generated with Kotlin compiler should be +// as close as possible to Java counter loops ('for (int i = a; i < b; ++i) { ... }'). +// Otherwise it may result in performance regression due to missing HotSpot optimizations. +// Run Kotlin compiler benchmarks (https://github.com/Kotlin/kotlin-benchmarks) +// with compiler built from your changes if you are not sure. + +const val M = 1L + +fun f(a: Long): Int { + var n = 0 + for (i in a downTo M) { + n++ + } + return n +} + +// 0 iterator +// 0 getStart +// 0 getEnd +// 0 getFirst +// 0 getLast +// 0 getStep +// 1 LCMP +// 1 IF + +// JVM_IR_TEMPLATES +// 1 ILOAD +// 1 ISTORE +// 0 IADD +// 0 ISUB +// 1 IINC \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forIntInDownTo.kt b/compiler/testData/codegen/bytecodeText/forLoop/forIntInDownTo.kt index 6e96c3673cc..9aedf800ac0 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/forIntInDownTo.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/forIntInDownTo.kt @@ -24,8 +24,8 @@ fun test(): Int { // 1 IF // JVM_IR_TEMPLATES -// 5 ILOAD -// 4 ISTORE +// 4 ILOAD +// 3 ISTORE // 1 IADD // 0 ISUB // 1 IINC \ No newline at end of file diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index f7740694b80..856a33cb09e 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -31145,6 +31145,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/ranges/forInDownTo"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); } + @Test + @TestMetadata("forInDownToWithPossibleUnderflow.kt") + public void testForInDownToWithPossibleUnderflow() throws Exception { + runTest("compiler/testData/codegen/box/ranges/forInDownTo/forInDownToWithPossibleUnderflow.kt"); + } + @Test @TestMetadata("forIntInDownTo.kt") public void testForIntInDownTo() throws Exception { 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 86a1129d745..041025d66db 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 @@ -2342,6 +2342,12 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { runTest("compiler/testData/codegen/bytecodeText/forLoop/forInDownToIntMinValue.kt"); } + @Test + @TestMetadata("forInDownToLongConstNoUnderflow.kt") + public void testForInDownToLongConstNoUnderflow() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/forLoop/forInDownToLongConstNoUnderflow.kt"); + } + @Test @TestMetadata("forInDownToLongMinValue.kt") public void testForInDownToLongMinValue() throws Exception { 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 3e7ba84390d..fec45f1f568 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 @@ -31271,6 +31271,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/ranges/forInDownTo"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } + @Test + @TestMetadata("forInDownToWithPossibleUnderflow.kt") + public void testForInDownToWithPossibleUnderflow() throws Exception { + runTest("compiler/testData/codegen/box/ranges/forInDownTo/forInDownToWithPossibleUnderflow.kt"); + } + @Test @TestMetadata("forIntInDownTo.kt") public void testForIntInDownTo() 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 123dc785132..4e2ba0c3852 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 @@ -2366,6 +2366,12 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest { runTest("compiler/testData/codegen/bytecodeText/forLoop/forInDownToIntMinValue.kt"); } + @Test + @TestMetadata("forInDownToLongConstNoUnderflow.kt") + public void testForInDownToLongConstNoUnderflow() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/forLoop/forInDownToLongConstNoUnderflow.kt"); + } + @Test @TestMetadata("forInDownToLongMinValue.kt") public void testForInDownToLongMinValue() throws Exception { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index a12dd55ba0f..e76d16278fa 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -26517,6 +26517,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/ranges/forInDownTo"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); } + @TestMetadata("forInDownToWithPossibleUnderflow.kt") + public void testForInDownToWithPossibleUnderflow() throws Exception { + runTest("compiler/testData/codegen/box/ranges/forInDownTo/forInDownToWithPossibleUnderflow.kt"); + } + @TestMetadata("forIntInDownTo.kt") public void testForIntInDownTo() throws Exception { runTest("compiler/testData/codegen/box/ranges/forInDownTo/forIntInDownTo.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java index 482ff2737e0..fc2a6056a41 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java @@ -21161,6 +21161,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/ranges/forInDownTo"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true); } + @TestMetadata("forInDownToWithPossibleUnderflow.kt") + public void testForInDownToWithPossibleUnderflow() throws Exception { + runTest("compiler/testData/codegen/box/ranges/forInDownTo/forInDownToWithPossibleUnderflow.kt"); + } + @TestMetadata("forIntInDownTo.kt") public void testForIntInDownTo() throws Exception { runTest("compiler/testData/codegen/box/ranges/forInDownTo/forIntInDownTo.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index fcdf3d03cfc..891021ff99a 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -20567,6 +20567,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/ranges/forInDownTo"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true); } + @TestMetadata("forInDownToWithPossibleUnderflow.kt") + public void testForInDownToWithPossibleUnderflow() throws Exception { + runTest("compiler/testData/codegen/box/ranges/forInDownTo/forInDownToWithPossibleUnderflow.kt"); + } + @TestMetadata("forIntInDownTo.kt") public void testForIntInDownTo() throws Exception { runTest("compiler/testData/codegen/box/ranges/forInDownTo/forIntInDownTo.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index a4f0d065a0d..67f7f327926 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -20582,6 +20582,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/ranges/forInDownTo"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true); } + @TestMetadata("forInDownToWithPossibleUnderflow.kt") + public void testForInDownToWithPossibleUnderflow() throws Exception { + runTest("compiler/testData/codegen/box/ranges/forInDownTo/forInDownToWithPossibleUnderflow.kt"); + } + @TestMetadata("forIntInDownTo.kt") public void testForIntInDownTo() throws Exception { runTest("compiler/testData/codegen/box/ranges/forInDownTo/forIntInDownTo.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java index 2f5df8772c4..c6e148ada5c 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java @@ -13952,6 +13952,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/ranges/forInDownTo"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true); } + @TestMetadata("forInDownToWithPossibleUnderflow.kt") + public void testForInDownToWithPossibleUnderflow() throws Exception { + runTest("compiler/testData/codegen/box/ranges/forInDownTo/forInDownToWithPossibleUnderflow.kt"); + } + @TestMetadata("forIntInDownTo.kt") public void testForIntInDownTo() throws Exception { runTest("compiler/testData/codegen/box/ranges/forInDownTo/forIntInDownTo.kt");