diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/CompareTo.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/CompareTo.kt index c3eeb91ae4c..35cace169f4 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/CompareTo.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/CompareTo.kt @@ -32,6 +32,7 @@ import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.org.objectweb.asm.Label +import org.jetbrains.org.objectweb.asm.Opcodes import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter @@ -67,6 +68,20 @@ object CompareTo : IntrinsicMethod() { } } +class IntegerZeroComparison(val op: IElementType, val a: MaterialValue): BooleanValue(a.codegen) { + override fun jumpIfFalse(target: Label) { + mv.visitJumpInsn(Opcodes.IFNE, target) + } + + override fun jumpIfTrue(target: Label) { + mv.visitJumpInsn(Opcodes.IFEQ, target) + } + + override fun discard() { + a.discard() + } +} + class BooleanComparison(val op: IElementType, val a: MaterialValue, val b: MaterialValue) : BooleanValue(a.codegen) { override fun jumpIfFalse(target: Label) { // TODO 1. get rid of the dependency; 2. take `b.type` into account. diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Equals.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Equals.kt index 6200c88d464..586e6e90df9 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Equals.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Equals.kt @@ -14,17 +14,15 @@ import org.jetbrains.kotlin.codegen.AsmUtil.genAreEqualCall import org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive import org.jetbrains.kotlin.codegen.StackValue import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods -import org.jetbrains.kotlin.codegen.pseudoInsns.fakeAlwaysFalseIfeq -import org.jetbrains.kotlin.codegen.pseudoInsns.fakeAlwaysTrueIfeq import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin -import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.classOrNull import org.jetbrains.kotlin.ir.types.isNullable import org.jetbrains.kotlin.ir.types.toKotlinType import org.jetbrains.kotlin.ir.util.isEnumClass import org.jetbrains.kotlin.ir.util.isEnumEntry +import org.jetbrains.kotlin.ir.util.isIntegerConst import org.jetbrains.kotlin.ir.util.isNullConst import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.resolve.jvm.AsmTypes @@ -97,9 +95,14 @@ class Equals(val operator: IElementType) : IntrinsicMethod() { MaterialValue(codegen, Type.BOOLEAN_TYPE, codegen.context.irBuiltIns.booleanType) } else { val operandType = if (!isPrimitive(leftType)) AsmTypes.OBJECT_TYPE else leftType - val aValue = a.accept(codegen, data).materializedAt(operandType, a.type) - val bValue = b.accept(codegen, data).materializedAt(operandType, b.type) - BooleanComparison(operator, aValue, bValue) + if (operandType == Type.INT_TYPE && (a.isIntegerConst(0) || b.isIntegerConst(0))) { + val nonZero = if (a.isIntegerConst(0)) b else a + IntegerZeroComparison(operator, nonZero.accept(codegen, data).materializedAt(operandType, nonZero.type)) + } else { + val aValue = a.accept(codegen, data).materializedAt(operandType, a.type) + val bValue = b.accept(codegen, data).materializedAt(operandType, b.type) + BooleanComparison(operator, aValue, bValue) + } } } } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt index 503c227fda3..353d4e15b71 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt @@ -154,6 +154,8 @@ fun IrExpression.isTrueConst() = this is IrConst<*> && this.kind == IrConstKind. fun IrExpression.isFalseConst() = this is IrConst<*> && this.kind == IrConstKind.Boolean && this.value == false +fun IrExpression.isIntegerConst(value: Int) = this is IrConst<*> && this.kind == IrConstKind.Int && this.value == value + fun IrExpression.coerceToUnit(builtins: IrBuiltIns): IrExpression { val valueType = getKotlinType(this) return coerceToUnitIfNeeded(valueType, builtins) diff --git a/compiler/testData/codegen/bytecodeText/when/whenZero.kt b/compiler/testData/codegen/bytecodeText/when/whenZero.kt index 97620cd2f50..33382844547 100644 --- a/compiler/testData/codegen/bytecodeText/when/whenZero.kt +++ b/compiler/testData/codegen/bytecodeText/when/whenZero.kt @@ -1,6 +1,3 @@ -// IGNORE_BACKEND: JVM_IR -// TODO KT-36841 Generate integer comparison with 0 instructions (IFNE, etc) when comparing integers with 0 in JVM_IR - fun test(a: Int, b: Int, c: Int) { when (0) { a -> throw IllegalArgumentException("a is 0")