[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.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.
@@ -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)
}
}
}
}
@@ -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)
@@ -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")