[JVM_IR] Use ifne and ifeq for integer zero comparisons.
This commit is contained in:
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
|
|||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.org.objectweb.asm.Label
|
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.Type
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
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) {
|
class BooleanComparison(val op: IElementType, val a: MaterialValue, val b: MaterialValue) : BooleanValue(a.codegen) {
|
||||||
override fun jumpIfFalse(target: Label) {
|
override fun jumpIfFalse(target: Label) {
|
||||||
// TODO 1. get rid of the dependency; 2. take `b.type` into account.
|
// TODO 1. get rid of the dependency; 2. take `b.type` into account.
|
||||||
|
|||||||
@@ -14,17 +14,15 @@ import org.jetbrains.kotlin.codegen.AsmUtil.genAreEqualCall
|
|||||||
import org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive
|
import org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive
|
||||||
import org.jetbrains.kotlin.codegen.StackValue
|
import org.jetbrains.kotlin.codegen.StackValue
|
||||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
|
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.config.LanguageFeature
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
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.classOrNull
|
||||||
import org.jetbrains.kotlin.ir.types.isNullable
|
import org.jetbrains.kotlin.ir.types.isNullable
|
||||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||||
import org.jetbrains.kotlin.ir.util.isEnumClass
|
import org.jetbrains.kotlin.ir.util.isEnumClass
|
||||||
import org.jetbrains.kotlin.ir.util.isEnumEntry
|
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.ir.util.isNullConst
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
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)
|
MaterialValue(codegen, Type.BOOLEAN_TYPE, codegen.context.irBuiltIns.booleanType)
|
||||||
} else {
|
} else {
|
||||||
val operandType = if (!isPrimitive(leftType)) AsmTypes.OBJECT_TYPE else leftType
|
val operandType = if (!isPrimitive(leftType)) AsmTypes.OBJECT_TYPE else leftType
|
||||||
val aValue = a.accept(codegen, data).materializedAt(operandType, a.type)
|
if (operandType == Type.INT_TYPE && (a.isIntegerConst(0) || b.isIntegerConst(0))) {
|
||||||
val bValue = b.accept(codegen, data).materializedAt(operandType, b.type)
|
val nonZero = if (a.isIntegerConst(0)) b else a
|
||||||
BooleanComparison(operator, aValue, bValue)
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.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 {
|
fun IrExpression.coerceToUnit(builtins: IrBuiltIns): IrExpression {
|
||||||
val valueType = getKotlinType(this)
|
val valueType = getKotlinType(this)
|
||||||
return coerceToUnitIfNeeded(valueType, builtins)
|
return coerceToUnitIfNeeded(valueType, builtins)
|
||||||
|
|||||||
@@ -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) {
|
fun test(a: Int, b: Int, c: Int) {
|
||||||
when (0) {
|
when (0) {
|
||||||
a -> throw IllegalArgumentException("a is 0")
|
a -> throw IllegalArgumentException("a is 0")
|
||||||
|
|||||||
Reference in New Issue
Block a user