diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/HeaderInfo.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/HeaderInfo.kt index 171358b88a4..f934c9ad173 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/HeaderInfo.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/HeaderInfo.kt @@ -80,7 +80,8 @@ class ProgressionHeaderInfo( isReversed: Boolean = false, canOverflow: Boolean? = null, direction: ProgressionDirection, - val additionalStatements: List = listOf() + val additionalStatements: List = listOf(), + val originalLastInclusive: IrExpression? = null ) : NumericHeaderInfo( progressionType, first, last, step, isLastInclusive, canCacheLast = true, @@ -88,6 +89,22 @@ class ProgressionHeaderInfo( direction = direction ) { + fun revertToLastInclusive(): ProgressionHeaderInfo? = + originalLastInclusive?.let { + ProgressionHeaderInfo( + progressionType = progressionType, + first = first, + last = originalLastInclusive, + step = step, + isLastInclusive = true, + isReversed = isReversed, + canOverflow = canOverflow, + direction = direction, + additionalStatements = additionalStatements, + originalLastInclusive = null + ) + } + val canOverflow: Boolean by lazy { if (canOverflow != null) return@lazy canOverflow @@ -148,21 +165,23 @@ class ProgressionHeaderInfo( } } - override fun asReversed() = if (isLastInclusive) { - ProgressionHeaderInfo( - progressionType = progressionType, - first = last, - last = first, - step = step.negate(), - isReversed = !isReversed, - direction = direction.asReversed(), - additionalStatements = additionalStatements - ) - } else { - // If reversed, we would have a "first-exclusive" loop. We are currently not supporting this since it would add more complexity - // due to possible overflow when pre-incrementing the loop variable (see KT-42533). - null - } + override fun asReversed(): HeaderInfo? = + if (isLastInclusive) { + ProgressionHeaderInfo( + progressionType = progressionType, + first = last, + last = first, + step = step.negate(), + isReversed = !isReversed, + direction = direction.asReversed(), + additionalStatements = additionalStatements + ) + } else { + // If reversed, we would have a "first-exclusive" loop. We are currently not supporting this since it would add more complexity + // due to possible overflow when pre-incrementing the loop variable (see KT-42533). + revertToLastInclusive()?.asReversed() + } + } /** 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 dddba51b0bf..aec822a1a2b 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 @@ -304,7 +304,7 @@ class ProgressionLoopHeader( override fun buildLoop(builder: DeclarationIrBuilder, oldLoop: IrLoop, newBody: IrExpression?) = with(builder) { - val newLoop = if (headerInfo.canOverflow) { + if (headerInfo.canOverflow) { // If the induction variable CAN overflow, we cannot use it in the loop condition. Loop is lowered into something like: // // if (inductionVar <= last) { @@ -315,7 +315,7 @@ class ProgressionLoopHeader( // // Loop body // } while (loopVar != last) // } - IrDoWhileLoopImpl(oldLoop.startOffset, oldLoop.endOffset, oldLoop.type, oldLoop.origin).apply { + val newLoop = IrDoWhileLoopImpl(oldLoop.startOffset, oldLoop.endOffset, oldLoop.type, oldLoop.origin).apply { val loopVariableExpression = irGet(loopVariable!!).let { headerInfo.progressionType.run { if (this is UnsignedProgressionType) { @@ -328,8 +328,30 @@ class ProgressionLoopHeader( condition = irNotEquals(loopVariableExpression, lastExpression) body = newBody } + + val loopCondition = buildLoopCondition(this@with) + LoopReplacement(newLoop, irIfThen(loopCondition, newLoop)) + } else if (!headerInfo.isLastInclusive) { + // It is critically important for loop code performance on JVM to "look like" a simple counter loop in Java when possible + // (`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: + // + // 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) } else { - // If the induction variable can NOT overflow, use a do-while loop. Loop is lowered into something like: + // Use an if-guarded do-while loop (note the difference in loop condition): // // if (inductionVar <= last) { // do { @@ -339,17 +361,14 @@ class ProgressionLoopHeader( // } while (inductionVar <= last) // } // - // Even though this can be simplified into a simpler while loop, using if + do-while (i.e., doing a loop inversion) - // performs better in benchmarks. In cases where `last` is a constant, the `if` may be optimized away. - IrDoWhileLoopImpl(oldLoop.startOffset, oldLoop.endOffset, oldLoop.type, oldLoop.origin).apply { + val newLoop = IrDoWhileLoopImpl(oldLoop.startOffset, oldLoop.endOffset, oldLoop.type, oldLoop.origin).apply { label = oldLoop.label condition = buildLoopCondition(this@with) body = newBody } + val loopCondition = buildLoopCondition(this@with) + LoopReplacement(newLoop, irIfThen(loopCondition, newLoop)) } - - val loopCondition = buildLoopCondition(this@with) - LoopReplacement(newLoop, irIfThen(loopCondition, newLoop)) } } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/IndicesHandlers.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/IndicesHandlers.kt index b41176e868b..2559b08bd7f 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/IndicesHandlers.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/IndicesHandlers.kt @@ -26,17 +26,18 @@ internal abstract class IndicesHandler(protected val context: CommonBackendConte override fun build(expression: IrCall, data: ProgressionType, scopeOwner: IrSymbol): HeaderInfo? = with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) { // `last = array.size - 1` (last is inclusive) for the loop `for (i in array.indices)`. - val last = irCall(expression.symbol.owner.extensionReceiverParameter!!.type.sizePropertyGetter).apply { - dispatchReceiver = expression.extensionReceiver!! - }.decrement() + val last = irCall(expression.symbol.owner.extensionReceiverParameter!!.type.sizePropertyGetter) + .apply { dispatchReceiver = expression.extensionReceiver!! } ProgressionHeaderInfo( data, first = irInt(0), last = last, step = irInt(1), + isLastInclusive = false, canOverflow = false, - direction = ProgressionDirection.INCREASING + direction = ProgressionDirection.INCREASING, + originalLastInclusive = last.decrement() ) } 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 67bba06b21f..8c29f0ae5fc 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 @@ -15,8 +15,11 @@ import org.jetbrains.kotlin.backend.common.lower.loops.ProgressionType 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.impl.IrConstImpl import org.jetbrains.kotlin.ir.symbols.IrSymbol -import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.util.OperatorNameConventions /** Builds a [HeaderInfo] for progressions built using the `rangeTo` function. */ @@ -34,12 +37,61 @@ 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 last = expression.getValueArgument(0)!! + + // Convert range with inclusive upper bound to exclusive upper bound if possible. + // This affects loop code performance on JVM. + if (canUseExclusiveUpperBound(last, data)) { + val lastExclusive = last.convertToExclusiveUpperBound() + if (lastExclusive != null) { + return@with ProgressionHeaderInfo( + data, + first = expression.dispatchReceiver!!, + last = lastExclusive, + step = irInt(1), + direction = ProgressionDirection.INCREASING, + isLastInclusive = false, + originalLastInclusive = last + ) + } + } + ProgressionHeaderInfo( data, first = expression.dispatchReceiver!!, - last = expression.getValueArgument(0)!!, + last = last, step = irInt(1), direction = ProgressionDirection.INCREASING ) } + + 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(): IrConstImpl? { + val irConst = this as? IrConst<*> ?: return null + return when (irConst.kind) { + IrConstKind.Char -> + IrConstImpl.char(startOffset, endOffset, type, IrConstKind.Char.valueOf(irConst).inc()) + IrConstKind.Byte -> + IrConstImpl.byte(startOffset, endOffset, type, IrConstKind.Byte.valueOf(irConst).inc()) + IrConstKind.Short -> + IrConstImpl.short(startOffset, endOffset, type, IrConstKind.Short.valueOf(irConst).inc()) + IrConstKind.Int -> + IrConstImpl.int(startOffset, endOffset, type, IrConstKind.Int.valueOf(irConst).inc()) + IrConstKind.Long -> + IrConstImpl.long(startOffset, endOffset, type, IrConstKind.Long.valueOf(irConst).inc()) + else -> + null + } + } + + } \ No newline at end of file diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/StepHandler.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/StepHandler.kt index 033bb3c5d6e..2b260737ac6 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/StepHandler.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/StepHandler.kt @@ -43,7 +43,7 @@ internal class StepHandler( override fun build(expression: IrCall, data: ProgressionType, scopeOwner: IrSymbol): HeaderInfo? = with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) { // Retrieve the HeaderInfo from the underlying progression (if any). - val nestedInfo = expression.extensionReceiver!!.accept(visitor, null) as? ProgressionHeaderInfo + var nestedInfo = expression.extensionReceiver!!.accept(visitor, null) as? ProgressionHeaderInfo ?: return null if (!nestedInfo.isLastInclusive) { @@ -51,7 +51,8 @@ internal class StepHandler( // underlying progression is last-exclusive, we must decrement the nested "last" by the step. However, this can cause // underflow if "last" is MIN_VALUE. We will not support fully optimizing this scenario (e.g., `for (i in A until B step C`) // for now. It will be partly optimized via DefaultProgressionHandler. - return null + nestedInfo = nestedInfo.revertToLastInclusive() + ?: return null } val stepArg = expression.getValueArgument(0)!! diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInIndices/forInCharSequenceIndices.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInIndices/forInCharSequenceIndices.kt index 523003165e8..264ac79e0e4 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/forInIndices/forInCharSequenceIndices.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInIndices/forInCharSequenceIndices.kt @@ -6,22 +6,15 @@ fun test(s: CharSequence): Int { return result } -// JVM non-IR uses while. -// JVM IR uses if + do-while. - // 0 iterator // 0 getStart // 0 getEnd // 0 getFirst // 0 getLast -// JVM_TEMPLATES // 0 IF_ICMPGT // 0 IF_ICMPEQ +// 0 IF_ICMPLE // 1 IF_ICMPGE // 1 IF -// JVM_IR_TEMPLATES -// 1 IF_ICMPGT -// 1 IF_ICMPLE -// 2 IF diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInIndices/forInCharSequenceTypeParameterIndices.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInIndices/forInCharSequenceTypeParameterIndices.kt index b12baad93a0..21ee58e2a4c 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/forInIndices/forInCharSequenceTypeParameterIndices.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInIndices/forInCharSequenceTypeParameterIndices.kt @@ -6,9 +6,6 @@ fun test(s: T): Int { return result } -// JVM non-IR uses while. -// JVM IR uses if + do-while. - // 0 iterator // 0 getStart // 0 getEnd @@ -16,13 +13,8 @@ fun test(s: T): Int { // 0 getLast // 1 INVOKEINTERFACE java/lang/CharSequence\.length \(\)I -// JVM_TEMPLATES // 0 IF_ICMPGT // 0 IF_ICMPEQ +// 0 IF_ICMPLE // 1 IF_ICMPGE // 1 IF - -// JVM_IR_TEMPLATES -// 1 IF_ICMPGT -// 1 IF_ICMPLE -// 2 IF diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInIndices/forInCollectionImplicitReceiverIndices.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInIndices/forInCollectionImplicitReceiverIndices.kt index f0c99958401..6392e9c0fcb 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/forInIndices/forInCollectionImplicitReceiverIndices.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInIndices/forInCollectionImplicitReceiverIndices.kt @@ -12,14 +12,7 @@ fun Collection.sumIndices(): Int { // 0 getFirst // 0 getLast -// JVM non-IR uses while. -// JVM IR uses if + do-while. - -// JVM_TEMPLATES // 1 IF_ICMPGE +// 0 IF_ICMPGT +// 0 IF_ICMPLE // 1 IF - -// JVM_IR_TEMPLATES -// 1 IF_ICMPGT -// 1 IF_ICMPLE -// 2 IF diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInIndices/forInCollectionIndices.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInIndices/forInCollectionIndices.kt index 1a71ce9723b..1fb322be881 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/forInIndices/forInCollectionIndices.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInIndices/forInCollectionIndices.kt @@ -11,14 +11,7 @@ fun test() { // 0 getFirst // 0 getLast -// JVM non-IR uses while. -// JVM IR uses if + do-while. - -// JVM_TEMPLATES // 1 IF_ICMPGE +// 0 IF_ICMPGT +// 0 IF_ICMPLE // 1 IF - -// JVM_IR_TEMPLATES -// 1 IF_ICMPGT -// 1 IF_ICMPLE -// 2 IF diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInIndices/forInCollectionTypeParameterIndices.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInIndices/forInCollectionTypeParameterIndices.kt index 7e758eab610..4dff26c0560 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/forInIndices/forInCollectionTypeParameterIndices.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInIndices/forInCollectionTypeParameterIndices.kt @@ -12,14 +12,7 @@ fun > test(c: T) { // 0 getLast // 1 INVOKEINTERFACE java/util/Collection\.size \(\)I -// JVM non-IR uses while. -// JVM IR uses if + do-while. - -// JVM_TEMPLATES // 1 IF_ICMPGE +// 0 IF_ICMPGT +// 0 IF_ICMPLE // 1 IF - -// JVM_IR_TEMPLATES -// 1 IF_ICMPGT -// 1 IF_ICMPLE -// 2 IF diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInIndices/forInObjectArrayIndices.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInIndices/forInObjectArrayIndices.kt index 22b6d3c0a02..12c30077122 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/forInIndices/forInObjectArrayIndices.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInIndices/forInObjectArrayIndices.kt @@ -5,20 +5,13 @@ fun test() { } } -// JVM non-IR uses while. -// JVM IR uses if + do-while. - // 0 iterator // 0 getStart // 0 getEnd // 0 getFirst // 0 getLast -// JVM_TEMPLATES // 1 IF_ICMPGE +// 0 IF_ICMPGT +// 0 IF_ICMPLE // 1 IF - -// JVM_IR_TEMPLATES -// 1 IF_ICMPGT -// 1 IF_ICMPLE -// 2 IF \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInIndices/forInPrimitiveArrayIndices.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInIndices/forInPrimitiveArrayIndices.kt index 2880b63cc07..d8bbd3900c0 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/forInIndices/forInPrimitiveArrayIndices.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInIndices/forInPrimitiveArrayIndices.kt @@ -5,20 +5,13 @@ fun test() { } } -// JVM non-IR uses while. -// JVM IR uses if + do-while. - // 0 iterator // 0 getStart // 0 getEnd // 0 getFirst // 0 getLast -// JVM_TEMPLATES // 1 IF_ICMPGE +// 0 IF_ICMPGT +// 0 IF_ICMPLE // 1 IF - -// JVM_IR_TEMPLATES -// 1 IF_ICMPGT -// 1 IF_ICMPLE -// 2 IF \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInRangeToCharConst.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeToCharConst.kt index e1c70c00dfb..afcc0512fcf 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/forInRangeToCharConst.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeToCharConst.kt @@ -8,19 +8,17 @@ fun test(): Int { return sum } -// JVM non-IR uses while. -// JVM IR uses if + do-while. The surrounding "if" gets optimized in this test (constant condition). - // 0 iterator // 0 getStart // 0 getEnd // 0 getFirst // 0 getLast // 0 getStep -// 1 IF // JVM_TEMPLATES // 1 IF_ICMPGT +// 1 IF // JVM_IR_TEMPLATES -// 1 IF_ICMPLE \ No newline at end of file +// 1 IF_ICMPGE +// 1 IF \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInRangeToConst.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeToConst.kt index 7b2d31d5bae..68e9b7e8e3c 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/forInRangeToConst.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeToConst.kt @@ -8,19 +8,17 @@ fun test(): Int { return sum } -// JVM non-IR uses while. -// JVM IR uses if + do-while. The surrounding "if" gets optimized in this test (constant condition). - // 0 iterator // 0 getStart // 0 getEnd // 0 getFirst // 0 getLast // 0 getStep -// 1 IF // JVM_TEMPLATES // 1 IF_ICMPGT +// 1 IF // JVM_IR_TEMPLATES -// 1 IF_ICMPLE \ No newline at end of file +// 1 IF_ICMPGE +// 1 IF \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInRangeToLongConst.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeToLongConst.kt index 9f7e39a2beb..8af84c78865 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/forInRangeToLongConst.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeToLongConst.kt @@ -8,24 +8,22 @@ fun test(): Long { return sum } -// JVM non-IR uses while. -// JVM IR uses if + do-while. - // 0 iterator // 0 getStart // 0 getEnd // 0 getFirst // 0 getLast // 0 getStep -// 1 IFGT + // 0 L2I // 0 I2L // JVM_TEMPLATES +// 1 IFGT // 1 LCMP // 1 IF // JVM_IR_TEMPLATES -// 2 LCMP -// 1 IFLE -// 2 IF \ No newline at end of file +// 1 LCMP +// 1 IFGE +// 1 IF \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInRangeToQualifiedConst.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeToQualifiedConst.kt index ad1094e5ec6..3c74ad7fc7e 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/forInRangeToQualifiedConst.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInRangeToQualifiedConst.kt @@ -11,19 +11,17 @@ fun test(): Int { return s } -// JVM non-IR uses while. -// JVM IR uses if + do-while. The surrounding "if" gets optimized in this test (constant condition). - // 0 iterator // 0 getStart // 0 getEnd // 0 getFirst // 0 getLast // 0 getStep -// 1 IF // JVM_TEMPLATES // 1 IF_ICMPGT +// 1 IF // JVM_IR_TEMPLATES -// 1 IF_ICMPLE \ No newline at end of file +// 1 IF_ICMPGE +// 1 IF \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedArrayIndices.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedArrayIndices.kt index 3313525e920..f9c80bf8a83 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedArrayIndices.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedArrayIndices.kt @@ -11,9 +11,6 @@ fun box(): String { return "OK" } -// JVM non-IR uses while. -// JVM IR uses if + do-while. - // 0 reversed // 0 iterator // 0 getStart diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedCharSequenceIndices.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedCharSequenceIndices.kt index bfbc7301d47..8d621117a5a 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedCharSequenceIndices.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedCharSequenceIndices.kt @@ -11,9 +11,6 @@ fun box(): String { return "OK" } -// JVM non-IR uses while. -// JVM IR uses if + do-while. - // 0 reversed // 0 iterator // 0 getStart diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedCollectionIndices.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedCollectionIndices.kt index 34f55e94d6f..000ec3c97df 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedCollectionIndices.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedCollectionIndices.kt @@ -11,9 +11,6 @@ fun box(): String { return "OK" } -// JVM non-IR uses while. -// JVM IR uses if + do-while. - // 0 reversed // 0 iterator // 0 getStart diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedDownTo.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedDownTo.kt index 137e2ec2f8a..3fecfcb40e0 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedDownTo.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedDownTo.kt @@ -22,9 +22,6 @@ fun box(): String { return "OK" } -// JVM non-IR uses while. -// JVM IR uses if + do-while. The surrounding "if" gets optimized in this test (constant condition), except for Long. - // 0 reversed // 0 iterator // 0 getStart diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedRangeLiteral.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedRangeLiteral.kt index bcfb3376ca4..701a6a520c2 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedRangeLiteral.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInReversed/forInReversedRangeLiteral.kt @@ -22,9 +22,6 @@ fun box(): String { return "OK" } -// JVM non-IR uses while. -// JVM IR uses if + do-while. The surrounding "if" gets optimized in this test (constant condition), except for Long. - // 0 reversed // 0 iterator // 0 getStart diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilChar.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilChar.kt index 635a29f49d1..2732ea00cdd 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilChar.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilChar.kt @@ -6,9 +6,6 @@ fun test(a: Char, b: Char): String { return s } -// JVM non-IR uses while. -// JVM IR uses if + do-while. - // 0 iterator // 0 getStart // 0 getEnd @@ -16,11 +13,6 @@ fun test(a: Char, b: Char): String { // 0 getLast // 0 getStep -// JVM_TEMPLATES // 1 IF_ICMPGE +// 0 IF_ICMPLT // 1 IF - -// JVM_IR_TEMPLATES -// 1 IF_ICMPGE -// 1 IF_ICMPLT -// 2 IF \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilCharMaxValue.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilCharMaxValue.kt index 033b2551069..9d390ce5456 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilCharMaxValue.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilCharMaxValue.kt @@ -8,9 +8,6 @@ fun f(a: Char): Int { return n } -// JVM non-IR uses while. -// JVM IR uses if + do-while. - // 0 iterator // 0 getStart // 0 getEnd @@ -18,11 +15,6 @@ fun f(a: Char): Int { // 0 getLast // 0 getStep -// JVM_TEMPLATES // 1 IF_ICMPGE +// 0 IF_ICMPLT // 1 IF - -// JVM_IR_TEMPLATES -// 1 IF_ICMPGE -// 1 IF_ICMPLT -// 2 IF \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilCharMinValue.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilCharMinValue.kt index 185280308d4..9a6cb0d349f 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilCharMinValue.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilCharMinValue.kt @@ -8,9 +8,6 @@ fun f(a: Char): Int { return n } -// JVM non-IR uses while. -// JVM IR uses if + do-while. - // 0 iterator // 0 getStart // 0 getEnd @@ -18,8 +15,5 @@ fun f(a: Char): Int { // 0 getLast // 0 getStep -// JVM_TEMPLATES -// 1 IF - -// JVM_IR_TEMPLATES -// 2 IF \ No newline at end of file +// 1 IFGE +// 1 IF \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilInt.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilInt.kt index ff338635e22..8200ae4370a 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilInt.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilInt.kt @@ -6,9 +6,6 @@ fun test(a: Int, b: Int): Int { return sum } -// JVM non-IR uses while. -// JVM IR uses if + do-while. - // 0 iterator // 0 getStart // 0 getEnd @@ -16,11 +13,5 @@ fun test(a: Int, b: Int): Int { // 0 getLast // 0 getStep -// JVM_TEMPLATES // 1 IF_ICMPGE // 1 IF - -// JVM_IR_TEMPLATES -// 1 IF_ICMPGE -// 1 IF_ICMPLT -// 2 IF \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilIntMaxValue.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilIntMaxValue.kt index 139e41ab921..35f7ce14c48 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilIntMaxValue.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilIntMaxValue.kt @@ -8,9 +8,6 @@ fun f(a: Int): Int { return n } -// JVM non-IR uses while. -// JVM IR uses if + do-while. - // 0 iterator // 0 getStart // 0 getEnd @@ -18,11 +15,5 @@ fun f(a: Int): Int { // 0 getLast // 0 getStep -// JVM_TEMPLATES // 1 IF_ICMPGE // 1 IF - -// JVM_IR_TEMPLATES -// 1 IF_ICMPGE -// 1 IF_ICMPLT -// 2 IF \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilIntMinValue.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilIntMinValue.kt index 1a6e9ac5624..3aa1c31f878 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilIntMinValue.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilIntMinValue.kt @@ -18,8 +18,5 @@ fun f(a: Int): Int { // 0 getLast // 0 getStep -// JVM_TEMPLATES +// 1 IF_ICMPGE // 1 IF - -// JVM_IR_TEMPLATES -// 2 IF diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilLong.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilLong.kt index ad469367e7a..4ae4e21711f 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilLong.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilLong.kt @@ -6,9 +6,6 @@ fun test(a: Long, b: Long): Long { return sum } -// JVM non-IR uses while. -// JVM IR uses if + do-while. - // 0 iterator // 0 getStart // 0 getEnd @@ -16,13 +13,6 @@ fun test(a: Long, b: Long): Long { // 0 getLast // 0 getStep -// JVM_TEMPLATES // 1 LCMP // 1 IFGE // 1 IF - -// JVM_IR_TEMPLATES -// 2 LCMP -// 1 IFGE -// 1 IFLT -// 2 IF \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilLongMaxValue.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilLongMaxValue.kt index d4b88076744..22b7cdeb29b 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilLongMaxValue.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilLongMaxValue.kt @@ -8,9 +8,6 @@ fun f(a: Long): Int { return n } -// JVM non-IR uses while. -// JVM IR uses if + do-while. - // 0 iterator // 0 getStart // 0 getEnd @@ -18,13 +15,6 @@ fun f(a: Long): Int { // 0 getLast // 0 getStep -// JVM_TEMPLATES // 1 LCMP // 1 IFGE // 1 IF - -// JVM_IR_TEMPLATES -// 2 LCMP -// 1 IFGE -// 1 IFLT -// 2 IF \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilLongMinValue.kt b/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilLongMinValue.kt index 96269275cff..aa7c2b18258 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilLongMinValue.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/forInUntil/forInUntilLongMinValue.kt @@ -8,9 +8,6 @@ fun f(a: Long): Int { return n } -// JVM non-IR uses while. -// JVM IR uses if + do-while. - // 0 iterator // 0 getStart // 0 getEnd @@ -18,8 +15,5 @@ fun f(a: Long): Int { // 0 getLast // 0 getStep -// JVM_TEMPLATES +// 1 IFGE // 1 IF - -// JVM_IR_TEMPLATES -// 2 IF diff --git a/compiler/testData/codegen/bytecodeText/forLoop/primitiveLiteralRange1.kt b/compiler/testData/codegen/bytecodeText/forLoop/primitiveLiteralRange1.kt index a4198855b28..93fa091f308 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/primitiveLiteralRange1.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/primitiveLiteralRange1.kt @@ -3,19 +3,18 @@ fun f() { } } -// JVM non-IR uses while. -// JVM IR uses if + do-while. The surrounding "if" gets optimized in this test (constant condition). - // 0 iterator // 0 getStart // 0 getEnd // 0 getFirst // 0 getLast // 0 getStep -// 1 IF + // JVM_TEMPLATES // 1 IF_ICMPGT +// 1 IF // JVM_IR_TEMPLATES -// 1 IF_ICMPLE \ No newline at end of file +// 1 IF_ICMPGE +// 1 IF diff --git a/compiler/testData/codegen/bytecodeText/forLoop/unsigned/forInUntilUIntMaxValue.kt b/compiler/testData/codegen/bytecodeText/forLoop/unsigned/forInUntilUIntMaxValue.kt index bd5e6feebcf..4458f4d04a9 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/unsigned/forInUntilUIntMaxValue.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/unsigned/forInUntilUIntMaxValue.kt @@ -9,9 +9,6 @@ fun f(a: UInt): Int { return n } -// JVM non-IR uses while. -// JVM IR uses if + do-while. - // 0 iterator // 0 getStart // 0 getEnd @@ -27,7 +24,6 @@ fun f(a: UInt): Int { // 1 IF // JVM_IR_TEMPLATES -// 2 INVOKESTATIC kotlin/UnsignedKt.uintCompare +// 1 INVOKESTATIC kotlin/UnsignedKt.uintCompare // 1 IFGE -// 1 IFLT -// 2 IF \ No newline at end of file +// 1 IF \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/unsigned/forInUntilUIntMinValue.kt b/compiler/testData/codegen/bytecodeText/forLoop/unsigned/forInUntilUIntMinValue.kt index f3b3acd8e53..24798f9ffad 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/unsigned/forInUntilUIntMinValue.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/unsigned/forInUntilUIntMinValue.kt @@ -25,4 +25,4 @@ fun f(a: UInt): Int { // 1 IF // JVM_IR_TEMPLATES -// 2 IF +// 1 IF diff --git a/compiler/testData/codegen/bytecodeText/forLoop/unsigned/forInUntilULongMaxValue.kt b/compiler/testData/codegen/bytecodeText/forLoop/unsigned/forInUntilULongMaxValue.kt index 148d41a3732..f18bb198ef0 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/unsigned/forInUntilULongMaxValue.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/unsigned/forInUntilULongMaxValue.kt @@ -27,7 +27,6 @@ fun f(a: ULong): Int { // 1 IF // JVM_IR_TEMPLATES -// 2 INVOKESTATIC kotlin/UnsignedKt.ulongCompare +// 1 INVOKESTATIC kotlin/UnsignedKt.ulongCompare // 1 IFGE -// 1 IFLT -// 2 IF \ No newline at end of file +// 1 IF \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/unsigned/forInUntilULongMinValue.kt b/compiler/testData/codegen/bytecodeText/forLoop/unsigned/forInUntilULongMinValue.kt index 78045efedeb..fda559fa914 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/unsigned/forInUntilULongMinValue.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/unsigned/forInUntilULongMinValue.kt @@ -25,4 +25,4 @@ fun f(a: ULong): Int { // 1 IF // JVM_IR_TEMPLATES -// 2 IF +// 1 IF