ForLoopsLowering: Eliminate construction/boxing/unboxing of UInt/ULong.

This needs further cleanup to encapsulate more logic into ProgressionType.
This commit is contained in:
Mark Punzalan
2020-05-02 00:17:26 -07:00
committed by Alexander Udalov
parent e1120f49d8
commit 177967258b
22 changed files with 192 additions and 94 deletions
@@ -289,6 +289,8 @@ abstract class Symbols<out T : CommonBackendContext>(val context: T, irBuiltIns:
abstract val returnIfSuspended: IrSimpleFunctionSymbol abstract val returnIfSuspended: IrSimpleFunctionSymbol
open val unsafeCoerceIntrinsic: IrSimpleFunctionSymbol? = null
companion object { companion object {
fun isLateinitIsInitializedPropertyGetter(symbol: IrFunctionSymbol): Boolean = fun isLateinitIsInitializedPropertyGetter(symbol: IrFunctionSymbol): Boolean =
symbol is IrSimpleFunctionSymbol && symbol.owner.let { function -> symbol is IrSimpleFunctionSymbol && symbol.owner.let { function ->
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.functions import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.ir.util.isUnsigned
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
@@ -32,11 +33,15 @@ internal enum class ProgressionType(
INT_PROGRESSION(Name.identifier("toInt"), Name.identifier("toInt")), INT_PROGRESSION(Name.identifier("toInt"), Name.identifier("toInt")),
LONG_PROGRESSION(Name.identifier("toLong"), Name.identifier("toLong"), isLong = true), LONG_PROGRESSION(Name.identifier("toLong"), Name.identifier("toLong"), isLong = true),
CHAR_PROGRESSION(Name.identifier("toChar"), Name.identifier("toInt")), CHAR_PROGRESSION(Name.identifier("toChar"), Name.identifier("toInt")),
UINT_PROGRESSION(Name.identifier("toUInt"), Name.identifier("toInt"), isUnsigned = true), UINT_PROGRESSION(Name.identifier("toInt"), Name.identifier("toInt"), isUnsigned = true),
ULONG_PROGRESSION(Name.identifier("toULong"), Name.identifier("toLong"), isLong = true, isUnsigned = true); ULONG_PROGRESSION(Name.identifier("toLong"), Name.identifier("toLong"), isLong = true, isUnsigned = true);
/** Returns the [IrType] of the `first`/`last` properties and elements in the progression. */ /** Returns the [IrType] of the `first`/`last` properties and elements in the progression. */
fun elementType(symbols: Symbols<CommonBackendContext>): IrType = elementClassifier(symbols).defaultType fun elementType(symbols: Symbols<CommonBackendContext>): IrType = when (this) {
INT_PROGRESSION, UINT_PROGRESSION -> symbols.int
LONG_PROGRESSION, ULONG_PROGRESSION -> symbols.long
CHAR_PROGRESSION -> symbols.char
}.defaultType
/** Returns the [IrClassSymbol] of the `first`/`last` properties and elements in the progression. */ /** Returns the [IrClassSymbol] of the `first`/`last` properties and elements in the progression. */
fun elementClassifier(symbols: Symbols<CommonBackendContext>): IrClassSymbol = when (this) { fun elementClassifier(symbols: Symbols<CommonBackendContext>): IrClassSymbol = when (this) {
@@ -59,6 +64,15 @@ internal enum class ProgressionType(
LONG_PROGRESSION, ULONG_PROGRESSION -> builtIns.longClass LONG_PROGRESSION, ULONG_PROGRESSION -> builtIns.longClass
} }
/** Returns the [IrType] used in loop conditions (`buildLoopCondition()`) and when calling `getProgressionLastElement()`. */
fun compareType(symbols: Symbols<CommonBackendContext>): IrType = when (this) {
INT_PROGRESSION -> symbols.int
LONG_PROGRESSION -> symbols.long
CHAR_PROGRESSION -> symbols.char
UINT_PROGRESSION -> symbols.uInt!!
ULONG_PROGRESSION -> symbols.uLong!!
}.defaultType
fun castElementIfNecessary(element: IrExpression, context: CommonBackendContext) = fun castElementIfNecessary(element: IrExpression, context: CommonBackendContext) =
element.castIfNecessary(elementType(context.ir.symbols), elementCastFunctionName) element.castIfNecessary(elementType(context.ir.symbols), elementCastFunctionName)
@@ -78,6 +92,69 @@ internal enum class ProgressionType(
.apply { dispatchReceiver = this@castIfNecessary } .apply { dispatchReceiver = this@castIfNecessary }
} }
fun coerceToUnsigned(value: IrExpression, symbols: Symbols<CommonBackendContext>): IrExpression {
if (!isUnsigned || value.type.isUnsigned()) return value
val unsafeCoerceIntrinsic = symbols.unsafeCoerceIntrinsic
return if (unsafeCoerceIntrinsic != null) {
val from = when (this) {
UINT_PROGRESSION -> symbols.int.defaultType
ULONG_PROGRESSION -> symbols.long.defaultType
else -> error("Unexpected progression type")
}
val to = when (this) {
UINT_PROGRESSION -> symbols.uInt!!.defaultType
ULONG_PROGRESSION -> symbols.uLong!!.defaultType
else -> error("Unexpected progression type")
}
IrCallImpl(value.startOffset, value.endOffset, to, unsafeCoerceIntrinsic).apply {
putTypeArgument(0, from)
putTypeArgument(1, to)
putValueArgument(0, value)
}
} else {
val conversionFunctionMap = when (this) {
UINT_PROGRESSION -> symbols.toUIntByExtensionReceiver
ULONG_PROGRESSION -> symbols.toULongByExtensionReceiver
else -> error("Unexpected progression type")
}
val from = when (this) {
UINT_PROGRESSION -> symbols.int.defaultType
ULONG_PROGRESSION -> symbols.long.defaultType
else -> error("Unexpected progression type")
}.toKotlinType()
val castFun = conversionFunctionMap.getValue(from)
IrCallImpl(value.startOffset, value.endOffset, castFun.owner.returnType, castFun).apply {
extensionReceiver = value
}
}
}
fun coerceToSigned(value: IrExpression, symbols: Symbols<CommonBackendContext>): IrExpression {
if (!isUnsigned || !value.type.isUnsigned()) return value
val unsafeCoerceIntrinsic = symbols.unsafeCoerceIntrinsic
return if (unsafeCoerceIntrinsic != null) {
val from = when (this) {
UINT_PROGRESSION -> symbols.uInt!!.defaultType
ULONG_PROGRESSION -> symbols.uLong!!.defaultType
else -> error("Unexpected progression type")
}
val to = when (this) {
UINT_PROGRESSION -> symbols.int.defaultType
ULONG_PROGRESSION -> symbols.long.defaultType
else -> error("Unexpected progression type")
}
IrCallImpl(value.startOffset, value.endOffset, to, unsafeCoerceIntrinsic).apply {
putTypeArgument(0, from)
putTypeArgument(1, to)
putValueArgument(0, value)
}
} else {
castElementIfNecessary(value, symbols.context)
}
}
companion object { companion object {
fun fromIrType(irType: IrType, symbols: Symbols<CommonBackendContext>): ProgressionType? = when { fun fromIrType(irType: IrType, symbols: Symbols<CommonBackendContext>): ProgressionType? = when {
irType.isSubtypeOfClass(symbols.charProgression) -> CHAR_PROGRESSION irType.isSubtypeOfClass(symbols.charProgression) -> CHAR_PROGRESSION
@@ -68,7 +68,6 @@ internal abstract class NumericForLoopHeader<T : NumericHeaderInfo>(
val inductionVariable: IrVariable val inductionVariable: IrVariable
protected val stepVariable: IrVariable? protected val stepVariable: IrVariable?
protected val stepVariableForIncrement: IrVariable?
val stepExpression: IrExpression val stepExpression: IrExpression
// Always copy `stepExpression` is it may be used multiple times. // Always copy `stepExpression` is it may be used multiple times.
get() = field.deepCopyWithSymbols() get() = field.deepCopyWithSymbols()
@@ -78,7 +77,7 @@ internal abstract class NumericForLoopHeader<T : NumericHeaderInfo>(
// Always copy `lastExpression` is it may be used in multiple conditions. // Always copy `lastExpression` is it may be used in multiple conditions.
get() = field.deepCopyWithSymbols() get() = field.deepCopyWithSymbols()
private val symbols = context.ir.symbols protected val symbols = context.ir.symbols
private val elementType: IrType private val elementType: IrType
init { init {
@@ -124,24 +123,6 @@ internal abstract class NumericForLoopHeader<T : NumericHeaderInfo>(
) )
stepVariable = tmpStepVar stepVariable = tmpStepVar
stepExpression = tmpStepExpression stepExpression = tmpStepExpression
stepVariableForIncrement = when (headerInfo.progressionType) {
ProgressionType.UINT_PROGRESSION -> {
val castFun = context.ir.symbols.toUIntByExtensionReceiver.getValue(stepType.toKotlinType())
scope.createTmpVariable(
irCall(castFun).apply { extensionReceiver = stepExpression },
nameHint = "stepForIncrement"
)
}
ProgressionType.ULONG_PROGRESSION -> {
val castFun = context.ir.symbols.toULongByExtensionReceiver.getValue(stepType.toKotlinType())
scope.createTmpVariable(
irCall(castFun).apply { extensionReceiver = stepExpression },
nameHint = "stepForIncrement"
)
}
else -> null
}
} }
} }
@@ -155,10 +136,9 @@ internal abstract class NumericForLoopHeader<T : NumericHeaderInfo>(
/** Statement used to increment the induction variable. */ /** Statement used to increment the induction variable. */
protected fun incrementInductionVariable(builder: DeclarationIrBuilder): IrStatement = with(builder) { protected fun incrementInductionVariable(builder: DeclarationIrBuilder): IrStatement = with(builder) {
// inductionVariable = inductionVariable + step // inductionVariable = inductionVariable + step
val stepExpressionToUse = stepVariableForIncrement?.let { irGet(stepVariableForIncrement) } ?: stepExpression // NOTE: We cannot use `stepExpression.type` to match the value parameter type because it may be of type `Nothing`.
// NOTE: We cannot use `stepExpression.type` below because it may be of type `Nothing`. This happens in the case of an illegal step // This happens in the case of an illegal step where the "step" is actually a `throw IllegalArgumentException(...)`.
// where the "step" is actually a `throw IllegalArgumentException(...)`. val stepType = headerInfo.progressionType.stepType(context.irBuiltIns)
val stepType = stepVariableForIncrement?.type ?: headerInfo.progressionType.stepType(context.irBuiltIns)
val plusFun = elementType.getClass()!!.functions.single { val plusFun = elementType.getClass()!!.functions.single {
it.name == OperatorNameConventions.PLUS && it.name == OperatorNameConventions.PLUS &&
it.valueParameters.size == 1 && it.valueParameters.size == 1 &&
@@ -168,7 +148,7 @@ internal abstract class NumericForLoopHeader<T : NumericHeaderInfo>(
inductionVariable.symbol, irCallOp( inductionVariable.symbol, irCallOp(
plusFun.symbol, plusFun.returnType, plusFun.symbol, plusFun.returnType,
irGet(inductionVariable), irGet(inductionVariable),
stepExpressionToUse stepExpression
) )
) )
} }
@@ -177,7 +157,7 @@ internal abstract class NumericForLoopHeader<T : NumericHeaderInfo>(
with(builder) { with(builder) {
val builtIns = context.irBuiltIns val builtIns = context.irBuiltIns
val progressionType = headerInfo.progressionType val progressionType = headerInfo.progressionType
val progressionElementType = progressionType.elementType(symbols) val progressionCompareType = progressionType.compareType(symbols)
// `compareTo` must be used for UInt/ULong; they don't have intrinsic comparison operators. // `compareTo` must be used for UInt/ULong; they don't have intrinsic comparison operators.
val intCompFun = if (isLastInclusive) { val intCompFun = if (isLastInclusive) {
@@ -185,17 +165,17 @@ internal abstract class NumericForLoopHeader<T : NumericHeaderInfo>(
} else { } else {
builtIns.lessFunByOperandType.getValue(builtIns.intClass) builtIns.lessFunByOperandType.getValue(builtIns.intClass)
} }
val elementCompareToFun = progressionElementType.getClass()!!.functions.single { val elementCompareToFun = progressionCompareType.getClass()!!.functions.single {
it.name == OperatorNameConventions.COMPARE_TO && it.name == OperatorNameConventions.COMPARE_TO &&
it.dispatchReceiverParameter != null && it.extensionReceiverParameter == null && it.dispatchReceiverParameter != null && it.extensionReceiverParameter == null &&
it.valueParameters.size == 1 && it.valueParameters[0].type == progressionElementType it.valueParameters.size == 1 && it.valueParameters[0].type == progressionCompareType
} }
val elementCompFun = val elementCompFun =
if (isLastInclusive) { if (isLastInclusive) {
builtIns.lessOrEqualFunByOperandType[progressionElementType.classifierOrFail] builtIns.lessOrEqualFunByOperandType[progressionCompareType.classifierOrFail]
} else { } else {
builtIns.lessFunByOperandType[progressionElementType.classifierOrFail] builtIns.lessFunByOperandType[progressionCompareType.classifierOrFail]
} }
fun conditionForDecreasing(): IrExpression = fun conditionForDecreasing(): IrExpression =
@@ -203,8 +183,8 @@ internal abstract class NumericForLoopHeader<T : NumericHeaderInfo>(
if (progressionType.isUnsigned) { if (progressionType.isUnsigned) {
irCall(intCompFun).apply { irCall(intCompFun).apply {
putValueArgument(0, irCall(elementCompareToFun).apply { putValueArgument(0, irCall(elementCompareToFun).apply {
dispatchReceiver = lastExpression dispatchReceiver = progressionType.coerceToUnsigned(lastExpression, symbols)
putValueArgument(0, irGet(inductionVariable)) putValueArgument(0, progressionType.coerceToUnsigned(irGet(inductionVariable), symbols))
}) })
putValueArgument(1, irInt(0)) putValueArgument(1, irInt(0))
} }
@@ -220,8 +200,8 @@ internal abstract class NumericForLoopHeader<T : NumericHeaderInfo>(
if (progressionType.isUnsigned) { if (progressionType.isUnsigned) {
irCall(intCompFun).apply { irCall(intCompFun).apply {
putValueArgument(0, irCall(elementCompareToFun).apply { putValueArgument(0, irCall(elementCompareToFun).apply {
dispatchReceiver = irGet(inductionVariable) dispatchReceiver = progressionType.coerceToUnsigned(irGet(inductionVariable), symbols)
putValueArgument(0, lastExpression) putValueArgument(0, progressionType.coerceToUnsigned(lastExpression, symbols))
}) })
putValueArgument(1, irInt(0)) putValueArgument(1, irInt(0))
} }
@@ -284,7 +264,7 @@ internal class ProgressionLoopHeader(
else else
listOfNotNull(inductionVariable, lastVariableIfCanCacheLast) listOfNotNull(inductionVariable, lastVariableIfCanCacheLast)
) + ) +
listOfNotNull(stepVariable, stepVariableForIncrement) listOfNotNull(stepVariable)
private var loopVariable: IrVariable? = null private var loopVariable: IrVariable? = null
@@ -303,7 +283,7 @@ internal class ProgressionLoopHeader(
isMutable = true isMutable = true
) )
} else { } else {
loopVariable?.initializer = irGet(inductionVariable) loopVariable?.initializer = headerInfo.progressionType.coerceToUnsigned(irGet(inductionVariable), symbols)
loopVariable loopVariable
} }
@@ -328,7 +308,7 @@ internal class ProgressionLoopHeader(
// } // }
IrDoWhileLoopImpl(oldLoop.startOffset, oldLoop.endOffset, oldLoop.type, oldLoop.origin).apply { IrDoWhileLoopImpl(oldLoop.startOffset, oldLoop.endOffset, oldLoop.type, oldLoop.origin).apply {
label = oldLoop.label label = oldLoop.label
condition = irNotEquals(irGet(loopVariable!!), lastExpression) condition = irNotEquals(headerInfo.progressionType.coerceToSigned(irGet(loopVariable!!), symbols), lastExpression)
body = newBody body = newBody
} }
} else { } else {
@@ -382,7 +362,7 @@ internal class IndexedGetLoopHeader(
) : NumericForLoopHeader<IndexedGetHeaderInfo>(headerInfo, builder, context, isLastInclusive = false) { ) : NumericForLoopHeader<IndexedGetHeaderInfo>(headerInfo, builder, context, isLastInclusive = false) {
override val loopInitStatements = override val loopInitStatements =
listOfNotNull(headerInfo.objectVariable, inductionVariable, lastVariableIfCanCacheLast, stepVariable, stepVariableForIncrement) listOfNotNull(headerInfo.objectVariable, inductionVariable, lastVariableIfCanCacheLast, stepVariable)
override fun initializeIteration( override fun initializeIteration(
loopVariable: IrVariable?, loopVariable: IrVariable?,
@@ -17,12 +17,10 @@ import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
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
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.types.asSimpleType
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
import kotlin.math.absoluteValue import kotlin.math.absoluteValue
@@ -148,29 +146,14 @@ internal class UntilHandler(private val context: CommonBackendContext, private v
val untilArgExpression = if (untilArgVar == null) untilArgCasted else irGet(untilArgVar) val untilArgExpression = if (untilArgVar == null) untilArgCasted else irGet(untilArgVar)
val last = untilArgExpression.decrement() val last = untilArgExpression.decrement()
// Type of MIN_VALUE constant is signed even for unsigned progressions since the bounds are signed.
val (minValueAsLong, minValueIrConst) = val (minValueAsLong, minValueIrConst) =
when (data) { when (data) {
ProgressionType.INT_PROGRESSION -> Pair(Int.MIN_VALUE.toLong(), irInt(Int.MIN_VALUE)) ProgressionType.INT_PROGRESSION -> Pair(Int.MIN_VALUE.toLong(), irInt(Int.MIN_VALUE))
ProgressionType.CHAR_PROGRESSION -> Pair(Char.MIN_VALUE.toLong(), irChar(Char.MIN_VALUE)) ProgressionType.CHAR_PROGRESSION -> Pair(Char.MIN_VALUE.toLong(), irChar(Char.MIN_VALUE))
ProgressionType.LONG_PROGRESSION -> Pair(Long.MIN_VALUE, irLong(Long.MIN_VALUE)) ProgressionType.LONG_PROGRESSION -> Pair(Long.MIN_VALUE, irLong(Long.MIN_VALUE))
ProgressionType.UINT_PROGRESSION -> Pair( ProgressionType.UINT_PROGRESSION -> Pair(UInt.MIN_VALUE.toLong(), irInt(UInt.MIN_VALUE.toInt()))
UInt.MIN_VALUE.toLong(), ProgressionType.ULONG_PROGRESSION -> Pair(ULong.MIN_VALUE.toLong(), irLong(ULong.MIN_VALUE.toLong()))
IrConstImpl.int(
startOffset,
endOffset,
symbols.uInt!!.defaultType,
UInt.MIN_VALUE.toInt()
)
)
ProgressionType.ULONG_PROGRESSION -> Pair(
ULong.MIN_VALUE.toLong(),
IrConstImpl.long(
startOffset,
endOffset,
symbols.uLong!!.defaultType,
ULong.MIN_VALUE.toLong()
)
)
} }
val additionalNotEmptyCondition = untilArg.constLongValue.let { val additionalNotEmptyCondition = untilArg.constLongValue.let {
when { when {
@@ -496,22 +479,43 @@ internal class StepHandler(
// - getProgressionLastElement(ULong, ULong, Long): ULong // Used by ULongProgression (uses Long step) // - getProgressionLastElement(ULong, ULong, Long): ULong // Used by ULongProgression (uses Long step)
// //
// We make sure to retrieve the correct symbol and use the correct argument types. // We make sure to retrieve the correct symbol and use the correct argument types.
val returnTypeClassifier = if (progressionType.isUnsigned) { return with(progressionType) {
progressionType.elementClassifier(symbols) val returnTypeClassifier = if (progressionType.isUnsigned) {
} else { progressionType.elementClassifier(symbols)
progressionType.stepClassifier(context.irBuiltIns)
}
val getProgressionLastElementFun = symbols.getProgressionLastElementByReturnType[returnTypeClassifier]
?: throw IllegalArgumentException("No `getProgressionLastElement` for return type ${returnTypeClassifier.defaultType}")
return irCall(getProgressionLastElementFun).apply {
if (progressionType.isUnsigned) {
putValueArgument(0, progressionType.castElementIfNecessary(first.deepCopyWithSymbols(), this@StepHandler.context))
putValueArgument(1, progressionType.castElementIfNecessary(last.deepCopyWithSymbols(), this@StepHandler.context))
} else { } else {
putValueArgument(0, progressionType.castStepIfNecessary(first.deepCopyWithSymbols(), this@StepHandler.context)) progressionType.stepClassifier(context.irBuiltIns)
putValueArgument(1, progressionType.castStepIfNecessary(last.deepCopyWithSymbols(), this@StepHandler.context)) }
val getProgressionLastElementFun = symbols.getProgressionLastElementByReturnType[returnTypeClassifier]
?: throw IllegalArgumentException("No `getProgressionLastElement` for return type ${returnTypeClassifier.defaultType}")
val call = irCall(getProgressionLastElementFun).apply {
if (isUnsigned) {
putValueArgument(
0,
coerceToUnsigned(
castElementIfNecessary(first.deepCopyWithSymbols(), this@StepHandler.context),
symbols
)
)
putValueArgument(
1,
coerceToUnsigned(
castElementIfNecessary(last.deepCopyWithSymbols(), this@StepHandler.context),
symbols
)
)
} else {
putValueArgument(0, castStepIfNecessary(first.deepCopyWithSymbols(), this@StepHandler.context))
putValueArgument(1, castStepIfNecessary(last.deepCopyWithSymbols(), this@StepHandler.context))
}
putValueArgument(2, castStepIfNecessary(step.deepCopyWithSymbols(), this@StepHandler.context))
}
if (isUnsigned) {
// Bounds are signed for unsigned progressions.
coerceToSigned(call, symbols)
} else {
call
} }
putValueArgument(2, progressionType.castStepIfNecessary(step.deepCopyWithSymbols(), this@StepHandler.context))
} }
} }
} }
@@ -507,7 +507,7 @@ class JvmSymbols(
javaLangClass.functionByName("desiredAssertionStatus") javaLangClass.functionByName("desiredAssertionStatus")
} }
val unsafeCoerceIntrinsic: IrSimpleFunctionSymbol = override val unsafeCoerceIntrinsic: IrSimpleFunctionSymbol =
buildFun { buildFun {
name = Name.special("<unsafe-coerce>") name = Name.special("<unsafe-coerce>")
origin = IrDeclarationOrigin.IR_BUILTINS_STUB origin = IrDeclarationOrigin.IR_BUILTINS_STUB
@@ -35,4 +35,6 @@ fun box(): String {
// 1 INVOKESTATIC kotlin/internal/UProgressionUtilKt.getProgressionLastElement // 1 INVOKESTATIC kotlin/internal/UProgressionUtilKt.getProgressionLastElement
// 0 NEW java/lang/IllegalArgumentException // 0 NEW java/lang/IllegalArgumentException
// 0 ATHROW // 0 ATHROW
// 0 IF // 0 IF
// 0 INVOKESTATIC kotlin/UInt.constructor-impl
// 0 INVOKE\w+ kotlin/UInt.(un)?box-impl
@@ -16,4 +16,6 @@ fun f(a: UInt): Int {
// 0 getLast // 0 getLast
// 0 getStep // 0 getStep
// 1 INVOKESTATIC kotlin/UnsignedKt.uintCompare // 1 INVOKESTATIC kotlin/UnsignedKt.uintCompare
// 2 IF // 2 IF
// 0 INVOKESTATIC kotlin/UInt.constructor-impl
// 0 INVOKE\w+ kotlin/UInt.(un)?box-impl
@@ -16,4 +16,6 @@ fun f(a: ULong): Int {
// 0 getLast // 0 getLast
// 0 getStep // 0 getStep
// 1 INVOKESTATIC kotlin/UnsignedKt.ulongCompare // 1 INVOKESTATIC kotlin/UnsignedKt.ulongCompare
// 2 IF // 2 IF
// 0 INVOKESTATIC kotlin/ULong.constructor-impl
// 0 INVOKE\w+ kotlin/ULong.(un)?box-impl
@@ -56,3 +56,5 @@ fun testULongDownTo(a: ULong, b: ULong): Int {
// 0 getFirst // 0 getFirst
// 0 getLast // 0 getLast
// 0 getStep // 0 getStep
// 0 INVOKESTATIC kotlin/U(Int|Long).constructor-impl
// 0 INVOKE\w+ kotlin/U(Int|Long).(un)?box-impl
@@ -1,3 +1,4 @@
// WITH_RUNTIME
const val M = UInt.MAX_VALUE const val M = UInt.MAX_VALUE
fun f(a: UInt): Int { fun f(a: UInt): Int {
@@ -15,4 +16,6 @@ fun f(a: UInt): Int {
// 0 getLast // 0 getLast
// 0 getStep // 0 getStep
// 1 INVOKESTATIC kotlin/UnsignedKt.uintCompare // 1 INVOKESTATIC kotlin/UnsignedKt.uintCompare
// 2 IF // 2 IF
// 0 INVOKESTATIC kotlin/UInt.constructor-impl
// 0 INVOKE\w+ kotlin/UInt.(un)?box-impl
@@ -16,4 +16,6 @@ fun f(a: ULong): Int {
// 0 getLast // 0 getLast
// 0 getStep // 0 getStep
// 1 INVOKESTATIC kotlin/UnsignedKt.ulongCompare // 1 INVOKESTATIC kotlin/UnsignedKt.ulongCompare
// 2 IF // 2 IF
// 0 INVOKESTATIC kotlin/ULong.constructor-impl
// 0 INVOKE\w+ kotlin/ULong.(un)?box-impl
@@ -18,6 +18,8 @@ fun f(a: UInt): Int {
// 0 getFirst // 0 getFirst
// 0 getLast // 0 getLast
// 0 getStep // 0 getStep
// 0 INVOKESTATIC kotlin/UInt.constructor-impl
// 0 INVOKE\w+ kotlin/UInt.(un)?box-impl
// JVM_TEMPLATES // JVM_TEMPLATES
// 1 INVOKESTATIC kotlin/UnsignedKt.uintCompare // 1 INVOKESTATIC kotlin/UnsignedKt.uintCompare
@@ -18,6 +18,8 @@ fun f(a: UInt): Int {
// 0 getFirst // 0 getFirst
// 0 getLast // 0 getLast
// 0 getStep // 0 getStep
// 0 INVOKESTATIC kotlin/UInt.constructor-impl
// 0 INVOKE\w+ kotlin/UInt.(un)?box-impl
// JVM_TEMPLATES // JVM_TEMPLATES
// 1 IF // 1 IF
@@ -18,6 +18,8 @@ fun f(a: ULong): Int {
// 0 getFirst // 0 getFirst
// 0 getLast // 0 getLast
// 0 getStep // 0 getStep
// 0 INVOKESTATIC kotlin/ULong.constructor-impl
// 0 INVOKE\w+ kotlin/ULong.(un)?box-impl
// JVM_TEMPLATES // JVM_TEMPLATES
// 1 INVOKESTATIC kotlin/UnsignedKt.ulongCompare // 1 INVOKESTATIC kotlin/UnsignedKt.ulongCompare
@@ -18,6 +18,8 @@ fun f(a: ULong): Int {
// 0 getFirst // 0 getFirst
// 0 getLast // 0 getLast
// 0 getStep // 0 getStep
// 0 INVOKESTATIC kotlin/ULong.constructor-impl
// 0 INVOKE\w+ kotlin/ULong.(un)?box-impl
// JVM_TEMPLATES // JVM_TEMPLATES
// 1 IF // 1 IF
@@ -1,17 +1,17 @@
// TARGET_BACKEND: JVM_IR // TARGET_BACKEND: JVM_IR
// WITH_RUNTIME // WITH_RUNTIME
fun testUByteUntilUByte(a: UByte, b: UByte): UInt { fun testUByteUntilUByte(a: UByte, b: UByte): Int {
var sum = 0u var sum = 0
for (i in a until b) { for (i in a until b) {
sum = sum * 10u + i sum += i.toInt()
} }
return sum return sum
} }
fun testUShortUntilUShort(a: UShort, b: UShort): UInt { fun testUShortUntilUShort(a: UShort, b: UShort): Int {
var sum = 0u var sum = 0
for (i in a until b) { for (i in a until b) {
sum = sum * 10u + i sum += i.toInt()
} }
return sum return sum
} }
@@ -31,4 +31,6 @@ fun testUShortUntilUShort(a: UShort, b: UShort): UInt {
// 0 getStep // 0 getStep
// 2 IFGT // 2 IFGT
// 2 IFLE // 2 IFLE
// 4 IF // 4 IF
// 0 INVOKESTATIC kotlin/UInt.constructor-impl
// 0 INVOKE\w+ kotlin/UInt.(un)?box-impl
@@ -38,4 +38,6 @@ fun box(): String {
// 1 NEW java/lang/IllegalArgumentException // 1 NEW java/lang/IllegalArgumentException
// 1 ATHROW // 1 ATHROW
// 0 IF // 0 IF
// 0 ARETURN // 0 ARETURN
// 0 INVOKESTATIC kotlin/UInt.constructor-impl
// 0 INVOKE\w+ kotlin/UInt.(un)?box-impl
@@ -40,4 +40,6 @@ fun box(): String {
// 0 ATHROW // 0 ATHROW
// 1 IFGT // 1 IFGT
// 1 IF_ICMPNE // 1 IF_ICMPNE
// 2 IF // 2 IF
// 0 INVOKESTATIC kotlin/UInt.constructor-impl
// 0 INVOKE\w+ kotlin/UInt.(un)?box-impl
@@ -50,4 +50,6 @@ fun box(): String {
// 3 IFLE // 3 IFLE
// 1 IFGE // 1 IFGE
// 6 IF // 6 IF
// 0 INEG // 0 INEG
// 0 INVOKESTATIC kotlin/UInt.constructor-impl
// 0 INVOKE\w+ kotlin/UInt.(un)?box-impl
@@ -54,4 +54,6 @@ fun box(): String {
// 4 IFLE // 4 IFLE
// 1 IFGE // 1 IFGE
// 7 IF // 7 IF
// 1 INEG // 1 INEG
// 0 INVOKESTATIC kotlin/UInt.constructor-impl
// 0 INVOKE\w+ kotlin/UInt.(un)?box-impl
@@ -42,4 +42,6 @@ fun box(): String {
// 1 INVOKESTATIC kotlin/UnsignedKt.uintCompare // 1 INVOKESTATIC kotlin/UnsignedKt.uintCompare
// 1 IFGT // 1 IFGT
// 1 IF_ICMPNE // 1 IF_ICMPNE
// 2 IF // 2 IF
// 0 INVOKESTATIC kotlin/UInt.constructor-impl
// 0 INVOKE\w+ kotlin/UInt.(un)?box-impl
@@ -42,4 +42,6 @@ fun box(): String {
// 1 IFEQ // 1 IFEQ
// 1 IFGT // 1 IFGT
// 1 IF_ICMPNE // 1 IF_ICMPNE
// 3 IF // 3 IF
// 0 INVOKESTATIC kotlin/UInt.constructor-impl
// 0 INVOKE\w+ kotlin/UInt.(un)?box-impl