Get rid of redundant boxing of unsigned operands of infix 'compareTo'

^KT-48759: Fixed
This commit is contained in:
Vladislav Grechko
2022-12-01 22:44:13 +01:00
committed by teamcity
parent 7423b35741
commit cb93e9d408
4 changed files with 48 additions and 13 deletions
@@ -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 {
@@ -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
}
}
@@ -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
@@ -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 {