[JVM_IR] Use ifne and ifeq for integer zero comparisons.

This commit is contained in:
Mads Ager
2020-04-23 14:23:40 +02:00
committed by max-kammerer
parent e8a6ddceaa
commit fed6272de4
4 changed files with 26 additions and 9 deletions
@@ -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")