Get rid of redundant boxing of unsigned operands of infix 'compareTo'
^KT-48759: Fixed
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 08e0c13..d09b673 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
@@ -21438,6 +21438,12 @@
}
@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 {
runTest("compiler/testData/codegen/box/inlineClasses/initBlock.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
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 07a8caf..f8eb2a6 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.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 @@
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 @@
("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 @@
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 0000000..875af02
--- /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 4ca22c2..18ed119 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
@@ -21438,6 +21438,12 @@
}
@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 {
runTest("compiler/testData/codegen/box/inlineClasses/initBlock.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());