JVM_IR KT-48435 use Java-like counter loop when possible
This commit is contained in:
committed by
TeamCityServer
parent
d4c91c96d3
commit
1c1b9547c1
+56
@@ -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]
|
||||
}
|
||||
+1
@@ -59,6 +59,7 @@ class OptimizationMethodVisitor(
|
||||
DeadCodeEliminationMethodTransformer(),
|
||||
RedundantGotoMethodTransformer(),
|
||||
RedundantNopsCleanupMethodTransformer(),
|
||||
NegatedJumpsMethodTransformer(),
|
||||
MethodVerifier("AFTER optimizations", generationState)
|
||||
)
|
||||
|
||||
|
||||
+1
-1
@@ -75,7 +75,7 @@ class RedundantGotoMethodTransformer : MethodTransformer() {
|
||||
}
|
||||
|
||||
// Rewrite branch instructions.
|
||||
if (!labelsToReplace.isEmpty()) {
|
||||
if (labelsToReplace.isNotEmpty()) {
|
||||
insns.filterIsInstance<JumpInsnNode>().forEach { rewriteLabelIfNeeded(it, labelsToReplace) }
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -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))
|
||||
|
||||
+12
@@ -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 {
|
||||
|
||||
+111
-11
@@ -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<T : NumericHeaderInfo>(
|
||||
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
|
||||
// <body>
|
||||
// } 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<IrSimpleFunction> {
|
||||
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 (<newLoopCondition>) {
|
||||
// {
|
||||
// <loopVarAssignments>
|
||||
// inductionVariable += step
|
||||
// }
|
||||
// <originalLoopBody>
|
||||
// }
|
||||
// to:
|
||||
// do {
|
||||
// if (!(<newLoopCondition>)) break
|
||||
// val forLoopVariable = inductionVariable
|
||||
// <originalLoopBody>
|
||||
// } 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() {
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
Vendored
-3
@@ -9,7 +9,4 @@ abstract class A8 : MutableCollection<Any> {
|
||||
// 0 INSTANCEOF
|
||||
|
||||
/* Only 1 null check should be within the contains method */
|
||||
// JVM_TEMPLATES:
|
||||
// 1 IFNULL
|
||||
// JVM_IR_TEMPLATES:
|
||||
// 1 IFNONNULL
|
||||
|
||||
Vendored
-3
@@ -9,7 +9,4 @@ abstract class A<T : Any> : MutableCollection<T> {
|
||||
// 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
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
+1
-1
@@ -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:
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+12
@@ -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 {
|
||||
|
||||
+12
@@ -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 {
|
||||
|
||||
+10
@@ -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");
|
||||
|
||||
js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java
Generated
+10
@@ -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");
|
||||
|
||||
Generated
+10
@@ -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");
|
||||
|
||||
Generated
+10
@@ -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");
|
||||
|
||||
js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java
Generated
+10
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user