From cb93e9d40812dc12612c81af7bf1bb4005858452 Mon Sep 17 00:00:00 2001 From: Vladislav Grechko Date: Thu, 1 Dec 2022 22:44:13 +0100 Subject: [PATCH] Get rid of redundant boxing of unsigned operands of infix 'compareTo' ^KT-48759: Fixed --- .../FirBlackBoxCodegenTestGenerated.java | 6 ++++ .../backend/jvm/lower/JvmBuiltInsLowering.kt | 33 +++++++++++-------- .../infixCompareToOptimization.kt | 16 +++++++++ .../IrBlackBoxCodegenTestGenerated.java | 6 ++++ 4 files changed, 48 insertions(+), 13 deletions(-) create mode 100644 compiler/testData/codegen/box/inlineClasses/infixCompareToOptimization.kt diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index 08e0c133ba1..d09b6737810 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -21437,6 +21437,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/inlineClasses/implicitCastToNonValueClassType.kt"); } + @Test + @TestMetadata("infixCompareToOptimization.kt") + public void testInfixCompareToOptimization() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/infixCompareToOptimization.kt"); + } + @Test @TestMetadata("initBlock.kt") public void testInitBlock() throws Exception { diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmBuiltInsLowering.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmBuiltInsLowering.kt index 07a8caff4fe..f8eb2a6acae 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmBuiltInsLowering.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmBuiltInsLowering.kt @@ -17,9 +17,7 @@ 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.IrSimpleFunctionSymbol -import org.jetbrains.kotlin.ir.types.IrType -import org.jetbrains.kotlin.ir.types.isInt -import org.jetbrains.kotlin.ir.types.isLong +import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.dump import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization import org.jetbrains.kotlin.ir.util.render @@ -42,6 +40,13 @@ class JvmBuiltInsLowering(val context: JvmBackendContext) : FileLoweringPass { if (context.state.target >= JvmTarget.JVM_1_8) { val parentClassName = callee.parent.fqNameForIrSerialization.asString() val functionName = callee.name.asString() + if (parentClassName == "kotlin.CompareToKt" && functionName == "compareTo") { + val operandType = expression.getValueArgument(0)!!.type + when { + operandType.isUInt() -> return expression.replaceWithCallTo(context.ir.symbols.compareUnsignedInt) + operandType.isULong() -> return expression.replaceWithCallTo(context.ir.symbols.compareUnsignedLong) + } + } val jvm8Replacement = jvm8builtInReplacements[parentClassName to functionName] if (jvm8Replacement != null) { return expression.replaceWithCallTo(jvm8Replacement) @@ -76,8 +81,8 @@ class JvmBuiltInsLowering(val context: JvmBackendContext) : FileLoweringPass { ("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. + // Originals are so far only instance methods and extensions, while the replacements are + // statics, so we copy dispatch and extension receivers to a value argument if needed. // If we can't coerce arguments to required types, keep original expression (see below). private fun IrCall.replaceWithCallTo(replacement: IrSimpleFunctionSymbol): IrExpression { val expectedType = this.type @@ -90,16 +95,18 @@ class JvmBuiltInsLowering(val context: JvmBackendContext) : FileLoweringPass { replacement ).also { newCall -> var valueArgumentOffset = 0 - this.dispatchReceiver?.let { - val coercedDispatchReceiver = it.coerceIfPossible(replacement.owner.valueParameters[valueArgumentOffset].type) - ?: return this@replaceWithCallTo - newCall.putValueArgument(valueArgumentOffset, coercedDispatchReceiver) - valueArgumentOffset++ + + fun tryToAddCoercedArgument(expr: IrExpression): Boolean { + val coercedExpr = expr.coerceIfPossible(replacement.owner.valueParameters[valueArgumentOffset].type) + ?: return false + newCall.putValueArgument(valueArgumentOffset++, coercedExpr) + return true } + + this.extensionReceiver?.let { if (!tryToAddCoercedArgument(it)) return this@replaceWithCallTo } + this.dispatchReceiver?.let { if (!tryToAddCoercedArgument(it)) return this@replaceWithCallTo } for (index in 0 until valueArgumentsCount) { - val coercedValueArgument = getValueArgument(index)!!.coerceIfPossible(replacement.owner.valueParameters[index].type) - ?: return this@replaceWithCallTo - newCall.putValueArgument(index + valueArgumentOffset, coercedValueArgument) + if (!tryToAddCoercedArgument(getValueArgument(index)!!)) return this@replaceWithCallTo } } diff --git a/compiler/testData/codegen/box/inlineClasses/infixCompareToOptimization.kt b/compiler/testData/codegen/box/inlineClasses/infixCompareToOptimization.kt new file mode 100644 index 00000000000..875af020b54 --- /dev/null +++ b/compiler/testData/codegen/box/inlineClasses/infixCompareToOptimization.kt @@ -0,0 +1,16 @@ +// WITH_STDLIB +// TARGET_BACKEND: JVM_IR + +fun compareUInts(a: UInt, b: UInt) = a compareTo b +fun compareULongs(a: ULong, b: ULong) = a compareTo b + + +fun box(): String { + if (compareUInts(0u, 1u) != -1) return "Fail 1" + if (compareULongs(0u, 1u) != -1) return "Fail 2" + return "OK" +} + +// CHECK_BYTECODE_TEXT +// 0 INVOKESTATIC kotlin/ULong.box-impl +// 0 INVOKESTATIC kotlin/UInt.box-impl diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index 4ca22c23c79..18ed1195550 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -21437,6 +21437,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/inlineClasses/implicitCastToNonValueClassType.kt"); } + @Test + @TestMetadata("infixCompareToOptimization.kt") + public void testInfixCompareToOptimization() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/infixCompareToOptimization.kt"); + } + @Test @TestMetadata("initBlock.kt") public void testInitBlock() throws Exception {