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).
This commit is contained in:
committed by
Alexander Udalov
parent
291d62f653
commit
b1ce21bc55
+4
-17
@@ -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.CommonBackendContext
|
||||||
import org.jetbrains.kotlin.backend.common.ir.Symbols
|
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.*
|
||||||
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.matchers.IrCallMatcher
|
import org.jetbrains.kotlin.backend.common.lower.matchers.IrCallMatcher
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
@@ -79,7 +66,7 @@ internal class ProgressionHeaderInfo(
|
|||||||
canOverflow: Boolean? = null,
|
canOverflow: Boolean? = null,
|
||||||
direction: ProgressionDirection,
|
direction: ProgressionDirection,
|
||||||
additionalNotEmptyCondition: IrExpression? = null,
|
additionalNotEmptyCondition: IrExpression? = null,
|
||||||
val additionalVariables: List<IrVariable> = listOf()
|
val additionalStatements: List<IrStatement> = listOf()
|
||||||
) : NumericHeaderInfo(
|
) : NumericHeaderInfo(
|
||||||
progressionType, first, last, step,
|
progressionType, first, last, step,
|
||||||
canCacheLast = true,
|
canCacheLast = true,
|
||||||
@@ -156,7 +143,7 @@ internal class ProgressionHeaderInfo(
|
|||||||
isReversed = !isReversed,
|
isReversed = !isReversed,
|
||||||
direction = direction.asReversed(),
|
direction = direction.asReversed(),
|
||||||
additionalNotEmptyCondition = additionalNotEmptyCondition,
|
additionalNotEmptyCondition = additionalNotEmptyCondition,
|
||||||
additionalVariables = additionalVariables
|
additionalStatements = additionalStatements
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -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
|
// 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.
|
// swapped to preserve the correct evaluation order.
|
||||||
override val loopInitStatements = headerInfo.additionalVariables + (
|
override val loopInitStatements = headerInfo.additionalStatements + (
|
||||||
if (headerInfo.isReversed)
|
if (headerInfo.isReversed)
|
||||||
listOfNotNull(lastVariableIfCanCacheLast, inductionVariable)
|
listOfNotNull(lastVariableIfCanCacheLast, inductionVariable)
|
||||||
else
|
else
|
||||||
|
|||||||
+2
-2
@@ -89,10 +89,10 @@ internal val IrExpression.constLongValue: Long?
|
|||||||
*/
|
*/
|
||||||
internal fun DeclarationIrBuilder.createTemporaryVariableIfNecessary(
|
internal fun DeclarationIrBuilder.createTemporaryVariableIfNecessary(
|
||||||
expression: IrExpression, nameHint: String? = null,
|
expression: IrExpression, nameHint: String? = null,
|
||||||
irType: IrType? = null
|
irType: IrType? = null, isMutable: Boolean = false
|
||||||
): Pair<IrVariable?, IrExpression> =
|
): Pair<IrVariable?, IrExpression> =
|
||||||
if (expression.canHaveSideEffects) {
|
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 {
|
} else {
|
||||||
Pair(null, expression)
|
Pair(null, expression)
|
||||||
}
|
}
|
||||||
+2
-1
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
|
|||||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.isSubtypeOfClass
|
import org.jetbrains.kotlin.ir.types.isSubtypeOfClass
|
||||||
import org.jetbrains.kotlin.ir.util.getSimpleFunction
|
import org.jetbrains.kotlin.ir.util.getSimpleFunction
|
||||||
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
|
|
||||||
/** Builds a [HeaderInfo] for Iterables not handled by more specialized handlers. */
|
/** Builds a [HeaderInfo] for Iterables not handled by more specialized handlers. */
|
||||||
internal open class DefaultIterableHandler(private val context: CommonBackendContext) :
|
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? =
|
override fun build(expression: IrExpression, scopeOwner: IrSymbol): HeaderInfo? =
|
||||||
with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) {
|
with(context.createIrBuilder(scopeOwner, expression.startOffset, expression.endOffset)) {
|
||||||
val iteratorFun =
|
val iteratorFun =
|
||||||
iterableClassSymbol.getSimpleFunction(org.jetbrains.kotlin.util.OperatorNameConventions.ITERATOR.asString())!!.owner
|
iterableClassSymbol.getSimpleFunction(OperatorNameConventions.ITERATOR.asString())!!.owner
|
||||||
IterableHeaderInfo(
|
IterableHeaderInfo(
|
||||||
scope.createTmpVariable(irCall(iteratorFun).apply { dispatchReceiver = expression }, nameHint = "iterator")
|
scope.createTmpVariable(irCall(iteratorFun).apply { dispatchReceiver = expression }, nameHint = "iterator")
|
||||||
)
|
)
|
||||||
|
|||||||
+1
-1
@@ -46,7 +46,7 @@ internal class DefaultProgressionHandler(private val context: CommonBackendConte
|
|||||||
first,
|
first,
|
||||||
last,
|
last,
|
||||||
step,
|
step,
|
||||||
additionalVariables = listOfNotNull(progressionVar),
|
additionalStatements = listOfNotNull(progressionVar),
|
||||||
direction = ProgressionDirection.UNKNOWN
|
direction = ProgressionDirection.UNKNOWN
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+70
-53
@@ -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.loops.*
|
||||||
import org.jetbrains.kotlin.backend.common.lower.matchers.SimpleCalleeMatcher
|
import org.jetbrains.kotlin.backend.common.lower.matchers.SimpleCalleeMatcher
|
||||||
import org.jetbrains.kotlin.backend.common.lower.matchers.singleArgumentExtension
|
import org.jetbrains.kotlin.backend.common.lower.matchers.singleArgumentExtension
|
||||||
import org.jetbrains.kotlin.ir.builders.irCall
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.builders.irConcat
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.builders.irIfThenElse
|
|
||||||
import org.jetbrains.kotlin.ir.builders.irString
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
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.
|
// 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:
|
// 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.")
|
// 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 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 zeroStep = data.run { zeroStepExpression() }
|
||||||
val throwIllegalStepExceptionCall = {
|
val throwIllegalStepExceptionCall = {
|
||||||
irCall(context.irBuiltIns.illegalArgumentExceptionSymbol).apply {
|
irCall(context.irBuiltIns.illegalArgumentExceptionSymbol).apply {
|
||||||
@@ -79,26 +78,25 @@ internal class StepHandler(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
val stepArgValueAsLong = stepArgExpression.constLongValue
|
val stepArgValueAsLong = stepArgExpression.constLongValue
|
||||||
val checkedStepExpression = when {
|
val stepCheck: IrStatement? = when {
|
||||||
stepArgValueAsLong == null -> {
|
stepArgValueAsLong == null -> {
|
||||||
// Step argument is not a constant.
|
// Step argument is not a constant. In this case, we check if step <= 0.
|
||||||
val stepPositiveCheck = irCall(stepGreaterFun).apply {
|
val stepNonPositiveCheck = irCall(stepCompFun).apply {
|
||||||
putValueArgument(0, stepArgExpression.deepCopyWithSymbols())
|
putValueArgument(0, stepArgExpression.deepCopyWithSymbols())
|
||||||
putValueArgument(1, zeroStep.deepCopyWithSymbols())
|
putValueArgument(1, zeroStep.deepCopyWithSymbols())
|
||||||
}
|
}
|
||||||
irIfThenElse(
|
irIfThen(
|
||||||
stepType,
|
context.irBuiltIns.unitType,
|
||||||
stepPositiveCheck,
|
stepNonPositiveCheck,
|
||||||
stepArgExpression.deepCopyWithSymbols(),
|
|
||||||
throwIllegalStepExceptionCall()
|
throwIllegalStepExceptionCall()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
stepArgValueAsLong > 0L ->
|
stepArgValueAsLong <= 0L ->
|
||||||
// Step argument is a positive constant and is valid.
|
|
||||||
stepArgExpression.deepCopyWithSymbols()
|
|
||||||
else ->
|
|
||||||
// Step argument is a non-positive constant and is invalid, directly throw the exception.
|
// Step argument is a non-positive constant and is invalid, directly throw the exception.
|
||||||
throwIllegalStepExceptionCall()
|
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
|
// 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
|
// 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.
|
// first to determine whether to negate.
|
||||||
var nestedStepVar: IrVariable? = null
|
var nestedStepVar: IrVariable? = null
|
||||||
var checkedStepVar: IrVariable? = null
|
var stepNegation: IrStatement? = null
|
||||||
val checkedAndMaybeNegatedStep = when (nestedInfo.direction) {
|
val finalStepExpression = when (nestedInfo.direction) {
|
||||||
ProgressionDirection.INCREASING -> checkedStepExpression
|
ProgressionDirection.INCREASING -> stepArgExpression
|
||||||
ProgressionDirection.DECREASING -> checkedStepExpression.negate()
|
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 -> {
|
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.
|
// A temporary variable is created only if necessary, so we can preserve the evaluation order.
|
||||||
val nestedStep = nestedInfo.step
|
val nestedStep = nestedInfo.step
|
||||||
val (tmpNestedStepVar, nestedStepExpression) = createTemporaryVariableIfNecessary(nestedStep, "nestedStep")
|
val (tmpNestedStepVar, nestedStepExpression) = createTemporaryVariableIfNecessary(nestedStep, "nestedStep")
|
||||||
nestedStepVar = tmpNestedStepVar
|
nestedStepVar = tmpNestedStepVar
|
||||||
val nestedStepPositiveCheck = irCall(stepGreaterFun).apply {
|
val nestedStepNonPositiveCheck = irCall(stepCompFun).apply {
|
||||||
putValueArgument(0, nestedStepExpression)
|
putValueArgument(0, nestedStepExpression)
|
||||||
putValueArgument(1, zeroStep.deepCopyWithSymbols())
|
putValueArgument(1, zeroStep.deepCopyWithSymbols())
|
||||||
}
|
}
|
||||||
|
if (stepArgVar == null) {
|
||||||
val (tmpCheckedStepVar, checkedStepOrGet) = createTemporaryVariableIfNecessary(checkedStepExpression, "checkedStep")
|
// Create a temporary variable for the possibly-negated step, so we don't have to re-check every time step is used.
|
||||||
checkedStepVar = tmpCheckedStepVar
|
stepNegation = scope.createTmpVariable(
|
||||||
irIfThenElse(stepType, nestedStepPositiveCheck, checkedStepOrGet, checkedStepOrGet.deepCopyWithSymbols().negate())
|
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.
|
// evaluation order.
|
||||||
val (nestedFirstVar, nestedFirstExpression) = createTemporaryVariableIfNecessary(nestedInfo.first, "nestedFirst")
|
val (nestedFirstVar, nestedFirstExpression) = createTemporaryVariableIfNecessary(nestedInfo.first, "nestedFirst")
|
||||||
val (nestedLastVar, nestedLastExpression) = createTemporaryVariableIfNecessary(nestedInfo.last, "nestedLast")
|
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
|
// 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.
|
// "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),
|
// 3),
|
||||||
// 2)
|
// 2)
|
||||||
val recalculatedLast =
|
val recalculatedLast =
|
||||||
callGetProgressionLastElementIfNecessary(data, nestedFirstExpression, nestedLastExpression, newStepExpression)
|
callGetProgressionLastElementIfNecessary(data, nestedFirstExpression, nestedLastExpression, finalStepExpression)
|
||||||
|
|
||||||
// Consider the following for-loop:
|
// Consider the following for-loop:
|
||||||
//
|
//
|
||||||
@@ -176,29 +198,26 @@ internal class StepHandler(
|
|||||||
// val innerNestedLast = B
|
// val innerNestedLast = B
|
||||||
// // No nested step var because step for `A..B` is a constant 1
|
// // No nested step var because step for `A..B` is a constant 1
|
||||||
// val innerStepArg = C
|
// val innerStepArg = C
|
||||||
// val innerNewStep = if (innerStepArg > 0) innerStepArg
|
// if (innerStepArg <= 0) throw IllegalArgumentException("Step must be positive, was: $innerStepArg.")
|
||||||
// else throw IllegalArgumentException("Step must be positive, was: $innerStepArg.")
|
|
||||||
//
|
//
|
||||||
// // Additional variables for outer step progression `(A..B step C) step D`:
|
// // 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)
|
// // No nested first var because `innerNestedFirst` is a local variable get (cannot have side-effects)
|
||||||
// val outerNestedLast = // "last" for `A..B step C`
|
// val outerNestedLast = // "last" for `A..B step C`
|
||||||
// getProgressionLastElement(innerNestedFirst, innerNestedLast, innerNewStep)
|
// getProgressionLastElement(innerNestedFirst, innerNestedLast, innerStepArg)
|
||||||
// // No nested step var because nested step `innerNewStep` is a local variable get (cannot have side-effects)
|
// // No nested step var because nested step `innerStepArg` is a local variable get (cannot have side-effects)
|
||||||
// val outerStepArg = D
|
// val outerStepArg = D
|
||||||
// val outerNewStep = if (outerStepArg > 0) outerStepArg
|
// if (outerStepArg <= 0) throw IllegalArgumentException("Step must be positive, was: $outerStepArg.")
|
||||||
// else throw IllegalArgumentException("Step must be positive, was: $outerStepArg.")
|
|
||||||
//
|
//
|
||||||
// // Standard form of loop over progression
|
// // Standard form of loop over progression
|
||||||
// var inductionVar = innerNestedFirst
|
// var inductionVar = innerNestedFirst
|
||||||
// val last = // "last" for `(A..B step C) step D`
|
// val last = // "last" for `(A..B step C) step D`
|
||||||
// getProgressionLastElement(innerNestedFirst, // "Passed through" from inner step progression
|
// getProgressionLastElement(innerNestedFirst, // "Passed through" from inner step progression
|
||||||
// outerNestedLast, outerNewStep)
|
// outerNestedLast, outerStepArg)
|
||||||
// val step = outerNewStep
|
|
||||||
// if (inductionVar <= last) {
|
// if (inductionVar <= last) {
|
||||||
// // Loop is not empty
|
// // Loop is not empty
|
||||||
// do {
|
// do {
|
||||||
// val i = inductionVar
|
// val i = inductionVar
|
||||||
// inductionVar += step
|
// inductionVar += outerStepArg
|
||||||
// // Loop body
|
// // Loop body
|
||||||
// } while (i != last)
|
// } while (i != last)
|
||||||
// }
|
// }
|
||||||
@@ -214,21 +233,19 @@ internal class StepHandler(
|
|||||||
// val nestedFirst = progression.first
|
// val nestedFirst = progression.first
|
||||||
// val nestedLast = progression.last
|
// val nestedLast = progression.last
|
||||||
// val nestedStep = progression.step
|
// val nestedStep = progression.step
|
||||||
// val stepArg = C
|
// var stepArg = C
|
||||||
// val checkedStep = if (stepArg > 0) stepArg
|
// if (stepArg <= 0) throw IllegalArgumentException("Step must be positive, was: $stepArg.")
|
||||||
// else throw IllegalArgumentException("Step must be positive, was: $stepArg.")
|
// // Direction of P is unknown so we check its step to determine whether to negate
|
||||||
// val newStep = // Direction of P is unknown so we check its step to determine whether to negate
|
// if (nestedStep <= 0) stepArg = -stepArg
|
||||||
// if (nestedStep > 0) checkedStep else -checkedStep
|
|
||||||
//
|
//
|
||||||
// // Standard form of loop over progression
|
// // Standard form of loop over progression
|
||||||
// var inductionVar = nestedFirst
|
// var inductionVar = nestedFirst
|
||||||
// val last = getProgressionLastElement(nestedFirst, nestedLast, newStep)
|
// val last = getProgressionLastElement(nestedFirst, nestedLast, stepArg)
|
||||||
// val step = newStep
|
// if ((stepArg > 0 && inductionVar <= last) || (stepArg < 0 && last <= inductionVar)) {
|
||||||
// if ((step > 0 && inductionVar <= last) || (step < 0 && last <= inductionVar)) {
|
|
||||||
// // Loop is not empty
|
// // Loop is not empty
|
||||||
// do {
|
// do {
|
||||||
// val i = inductionVar
|
// val i = inductionVar
|
||||||
// inductionVar += step
|
// inductionVar += stepArg
|
||||||
// // Loop body
|
// // Loop body
|
||||||
// } while (i != last)
|
// } 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,
|
// ...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).
|
// the nested "last" variable must come before the nested "first" variable (if both variables are necessary).
|
||||||
val additionalVariables = nestedInfo.additionalVariables + if (nestedInfo.isReversed) {
|
val additionalStatements = nestedInfo.additionalStatements + if (nestedInfo.isReversed) {
|
||||||
listOfNotNull(nestedLastVar, nestedFirstVar, nestedStepVar, stepArgVar, checkedStepVar, newStepVar)
|
listOfNotNull(nestedLastVar, nestedFirstVar, nestedStepVar, stepArgVar, stepCheck, stepNegation)
|
||||||
} else {
|
} else {
|
||||||
listOfNotNull(nestedFirstVar, nestedLastVar, nestedStepVar, stepArgVar, checkedStepVar, newStepVar)
|
listOfNotNull(nestedFirstVar, nestedLastVar, nestedStepVar, stepArgVar, stepCheck, stepNegation)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ProgressionHeaderInfo(
|
return ProgressionHeaderInfo(
|
||||||
data,
|
data,
|
||||||
first = nestedFirstExpression,
|
first = nestedFirstExpression,
|
||||||
last = recalculatedLast,
|
last = recalculatedLast,
|
||||||
step = newStepExpression,
|
step = finalStepExpression,
|
||||||
isReversed = nestedInfo.isReversed,
|
isReversed = nestedInfo.isReversed,
|
||||||
additionalVariables = additionalVariables,
|
additionalStatements = additionalStatements,
|
||||||
additionalNotEmptyCondition = nestedInfo.additionalNotEmptyCondition,
|
additionalNotEmptyCondition = nestedInfo.additionalNotEmptyCondition,
|
||||||
direction = nestedInfo.direction
|
direction = nestedInfo.direction
|
||||||
)
|
)
|
||||||
|
|||||||
+1
-1
@@ -120,7 +120,7 @@ internal class UntilHandler(private val context: CommonBackendContext, private v
|
|||||||
last = last,
|
last = last,
|
||||||
step = irInt(1),
|
step = irInt(1),
|
||||||
canOverflow = false,
|
canOverflow = false,
|
||||||
additionalVariables = additionalVariables,
|
additionalStatements = additionalVariables,
|
||||||
additionalNotEmptyCondition = additionalNotEmptyCondition,
|
additionalNotEmptyCondition = additionalNotEmptyCondition,
|
||||||
direction = ProgressionDirection.INCREASING
|
direction = ProgressionDirection.INCREASING
|
||||||
)
|
)
|
||||||
|
|||||||
+1
-2
@@ -15,12 +15,11 @@ fun box(): String {
|
|||||||
// // Standard form of loop over progression
|
// // Standard form of loop over progression
|
||||||
// var inductionVar = 2
|
// var inductionVar = 2
|
||||||
// val last = getProgressionLastElement(2, Int.MIN_VALUE - 1, 2) // `(Int.MIN_VALUE - 1)` underflows to Int.MAX_VALUE
|
// 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`
|
// if (false && inductionVar <= last) { // `false` comes from constant folding of `Int.MIN_VALUE != Int.MIN_VALUE`
|
||||||
// // Loop is not empty
|
// // Loop is not empty
|
||||||
// do {
|
// do {
|
||||||
// val i = inductionVar
|
// val i = inductionVar
|
||||||
// inductionVar += step
|
// inductionVar += 2
|
||||||
// // Loop body
|
// // Loop body
|
||||||
// } while (i != last)
|
// } while (i != last)
|
||||||
// }
|
// }
|
||||||
|
|||||||
@@ -11,18 +11,17 @@ fun box(): String {
|
|||||||
//
|
//
|
||||||
// Expected lowered form of loop (before bytecode optimization):
|
// Expected lowered form of loop (before bytecode optimization):
|
||||||
//
|
//
|
||||||
// // Additional variables:
|
// // Additional statements:
|
||||||
// val newStep = throw IllegalArgumentException("Step must be positive, was: 0.")
|
// throw IllegalArgumentException("Step must be positive, was: 0.")
|
||||||
//
|
//
|
||||||
// // Standard form of loop over progression
|
// // Standard form of loop over progression
|
||||||
// var inductionVar = 1
|
// var inductionVar = 1
|
||||||
// val last = getProgressionLastElement(1, 6, newStep)
|
// val last = getProgressionLastElement(1, 6, 0)
|
||||||
// val step = newStep
|
|
||||||
// if (inductionVar <= last) {
|
// if (inductionVar <= last) {
|
||||||
// // Loop is not empty
|
// // Loop is not empty
|
||||||
// do {
|
// do {
|
||||||
// val i = inductionVar
|
// val i = inductionVar
|
||||||
// inductionVar += step
|
// inductionVar += 0
|
||||||
// // Loop body
|
// // Loop body
|
||||||
// } while (i != last)
|
// } while (i != last)
|
||||||
// }
|
// }
|
||||||
|
|||||||
@@ -15,12 +15,11 @@ fun box(): String {
|
|||||||
// // Standard form of loop over progression
|
// // Standard form of loop over progression
|
||||||
// val last = getProgressionLastElement(8, 1, -2)
|
// val last = getProgressionLastElement(8, 1, -2)
|
||||||
// var inductionVar = 8
|
// var inductionVar = 8
|
||||||
// val step = -2
|
|
||||||
// if (last <= inductionVar) {
|
// if (last <= inductionVar) {
|
||||||
// // Loop is not empty
|
// // Loop is not empty
|
||||||
// do {
|
// do {
|
||||||
// val i = inductionVar
|
// val i = inductionVar
|
||||||
// inductionVar += step
|
// inductionVar += -2
|
||||||
// // Loop body
|
// // Loop body
|
||||||
// } while (i != last)
|
// } while (i != last)
|
||||||
// }
|
// }
|
||||||
|
|||||||
@@ -15,12 +15,11 @@ fun box(): String {
|
|||||||
// // Standard form of loop over progression
|
// // Standard form of loop over progression
|
||||||
// var inductionVar = 1
|
// var inductionVar = 1
|
||||||
// val last = getProgressionLastElement(1, 7, 2)
|
// val last = getProgressionLastElement(1, 7, 2)
|
||||||
// val step = 2
|
|
||||||
// if (inductionVar <= last) {
|
// if (inductionVar <= last) {
|
||||||
// // Loop is not empty
|
// // Loop is not empty
|
||||||
// do {
|
// do {
|
||||||
// val i = inductionVar
|
// val i = inductionVar
|
||||||
// inductionVar += step
|
// inductionVar += 2
|
||||||
// // Loop body
|
// // Loop body
|
||||||
// } while (i != last)
|
// } while (i != last)
|
||||||
// }
|
// }
|
||||||
|
|||||||
+7
-7
@@ -14,22 +14,21 @@ fun box(): String {
|
|||||||
//
|
//
|
||||||
// Expected lowered form of loop:
|
// Expected lowered form of loop:
|
||||||
//
|
//
|
||||||
// // Additional variables:
|
// // Additional statements:
|
||||||
// val progression = intProgression
|
// val progression = intProgression
|
||||||
// val nestedFirst = progression.first
|
// val nestedFirst = progression.first
|
||||||
// val nestedLast = progression.last
|
// val nestedLast = progression.last
|
||||||
// val nestedStep = progression.step
|
// 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
|
// // Standard form of loop over progression
|
||||||
// var inductionVar = nestedFirst
|
// var inductionVar = nestedFirst
|
||||||
// val last = getProgressionLastElement(nestedFirst, nestedLast, newStep)
|
// val last = getProgressionLastElement(nestedFirst, nestedLast, maybeNegatedStep)
|
||||||
// val step = newStep
|
// if ((maybeNegatedStep > 0 && inductionVar <= last) || (maybeNegatedStep < 0 && last <= inductionVar)) {
|
||||||
// if ((step > 0 && inductionVar <= last) || (step < 0 && last <= inductionVar)) {
|
|
||||||
// // Loop is not empty
|
// // Loop is not empty
|
||||||
// do {
|
// do {
|
||||||
// val i = inductionVar
|
// val i = inductionVar
|
||||||
// inductionVar += step
|
// inductionVar += maybeNegatedStep
|
||||||
// // Loop body
|
// // Loop body
|
||||||
// } while (i != last)
|
// } while (i != last)
|
||||||
// }
|
// }
|
||||||
@@ -46,7 +45,8 @@ fun box(): String {
|
|||||||
// 1 IF_ICMPGT
|
// 1 IF_ICMPGT
|
||||||
// 1 IF_ICMPLE
|
// 1 IF_ICMPLE
|
||||||
// 1 IF_ICMPNE
|
// 1 IF_ICMPNE
|
||||||
// 2 IFLE
|
// 1 IFLE
|
||||||
|
// 1 IFGT
|
||||||
// 1 IFGE
|
// 1 IFGE
|
||||||
// 6 IF
|
// 6 IF
|
||||||
// 0 INEG
|
// 0 INEG
|
||||||
@@ -13,20 +13,18 @@ fun box(): String {
|
|||||||
//
|
//
|
||||||
// Expected lowered form of loop:
|
// Expected lowered form of loop:
|
||||||
//
|
//
|
||||||
// // Additional variables:
|
// // Additional statements:
|
||||||
// val stepArg = one()
|
// var stepArg = one()
|
||||||
// val newStep = if (stepArg > 0) stepArg
|
// if (stepArg <= 0) throw IllegalArgumentException("Step must be positive, was: $stepArg.")
|
||||||
// else throw IllegalArgumentException("Step must be positive, was: $stepArg.")
|
|
||||||
//
|
//
|
||||||
// // Standard form of loop over progression
|
// // Standard form of loop over progression
|
||||||
// var inductionVar = 1
|
// var inductionVar = 1
|
||||||
// val last = getProgressionLastElement(1, 7, newStep)
|
// val last = getProgressionLastElement(1, 7, stepArg)
|
||||||
// val step = newStep
|
|
||||||
// if (inductionVar <= last) {
|
// if (inductionVar <= last) {
|
||||||
// // Loop is not empty
|
// // Loop is not empty
|
||||||
// do {
|
// do {
|
||||||
// val i = inductionVar
|
// val i = inductionVar
|
||||||
// inductionVar += step
|
// inductionVar += stepArg
|
||||||
// // Loop body
|
// // Loop body
|
||||||
// } while (i != last)
|
// } while (i != last)
|
||||||
// }
|
// }
|
||||||
@@ -42,5 +40,5 @@ fun box(): String {
|
|||||||
// 1 ATHROW
|
// 1 ATHROW
|
||||||
// 1 IF_ICMPGT
|
// 1 IF_ICMPGT
|
||||||
// 1 IF_ICMPNE
|
// 1 IF_ICMPNE
|
||||||
// 1 IFLE
|
// 1 IFGT
|
||||||
// 3 IF
|
// 3 IF
|
||||||
Vendored
+9
-10
@@ -15,25 +15,23 @@ fun box(): String {
|
|||||||
//
|
//
|
||||||
// Expected lowered form of loop:
|
// Expected lowered form of loop:
|
||||||
//
|
//
|
||||||
// // Additional variables:
|
// // Additional statements:
|
||||||
// val progression = intProgression
|
// val progression = intProgression
|
||||||
// val nestedFirst = progression.first
|
// val nestedFirst = progression.first
|
||||||
// val nestedLast = progression.last
|
// val nestedLast = progression.last
|
||||||
// val nestedStep = progression.step
|
// val nestedStep = progression.step
|
||||||
// val stepArg = one()
|
// var stepArg = one()
|
||||||
// val checkedStep = if (stepArg > 0) stepArg
|
// if (stepArg <= 0) throw IllegalArgumentException("Step must be positive, was: $stepArg.")
|
||||||
// else throw IllegalArgumentException("Step must be positive, was: $stepArg.")
|
// if (nestedStep <= 0) stepArg = -stepArg
|
||||||
// val newStep = if (nestedStep > 0) checkedStep else -checkedStep
|
|
||||||
//
|
//
|
||||||
// // Standard form of loop over progression
|
// // Standard form of loop over progression
|
||||||
// var inductionVar = nestedFirst
|
// var inductionVar = nestedFirst
|
||||||
// val last = getProgressionLastElement(nestedFirst, nestedLast, newStep)
|
// val last = getProgressionLastElement(nestedFirst, nestedLast, stepArg)
|
||||||
// val step = newStep
|
// if ((stepArg > 0 && inductionVar <= last) || (stepArg < 0 && last <= inductionVar)) {
|
||||||
// if ((step > 0 && inductionVar <= last) || (step < 0 && last <= inductionVar)) {
|
|
||||||
// // Loop is not empty
|
// // Loop is not empty
|
||||||
// do {
|
// do {
|
||||||
// val i = inductionVar
|
// val i = inductionVar
|
||||||
// inductionVar += step
|
// inductionVar += stepArg
|
||||||
// // Loop body
|
// // Loop body
|
||||||
// } while (i != last)
|
// } while (i != last)
|
||||||
// }
|
// }
|
||||||
@@ -50,7 +48,8 @@ fun box(): String {
|
|||||||
// 1 IF_ICMPGT
|
// 1 IF_ICMPGT
|
||||||
// 1 IF_ICMPLE
|
// 1 IF_ICMPLE
|
||||||
// 1 IF_ICMPNE
|
// 1 IF_ICMPNE
|
||||||
// 3 IFLE
|
// 1 IFLE
|
||||||
|
// 2 IFGT
|
||||||
// 1 IFGE
|
// 1 IFGE
|
||||||
// 7 IF
|
// 7 IF
|
||||||
// 1 INEG
|
// 1 INEG
|
||||||
@@ -14,12 +14,11 @@ fun box(): String {
|
|||||||
// // Standard form of loop over progression
|
// // Standard form of loop over progression
|
||||||
// var inductionVar = 1
|
// var inductionVar = 1
|
||||||
// val last = 4
|
// val last = 4
|
||||||
// val step = 1
|
|
||||||
// if (inductionVar <= last) {
|
// if (inductionVar <= last) {
|
||||||
// // Loop is not empty
|
// // Loop is not empty
|
||||||
// do {
|
// do {
|
||||||
// val i = inductionVar
|
// val i = inductionVar
|
||||||
// inductionVar += step
|
// inductionVar += 1
|
||||||
// // Loop body
|
// // Loop body
|
||||||
// } while (inductionVar <= last)
|
// } while (inductionVar <= last)
|
||||||
// }
|
// }
|
||||||
|
|||||||
+1
-2
@@ -14,12 +14,11 @@ fun box(): String {
|
|||||||
// // Standard form of loop over progression
|
// // Standard form of loop over progression
|
||||||
// var inductionVar = 1
|
// var inductionVar = 1
|
||||||
// val last = 4
|
// val last = 4
|
||||||
// val step = 1
|
|
||||||
// if (inductionVar <= last) {
|
// if (inductionVar <= last) {
|
||||||
// // Loop is not empty
|
// // Loop is not empty
|
||||||
// do {
|
// do {
|
||||||
// val i = inductionVar
|
// val i = inductionVar
|
||||||
// inductionVar += step
|
// inductionVar += 1
|
||||||
// // Loop body
|
// // Loop body
|
||||||
// } while (inductionVar <= last)
|
// } while (inductionVar <= last)
|
||||||
// }
|
// }
|
||||||
|
|||||||
+1
-2
@@ -19,12 +19,11 @@ fun box(): String {
|
|||||||
// // Standard form of loop over progression
|
// // Standard form of loop over progression
|
||||||
// var inductionVar = 1
|
// var inductionVar = 1
|
||||||
// val last = getProgressionLastElement(1, outerNestedLast, 2)
|
// val last = getProgressionLastElement(1, outerNestedLast, 2)
|
||||||
// val step = 2
|
|
||||||
// if (inductionVar <= last) {
|
// if (inductionVar <= last) {
|
||||||
// // Loop is not empty
|
// // Loop is not empty
|
||||||
// do {
|
// do {
|
||||||
// val i = inductionVar
|
// val i = inductionVar
|
||||||
// inductionVar += step
|
// inductionVar += 2
|
||||||
// // Loop body
|
// // Loop body
|
||||||
// } while (i != last)
|
// } while (i != last)
|
||||||
// }
|
// }
|
||||||
|
|||||||
@@ -15,12 +15,11 @@ fun box(): String {
|
|||||||
// // Standard form of loop over progression
|
// // Standard form of loop over progression
|
||||||
// val last = 1
|
// val last = 1
|
||||||
// var inductionVar = getProgressionLastElement(1, 8, 2)
|
// var inductionVar = getProgressionLastElement(1, 8, 2)
|
||||||
// val step = -2
|
|
||||||
// if (last <= inductionVar) {
|
// if (last <= inductionVar) {
|
||||||
// // Loop is not empty
|
// // Loop is not empty
|
||||||
// do {
|
// do {
|
||||||
// val i = inductionVar
|
// val i = inductionVar
|
||||||
// inductionVar += step
|
// inductionVar += -2
|
||||||
// // Loop body
|
// // Loop body
|
||||||
// } while (last <= inductionVar)
|
// } while (last <= inductionVar)
|
||||||
// }
|
// }
|
||||||
|
|||||||
@@ -16,12 +16,11 @@ fun box(): String {
|
|||||||
// // Standard form of loop over progression
|
// // Standard form of loop over progression
|
||||||
// var inductionVar = 1
|
// var inductionVar = 1
|
||||||
// val last = getProgressionLastElement(1, 8, 2)
|
// val last = getProgressionLastElement(1, 8, 2)
|
||||||
// val step = 2
|
|
||||||
// if (inductionVar <= last) {
|
// if (inductionVar <= last) {
|
||||||
// // Loop is not empty
|
// // Loop is not empty
|
||||||
// do {
|
// do {
|
||||||
// val i = inductionVar
|
// val i = inductionVar
|
||||||
// inductionVar += step
|
// inductionVar += 2
|
||||||
// // Loop body
|
// // Loop body
|
||||||
// } while (i != last)
|
// } while (i != last)
|
||||||
// }
|
// }
|
||||||
|
|||||||
+9
-12
@@ -13,24 +13,21 @@ fun box(): String {
|
|||||||
//
|
//
|
||||||
// Expected lowered form of loop:
|
// Expected lowered form of loop:
|
||||||
//
|
//
|
||||||
// // Additional variables:
|
// // Additional statments:
|
||||||
// val innerStepArg = one()
|
// var innerStepArg = one()
|
||||||
// val innerNewStep = if (innerStepArg > 0) innerStepArg
|
// if (innerStepArg <= 0) throw IllegalArgumentException("Step must be positive, was: $innerStepArg.")
|
||||||
// else throw IllegalArgumentException("Step must be positive, was: $innerStepArg.")
|
// val outerNestedLast = getProgressionLastElement(1, 6, innerStepArg)
|
||||||
// val outerNestedLast = getProgressionLastElement(1, 6, innerNewStep)
|
// var outerStepArg = one()
|
||||||
// val outerStepArg = one()
|
// if (outerStepArg <= 0) throw IllegalArgumentException("Step must be positive, was: $outerStepArg.")
|
||||||
// val outerNewStep = if (outerStepArg > 0) outerStepArg
|
|
||||||
// else throw IllegalArgumentException("Step must be positive, was: $outerStepArg.")
|
|
||||||
//
|
//
|
||||||
// // Standard form of loop over progression
|
// // Standard form of loop over progression
|
||||||
// var inductionVar = 1
|
// var inductionVar = 1
|
||||||
// val last = getProgressionLastElement(1, outerNestedLast, outerNewStep)
|
// val last = getProgressionLastElement(1, outerNestedLast, outerStepArg)
|
||||||
// val step = outerNewStep
|
|
||||||
// if (inductionVar <= last) {
|
// if (inductionVar <= last) {
|
||||||
// // Loop is not empty
|
// // Loop is not empty
|
||||||
// do {
|
// do {
|
||||||
// val i = inductionVar
|
// val i = inductionVar
|
||||||
// inductionVar += step
|
// inductionVar += outerStepArg
|
||||||
// // Loop body
|
// // Loop body
|
||||||
// } while (i != last)
|
// } while (i != last)
|
||||||
// }
|
// }
|
||||||
@@ -46,5 +43,5 @@ fun box(): String {
|
|||||||
// 2 ATHROW
|
// 2 ATHROW
|
||||||
// 1 IF_ICMPGT
|
// 1 IF_ICMPGT
|
||||||
// 1 IF_ICMPNE
|
// 1 IF_ICMPNE
|
||||||
// 2 IFLE
|
// 2 IFGT
|
||||||
// 4 IF
|
// 4 IF
|
||||||
@@ -19,12 +19,11 @@ fun box(): String {
|
|||||||
// // Standard form of loop over progression
|
// // Standard form of loop over progression
|
||||||
// var inductionVar = 1
|
// var inductionVar = 1
|
||||||
// val last = innerNestedLast
|
// val last = innerNestedLast
|
||||||
// val step = 1
|
|
||||||
// if (inductionVar <= last) {
|
// if (inductionVar <= last) {
|
||||||
// // Loop is not empty
|
// // Loop is not empty
|
||||||
// do {
|
// do {
|
||||||
// val i = inductionVar
|
// val i = inductionVar
|
||||||
// inductionVar += step
|
// inductionVar += 1
|
||||||
// // Loop body
|
// // Loop body
|
||||||
// } while (i != last)
|
// } while (i != last)
|
||||||
// }
|
// }
|
||||||
|
|||||||
+2
-3
@@ -12,19 +12,18 @@ fun box(): String {
|
|||||||
//
|
//
|
||||||
// Expected lowered form of loop (before bytecode optimizations):
|
// Expected lowered form of loop (before bytecode optimizations):
|
||||||
//
|
//
|
||||||
// // Additional variables:
|
// // Additional statements:
|
||||||
// val untilArg = nine()
|
// val untilArg = nine()
|
||||||
// val nestedLast = untilArg - 1
|
// val nestedLast = untilArg - 1
|
||||||
//
|
//
|
||||||
// // Standard form of loop over progression
|
// // Standard form of loop over progression
|
||||||
// var inductionVar = 1
|
// var inductionVar = 1
|
||||||
// val last = getProgressionLastElement(1, nestedLast, 2)
|
// val last = getProgressionLastElement(1, nestedLast, 2)
|
||||||
// val step = 2
|
|
||||||
// if (untilArg != Int.MIN_VALUE && inductionVar <= last) {
|
// if (untilArg != Int.MIN_VALUE && inductionVar <= last) {
|
||||||
// // Loop is not empty
|
// // Loop is not empty
|
||||||
// do {
|
// do {
|
||||||
// val i = inductionVar
|
// val i = inductionVar
|
||||||
// inductionVar += step
|
// inductionVar += 2
|
||||||
// // Loop body
|
// // Loop body
|
||||||
// } while (i != last)
|
// } while (i != last)
|
||||||
// }
|
// }
|
||||||
|
|||||||
+1
-2
@@ -16,12 +16,11 @@ fun box(): String {
|
|||||||
// // Standard form of loop over progression
|
// // Standard form of loop over progression
|
||||||
// var inductionVar = 2u
|
// var inductionVar = 2u
|
||||||
// val last = getProgressionLastElement(2u, UInt.MIN_VALUE - 1, 2) // `(UInt.MIN_VALUE - 1)` underflows to UInt.MAX_VALUE
|
// 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`
|
// if (false && inductionVar <= last) { // `false` comes from constant folding of `Int.MIN_VALUE != Int.MIN_VALUE`
|
||||||
// // Loop is not empty
|
// // Loop is not empty
|
||||||
// do {
|
// do {
|
||||||
// val i = inductionVar
|
// val i = inductionVar
|
||||||
// inductionVar += step
|
// inductionVar += 2
|
||||||
// // Loop body
|
// // Loop body
|
||||||
// } while (i != last)
|
// } while (i != last)
|
||||||
// }
|
// }
|
||||||
|
|||||||
+4
-5
@@ -12,18 +12,17 @@ fun box(): String {
|
|||||||
//
|
//
|
||||||
// Expected lowered form of loop (before bytecode optimization):
|
// Expected lowered form of loop (before bytecode optimization):
|
||||||
//
|
//
|
||||||
// // Additional variables:
|
// // Additional statements:
|
||||||
// val newStep = throw IllegalArgumentException("Step must be positive, was: 0.")
|
// throw IllegalArgumentException("Step must be positive, was: 0.")
|
||||||
//
|
//
|
||||||
// // Standard form of loop over progression
|
// // Standard form of loop over progression
|
||||||
// var inductionVar = 1u
|
// var inductionVar = 1u
|
||||||
// val last = getProgressionLastElement(1u, 6u, newStep)
|
// val last = getProgressionLastElement(1u, 6u, 0)
|
||||||
// val step = newStep
|
|
||||||
// if (inductionVar <= last) {
|
// if (inductionVar <= last) {
|
||||||
// // Loop is not empty
|
// // Loop is not empty
|
||||||
// do {
|
// do {
|
||||||
// val i = inductionVar
|
// val i = inductionVar
|
||||||
// inductionVar += step
|
// inductionVar += 0
|
||||||
// // Loop body
|
// // Loop body
|
||||||
// } while (i != last)
|
// } while (i != last)
|
||||||
// }
|
// }
|
||||||
|
|||||||
+1
-2
@@ -16,12 +16,11 @@ fun box(): String {
|
|||||||
// // Standard form of loop over progression
|
// // Standard form of loop over progression
|
||||||
// val last = getProgressionLastElement(8u, 1u, -2)
|
// val last = getProgressionLastElement(8u, 1u, -2)
|
||||||
// var inductionVar = 8u
|
// var inductionVar = 8u
|
||||||
// val step = -2
|
|
||||||
// if (last <= inductionVar) {
|
// if (last <= inductionVar) {
|
||||||
// // Loop is not empty
|
// // Loop is not empty
|
||||||
// do {
|
// do {
|
||||||
// val i = inductionVar
|
// val i = inductionVar
|
||||||
// inductionVar += step
|
// inductionVar += -2
|
||||||
// // Loop body
|
// // Loop body
|
||||||
// } while (i != last)
|
// } while (i != last)
|
||||||
// }
|
// }
|
||||||
|
|||||||
Vendored
+7
-8
@@ -15,22 +15,21 @@ fun box(): String {
|
|||||||
//
|
//
|
||||||
// Expected lowered form of loop:
|
// Expected lowered form of loop:
|
||||||
//
|
//
|
||||||
// // Additional variables:
|
// // Additional statements:
|
||||||
// val progression = intProgression
|
// val progression = intProgression
|
||||||
// val nestedFirst = progression.first
|
// val nestedFirst = progression.first
|
||||||
// val nestedLast = progression.last
|
// val nestedLast = progression.last
|
||||||
// val nestedStep = progression.step
|
// 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
|
// // Standard form of loop over progression
|
||||||
// var inductionVar = nestedFirst
|
// var inductionVar = nestedFirst
|
||||||
// val last = getProgressionLastElement(nestedFirst, nestedLast, newStep)
|
// val last = getProgressionLastElement(nestedFirst, nestedLast, maybeNegatedStep)
|
||||||
// val step = newStep
|
// if ((maybeNegatedStep > 0 && inductionVar <= last) || (maybeNegatedStep < 0 && last <= inductionVar)) {
|
||||||
// if ((step > 0 && inductionVar <= last) || (step < 0 && last <= inductionVar)) {
|
|
||||||
// // Loop is not empty
|
// // Loop is not empty
|
||||||
// do {
|
// do {
|
||||||
// val i = inductionVar
|
// val i = inductionVar
|
||||||
// inductionVar += step
|
// inductionVar += maybeNegatedStep
|
||||||
// // Loop body
|
// // Loop body
|
||||||
// } while (i != last)
|
// } while (i != last)
|
||||||
// }
|
// }
|
||||||
@@ -45,9 +44,9 @@ fun box(): String {
|
|||||||
// 0 NEW java/lang/IllegalArgumentException
|
// 0 NEW java/lang/IllegalArgumentException
|
||||||
// 0 ATHROW
|
// 0 ATHROW
|
||||||
// 2 INVOKESTATIC kotlin/UnsignedKt.uintCompare
|
// 2 INVOKESTATIC kotlin/UnsignedKt.uintCompare
|
||||||
// 1 IFGT
|
// 2 IFGT
|
||||||
// 1 IF_ICMPNE
|
// 1 IF_ICMPNE
|
||||||
// 3 IFLE
|
// 2 IFLE
|
||||||
// 1 IFGE
|
// 1 IFGE
|
||||||
// 6 IF
|
// 6 IF
|
||||||
// 0 INEG
|
// 0 INEG
|
||||||
|
|||||||
Vendored
+9
-11
@@ -16,25 +16,23 @@ fun box(): String {
|
|||||||
//
|
//
|
||||||
// Expected lowered form of loop:
|
// Expected lowered form of loop:
|
||||||
//
|
//
|
||||||
// // Additional variables:
|
// // Additional statements:
|
||||||
// val progression = intProgression
|
// val progression = intProgression
|
||||||
// val nestedFirst = progression.first
|
// val nestedFirst = progression.first
|
||||||
// val nestedLast = progression.last
|
// val nestedLast = progression.last
|
||||||
// val nestedStep = progression.step
|
// val nestedStep = progression.step
|
||||||
// val stepArg = one()
|
// var stepArg = one()
|
||||||
// val checkedStep = if (stepArg > 0) stepArg
|
// if (stepArg <= 0) throw IllegalArgumentException("Step must be positive, was: $stepArg.")
|
||||||
// else throw IllegalArgumentException("Step must be positive, was: $stepArg.")
|
// if (nestedStep <= 0) stepArg = -stepArg
|
||||||
// val newStep = if (nestedStep > 0) checkedStep else -checkedStep
|
|
||||||
//
|
//
|
||||||
// // Standard form of loop over progression
|
// // Standard form of loop over progression
|
||||||
// var inductionVar = nestedFirst
|
// var inductionVar = nestedFirst
|
||||||
// val last = getProgressionLastElement(nestedFirst, nestedLast, newStep)
|
// val last = getProgressionLastElement(nestedFirst, nestedLast, stepArg)
|
||||||
// val step = newStep
|
// if ((stepArg > 0 && inductionVar <= last) || (stepArg < 0 && last <= inductionVar)) {
|
||||||
// if ((step > 0 && inductionVar <= last) || (step < 0 && last <= inductionVar)) {
|
|
||||||
// // Loop is not empty
|
// // Loop is not empty
|
||||||
// do {
|
// do {
|
||||||
// val i = inductionVar
|
// val i = inductionVar
|
||||||
// inductionVar += step
|
// inductionVar += stepArg
|
||||||
// // Loop body
|
// // Loop body
|
||||||
// } while (i != last)
|
// } while (i != last)
|
||||||
// }
|
// }
|
||||||
@@ -49,9 +47,9 @@ fun box(): String {
|
|||||||
// 1 NEW java/lang/IllegalArgumentException
|
// 1 NEW java/lang/IllegalArgumentException
|
||||||
// 1 ATHROW
|
// 1 ATHROW
|
||||||
// 2 INVOKESTATIC kotlin/UnsignedKt.uintCompare
|
// 2 INVOKESTATIC kotlin/UnsignedKt.uintCompare
|
||||||
// 1 IFGT
|
// 3 IFGT
|
||||||
// 1 IF_ICMPNE
|
// 1 IF_ICMPNE
|
||||||
// 4 IFLE
|
// 2 IFLE
|
||||||
// 1 IFGE
|
// 1 IFGE
|
||||||
// 7 IF
|
// 7 IF
|
||||||
// 1 INEG
|
// 1 INEG
|
||||||
|
|||||||
+2
-3
@@ -14,18 +14,17 @@ fun box(): String {
|
|||||||
//
|
//
|
||||||
// Expected lowered form of loop:
|
// Expected lowered form of loop:
|
||||||
//
|
//
|
||||||
// // Additional variables:
|
// // Additional statements:
|
||||||
// val outerNestedLast = getProgressionLastElement(1u, 7u, 3)
|
// val outerNestedLast = getProgressionLastElement(1u, 7u, 3)
|
||||||
//
|
//
|
||||||
// // Standard form of loop over progression
|
// // Standard form of loop over progression
|
||||||
// var inductionVar = 1u
|
// var inductionVar = 1u
|
||||||
// val last = getProgressionLastElement(1u, outerNestedLast, 2)
|
// val last = getProgressionLastElement(1u, outerNestedLast, 2)
|
||||||
// val step = 2
|
|
||||||
// if (inductionVar <= last) {
|
// if (inductionVar <= last) {
|
||||||
// // Loop is not empty
|
// // Loop is not empty
|
||||||
// do {
|
// do {
|
||||||
// val i = inductionVar
|
// val i = inductionVar
|
||||||
// inductionVar += step
|
// inductionVar += 2
|
||||||
// // Loop body
|
// // Loop body
|
||||||
// } while (i != last)
|
// } while (i != last)
|
||||||
// }
|
// }
|
||||||
|
|||||||
+2
-3
@@ -13,19 +13,18 @@ fun box(): String {
|
|||||||
//
|
//
|
||||||
// Expected lowered form of loop (before bytecode optimizations):
|
// Expected lowered form of loop (before bytecode optimizations):
|
||||||
//
|
//
|
||||||
// // Additional variables:
|
// // Additional statements:
|
||||||
// val untilArg = nine()
|
// val untilArg = nine()
|
||||||
// val nestedLast = untilArg - 1u
|
// val nestedLast = untilArg - 1u
|
||||||
//
|
//
|
||||||
// // Standard form of loop over progression
|
// // Standard form of loop over progression
|
||||||
// var inductionVar = 1
|
// var inductionVar = 1
|
||||||
// val last = getProgressionLastElement(1u, nestedLast, 2)
|
// val last = getProgressionLastElement(1u, nestedLast, 2)
|
||||||
// val step = 2
|
|
||||||
// if (untilArg != UInt.MIN_VALUE && inductionVar <= last) {
|
// if (untilArg != UInt.MIN_VALUE && inductionVar <= last) {
|
||||||
// // Loop is not empty
|
// // Loop is not empty
|
||||||
// do {
|
// do {
|
||||||
// val i = inductionVar
|
// val i = inductionVar
|
||||||
// inductionVar += step
|
// inductionVar += 2
|
||||||
// // Loop body
|
// // Loop body
|
||||||
// } while (i != last)
|
// } while (i != last)
|
||||||
// }
|
// }
|
||||||
|
|||||||
Reference in New Issue
Block a user