From 1c1b9547c1420a502689888211d8ded98956c982 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Mon, 30 Aug 2021 16:05:34 +0300 Subject: [PATCH] JVM_IR KT-48435 use Java-like counter loop when possible --- .../NegatedJumpsMethodTransformer.kt | 56 ++++++++ .../optimization/OptimizationMethodVisitor.kt | 1 + .../RedundantGotoMethodTransformer.kt | 2 +- .../StackPeepholeOptimizationsTransformer.kt | 8 +- .../FirBlackBoxCodegenTestGenerated.java | 12 ++ .../common/lower/loops/HeaderProcessor.kt | 122 ++++++++++++++++-- .../ranges/forInIntRangeToConstWithBreak.kt | 16 +++ .../forInIntRangeToConstWithContinue.kt | 16 +++ .../genericParameterBridge/notNullAnyMC.kt | 3 - .../genericParameterBridge/notNullParamMC.kt | 3 - .../safeCallAndElvisChains.kt | 4 +- .../debug/localVariables/tryFinally15.kt | 2 +- .../debug/localVariables/tryFinally9.kt | 2 +- .../codegen/BlackBoxCodegenTestGenerated.java | 12 ++ .../IrBlackBoxCodegenTestGenerated.java | 12 ++ .../LightAnalysisModeTestGenerated.java | 10 ++ .../IrJsCodegenBoxES6TestGenerated.java | 10 ++ .../IrJsCodegenBoxTestGenerated.java | 10 ++ .../semantics/JsCodegenBoxTestGenerated.java | 10 ++ .../IrCodegenBoxWasmTestGenerated.java | 10 ++ 20 files changed, 295 insertions(+), 26 deletions(-) create mode 100644 compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/NegatedJumpsMethodTransformer.kt create mode 100644 compiler/testData/codegen/box/ranges/forInIntRangeToConstWithBreak.kt create mode 100644 compiler/testData/codegen/box/ranges/forInIntRangeToConstWithContinue.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/NegatedJumpsMethodTransformer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/NegatedJumpsMethodTransformer.kt new file mode 100644 index 00000000000..80f7e86b602 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/NegatedJumpsMethodTransformer.kt @@ -0,0 +1,56 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.codegen.optimization + +import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer +import org.jetbrains.org.objectweb.asm.Opcodes +import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode +import org.jetbrains.org.objectweb.asm.tree.JumpInsnNode +import org.jetbrains.org.objectweb.asm.tree.MethodNode + +class NegatedJumpsMethodTransformer : MethodTransformer() { + override fun transform(internalClassName: String, methodNode: MethodNode) { + val insnList = methodNode.instructions + + // Replace sequence of instructions such as + // IF_ICMPLT L1 = insn + // GOTO L2 = next1 + // L1: = next2 + // with + // IF_ICMPGE L2 = negatedJumpInsn + // L1: = next2 + for (insn in insnList.toArray()) { + if (insn.type != AbstractInsnNode.JUMP_INSN || insn.opcode == Opcodes.GOTO) continue + val next1 = insn.next ?: continue + if (next1.opcode != Opcodes.GOTO) continue + val next2 = next1.next ?: continue + if (next2 != (insn as JumpInsnNode).label) continue + + val negatedJumpInsn = JumpInsnNode(negateConditionalJumpOpcode(insn.opcode), (next1 as JumpInsnNode).label) + insnList.insertBefore(insn, negatedJumpInsn) + insnList.remove(insn) + insnList.remove(next1) + } + } + + private val negatedConditionalJumpOpcode = IntArray(255).also { a -> + fun negated(opcode1: Int, opcode2: Int) { + a[opcode1] = opcode2 + a[opcode2] = opcode1 + } + negated(Opcodes.IFNULL, Opcodes.IFNONNULL) + negated(Opcodes.IFEQ, Opcodes.IFNE) + negated(Opcodes.IFLT, Opcodes.IFGE) + negated(Opcodes.IFLE, Opcodes.IFGT) + negated(Opcodes.IF_ICMPEQ, Opcodes.IF_ICMPNE) + negated(Opcodes.IF_ICMPLT, Opcodes.IF_ICMPGE) + negated(Opcodes.IF_ICMPLE, Opcodes.IF_ICMPGT) + negated(Opcodes.IF_ACMPEQ, Opcodes.IF_ACMPNE) + } + + private fun negateConditionalJumpOpcode(opcode: Int): Int = + negatedConditionalJumpOpcode[opcode] +} diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/OptimizationMethodVisitor.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/OptimizationMethodVisitor.kt index d8ad16667b3..6215c5ce9cb 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/OptimizationMethodVisitor.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/OptimizationMethodVisitor.kt @@ -59,6 +59,7 @@ class OptimizationMethodVisitor( DeadCodeEliminationMethodTransformer(), RedundantGotoMethodTransformer(), RedundantNopsCleanupMethodTransformer(), + NegatedJumpsMethodTransformer(), MethodVerifier("AFTER optimizations", generationState) ) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/RedundantGotoMethodTransformer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/RedundantGotoMethodTransformer.kt index b4dd65063e2..193937676f9 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/RedundantGotoMethodTransformer.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/RedundantGotoMethodTransformer.kt @@ -75,7 +75,7 @@ class RedundantGotoMethodTransformer : MethodTransformer() { } // Rewrite branch instructions. - if (!labelsToReplace.isEmpty()) { + if (labelsToReplace.isNotEmpty()) { insns.filterIsInstance().forEach { rewriteLabelIfNeeded(it, labelsToReplace) } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/boxing/StackPeepholeOptimizationsTransformer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/boxing/StackPeepholeOptimizationsTransformer.kt index 18fd1923152..68dee7ebafc 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/boxing/StackPeepholeOptimizationsTransformer.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/boxing/StackPeepholeOptimizationsTransformer.kt @@ -33,10 +33,10 @@ class StackPeepholeOptimizationsTransformer : MethodTransformer() { val insns = methodNode.instructions.toArray() - forInsn@ for (i in 1 until insns.size) { + for (i in 1 until insns.size) { val insn = insns[i] val prev = insn.previous - val prevNonNop = insn.findPreviousOrNull { it.opcode != Opcodes.NOP } ?: continue@forInsn + val prevNonNop = insn.findPreviousOrNull { it.opcode != Opcodes.NOP } ?: continue when (insn.opcode) { Opcodes.POP -> { @@ -53,7 +53,7 @@ class StackPeepholeOptimizationsTransformer : MethodTransformer() { } Opcodes.SWAP -> { - val prevNonNop2 = prevNonNop.findPreviousOrNull { it.opcode != Opcodes.NOP } ?: continue@forInsn + val prevNonNop2 = prevNonNop.findPreviousOrNull { it.opcode != Opcodes.NOP } ?: continue if (prevNonNop.isPurePushOfSize1() && prevNonNop2.isPurePushOfSize1()) { actions.add { it.remove(insn) @@ -83,7 +83,7 @@ class StackPeepholeOptimizationsTransformer : MethodTransformer() { it.remove(prevNonNop) } } else if (i > 1) { - val prevNonNop2 = prevNonNop.findPreviousOrNull { it.opcode != Opcodes.NOP } ?: continue@forInsn + val prevNonNop2 = prevNonNop.findPreviousOrNull { it.opcode != Opcodes.NOP } ?: continue if (prevNonNop.isEliminatedByPop() && prevNonNop2.isEliminatedByPop()) { actions.add { it.set(insn, InsnNode(Opcodes.NOP)) 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 46c621f84f1..e2b23e97e89 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 @@ -30198,6 +30198,18 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/ranges/forInFloatRangeWithCustomIterator.kt"); } + @Test + @TestMetadata("forInIntRangeToConstWithBreak.kt") + public void testForInIntRangeToConstWithBreak() throws Exception { + runTest("compiler/testData/codegen/box/ranges/forInIntRangeToConstWithBreak.kt"); + } + + @Test + @TestMetadata("forInIntRangeToConstWithContinue.kt") + public void testForInIntRangeToConstWithContinue() throws Exception { + runTest("compiler/testData/codegen/box/ranges/forInIntRangeToConstWithContinue.kt"); + } + @Test @TestMetadata("forInRangeLiteralWithMixedTypeBounds.kt") public void testForInRangeLiteralWithMixedTypeBounds() throws Exception { diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/HeaderProcessor.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/HeaderProcessor.kt index bd934c36ded..d44537477c1 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/HeaderProcessor.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/HeaderProcessor.kt @@ -12,10 +12,10 @@ import org.jetbrains.kotlin.backend.common.lower.irIfThen import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.expressions.impl.IrDoWhileLoopImpl -import org.jetbrains.kotlin.ir.expressions.impl.IrWhileLoopImpl +import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.* @@ -59,7 +59,7 @@ interface ForLoopHeader { abstract class NumericForLoopHeader( val headerInfo: T, builder: DeclarationIrBuilder, - context: CommonBackendContext + protected val context: CommonBackendContext ) : ForLoopHeader { override val consumesLoopVariableComponents = false @@ -338,20 +338,25 @@ class ProgressionLoopHeader( // (`for (int i = first; i < lastExclusive; ++i) { ... }`). // Otherwise loop-related optimizations will not kick in, resulting in significant performance degradation. // - // Use a simple while loop: + // If possible, use a do-while loop: + // do { + // if ( !( inductionVariable < last ) ) break + // val loopVariable = inductionVariable + // + // } while ( { inductionVariable += step; true } ) + // This loop form is equivalent to the Java counter loop shown above. // + // Otherwise, use a simple while loop: // while (inductionVar < last) { // val loopVar = inductionVar // inductionVar += step // // Loop body // } - // - val newLoop = IrWhileLoopImpl(oldLoop.startOffset, oldLoop.endOffset, oldLoop.type, oldLoop.origin).apply { - label = oldLoop.label - condition = buildLoopCondition(this@with) - body = newBody - } - LoopReplacement(newLoop, newLoop) + + val newLoopCondition = buildLoopCondition(this@with) + + buildJavaLikeDoWhileCounterLoop(oldLoop, newLoopCondition, newBody) + ?: buildJavaLikeWhileCounterLoop(oldLoop, newLoopCondition, newBody) } else { // Use an if-guarded do-while loop (note the difference in loop condition): // @@ -372,6 +377,101 @@ class ProgressionLoopHeader( LoopReplacement(newLoop, irIfThen(loopCondition, newLoop)) } } + + private val booleanNot = + context.irBuiltIns.booleanClass.owner.findDeclaration { + it.name == OperatorNameConventions.NOT + } ?: error("No '${OperatorNameConventions.NOT}' in ${context.irBuiltIns.booleanClass.owner.render()}") + + private fun buildJavaLikeDoWhileCounterLoop( + oldLoop: IrLoop, + newLoopCondition: IrExpression, + newBody: IrExpression? + ): LoopReplacement? { + // Transform loop: + // while () { + // { + // + // inductionVariable += step + // } + // + // } + // to: + // do { + // if (!()) break + // val forLoopVariable = inductionVariable + // + // } while ( { inductionVariable += step; true } ) + val bodyBlock = newBody as? IrContainerExpression ?: return null + val forLoopNextBlock = bodyBlock.statements[0] as? IrContainerExpression ?: return null + if (forLoopNextBlock.origin != IrStatementOrigin.FOR_LOOP_NEXT) return null + val loopStep = forLoopNextBlock.statements.last() as? IrSetValue ?: return null + + val doWhileLoop = IrDoWhileLoopImpl(oldLoop.startOffset, oldLoop.endOffset, oldLoop.type, oldLoop.origin) + doWhileLoop.label = oldLoop.label + + val conditionStartOffset = newLoopCondition.startOffset + val conditionEndOffset = newLoopCondition.endOffset + val negatedCondition = + IrCallImpl.fromSymbolOwner(conditionStartOffset, conditionEndOffset, booleanNot.symbol).apply { + dispatchReceiver = newLoopCondition + } + + val negatedConditionCheck = + IrWhenImpl( + conditionStartOffset, conditionEndOffset, context.irBuiltIns.unitType, null, + listOf( + IrBranchImpl( + negatedCondition, + IrBreakImpl(conditionStartOffset, conditionEndOffset, context.irBuiltIns.nothingType, doWhileLoop) + ) + ) + ) + + bodyBlock.statements[0] = negatedConditionCheck + val loopVarAssignments = + if (forLoopNextBlock.statements.size == 2) + forLoopNextBlock.statements[0] + else + IrCompositeImpl( + forLoopNextBlock.startOffset, forLoopNextBlock.endOffset, forLoopNextBlock.type, null, + forLoopNextBlock.statements.subList(0, forLoopNextBlock.statements.lastIndex) + ) + bodyBlock.statements.add(1, loopVarAssignments) + doWhileLoop.body = bodyBlock + + val stepStartOffset = loopStep.startOffset + val stepEndOffset = loopStep.endOffset + val doWhileCondition = + IrCompositeImpl( + stepStartOffset, stepEndOffset, context.irBuiltIns.booleanType, null, + listOf( + loopStep, + IrConstImpl.boolean(stepStartOffset, stepEndOffset, context.irBuiltIns.booleanType, true) + ) + ) + doWhileLoop.condition = doWhileCondition + + return LoopReplacement(doWhileLoop, doWhileLoop) + } + + private fun buildJavaLikeWhileCounterLoop( + oldLoop: IrLoop, + newLoopCondition: IrExpression, + newBody: IrExpression? + ): LoopReplacement { + // while (inductionVar < last) { + // val loopVar = inductionVar + // inductionVar += step + // // Loop body + // } + val newLoop = IrWhileLoopImpl(oldLoop.startOffset, oldLoop.endOffset, oldLoop.type, oldLoop.origin).apply { + label = oldLoop.label + condition = newLoopCondition + body = newBody + } + return LoopReplacement(newLoop, newLoop) + } } private class InitializerCallReplacer(val replacementCall: IrCall) : IrElementTransformerVoid() { diff --git a/compiler/testData/codegen/box/ranges/forInIntRangeToConstWithBreak.kt b/compiler/testData/codegen/box/ranges/forInIntRangeToConstWithBreak.kt new file mode 100644 index 00000000000..9aba713245f --- /dev/null +++ b/compiler/testData/codegen/box/ranges/forInIntRangeToConstWithBreak.kt @@ -0,0 +1,16 @@ +const val N = 10 + +fun sumUntil6(): Int { + var sum = 0 + for (i in 0..N) { + if (i == 6) break + sum += i + } + return sum +} + +fun box(): String { + val test = sumUntil6() + if (test != 15) return "Failed: $test" + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/ranges/forInIntRangeToConstWithContinue.kt b/compiler/testData/codegen/box/ranges/forInIntRangeToConstWithContinue.kt new file mode 100644 index 00000000000..c0b4d47f527 --- /dev/null +++ b/compiler/testData/codegen/box/ranges/forInIntRangeToConstWithContinue.kt @@ -0,0 +1,16 @@ +const val N = 10 + +fun sumOdds(): Int { + var sum = 0 + for (i in 0..N) { + if (i%2 == 0) continue + sum += i + } + return sum +} + +fun box(): String { + val test = sumOdds() + if (test != 25) return "Failed: $test" + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/builtinFunctions/genericParameterBridge/notNullAnyMC.kt b/compiler/testData/codegen/bytecodeText/builtinFunctions/genericParameterBridge/notNullAnyMC.kt index 4e73e898f7c..5addfb8e81b 100644 --- a/compiler/testData/codegen/bytecodeText/builtinFunctions/genericParameterBridge/notNullAnyMC.kt +++ b/compiler/testData/codegen/bytecodeText/builtinFunctions/genericParameterBridge/notNullAnyMC.kt @@ -9,7 +9,4 @@ abstract class A8 : MutableCollection { // 0 INSTANCEOF /* Only 1 null check should be within the contains method */ -// JVM_TEMPLATES: -// 1 IFNULL -// JVM_IR_TEMPLATES: // 1 IFNONNULL diff --git a/compiler/testData/codegen/bytecodeText/builtinFunctions/genericParameterBridge/notNullParamMC.kt b/compiler/testData/codegen/bytecodeText/builtinFunctions/genericParameterBridge/notNullParamMC.kt index 2cde9869764..9c1eecb9a3a 100644 --- a/compiler/testData/codegen/bytecodeText/builtinFunctions/genericParameterBridge/notNullParamMC.kt +++ b/compiler/testData/codegen/bytecodeText/builtinFunctions/genericParameterBridge/notNullParamMC.kt @@ -9,7 +9,4 @@ abstract class A : MutableCollection { // 0 INSTANCEOF /* Only 1 null check should be within the contains method (because T is not nullable) */ -// JVM_TEMPLATES: -// 1 IFNULL -// JVM_IR_TEMPLATES: // 1 IFNONNULL diff --git a/compiler/testData/codegen/bytecodeText/nullCheckOptimization/safeCallAndElvisChains.kt b/compiler/testData/codegen/bytecodeText/nullCheckOptimization/safeCallAndElvisChains.kt index 5f083a8dd30..29b94cd839d 100644 --- a/compiler/testData/codegen/bytecodeText/nullCheckOptimization/safeCallAndElvisChains.kt +++ b/compiler/testData/codegen/bytecodeText/nullCheckOptimization/safeCallAndElvisChains.kt @@ -8,8 +8,8 @@ class A(val x: String) { // JVM_TEMPLATES // Optimization not implemented -// 8 IFNULL -// 0 IFNONNULL +// 4 IFNULL +// 4 IFNONNULL // 2 ACONST_NULL // JVM_IR_TEMPLATES diff --git a/compiler/testData/debug/localVariables/tryFinally15.kt b/compiler/testData/debug/localVariables/tryFinally15.kt index 94046bed91d..5026c02938a 100644 --- a/compiler/testData/debug/localVariables/tryFinally15.kt +++ b/compiler/testData/debug/localVariables/tryFinally15.kt @@ -26,6 +26,6 @@ fun box(): String { // LOCAL VARIABLES JVM // test.kt:5 box: i:int=0:int // LOCAL VARIABLES JVM_IR -// test.kt:5 box: +// test.kt:5 box: i:int=0:int // LOCAL VARIABLES // test.kt:14 box: diff --git a/compiler/testData/debug/localVariables/tryFinally9.kt b/compiler/testData/debug/localVariables/tryFinally9.kt index d9113f8de17..af1a8bb1e30 100644 --- a/compiler/testData/debug/localVariables/tryFinally9.kt +++ b/compiler/testData/debug/localVariables/tryFinally9.kt @@ -53,7 +53,7 @@ fun box() { // test.kt:24 compute: // test.kt:25 compute: s2:java.lang.String="NOPE":java.lang.String // test.kt:26 compute: s2:java.lang.String="NOPE":java.lang.String, j:int=0:int -// test.kt:25 compute: s2:java.lang.String="OK":java.lang.String +// test.kt:25 compute: s2:java.lang.String="OK":java.lang.String, j:int=0:int // test.kt:28 compute: s2:java.lang.String="OK":java.lang.String // test.kt:34 box: // test.kt:35 box: result:java.lang.String="NON_LOCAL_RETURN":java.lang.String 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 433991c9ec9..c555d2b5f1e 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 @@ -30042,6 +30042,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/ranges/forInFloatRangeWithCustomIterator.kt"); } + @Test + @TestMetadata("forInIntRangeToConstWithBreak.kt") + public void testForInIntRangeToConstWithBreak() throws Exception { + runTest("compiler/testData/codegen/box/ranges/forInIntRangeToConstWithBreak.kt"); + } + + @Test + @TestMetadata("forInIntRangeToConstWithContinue.kt") + public void testForInIntRangeToConstWithContinue() throws Exception { + runTest("compiler/testData/codegen/box/ranges/forInIntRangeToConstWithContinue.kt"); + } + @Test @TestMetadata("forInRangeLiteralWithMixedTypeBounds.kt") public void testForInRangeLiteralWithMixedTypeBounds() 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 37c80f1bf28..9557de8f945 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 @@ -30198,6 +30198,18 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/ranges/forInFloatRangeWithCustomIterator.kt"); } + @Test + @TestMetadata("forInIntRangeToConstWithBreak.kt") + public void testForInIntRangeToConstWithBreak() throws Exception { + runTest("compiler/testData/codegen/box/ranges/forInIntRangeToConstWithBreak.kt"); + } + + @Test + @TestMetadata("forInIntRangeToConstWithContinue.kt") + public void testForInIntRangeToConstWithContinue() throws Exception { + runTest("compiler/testData/codegen/box/ranges/forInIntRangeToConstWithContinue.kt"); + } + @Test @TestMetadata("forInRangeLiteralWithMixedTypeBounds.kt") public void testForInRangeLiteralWithMixedTypeBounds() 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 c9a68c1dd0a..ccf9c1f8f23 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -25556,6 +25556,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/ranges/forInCustomIterable.kt"); } + @TestMetadata("forInIntRangeToConstWithBreak.kt") + public void testForInIntRangeToConstWithBreak() throws Exception { + runTest("compiler/testData/codegen/box/ranges/forInIntRangeToConstWithBreak.kt"); + } + + @TestMetadata("forInIntRangeToConstWithContinue.kt") + public void testForInIntRangeToConstWithContinue() throws Exception { + runTest("compiler/testData/codegen/box/ranges/forInIntRangeToConstWithContinue.kt"); + } + @TestMetadata("forInRangeLiteralWithMixedTypeBounds.kt") public void testForInRangeLiteralWithMixedTypeBounds() throws Exception { runTest("compiler/testData/codegen/box/ranges/forInRangeLiteralWithMixedTypeBounds.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 4f1a22a34a2..b881432fe36 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 @@ -20210,6 +20210,16 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes runTest("compiler/testData/codegen/box/ranges/forInFloatRangeWithCustomIterator.kt"); } + @TestMetadata("forInIntRangeToConstWithBreak.kt") + public void testForInIntRangeToConstWithBreak() throws Exception { + runTest("compiler/testData/codegen/box/ranges/forInIntRangeToConstWithBreak.kt"); + } + + @TestMetadata("forInIntRangeToConstWithContinue.kt") + public void testForInIntRangeToConstWithContinue() throws Exception { + runTest("compiler/testData/codegen/box/ranges/forInIntRangeToConstWithContinue.kt"); + } + @TestMetadata("forInRangeLiteralWithMixedTypeBounds.kt") public void testForInRangeLiteralWithMixedTypeBounds() throws Exception { runTest("compiler/testData/codegen/box/ranges/forInRangeLiteralWithMixedTypeBounds.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 0e11aa39c1a..26dec553100 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 @@ -19616,6 +19616,16 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/ranges/forInFloatRangeWithCustomIterator.kt"); } + @TestMetadata("forInIntRangeToConstWithBreak.kt") + public void testForInIntRangeToConstWithBreak() throws Exception { + runTest("compiler/testData/codegen/box/ranges/forInIntRangeToConstWithBreak.kt"); + } + + @TestMetadata("forInIntRangeToConstWithContinue.kt") + public void testForInIntRangeToConstWithContinue() throws Exception { + runTest("compiler/testData/codegen/box/ranges/forInIntRangeToConstWithContinue.kt"); + } + @TestMetadata("forInRangeLiteralWithMixedTypeBounds.kt") public void testForInRangeLiteralWithMixedTypeBounds() throws Exception { runTest("compiler/testData/codegen/box/ranges/forInRangeLiteralWithMixedTypeBounds.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 b3e2b257143..2eda5f27f32 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 @@ -19666,6 +19666,16 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/ranges/forInFloatRangeWithCustomIterator.kt"); } + @TestMetadata("forInIntRangeToConstWithBreak.kt") + public void testForInIntRangeToConstWithBreak() throws Exception { + runTest("compiler/testData/codegen/box/ranges/forInIntRangeToConstWithBreak.kt"); + } + + @TestMetadata("forInIntRangeToConstWithContinue.kt") + public void testForInIntRangeToConstWithContinue() throws Exception { + runTest("compiler/testData/codegen/box/ranges/forInIntRangeToConstWithContinue.kt"); + } + @TestMetadata("forInRangeLiteralWithMixedTypeBounds.kt") public void testForInRangeLiteralWithMixedTypeBounds() throws Exception { runTest("compiler/testData/codegen/box/ranges/forInRangeLiteralWithMixedTypeBounds.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 80e0c1b3bb4..8ed3495e527 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 @@ -12617,6 +12617,16 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest runTest("compiler/testData/codegen/box/ranges/forInFloatRangeWithCustomIterator.kt"); } + @TestMetadata("forInIntRangeToConstWithBreak.kt") + public void testForInIntRangeToConstWithBreak() throws Exception { + runTest("compiler/testData/codegen/box/ranges/forInIntRangeToConstWithBreak.kt"); + } + + @TestMetadata("forInIntRangeToConstWithContinue.kt") + public void testForInIntRangeToConstWithContinue() throws Exception { + runTest("compiler/testData/codegen/box/ranges/forInIntRangeToConstWithContinue.kt"); + } + @TestMetadata("forInRangeLiteralWithMixedTypeBounds.kt") public void testForInRangeLiteralWithMixedTypeBounds() throws Exception { runTest("compiler/testData/codegen/box/ranges/forInRangeLiteralWithMixedTypeBounds.kt");