From b1ce21bc55e447439e52b55b8505d665cecc9800 Mon Sep 17 00:00:00 2001 From: Mark Punzalan Date: Thu, 16 Jul 2020 00:42:36 -0700 Subject: [PATCH] ForLoopsLowering: Reduce unnecessary temporary variables for the "checked step" (check for a positive step arg) and "negated step" (negate the step arg when the nested step is negative). --- .../backend/common/lower/loops/HeaderInfo.kt | 21 +-- .../common/lower/loops/HeaderProcessor.kt | 2 +- .../backend/common/lower/loops/Utils.kt | 4 +- .../loops/handlers/DefaultIterableHandler.kt | 3 +- .../handlers/DefaultProgressionHandler.kt | 2 +- .../lower/loops/handlers/StepHandler.kt | 123 ++++++++++-------- .../lower/loops/handlers/UntilHandler.kt | 2 +- .../emptyUntilProgressionToMinValue.kt | 3 +- .../forLoop/stepped/illegalStepConst.kt | 9 +- .../forLoop/stepped/reversedThenStep.kt | 3 +- .../bytecodeText/forLoop/stepped/stepConst.kt | 3 +- .../stepConstOnNonLiteralProgression.kt | 14 +- .../forLoop/stepped/stepNonConst.kt | 14 +- .../stepNonConstOnNonLiteralProgression.kt | 19 ++- .../bytecodeText/forLoop/stepped/stepOne.kt | 3 +- .../forLoop/stepped/stepOneThenStepOne.kt | 3 +- .../forLoop/stepped/stepThenDifferentStep.kt | 3 +- .../forLoop/stepped/stepThenReversed.kt | 3 +- .../forLoop/stepped/stepThenSameStep.kt | 3 +- .../forLoop/stepped/stepThenStepNonConst.kt | 21 ++- .../forLoop/stepped/stepThenStepOne.kt | 3 +- .../stepped/untilProgressionToNonConst.kt | 5 +- .../emptyUntilProgressionToMinValue.kt | 3 +- .../forLoop/unsigned/illegalStepConst.kt | 9 +- .../forLoop/unsigned/reversedThenStep.kt | 3 +- .../stepConstOnNonLiteralProgression.kt | 15 +-- .../stepNonConstOnNonLiteralProgression.kt | 20 ++- .../forLoop/unsigned/stepThenDifferentStep.kt | 5 +- .../unsigned/untilProgressionToNonConst.kt | 5 +- 29 files changed, 153 insertions(+), 173 deletions(-) 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 d78c1906f4d..1cd87f96001 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 @@ -9,23 +9,10 @@ package org.jetbrains.kotlin.backend.common.lower.loops import org.jetbrains.kotlin.backend.common.CommonBackendContext import org.jetbrains.kotlin.backend.common.ir.Symbols -import org.jetbrains.kotlin.backend.common.lower.loops.handlers.ArrayIndicesHandler -import org.jetbrains.kotlin.backend.common.lower.loops.handlers.ArrayIterationHandler -import org.jetbrains.kotlin.backend.common.lower.loops.handlers.CharSequenceIndicesHandler -import org.jetbrains.kotlin.backend.common.lower.loops.handlers.CharSequenceIterationHandler -import org.jetbrains.kotlin.backend.common.lower.loops.handlers.CollectionIndicesHandler -import org.jetbrains.kotlin.backend.common.lower.loops.handlers.DefaultIterableHandler -import org.jetbrains.kotlin.backend.common.lower.loops.handlers.DefaultProgressionHandler -import org.jetbrains.kotlin.backend.common.lower.loops.handlers.DownToHandler -import org.jetbrains.kotlin.backend.common.lower.loops.handlers.IndexedGetIterationHandler -import org.jetbrains.kotlin.backend.common.lower.loops.handlers.RangeToHandler -import org.jetbrains.kotlin.backend.common.lower.loops.handlers.ReversedHandler -import org.jetbrains.kotlin.backend.common.lower.loops.handlers.StepHandler -import org.jetbrains.kotlin.backend.common.lower.loops.handlers.StringIterationHandler -import org.jetbrains.kotlin.backend.common.lower.loops.handlers.UntilHandler -import org.jetbrains.kotlin.backend.common.lower.loops.handlers.WithIndexHandler +import org.jetbrains.kotlin.backend.common.lower.loops.handlers.* import org.jetbrains.kotlin.backend.common.lower.matchers.IrCallMatcher import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrExpression @@ -79,7 +66,7 @@ internal class ProgressionHeaderInfo( canOverflow: Boolean? = null, direction: ProgressionDirection, additionalNotEmptyCondition: IrExpression? = null, - val additionalVariables: List = listOf() + val additionalStatements: List = listOf() ) : NumericHeaderInfo( progressionType, first, last, step, canCacheLast = true, @@ -156,7 +143,7 @@ internal class ProgressionHeaderInfo( isReversed = !isReversed, direction = direction.asReversed(), additionalNotEmptyCondition = additionalNotEmptyCondition, - additionalVariables = additionalVariables + additionalStatements = additionalStatements ) } 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 1b81723cc70..fec618093d2 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 @@ -260,7 +260,7 @@ internal class ProgressionLoopHeader( // // In the case of a reversed range, the `inductionVariable` and `last` variables are swapped, therefore the declaration order must be // swapped to preserve the correct evaluation order. - override val loopInitStatements = headerInfo.additionalVariables + ( + override val loopInitStatements = headerInfo.additionalStatements + ( if (headerInfo.isReversed) listOfNotNull(lastVariableIfCanCacheLast, inductionVariable) else diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/Utils.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/Utils.kt index b230c05e683..b436024816e 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/Utils.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/Utils.kt @@ -89,10 +89,10 @@ internal val IrExpression.constLongValue: Long? */ internal fun DeclarationIrBuilder.createTemporaryVariableIfNecessary( expression: IrExpression, nameHint: String? = null, - irType: IrType? = null + irType: IrType? = null, isMutable: Boolean = false ): Pair = if (expression.canHaveSideEffects) { - scope.createTmpVariable(expression, nameHint = nameHint, irType = irType).let { Pair(it, irGet(it)) } + scope.createTmpVariable(expression, nameHint = nameHint, irType = irType, isMutable = isMutable).let { Pair(it, irGet(it)) } } else { Pair(null, expression) } \ No newline at end of file diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/DefaultIterableHandler.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/DefaultIterableHandler.kt index 499efd633d8..9f7456c45ae 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/DefaultIterableHandler.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/DefaultIterableHandler.kt @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.types.isSubtypeOfClass import org.jetbrains.kotlin.ir.util.getSimpleFunction +import org.jetbrains.kotlin.util.OperatorNameConventions /** Builds a [HeaderInfo] for Iterables not handled by more specialized handlers. */ internal open class DefaultIterableHandler(private val context: CommonBackendContext) : @@ -28,7 +29,7 @@ internal open class DefaultIterableHandler(private val context: CommonBackendCon override fun build(expression: IrExpression, scopeOwner: IrSymbol): HeaderInfo? = with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) { val iteratorFun = - iterableClassSymbol.getSimpleFunction(org.jetbrains.kotlin.util.OperatorNameConventions.ITERATOR.asString())!!.owner + iterableClassSymbol.getSimpleFunction(OperatorNameConventions.ITERATOR.asString())!!.owner IterableHeaderInfo( scope.createTmpVariable(irCall(iteratorFun).apply { dispatchReceiver = expression }, nameHint = "iterator") ) diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/DefaultProgressionHandler.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/DefaultProgressionHandler.kt index 417371f9cb7..32ec8026287 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/DefaultProgressionHandler.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/DefaultProgressionHandler.kt @@ -46,7 +46,7 @@ internal class DefaultProgressionHandler(private val context: CommonBackendConte first, last, step, - additionalVariables = listOfNotNull(progressionVar), + additionalStatements = listOfNotNull(progressionVar), direction = ProgressionDirection.UNKNOWN ) } 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 c15e2dcff92..ea99987cf91 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 @@ -11,10 +11,8 @@ import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.loops.* import org.jetbrains.kotlin.backend.common.lower.matchers.SimpleCalleeMatcher import org.jetbrains.kotlin.backend.common.lower.matchers.singleArgumentExtension -import org.jetbrains.kotlin.ir.builders.irCall -import org.jetbrains.kotlin.ir.builders.irConcat -import org.jetbrains.kotlin.ir.builders.irIfThenElse -import org.jetbrains.kotlin.ir.builders.irString +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrExpression @@ -59,15 +57,16 @@ internal class StepHandler( } // To reduce local variable usage, we create and use temporary variables only if necessary. - val (stepArgVar, stepArgExpression) = createTemporaryVariableIfNecessary(stepArg, "stepArg") + // This temporary variable for step needs to be mutable for certain cases (see below). + val (stepArgVar, stepArgExpression) = createTemporaryVariableIfNecessary(stepArg, "stepArg", isMutable = true) // The `step` standard library function only accepts positive values, and performs the following check: // // if (step > 0) step else throw IllegalArgumentException("Step must be positive, was: $step.") // - // We insert this check in the lowered form only if necessary. + // We insert a similar check in the lowered form only if necessary. val stepType = data.stepClass.defaultType - val stepGreaterFun = context.irBuiltIns.greaterFunByOperandType.getValue(data.stepClass.symbol) + val stepCompFun = context.irBuiltIns.lessOrEqualFunByOperandType.getValue(data.stepClass.symbol) val zeroStep = data.run { zeroStepExpression() } val throwIllegalStepExceptionCall = { irCall(context.irBuiltIns.illegalArgumentExceptionSymbol).apply { @@ -79,26 +78,25 @@ internal class StepHandler( } } val stepArgValueAsLong = stepArgExpression.constLongValue - val checkedStepExpression = when { + val stepCheck: IrStatement? = when { stepArgValueAsLong == null -> { - // Step argument is not a constant. - val stepPositiveCheck = irCall(stepGreaterFun).apply { + // Step argument is not a constant. In this case, we check if step <= 0. + val stepNonPositiveCheck = irCall(stepCompFun).apply { putValueArgument(0, stepArgExpression.deepCopyWithSymbols()) putValueArgument(1, zeroStep.deepCopyWithSymbols()) } - irIfThenElse( - stepType, - stepPositiveCheck, - stepArgExpression.deepCopyWithSymbols(), + irIfThen( + context.irBuiltIns.unitType, + stepNonPositiveCheck, throwIllegalStepExceptionCall() ) } - stepArgValueAsLong > 0L -> - // Step argument is a positive constant and is valid. - stepArgExpression.deepCopyWithSymbols() - else -> + stepArgValueAsLong <= 0L -> // Step argument is a non-positive constant and is invalid, directly throw the exception. throwIllegalStepExceptionCall() + else -> + // Step argument is a positive constant and is valid. No check is needed. + null } // While the `step` function accepts positive values, the "step" value in the progression depends on the direction of the @@ -108,24 +106,49 @@ internal class StepHandler( // If we don't know the direction of the nested progression (e.g., `someProgression() step 2`) then we have to check its value // first to determine whether to negate. var nestedStepVar: IrVariable? = null - var checkedStepVar: IrVariable? = null - val checkedAndMaybeNegatedStep = when (nestedInfo.direction) { - ProgressionDirection.INCREASING -> checkedStepExpression - ProgressionDirection.DECREASING -> checkedStepExpression.negate() + var stepNegation: IrStatement? = null + val finalStepExpression = when (nestedInfo.direction) { + ProgressionDirection.INCREASING -> stepArgExpression + ProgressionDirection.DECREASING -> { + if (stepArgVar == null) { + stepArgExpression.negate() + } else { + // Step is already stored in a variable, just negate it. + stepNegation = irSetVar(stepArgVar.symbol, irGet(stepArgVar).negate()) + irGet(stepArgVar) + } + } ProgressionDirection.UNKNOWN -> { - // Check value of nested step and negate step arg if needed: `if (nestedStep > 0) checkedStep else -checkedStep` + // Check value of nested step and negate step arg if needed: `if (nestedStep <= 0) -step else step` // A temporary variable is created only if necessary, so we can preserve the evaluation order. val nestedStep = nestedInfo.step val (tmpNestedStepVar, nestedStepExpression) = createTemporaryVariableIfNecessary(nestedStep, "nestedStep") nestedStepVar = tmpNestedStepVar - val nestedStepPositiveCheck = irCall(stepGreaterFun).apply { + val nestedStepNonPositiveCheck = irCall(stepCompFun).apply { putValueArgument(0, nestedStepExpression) putValueArgument(1, zeroStep.deepCopyWithSymbols()) } - - val (tmpCheckedStepVar, checkedStepOrGet) = createTemporaryVariableIfNecessary(checkedStepExpression, "checkedStep") - checkedStepVar = tmpCheckedStepVar - irIfThenElse(stepType, nestedStepPositiveCheck, checkedStepOrGet, checkedStepOrGet.deepCopyWithSymbols().negate()) + if (stepArgVar == null) { + // Create a temporary variable for the possibly-negated step, so we don't have to re-check every time step is used. + stepNegation = scope.createTmpVariable( + irIfThenElse( + stepType, + nestedStepNonPositiveCheck, + stepArgExpression.deepCopyWithSymbols().negate(), + stepArgExpression.deepCopyWithSymbols() + ), + nameHint = "maybeNegatedStep" + ) + irGet(stepNegation) + } else { + // Step is already stored in a variable, just negate it. + stepNegation = irIfThen( + context.irBuiltIns.unitType, + nestedStepNonPositiveCheck, + irSetVar(stepArgVar.symbol, irGet(stepArgVar).negate()) + ) + irGet(stepArgVar) + } } } @@ -133,7 +156,6 @@ internal class StepHandler( // evaluation order. val (nestedFirstVar, nestedFirstExpression) = createTemporaryVariableIfNecessary(nestedInfo.first, "nestedFirst") val (nestedLastVar, nestedLastExpression) = createTemporaryVariableIfNecessary(nestedInfo.last, "nestedLast") - val (newStepVar, newStepExpression) = createTemporaryVariableIfNecessary(checkedAndMaybeNegatedStep, "newStep") // Creating a progression with a step value != 1 may result in a "last" value that is smaller than the given "last". The new // "last" value is such that iterating over the progression (by incrementing by "step") does not go over the "last" value. @@ -161,7 +183,7 @@ internal class StepHandler( // 3), // 2) val recalculatedLast = - callGetProgressionLastElementIfNecessary(data, nestedFirstExpression, nestedLastExpression, newStepExpression) + callGetProgressionLastElementIfNecessary(data, nestedFirstExpression, nestedLastExpression, finalStepExpression) // Consider the following for-loop: // @@ -176,29 +198,26 @@ internal class StepHandler( // val innerNestedLast = B // // No nested step var because step for `A..B` is a constant 1 // val innerStepArg = C - // val innerNewStep = if (innerStepArg > 0) innerStepArg - // else throw IllegalArgumentException("Step must be positive, was: $innerStepArg.") + // if (innerStepArg <= 0) throw IllegalArgumentException("Step must be positive, was: $innerStepArg.") // // // Additional variables for outer step progression `(A..B step C) step D`: // // No nested first var because `innerNestedFirst` is a local variable get (cannot have side-effects) // val outerNestedLast = // "last" for `A..B step C` - // getProgressionLastElement(innerNestedFirst, innerNestedLast, innerNewStep) - // // No nested step var because nested step `innerNewStep` is a local variable get (cannot have side-effects) + // getProgressionLastElement(innerNestedFirst, innerNestedLast, innerStepArg) + // // No nested step var because nested step `innerStepArg` is a local variable get (cannot have side-effects) // val outerStepArg = D - // val outerNewStep = if (outerStepArg > 0) outerStepArg - // else throw IllegalArgumentException("Step must be positive, was: $outerStepArg.") + // if (outerStepArg <= 0) throw IllegalArgumentException("Step must be positive, was: $outerStepArg.") // // // Standard form of loop over progression // var inductionVar = innerNestedFirst // val last = // "last" for `(A..B step C) step D` // getProgressionLastElement(innerNestedFirst, // "Passed through" from inner step progression - // outerNestedLast, outerNewStep) - // val step = outerNewStep + // outerNestedLast, outerStepArg) // if (inductionVar <= last) { // // Loop is not empty // do { // val i = inductionVar - // inductionVar += step + // inductionVar += outerStepArg // // Loop body // } while (i != last) // } @@ -214,21 +233,19 @@ internal class StepHandler( // val nestedFirst = progression.first // val nestedLast = progression.last // val nestedStep = progression.step - // val stepArg = C - // val checkedStep = if (stepArg > 0) stepArg - // else throw IllegalArgumentException("Step must be positive, was: $stepArg.") - // val newStep = // Direction of P is unknown so we check its step to determine whether to negate - // if (nestedStep > 0) checkedStep else -checkedStep + // var stepArg = C + // if (stepArg <= 0) throw IllegalArgumentException("Step must be positive, was: $stepArg.") + // // Direction of P is unknown so we check its step to determine whether to negate + // if (nestedStep <= 0) stepArg = -stepArg // // // Standard form of loop over progression // var inductionVar = nestedFirst - // val last = getProgressionLastElement(nestedFirst, nestedLast, newStep) - // val step = newStep - // if ((step > 0 && inductionVar <= last) || (step < 0 && last <= inductionVar)) { + // val last = getProgressionLastElement(nestedFirst, nestedLast, stepArg) + // if ((stepArg > 0 && inductionVar <= last) || (stepArg < 0 && last <= inductionVar)) { // // Loop is not empty // do { // val i = inductionVar - // inductionVar += step + // inductionVar += stepArg // // Loop body // } while (i != last) // } @@ -239,19 +256,19 @@ internal class StepHandler( // // ...in the nested HeaderInfo, "first" is `B` and "last" is `A` (the progression goes from `B` to `A`). Therefore in this case, // the nested "last" variable must come before the nested "first" variable (if both variables are necessary). - val additionalVariables = nestedInfo.additionalVariables + if (nestedInfo.isReversed) { - listOfNotNull(nestedLastVar, nestedFirstVar, nestedStepVar, stepArgVar, checkedStepVar, newStepVar) + val additionalStatements = nestedInfo.additionalStatements + if (nestedInfo.isReversed) { + listOfNotNull(nestedLastVar, nestedFirstVar, nestedStepVar, stepArgVar, stepCheck, stepNegation) } else { - listOfNotNull(nestedFirstVar, nestedLastVar, nestedStepVar, stepArgVar, checkedStepVar, newStepVar) + listOfNotNull(nestedFirstVar, nestedLastVar, nestedStepVar, stepArgVar, stepCheck, stepNegation) } return ProgressionHeaderInfo( data, first = nestedFirstExpression, last = recalculatedLast, - step = newStepExpression, + step = finalStepExpression, isReversed = nestedInfo.isReversed, - additionalVariables = additionalVariables, + additionalStatements = additionalStatements, additionalNotEmptyCondition = nestedInfo.additionalNotEmptyCondition, direction = nestedInfo.direction ) diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/UntilHandler.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/UntilHandler.kt index 35899f657da..31363b33c52 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/UntilHandler.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/loops/handlers/UntilHandler.kt @@ -120,7 +120,7 @@ internal class UntilHandler(private val context: CommonBackendContext, private v last = last, step = irInt(1), canOverflow = false, - additionalVariables = additionalVariables, + additionalStatements = additionalVariables, additionalNotEmptyCondition = additionalNotEmptyCondition, direction = ProgressionDirection.INCREASING ) diff --git a/compiler/testData/codegen/bytecodeText/forLoop/stepped/emptyUntilProgressionToMinValue.kt b/compiler/testData/codegen/bytecodeText/forLoop/stepped/emptyUntilProgressionToMinValue.kt index 748c3a39e6a..bea4532e54d 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/stepped/emptyUntilProgressionToMinValue.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/stepped/emptyUntilProgressionToMinValue.kt @@ -15,12 +15,11 @@ fun box(): String { // // Standard form of loop over progression // var inductionVar = 2 // val last = getProgressionLastElement(2, Int.MIN_VALUE - 1, 2) // `(Int.MIN_VALUE - 1)` underflows to Int.MAX_VALUE -// val step = 2 // if (false && inductionVar <= last) { // `false` comes from constant folding of `Int.MIN_VALUE != Int.MIN_VALUE` // // Loop is not empty // do { // val i = inductionVar -// inductionVar += step +// inductionVar += 2 // // Loop body // } while (i != last) // } diff --git a/compiler/testData/codegen/bytecodeText/forLoop/stepped/illegalStepConst.kt b/compiler/testData/codegen/bytecodeText/forLoop/stepped/illegalStepConst.kt index cb7e708f71c..196e206947e 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/stepped/illegalStepConst.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/stepped/illegalStepConst.kt @@ -11,18 +11,17 @@ fun box(): String { // // Expected lowered form of loop (before bytecode optimization): // -// // Additional variables: -// val newStep = throw IllegalArgumentException("Step must be positive, was: 0.") +// // Additional statements: +// throw IllegalArgumentException("Step must be positive, was: 0.") // // // Standard form of loop over progression // var inductionVar = 1 -// val last = getProgressionLastElement(1, 6, newStep) -// val step = newStep +// val last = getProgressionLastElement(1, 6, 0) // if (inductionVar <= last) { // // Loop is not empty // do { // val i = inductionVar -// inductionVar += step +// inductionVar += 0 // // Loop body // } while (i != last) // } diff --git a/compiler/testData/codegen/bytecodeText/forLoop/stepped/reversedThenStep.kt b/compiler/testData/codegen/bytecodeText/forLoop/stepped/reversedThenStep.kt index 69ad73d3a2b..1c723bcc8ea 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/stepped/reversedThenStep.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/stepped/reversedThenStep.kt @@ -15,12 +15,11 @@ fun box(): String { // // Standard form of loop over progression // val last = getProgressionLastElement(8, 1, -2) // var inductionVar = 8 -// val step = -2 // if (last <= inductionVar) { // // Loop is not empty // do { // val i = inductionVar -// inductionVar += step +// inductionVar += -2 // // Loop body // } while (i != last) // } diff --git a/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepConst.kt b/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepConst.kt index f03acf76cd5..2a20594985c 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepConst.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepConst.kt @@ -15,12 +15,11 @@ fun box(): String { // // Standard form of loop over progression // var inductionVar = 1 // val last = getProgressionLastElement(1, 7, 2) -// val step = 2 // if (inductionVar <= last) { // // Loop is not empty // do { // val i = inductionVar -// inductionVar += step +// inductionVar += 2 // // Loop body // } while (i != last) // } diff --git a/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepConstOnNonLiteralProgression.kt b/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepConstOnNonLiteralProgression.kt index 60094b93173..247ccc32e28 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepConstOnNonLiteralProgression.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepConstOnNonLiteralProgression.kt @@ -14,22 +14,21 @@ fun box(): String { // // Expected lowered form of loop: // -// // Additional variables: +// // Additional statements: // val progression = intProgression // val nestedFirst = progression.first // val nestedLast = progression.last // val nestedStep = progression.step -// val newStep = if (nestedStep > 0) 2 else -2 +// val maybeNegatedStep = if (nestedStep <= 0) -2 else 2 // // // Standard form of loop over progression // var inductionVar = nestedFirst -// val last = getProgressionLastElement(nestedFirst, nestedLast, newStep) -// val step = newStep -// if ((step > 0 && inductionVar <= last) || (step < 0 && last <= inductionVar)) { +// val last = getProgressionLastElement(nestedFirst, nestedLast, maybeNegatedStep) +// if ((maybeNegatedStep > 0 && inductionVar <= last) || (maybeNegatedStep < 0 && last <= inductionVar)) { // // Loop is not empty // do { // val i = inductionVar -// inductionVar += step +// inductionVar += maybeNegatedStep // // Loop body // } while (i != last) // } @@ -46,7 +45,8 @@ fun box(): String { // 1 IF_ICMPGT // 1 IF_ICMPLE // 1 IF_ICMPNE -// 2 IFLE +// 1 IFLE +// 1 IFGT // 1 IFGE // 6 IF // 0 INEG \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepNonConst.kt b/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepNonConst.kt index 90918c7d2d5..f51481ef067 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepNonConst.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepNonConst.kt @@ -13,20 +13,18 @@ fun box(): String { // // Expected lowered form of loop: // -// // Additional variables: -// val stepArg = one() -// val newStep = if (stepArg > 0) stepArg -// else throw IllegalArgumentException("Step must be positive, was: $stepArg.") +// // Additional statements: +// var stepArg = one() +// if (stepArg <= 0) throw IllegalArgumentException("Step must be positive, was: $stepArg.") // // // Standard form of loop over progression // var inductionVar = 1 -// val last = getProgressionLastElement(1, 7, newStep) -// val step = newStep +// val last = getProgressionLastElement(1, 7, stepArg) // if (inductionVar <= last) { // // Loop is not empty // do { // val i = inductionVar -// inductionVar += step +// inductionVar += stepArg // // Loop body // } while (i != last) // } @@ -42,5 +40,5 @@ fun box(): String { // 1 ATHROW // 1 IF_ICMPGT // 1 IF_ICMPNE -// 1 IFLE +// 1 IFGT // 3 IF \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepNonConstOnNonLiteralProgression.kt b/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepNonConstOnNonLiteralProgression.kt index 1a1620d1ff4..67e0e1e9639 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepNonConstOnNonLiteralProgression.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepNonConstOnNonLiteralProgression.kt @@ -15,25 +15,23 @@ fun box(): String { // // Expected lowered form of loop: // -// // Additional variables: +// // Additional statements: // val progression = intProgression // val nestedFirst = progression.first // val nestedLast = progression.last // val nestedStep = progression.step -// val stepArg = one() -// val checkedStep = if (stepArg > 0) stepArg -// else throw IllegalArgumentException("Step must be positive, was: $stepArg.") -// val newStep = if (nestedStep > 0) checkedStep else -checkedStep +// var stepArg = one() +// if (stepArg <= 0) throw IllegalArgumentException("Step must be positive, was: $stepArg.") +// if (nestedStep <= 0) stepArg = -stepArg // // // Standard form of loop over progression // var inductionVar = nestedFirst -// val last = getProgressionLastElement(nestedFirst, nestedLast, newStep) -// val step = newStep -// if ((step > 0 && inductionVar <= last) || (step < 0 && last <= inductionVar)) { +// val last = getProgressionLastElement(nestedFirst, nestedLast, stepArg) +// if ((stepArg > 0 && inductionVar <= last) || (stepArg < 0 && last <= inductionVar)) { // // Loop is not empty // do { // val i = inductionVar -// inductionVar += step +// inductionVar += stepArg // // Loop body // } while (i != last) // } @@ -50,7 +48,8 @@ fun box(): String { // 1 IF_ICMPGT // 1 IF_ICMPLE // 1 IF_ICMPNE -// 3 IFLE +// 1 IFLE +// 2 IFGT // 1 IFGE // 7 IF // 1 INEG \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepOne.kt b/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepOne.kt index da34afd18bb..7851e4878e9 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepOne.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepOne.kt @@ -14,12 +14,11 @@ fun box(): String { // // Standard form of loop over progression // var inductionVar = 1 // val last = 4 -// val step = 1 // if (inductionVar <= last) { // // Loop is not empty // do { // val i = inductionVar -// inductionVar += step +// inductionVar += 1 // // Loop body // } while (inductionVar <= last) // } diff --git a/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepOneThenStepOne.kt b/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepOneThenStepOne.kt index 94d8a1b7cea..5d29051ecf6 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepOneThenStepOne.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepOneThenStepOne.kt @@ -14,12 +14,11 @@ fun box(): String { // // Standard form of loop over progression // var inductionVar = 1 // val last = 4 -// val step = 1 // if (inductionVar <= last) { // // Loop is not empty // do { // val i = inductionVar -// inductionVar += step +// inductionVar += 1 // // Loop body // } while (inductionVar <= last) // } diff --git a/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepThenDifferentStep.kt b/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepThenDifferentStep.kt index 7a364f7db64..20cd8c37512 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepThenDifferentStep.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepThenDifferentStep.kt @@ -19,12 +19,11 @@ fun box(): String { // // Standard form of loop over progression // var inductionVar = 1 // val last = getProgressionLastElement(1, outerNestedLast, 2) -// val step = 2 // if (inductionVar <= last) { // // Loop is not empty // do { // val i = inductionVar -// inductionVar += step +// inductionVar += 2 // // Loop body // } while (i != last) // } diff --git a/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepThenReversed.kt b/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepThenReversed.kt index 9892dc76b82..8f8eccd84fe 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepThenReversed.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepThenReversed.kt @@ -15,12 +15,11 @@ fun box(): String { // // Standard form of loop over progression // val last = 1 // var inductionVar = getProgressionLastElement(1, 8, 2) -// val step = -2 // if (last <= inductionVar) { // // Loop is not empty // do { // val i = inductionVar -// inductionVar += step +// inductionVar += -2 // // Loop body // } while (last <= inductionVar) // } diff --git a/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepThenSameStep.kt b/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepThenSameStep.kt index ed96201cca2..699aa7362ef 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepThenSameStep.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepThenSameStep.kt @@ -16,12 +16,11 @@ fun box(): String { // // Standard form of loop over progression // var inductionVar = 1 // val last = getProgressionLastElement(1, 8, 2) -// val step = 2 // if (inductionVar <= last) { // // Loop is not empty // do { // val i = inductionVar -// inductionVar += step +// inductionVar += 2 // // Loop body // } while (i != last) // } diff --git a/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepThenStepNonConst.kt b/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepThenStepNonConst.kt index 34973136ad2..320e2963414 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepThenStepNonConst.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepThenStepNonConst.kt @@ -13,24 +13,21 @@ fun box(): String { // // Expected lowered form of loop: // -// // Additional variables: -// val innerStepArg = one() -// val innerNewStep = if (innerStepArg > 0) innerStepArg -// else throw IllegalArgumentException("Step must be positive, was: $innerStepArg.") -// val outerNestedLast = getProgressionLastElement(1, 6, innerNewStep) -// val outerStepArg = one() -// val outerNewStep = if (outerStepArg > 0) outerStepArg -// else throw IllegalArgumentException("Step must be positive, was: $outerStepArg.") +// // Additional statments: +// var innerStepArg = one() +// if (innerStepArg <= 0) throw IllegalArgumentException("Step must be positive, was: $innerStepArg.") +// val outerNestedLast = getProgressionLastElement(1, 6, innerStepArg) +// var outerStepArg = one() +// if (outerStepArg <= 0) throw IllegalArgumentException("Step must be positive, was: $outerStepArg.") // // // Standard form of loop over progression // var inductionVar = 1 -// val last = getProgressionLastElement(1, outerNestedLast, outerNewStep) -// val step = outerNewStep +// val last = getProgressionLastElement(1, outerNestedLast, outerStepArg) // if (inductionVar <= last) { // // Loop is not empty // do { // val i = inductionVar -// inductionVar += step +// inductionVar += outerStepArg // // Loop body // } while (i != last) // } @@ -46,5 +43,5 @@ fun box(): String { // 2 ATHROW // 1 IF_ICMPGT // 1 IF_ICMPNE -// 2 IFLE +// 2 IFGT // 4 IF \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepThenStepOne.kt b/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepThenStepOne.kt index ed626efb7b4..b8eb8bf3352 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepThenStepOne.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/stepped/stepThenStepOne.kt @@ -19,12 +19,11 @@ fun box(): String { // // Standard form of loop over progression // var inductionVar = 1 // val last = innerNestedLast -// val step = 1 // if (inductionVar <= last) { // // Loop is not empty // do { // val i = inductionVar -// inductionVar += step +// inductionVar += 1 // // Loop body // } while (i != last) // } diff --git a/compiler/testData/codegen/bytecodeText/forLoop/stepped/untilProgressionToNonConst.kt b/compiler/testData/codegen/bytecodeText/forLoop/stepped/untilProgressionToNonConst.kt index b105e7ac89c..f9598762719 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/stepped/untilProgressionToNonConst.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/stepped/untilProgressionToNonConst.kt @@ -12,19 +12,18 @@ fun box(): String { // // Expected lowered form of loop (before bytecode optimizations): // -// // Additional variables: +// // Additional statements: // val untilArg = nine() // val nestedLast = untilArg - 1 // // // Standard form of loop over progression // var inductionVar = 1 // val last = getProgressionLastElement(1, nestedLast, 2) -// val step = 2 // if (untilArg != Int.MIN_VALUE && inductionVar <= last) { // // Loop is not empty // do { // val i = inductionVar -// inductionVar += step +// inductionVar += 2 // // Loop body // } while (i != last) // } diff --git a/compiler/testData/codegen/bytecodeText/forLoop/unsigned/emptyUntilProgressionToMinValue.kt b/compiler/testData/codegen/bytecodeText/forLoop/unsigned/emptyUntilProgressionToMinValue.kt index 38d2d3e6a9c..85168c8ea59 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/unsigned/emptyUntilProgressionToMinValue.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/unsigned/emptyUntilProgressionToMinValue.kt @@ -16,12 +16,11 @@ fun box(): String { // // Standard form of loop over progression // var inductionVar = 2u // val last = getProgressionLastElement(2u, UInt.MIN_VALUE - 1, 2) // `(UInt.MIN_VALUE - 1)` underflows to UInt.MAX_VALUE -// val step = 2 // if (false && inductionVar <= last) { // `false` comes from constant folding of `Int.MIN_VALUE != Int.MIN_VALUE` // // Loop is not empty // do { // val i = inductionVar -// inductionVar += step +// inductionVar += 2 // // Loop body // } while (i != last) // } diff --git a/compiler/testData/codegen/bytecodeText/forLoop/unsigned/illegalStepConst.kt b/compiler/testData/codegen/bytecodeText/forLoop/unsigned/illegalStepConst.kt index 9f2849e7f60..781e8977aa5 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/unsigned/illegalStepConst.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/unsigned/illegalStepConst.kt @@ -12,18 +12,17 @@ fun box(): String { // // Expected lowered form of loop (before bytecode optimization): // -// // Additional variables: -// val newStep = throw IllegalArgumentException("Step must be positive, was: 0.") +// // Additional statements: +// throw IllegalArgumentException("Step must be positive, was: 0.") // // // Standard form of loop over progression // var inductionVar = 1u -// val last = getProgressionLastElement(1u, 6u, newStep) -// val step = newStep +// val last = getProgressionLastElement(1u, 6u, 0) // if (inductionVar <= last) { // // Loop is not empty // do { // val i = inductionVar -// inductionVar += step +// inductionVar += 0 // // Loop body // } while (i != last) // } diff --git a/compiler/testData/codegen/bytecodeText/forLoop/unsigned/reversedThenStep.kt b/compiler/testData/codegen/bytecodeText/forLoop/unsigned/reversedThenStep.kt index 0bd2d2d06bb..be11ac3899c 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/unsigned/reversedThenStep.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/unsigned/reversedThenStep.kt @@ -16,12 +16,11 @@ fun box(): String { // // Standard form of loop over progression // val last = getProgressionLastElement(8u, 1u, -2) // var inductionVar = 8u -// val step = -2 // if (last <= inductionVar) { // // Loop is not empty // do { // val i = inductionVar -// inductionVar += step +// inductionVar += -2 // // Loop body // } while (i != last) // } diff --git a/compiler/testData/codegen/bytecodeText/forLoop/unsigned/stepConstOnNonLiteralProgression.kt b/compiler/testData/codegen/bytecodeText/forLoop/unsigned/stepConstOnNonLiteralProgression.kt index add0c6fe432..ee5e4941747 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/unsigned/stepConstOnNonLiteralProgression.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/unsigned/stepConstOnNonLiteralProgression.kt @@ -15,22 +15,21 @@ fun box(): String { // // Expected lowered form of loop: // -// // Additional variables: +// // Additional statements: // val progression = intProgression // val nestedFirst = progression.first // val nestedLast = progression.last // val nestedStep = progression.step -// val newStep = if (nestedStep > 0) 2 else -2 +// val maybeNegatedStep = if (nestedStep <= 0) -2 else 2 // // // Standard form of loop over progression // var inductionVar = nestedFirst -// val last = getProgressionLastElement(nestedFirst, nestedLast, newStep) -// val step = newStep -// if ((step > 0 && inductionVar <= last) || (step < 0 && last <= inductionVar)) { +// val last = getProgressionLastElement(nestedFirst, nestedLast, maybeNegatedStep) +// if ((maybeNegatedStep > 0 && inductionVar <= last) || (maybeNegatedStep < 0 && last <= inductionVar)) { // // Loop is not empty // do { // val i = inductionVar -// inductionVar += step +// inductionVar += maybeNegatedStep // // Loop body // } while (i != last) // } @@ -45,9 +44,9 @@ fun box(): String { // 0 NEW java/lang/IllegalArgumentException // 0 ATHROW // 2 INVOKESTATIC kotlin/UnsignedKt.uintCompare -// 1 IFGT +// 2 IFGT // 1 IF_ICMPNE -// 3 IFLE +// 2 IFLE // 1 IFGE // 6 IF // 0 INEG diff --git a/compiler/testData/codegen/bytecodeText/forLoop/unsigned/stepNonConstOnNonLiteralProgression.kt b/compiler/testData/codegen/bytecodeText/forLoop/unsigned/stepNonConstOnNonLiteralProgression.kt index 7fc353014fb..fae5292fe6c 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/unsigned/stepNonConstOnNonLiteralProgression.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/unsigned/stepNonConstOnNonLiteralProgression.kt @@ -16,25 +16,23 @@ fun box(): String { // // Expected lowered form of loop: // -// // Additional variables: +// // Additional statements: // val progression = intProgression // val nestedFirst = progression.first // val nestedLast = progression.last // val nestedStep = progression.step -// val stepArg = one() -// val checkedStep = if (stepArg > 0) stepArg -// else throw IllegalArgumentException("Step must be positive, was: $stepArg.") -// val newStep = if (nestedStep > 0) checkedStep else -checkedStep +// var stepArg = one() +// if (stepArg <= 0) throw IllegalArgumentException("Step must be positive, was: $stepArg.") +// if (nestedStep <= 0) stepArg = -stepArg // // // Standard form of loop over progression // var inductionVar = nestedFirst -// val last = getProgressionLastElement(nestedFirst, nestedLast, newStep) -// val step = newStep -// if ((step > 0 && inductionVar <= last) || (step < 0 && last <= inductionVar)) { +// val last = getProgressionLastElement(nestedFirst, nestedLast, stepArg) +// if ((stepArg > 0 && inductionVar <= last) || (stepArg < 0 && last <= inductionVar)) { // // Loop is not empty // do { // val i = inductionVar -// inductionVar += step +// inductionVar += stepArg // // Loop body // } while (i != last) // } @@ -49,9 +47,9 @@ fun box(): String { // 1 NEW java/lang/IllegalArgumentException // 1 ATHROW // 2 INVOKESTATIC kotlin/UnsignedKt.uintCompare -// 1 IFGT +// 3 IFGT // 1 IF_ICMPNE -// 4 IFLE +// 2 IFLE // 1 IFGE // 7 IF // 1 INEG diff --git a/compiler/testData/codegen/bytecodeText/forLoop/unsigned/stepThenDifferentStep.kt b/compiler/testData/codegen/bytecodeText/forLoop/unsigned/stepThenDifferentStep.kt index 53d88968c59..7b6d60153e2 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/unsigned/stepThenDifferentStep.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/unsigned/stepThenDifferentStep.kt @@ -14,18 +14,17 @@ fun box(): String { // // Expected lowered form of loop: // -// // Additional variables: +// // Additional statements: // val outerNestedLast = getProgressionLastElement(1u, 7u, 3) // // // Standard form of loop over progression // var inductionVar = 1u // val last = getProgressionLastElement(1u, outerNestedLast, 2) -// val step = 2 // if (inductionVar <= last) { // // Loop is not empty // do { // val i = inductionVar -// inductionVar += step +// inductionVar += 2 // // Loop body // } while (i != last) // } diff --git a/compiler/testData/codegen/bytecodeText/forLoop/unsigned/untilProgressionToNonConst.kt b/compiler/testData/codegen/bytecodeText/forLoop/unsigned/untilProgressionToNonConst.kt index 0d0986e8b3d..f734cc2cde0 100644 --- a/compiler/testData/codegen/bytecodeText/forLoop/unsigned/untilProgressionToNonConst.kt +++ b/compiler/testData/codegen/bytecodeText/forLoop/unsigned/untilProgressionToNonConst.kt @@ -13,19 +13,18 @@ fun box(): String { // // Expected lowered form of loop (before bytecode optimizations): // -// // Additional variables: +// // Additional statements: // val untilArg = nine() // val nestedLast = untilArg - 1u // // // Standard form of loop over progression // var inductionVar = 1 // val last = getProgressionLastElement(1u, nestedLast, 2) -// val step = 2 // if (untilArg != UInt.MIN_VALUE && inductionVar <= last) { // // Loop is not empty // do { // val i = inductionVar -// inductionVar += step +// inductionVar += 2 // // Loop body // } while (i != last) // }