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());