From f0ff8f202cd3d08f4c9d51ca422b3e0169d417d8 Mon Sep 17 00:00:00 2001 From: Kristoffer Andersen Date: Mon, 18 May 2020 09:57:53 +0200 Subject: [PATCH] [JVM IR] Use JVM8 support for unsigned int operations - unmute tests - add test to ensure JVM target is respected - add test to cover smart-casted cases - implement function matching and replacement - Switching on uint constants - introduce lowering for standard library replacements --- .../jetbrains/kotlin/backend/jvm/JvmLower.kt | 2 + .../kotlin/backend/jvm/JvmSymbols.kt | 46 ++++++ .../backend/jvm/codegen/SwitchGenerator.kt | 140 +++++++++++++++--- .../jvm/lower/JvmInlineClassLowering.kt | 3 +- .../jvm/lower/JvmOptimizationLowering.kt | 4 +- .../JvmStandardLibraryBuiltInsLowering.kt | 90 +++++++++++ .../unsignedIntCompare_before.kt | 15 ++ .../unsignedTypes/unsignedIntCompare_jvm18.kt | 2 - .../unsignedTypes/unsignedIntDivide_jvm18.kt | 2 - .../unsignedIntRemainder_jvm18.kt | 2 - .../unsignedIntSmartCasts_jvm18.kt | 7 + .../unsignedIntToString_jvm18.kt | 2 - .../unsignedLongCompare_jvm18.kt | 2 - .../unsignedTypes/unsignedLongDivide_jvm18.kt | 2 - .../unsignedLongRemainder_jvm18.kt | 2 - .../unsignedLongToString_jvm18.kt | 2 - .../unsignedTypes/whenByUnsigned.kt | 2 - .../codegen/BytecodeTextTestGenerated.java | 10 ++ .../ir/IrBytecodeTextTestGenerated.java | 10 ++ 19 files changed, 302 insertions(+), 43 deletions(-) create mode 100644 compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmStandardLibraryBuiltInsLowering.kt create mode 100644 compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntCompare_before.kt create mode 100644 compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntSmartCasts_jvm18.kt diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt index 74c30b01427..b81b0921d36 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt @@ -300,6 +300,8 @@ private val jvmFilePhases = anonymousObjectSuperConstructorPhase then tailrecPhase then + jvmStandardLibraryBuiltInsPhase then + forLoopsPhase then jvmInlineClassPhase then diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmSymbols.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmSymbols.kt index 79b4770c0e8..e817e1624fa 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmSymbols.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmSymbols.kt @@ -616,6 +616,52 @@ class JvmSymbols( } } + private val javaLangInteger: IrClassSymbol = createClass(FqName("java.lang.Integer")) { klass -> + klass.addFunction("compareUnsigned", irBuiltIns.intType, isStatic = true).apply { + addValueParameter("x", irBuiltIns.intType) + addValueParameter("y", irBuiltIns.intType) + } + klass.addFunction("divideUnsigned", irBuiltIns.intType, isStatic = true).apply { + addValueParameter("dividend", irBuiltIns.intType) + addValueParameter("divisor", irBuiltIns.intType) + } + klass.addFunction("remainderUnsigned", irBuiltIns.intType, isStatic = true).apply { + addValueParameter("dividend", irBuiltIns.intType) + addValueParameter("divisor", irBuiltIns.intType) + } + klass.addFunction("toUnsignedString", irBuiltIns.stringType, isStatic = true).apply { + addValueParameter("i", irBuiltIns.intType) + } + } + + val compareUnsignedInt: IrSimpleFunctionSymbol = javaLangInteger.functionByName("compareUnsigned") + val divideUnsignedInt: IrSimpleFunctionSymbol = javaLangInteger.functionByName("divideUnsigned") + val remainderUnsignedInt: IrSimpleFunctionSymbol = javaLangInteger.functionByName("remainderUnsigned") + val toUnsignedStringInt: IrSimpleFunctionSymbol = javaLangInteger.functionByName("toUnsignedString") + + private val javaLangLong: IrClassSymbol = createClass(FqName("java.lang.Long")) { klass -> + klass.addFunction("compareUnsigned", irBuiltIns.intType, isStatic = true).apply { + addValueParameter("x", irBuiltIns.longType) + addValueParameter("y", irBuiltIns.longType) + } + klass.addFunction("divideUnsigned", irBuiltIns.longType, isStatic = true).apply { + addValueParameter("dividend", irBuiltIns.longType) + addValueParameter("divisor", irBuiltIns.longType) + } + klass.addFunction("remainderUnsigned", irBuiltIns.longType, isStatic = true).apply { + addValueParameter("dividend", irBuiltIns.longType) + addValueParameter("divisor", irBuiltIns.longType) + } + klass.addFunction("toUnsignedString", irBuiltIns.stringType, isStatic = true).apply { + addValueParameter("i", irBuiltIns.longType) + } + } + + val compareUnsignedLong: IrSimpleFunctionSymbol = javaLangLong.functionByName("compareUnsigned") + val divideUnsignedLong: IrSimpleFunctionSymbol = javaLangLong.functionByName("divideUnsigned") + val remainderUnsignedLong: IrSimpleFunctionSymbol = javaLangLong.functionByName("remainderUnsigned") + val toUnsignedStringLong: IrSimpleFunctionSymbol = javaLangLong.functionByName("toUnsignedString") + val systemArraycopy: IrSimpleFunctionSymbol = systemClass.functionByName("arraycopy") val signatureStringIntrinsic: IrSimpleFunctionSymbol = diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/SwitchGenerator.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/SwitchGenerator.kt index 7ee9378cdf7..3dd3b57a181 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/SwitchGenerator.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/SwitchGenerator.kt @@ -43,48 +43,125 @@ class SwitchGenerator(private val expression: IrWhen, private val data: BlockInf val calls = callToLabels.map { it.call } - // Checks if all conditions are CALL EQEQ(tmp_variable, some_constant) - if (!areConstComparisons(calls)) - return null + // To generate a switch from a when it must be a comparison of a single + // variable, the "subject", against a series of constants. We assume the + // subject is the left hand side of the first condition, provided the + // first condition is a comparison. If the first condition is of the form: + // + // CALL EQEQ((var),_) + // + // we must be trying to generate an _unsigned_ int switch, and need to + // account for unsafe-coerce in all comparisons that arise from the + // wrapping and unwrapping of the UInt inline class wrapper. Otherwise, + // this is a primitive Int or String switch, with a condition of the form + // + // CALL EQEQ(var,_) - // Subject should be the same for all conditions. Let's pick the first. - val subject = callToLabels[0].call.getValueArgument(0)!! as IrGetValue + val firstCondition = callToLabels[0].call + if (firstCondition.symbol != codegen.classCodegen.context.irBuiltIns.eqeqSymbol) return null + val subject = firstCondition.getValueArgument(0) + return when { + subject is IrCall && subject.isCoerceFromUIntToInt() -> + generateUIntSwitch(subject.getValueArgument(0)!! as? IrGetValue, calls, callToLabels, expressionToLabels, elseExpression) + subject is IrGetValue -> + generatePrimitiveSwitch(subject, calls, callToLabels, expressionToLabels, elseExpression) + else -> + null + }?.genOptimizedIfEnoughCases() + } - // Don't generate repeated cases, which are unreachable but allowed in Kotlin. - // Only keep the first encountered case: - val cases = - callToLabels.map { ValueToLabel((it.call.getValueArgument(1) as IrConst<*>).value, it.label) }.distinctBy { it.value } + fun IrCall.isCoerceFromUIntToInt(): Boolean = + symbol == codegen.classCodegen.context.ir.symbols.unsafeCoerceIntrinsic + && getTypeArgument(0)?.isUInt() == true + && getTypeArgument(1)?.isInt() == true - // Remove labels and "then expressions" that are not reachable. - val reachableLabels = HashSet(cases.map { it.label }) - expressionToLabels.removeIf { it.label !in reachableLabels } + private fun generateUIntSwitch( + subject: IrGetValue?, + conditions: List, + callToLabels: ArrayList, + expressionToLabels: ArrayList, + elseExpression: IrExpression? + ): Switch? { + if (subject == null) return null + // We check that all conditions are of the form + // CALL EQEQ ((subject), + // ( Constant )) + if (!areConstUIntComparisons(conditions)) return null + + // Filter repeated cases. Allowed in Kotlin but unreachable. + val cases = callToLabels.map { + val constCoercion = it.call.getValueArgument(1)!! as IrCall + val constValue = (constCoercion.getValueArgument(0) as IrConst<*>).value + ValueToLabel( + constValue, + it.label + ) + }.distinctBy { it.value } + + expressionToLabels.removeUnreachableLabels(cases) + + return IntSwitch( + subject, + elseExpression, + expressionToLabels, + cases + ) + } + + private fun generatePrimitiveSwitch( + subject: IrGetValue, + conditions: List, + callToLabels: ArrayList, + expressionToLabels: ArrayList, + elseExpression: IrExpression? + ): Switch? { + // Checks if all conditions are CALL EQEQ(var,constant) + if (!areConstantComparisons(conditions)) return null return when { - areConstIntComparisons(calls) -> + areConstIntComparisons(conditions) -> { + val cases = extractSwitchCasesAndFilterUnreachableLabels(callToLabels, expressionToLabels) IntSwitch( subject, elseExpression, expressionToLabels, cases ) - areConstStringComparisons(calls) -> + } + areConstStringComparisons(conditions) -> { + val cases = extractSwitchCasesAndFilterUnreachableLabels(callToLabels, expressionToLabels) StringSwitch( subject, elseExpression, expressionToLabels, cases ) - else -> null // TODO: Enum, etc. - }?.genOptimizedIfEnoughCases() + } + else -> + null + } } - private fun areConstComparisons(conditions: List): Boolean { - // All branches must be CALL 'EQEQ(Any?, Any?)': Boolean - if (conditions.any { it.symbol != codegen.classCodegen.context.irBuiltIns.eqeqSymbol }) - return false + // Check that all conditions are of the form + // + // CALL EQEQ ((subject), ( Constant )) + // + // where subject is taken to be the first variable compared on the left hand side, if any. + private fun areConstUIntComparisons(conditions: List): Boolean { + val lhs = conditions.map { it.takeIf { it.symbol == codegen.context.irBuiltIns.eqeqSymbol }?.getValueArgument(0) as? IrCall } + if (lhs.any { it == null || !it.isCoerceFromUIntToInt() }) return false + val lhsVariableAccesses = lhs.map { it!!.getValueArgument(0) as? IrGetValue } + if (lhsVariableAccesses.any { it == null || it.symbol != lhsVariableAccesses[0]!!.symbol }) return false - // All LHS refer to the same tmp variable. - val lhs = conditions.map { it.getValueArgument(0) as? IrGetValue } + val rhs = conditions.map { it.getValueArgument(1) as? IrCall } + if (rhs.any { it == null || !it.isCoerceFromUIntToInt() || it.getValueArgument(0) !is IrConst<*> }) return false + + return true + } + + private fun areConstantComparisons(conditions: List): Boolean { + // All conditions are equality checks && all LHS refer to the same tmp variable. + val lhs = conditions.map { it.takeIf { it.symbol == codegen.context.irBuiltIns.eqeqSymbol }?.getValueArgument(0) as? IrGetValue } if (lhs.any { it == null || it.symbol != lhs[0]!!.symbol }) return false @@ -122,6 +199,25 @@ class SwitchGenerator(private val expression: IrWhen, private val data: BlockInf return true } + private fun extractSwitchCasesAndFilterUnreachableLabels( + callToLabels: List, + expressionToLabels: ArrayList + ): List { + // Don't generate repeated cases, which are unreachable but allowed in Kotlin. + // Only keep the first encountered case: + val cases = + callToLabels.map { ValueToLabel((it.call.getValueArgument(1) as IrConst<*>).value, it.label) }.distinctBy { it.value } + + expressionToLabels.removeUnreachableLabels(cases) + + return cases + } + + private fun ArrayList.removeUnreachableLabels(cases: List) { + val reachableLabels = HashSet(cases.map { it.label }) + removeIf { it.label !in reachableLabels } + } + // psi2ir lowers multiple cases to nested conditions. For example, // // when (subject) { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmInlineClassLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmInlineClassLowering.kt index caf47ec5443..8cf0cf39a50 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmInlineClassLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmInlineClassLowering.kt @@ -53,7 +53,8 @@ val jvmInlineClassPhase = makeIrFilePhase( name = "Inline Classes", description = "Lower inline classes", // forLoopsPhase may produce UInt and ULong which are inline classes. - prerequisite = setOf(forLoopsPhase) + // standard library replacements are done on the unmangled names for UInt and ULong classes. + prerequisite = setOf(forLoopsPhase, jvmStandardLibraryBuiltInsPhase) ) /** diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmOptimizationLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmOptimizationLowering.kt index 2bc3bdf2055..3916b621fb4 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmOptimizationLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmOptimizationLowering.kt @@ -46,7 +46,7 @@ class JvmOptimizationLowering(val context: JvmBackendContext) : FileLoweringPass dispatchReceiverParameter != null - private fun getOperandsIfCallToEqeqOrEquals(call: IrCall): Pair? = + private fun getOperandsIfCallToEQEQOrEquals(call: IrCall): Pair? = when { call.symbol == context.irBuiltIns.eqeqSymbol -> { val left = call.getValueArgument(0)!! @@ -103,7 +103,7 @@ class JvmOptimizationLowering(val context: JvmBackendContext) : FileLoweringPass return (expression.dispatchReceiver as IrCall).dispatchReceiver!! } - getOperandsIfCallToEqeqOrEquals(expression)?.let { (left, right) -> + getOperandsIfCallToEQEQOrEquals(expression)?.let { (left, right) -> return when { left.isNullConst() && right.isNullConst() -> IrConstImpl.constTrue(expression.startOffset, expression.endOffset, context.irBuiltIns.booleanType) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmStandardLibraryBuiltInsLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmStandardLibraryBuiltInsLowering.kt new file mode 100644 index 00000000000..bcd34f48449 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmStandardLibraryBuiltInsLowering.kt @@ -0,0 +1,90 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.jvm.lower + +import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.config.JvmTarget +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl +import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization +import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid + +internal val jvmStandardLibraryBuiltInsPhase = makeIrFilePhase( + ::JvmStandardLibraryBuiltInsLowering, + name = "JvmStandardLibraryBuiltInsLowering", + description = "Use Java Standard Library implementations of built-ins" +) + +class JvmStandardLibraryBuiltInsLowering(val context: JvmBackendContext) : FileLoweringPass { + + override fun lower(irFile: IrFile) { + if (context.state.target < JvmTarget.JVM_1_8) return + + val transformer = object : IrElementTransformerVoid() { + override fun visitCall(expression: IrCall): IrExpression { + expression.transformChildren(this, null) + + val parentClass = expression.symbol.owner.parent.fqNameForIrSerialization.asString() + val functionName = expression.symbol.owner.name.asString() + Jvm8builtInReplacements[parentClass to functionName]?.let { + return expression.replaceWithCallTo(it) + } + + return expression + } + } + + irFile.transformChildren(transformer, null) + } + + private val Jvm8builtInReplacements = mapOf( + ("kotlin.UInt" to "compareTo") to context.ir.symbols.compareUnsignedInt, + ("kotlin.UInt" to "div") to context.ir.symbols.divideUnsignedInt, + ("kotlin.UInt" to "rem") to context.ir.symbols.remainderUnsignedInt, + ("kotlin.UInt" to "toString") to context.ir.symbols.toUnsignedStringInt, + ("kotlin.ULong" to "compareTo") to context.ir.symbols.compareUnsignedLong, + ("kotlin.ULong" to "div") to context.ir.symbols.divideUnsignedLong, + ("kotlin.ULong" to "rem") to context.ir.symbols.remainderUnsignedLong, + ("kotlin.ULong" to "toString") to context.ir.symbols.toUnsignedStringLong + ) + + // Originals are so far only instance methods, and the replacements are + // statics, so we copy dispatch receivers to a value argument if needed. + private fun IrCall.replaceWithCallTo(replacement: IrFunctionSymbol) = + IrCallImpl( + startOffset, + endOffset, + type, + replacement + ).also { newCall -> + var valueArgumentOffset = 0 + this.dispatchReceiver?.let { + newCall.putValueArgument(valueArgumentOffset, it.coerceTo(replacement.owner.valueParameters[valueArgumentOffset].type)) + valueArgumentOffset++ + } + (0 until valueArgumentsCount).forEach { + newCall.putValueArgument(it + valueArgumentOffset, getValueArgument(it)!!.coerceTo(replacement.owner.valueParameters[it].type)) + } + } + + private fun IrExpression.coerceTo(target: IrType): IrExpression = + IrCallImpl( + startOffset, + endOffset, + target, + context.ir.symbols.unsafeCoerceIntrinsic + ).also { call -> + call.putTypeArgument(0, type) + call.putTypeArgument(1, target) + call.putValueArgument(0, this) + } +} diff --git a/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntCompare_before.kt b/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntCompare_before.kt new file mode 100644 index 00000000000..d08c93ab158 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntCompare_before.kt @@ -0,0 +1,15 @@ +// WITH_RUNTIME + +val ua = 1234U +val ub = 5678U + +fun box(): String { + if (ua.compareTo(ub) > 0) { + throw AssertionError() + } + + return "OK" +} + +// 1 kotlin/UnsignedKt.uintCompare +// 0 INVOKESTATIC java/lang/Integer.compareUnsigned \(II\)I diff --git a/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntCompare_jvm18.kt b/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntCompare_jvm18.kt index d581efd5cb4..f5483dd6bb3 100644 --- a/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntCompare_jvm18.kt +++ b/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntCompare_jvm18.kt @@ -1,7 +1,5 @@ // JVM_TARGET: 1.8 // WITH_RUNTIME -// IGNORE_BACKEND: JVM_IR -// TODO KT-36838 Use potentially intrinsified methods for unsigned available in JDK 1.8+ in JVM_IR val ua = 1234U val ub = 5678U diff --git a/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntDivide_jvm18.kt b/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntDivide_jvm18.kt index 58df5a9128c..6765deea354 100644 --- a/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntDivide_jvm18.kt +++ b/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntDivide_jvm18.kt @@ -1,7 +1,5 @@ // JVM_TARGET: 1.8 // WITH_RUNTIME -// IGNORE_BACKEND: JVM_IR -// TODO KT-36838 Use potentially intrinsified methods for unsigned available in JDK 1.8+ in JVM_IR val ua = 1234U val ub = 5678U diff --git a/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntRemainder_jvm18.kt b/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntRemainder_jvm18.kt index a1c9be6a204..cd5135f232b 100644 --- a/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntRemainder_jvm18.kt +++ b/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntRemainder_jvm18.kt @@ -1,7 +1,5 @@ // JVM_TARGET: 1.8 // WITH_RUNTIME -// IGNORE_BACKEND: JVM_IR -// TODO KT-36838 Use potentially intrinsified methods for unsigned available in JDK 1.8+ in JVM_IR val ua = 1234U val ub = 5678U diff --git a/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntSmartCasts_jvm18.kt b/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntSmartCasts_jvm18.kt new file mode 100644 index 00000000000..d91fe02fcc3 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntSmartCasts_jvm18.kt @@ -0,0 +1,7 @@ +// JVM_TARGET: 1.8 +// WITH_RUNTIME + +fun both(a: Any?, b: Any?) = if (a is UInt && b is UInt) a < b else null!! + +// 1 compareUnsigned +// 0 uintCompare \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntToString_jvm18.kt b/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntToString_jvm18.kt index a5e8b953df3..0f121609524 100644 --- a/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntToString_jvm18.kt +++ b/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntToString_jvm18.kt @@ -1,7 +1,5 @@ // JVM_TARGET: 1.8 // WITH_RUNTIME -// IGNORE_BACKEND: JVM_IR -// TODO KT-36838 Use potentially intrinsified methods for unsigned available in JDK 1.8+ in JVM_IR fun box(): String { val min = 0U.toString() diff --git a/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedLongCompare_jvm18.kt b/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedLongCompare_jvm18.kt index 82dc5abadc5..17f91e0eb87 100644 --- a/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedLongCompare_jvm18.kt +++ b/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedLongCompare_jvm18.kt @@ -1,7 +1,5 @@ // JVM_TARGET: 1.8 // WITH_RUNTIME -// IGNORE_BACKEND: JVM_IR -// TODO KT-36838 Use potentially intrinsified methods for unsigned available in JDK 1.8+ in JVM_IR val ua = 1234UL val ub = 5678UL diff --git a/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedLongDivide_jvm18.kt b/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedLongDivide_jvm18.kt index 4c323b8b16b..795efb5e002 100644 --- a/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedLongDivide_jvm18.kt +++ b/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedLongDivide_jvm18.kt @@ -1,7 +1,5 @@ // JVM_TARGET: 1.8 // WITH_RUNTIME -// IGNORE_BACKEND: JVM_IR -// TODO KT-36838 Use potentially intrinsified methods for unsigned available in JDK 1.8+ in JVM_IR val ua = 1234UL val ub = 5678UL diff --git a/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedLongRemainder_jvm18.kt b/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedLongRemainder_jvm18.kt index 5462747fd51..de7b81bb0ed 100644 --- a/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedLongRemainder_jvm18.kt +++ b/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedLongRemainder_jvm18.kt @@ -1,7 +1,5 @@ // JVM_TARGET: 1.8 // WITH_RUNTIME -// IGNORE_BACKEND: JVM_IR -// TODO KT-36838 Use potentially intrinsified methods for unsigned available in JDK 1.8+ in JVM_IR val ua = 1234UL val ub = 5678UL diff --git a/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedLongToString_jvm18.kt b/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedLongToString_jvm18.kt index acab682c5d7..f52ad28310d 100644 --- a/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedLongToString_jvm18.kt +++ b/compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedLongToString_jvm18.kt @@ -1,7 +1,5 @@ // JVM_TARGET: 1.8 // WITH_RUNTIME -// IGNORE_BACKEND: JVM_IR -// TODO KT-36838 Use potentially intrinsified methods for unsigned available in JDK 1.8+ in JVM_IR fun box(): String { val min = 0UL.toString() diff --git a/compiler/testData/codegen/bytecodeText/unsignedTypes/whenByUnsigned.kt b/compiler/testData/codegen/bytecodeText/unsignedTypes/whenByUnsigned.kt index 452e37241b8..2d3ab0a8e54 100644 --- a/compiler/testData/codegen/bytecodeText/unsignedTypes/whenByUnsigned.kt +++ b/compiler/testData/codegen/bytecodeText/unsignedTypes/whenByUnsigned.kt @@ -1,6 +1,4 @@ // WITH_RUNTIME -// IGNORE_BACKEND: JVM_IR -// TODO KT-36839 Generate 'when' with unsigned subject using TABLESWITCH/LOOKUPSWITCH in JVM_IR const val M1: UInt = 2147483648u diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java index b0ccbd6c106..071ca7d1b71 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java @@ -4483,6 +4483,11 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/unsignedTypes"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); } + @TestMetadata("unsignedIntCompare_before.kt") + public void testUnsignedIntCompare_before() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntCompare_before.kt"); + } + @TestMetadata("unsignedIntCompare_jvm18.kt") public void testUnsignedIntCompare_jvm18() throws Exception { runTest("compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntCompare_jvm18.kt"); @@ -4498,6 +4503,11 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { runTest("compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntRemainder_jvm18.kt"); } + @TestMetadata("unsignedIntSmartCasts_jvm18.kt") + public void testUnsignedIntSmartCasts_jvm18() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntSmartCasts_jvm18.kt"); + } + @TestMetadata("unsignedIntToString_jvm18.kt") public void testUnsignedIntToString_jvm18() throws Exception { runTest("compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntToString_jvm18.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java index 4173b4ec9a3..d53779a2b6b 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java @@ -4441,6 +4441,11 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest { KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/unsignedTypes"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } + @TestMetadata("unsignedIntCompare_before.kt") + public void testUnsignedIntCompare_before() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntCompare_before.kt"); + } + @TestMetadata("unsignedIntCompare_jvm18.kt") public void testUnsignedIntCompare_jvm18() throws Exception { runTest("compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntCompare_jvm18.kt"); @@ -4456,6 +4461,11 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest { runTest("compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntRemainder_jvm18.kt"); } + @TestMetadata("unsignedIntSmartCasts_jvm18.kt") + public void testUnsignedIntSmartCasts_jvm18() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntSmartCasts_jvm18.kt"); + } + @TestMetadata("unsignedIntToString_jvm18.kt") public void testUnsignedIntToString_jvm18() throws Exception { runTest("compiler/testData/codegen/bytecodeText/unsignedTypes/unsignedIntToString_jvm18.kt");