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 35cace169f4..20617cea078 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 @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.backend.jvm.codegen.* import org.jetbrains.kotlin.backend.jvm.ir.isSmartcastFromHigherThanNullable import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.codegen.AsmUtil.comparisonOperandType +import org.jetbrains.kotlin.codegen.AsmUtil.unboxType import org.jetbrains.kotlin.codegen.BranchedValue import org.jetbrains.kotlin.codegen.NumberCompare import org.jetbrains.kotlin.codegen.ObjectCompare @@ -68,7 +69,7 @@ object CompareTo : IntrinsicMethod() { } } -class IntegerZeroComparison(val op: IElementType, val a: MaterialValue): BooleanValue(a.codegen) { +class IntegerZeroComparison(val op: IElementType, val a: MaterialValue) : BooleanValue(a.codegen) { override fun jumpIfFalse(target: Label) { mv.visitJumpInsn(Opcodes.IFNE, target) } @@ -134,6 +135,41 @@ class NonIEEE754FloatComparison(val op: IElementType, val a: MaterialValue, val } } +class PrimitiveToBoxedComparison( + val op: IElementType, + private val boxedValue: MaterialValue, + private val loadOther: () -> MaterialValue +) : BooleanValue(boxedValue.codegen) { + + override fun jumpIfFalse(target: Label) { + val compareLabel = Label() + mv.dup() + mv.ifnonnull(compareLabel) + mv.pop() + mv.goTo(target) + mv.mark(compareLabel) + val unboxedValue = boxedValue.materializedAt(unboxType(boxedValue.type), boxedValue.irType) + BooleanComparison(op, unboxedValue, loadOther()).jumpIfFalse(target) + } + + override fun jumpIfTrue(target: Label) { + val compareLabel = Label() + val endLabel = Label() + mv.dup() + mv.ifnonnull(compareLabel) + mv.pop() + mv.goTo(endLabel) + mv.mark(compareLabel) + val unboxedValue = boxedValue.materializedAt(unboxType(boxedValue.type), boxedValue.irType) + BooleanComparison(op, unboxedValue, loadOther()).jumpIfTrue(target) + mv.mark(endLabel) + } + + override fun discard() { + boxedValue.discard() + } +} + class PrimitiveComparison( private val primitiveNumberType: KotlinType, private val operatorToken: KtSingleValueToken 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 586e6e90df9..5f86aed4753 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 @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive import org.jetbrains.kotlin.codegen.StackValue import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods import org.jetbrains.kotlin.config.LanguageFeature +import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin import org.jetbrains.kotlin.ir.types.classOrNull @@ -25,6 +26,7 @@ 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.psi2ir.generators.hasNoSideEffects import org.jetbrains.kotlin.resolve.jvm.AsmTypes import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature import org.jetbrains.kotlin.types.isNullable @@ -80,6 +82,38 @@ class Equals(val operator: IElementType) : IntrinsicMethod() { val leftType = with(codegen) { a.asmType } val rightType = with(codegen) { b.asmType } val opToken = expression.origin + + fun loadOther(expression: IrExpression, type: Type): () -> MaterialValue { + return if (expression.hasNoSideEffects()) { + { expression.accept(codegen, data).materializedAt(type, expression.type) } + } else { + val aValue = expression.accept(codegen, data).materializedAt(type, expression.type) + val local = codegen.frameMap.enterTemp(type) + codegen.mv.store(local, type) + ({ + codegen.mv.load(local, type) + codegen.frameMap.leaveTemp(type) + aValue + }) + } + } + + if ((opToken == IrStatementOrigin.EQEQ || opToken == IrStatementOrigin.EXCLEQ) && + (AsmUtil.isIntOrLongPrimitive(leftType) || AsmUtil.isIntOrLongPrimitive(rightType)) && + (AsmUtil.isBoxedTypeOf(leftType, rightType) || AsmUtil.isBoxedTypeOf(rightType, leftType)) + ) { + val leftIsPrimitive = AsmUtil.isIntOrLongPrimitive(leftType) + return if (leftIsPrimitive) { + val loadOther = loadOther(a, leftType) + val boxedValue = b.accept(codegen, data).materializedAt(rightType, b.type) + PrimitiveToBoxedComparison(operator, boxedValue, loadOther) + } else { + val boxedValue = a.accept(codegen, data).materializedAt(leftType, a.type) + val loadOther = loadOther(b, rightType) + PrimitiveToBoxedComparison(operator, boxedValue, loadOther) + } + } + val aIsEnum = a.type.classOrNull?.owner?.run { isEnumClass || isEnumEntry } == true val bIsEnum = b.type.classOrNull?.owner?.run { isEnumClass || isEnumEntry } == true val useEquals = opToken !== IrStatementOrigin.EQEQEQ && opToken !== IrStatementOrigin.EXCLEQEQ && diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt index f3c33daf047..7d98feb27ce 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt @@ -408,7 +408,8 @@ fun IrExpression.hasNoSideEffects() = this is IrFunctionExpression || (this is IrCallableReference && dispatchReceiver == null && extensionReceiver == null) || this is IrClassReference || - this is IrConst<*> + this is IrConst<*> || + this is IrGetValue fun CallGenerator.generateCall(ktElement: KtElement, call: CallBuilder, origin: IrStatementOrigin? = null) = generateCall(ktElement.startOffsetSkippingComments, ktElement.endOffset, call, origin) diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt index d30c0d5b6a9..32175048257 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt @@ -45,9 +45,7 @@ import org.jetbrains.kotlin.resolve.checkers.PrimitiveNumericComparisonInfo import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.checker.intersectTypes -import org.jetbrains.kotlin.types.typeUtil.isPrimitiveNumberType -import org.jetbrains.kotlin.types.typeUtil.makeNotNullable -import org.jetbrains.kotlin.types.typeUtil.makeNullable +import org.jetbrains.kotlin.types.typeUtil.* class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : StatementGeneratorExtension(statementGenerator) { @@ -390,6 +388,9 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat operandType == targetType || operandNNType == targetType -> this + targetType.isInt() && (operandNNType.isShort() || operandNNType.isByte()) -> + this + // TODO: don't rely on originalKotlinType. type.originalKotlinType!!.containsNull() -> safeCallOnDispatchReceiver(this@OperatorExpressionGenerator, startOffset, endOffset) { dispatchReceiver -> diff --git a/compiler/testData/codegen/bytecodeText/conditions/noBoxingForBoxedEqPrimitive.kt b/compiler/testData/codegen/bytecodeText/conditions/noBoxingForBoxedEqPrimitive.kt index 8fe6c521665..d20f0230e33 100644 --- a/compiler/testData/codegen/bytecodeText/conditions/noBoxingForBoxedEqPrimitive.kt +++ b/compiler/testData/codegen/bytecodeText/conditions/noBoxingForBoxedEqPrimitive.kt @@ -1,6 +1,3 @@ -// IGNORE_BACKEND: JVM_IR -// TODO KT-36646 Don't box primitive values in equality comparison with nullable primitive values in JVM_IR - fun testBoolean1(a: Boolean?, b: Boolean) = a == b fun testBoolean2(a: Boolean?, b: Boolean) = a != b diff --git a/compiler/testData/codegen/bytecodeText/conditions/noBoxingForPrimitiveEqBoxed.kt b/compiler/testData/codegen/bytecodeText/conditions/noBoxingForPrimitiveEqBoxed.kt index adbfe82cb82..7fb29c4428c 100644 --- a/compiler/testData/codegen/bytecodeText/conditions/noBoxingForPrimitiveEqBoxed.kt +++ b/compiler/testData/codegen/bytecodeText/conditions/noBoxingForPrimitiveEqBoxed.kt @@ -1,6 +1,3 @@ -// IGNORE_BACKEND: JVM_IR -// TODO KT-36646 Don't box primitive values in equality comparison with nullable primitive values in JVM_IR - fun testBoolean1(a: Boolean, b: Boolean?) = a == b fun testBoolean2(a: Boolean, b: Boolean?) = a != b diff --git a/compiler/testData/codegen/bytecodeText/intrinsicsCompare/byteSmartCast_after.kt b/compiler/testData/codegen/bytecodeText/intrinsicsCompare/byteSmartCast_after.kt index 49f6718c343..c3a6db9113c 100644 --- a/compiler/testData/codegen/bytecodeText/intrinsicsCompare/byteSmartCast_after.kt +++ b/compiler/testData/codegen/bytecodeText/intrinsicsCompare/byteSmartCast_after.kt @@ -11,17 +11,9 @@ fun less4(a: Byte?, b: Byte?) = if (a is Byte && b is Byte) a < b else true fun less5(a: Any?, b: Any?) = if (a is Byte && b is Byte) a < b else true -// JVM_TEMPLATES // 3 Intrinsics\.areEqual // 0 Intrinsics\.compare +// 4 INVOKEVIRTUAL java/lang/Byte\.byteValue \(\)B +// 2 INVOKEVIRTUAL java/lang/Number\.intValue \(\)I // 0 IFGE // 3 IF_ICMPGE - -// JVM_IR_TEMPLATES -// 0 Intrinsics\.areEqual -// 0 Intrinsics\.compare -// 8 INVOKEVIRTUAL java/lang/Byte\.byteValue \(\)B -// 4 INVOKEVIRTUAL java/lang/Number\.byteValue \(\)B -// 0 IFGE -// 3 IF_ICMPNE -// 3 IF_ICMPGE diff --git a/compiler/testData/codegen/bytecodeText/intrinsicsCompare/byteSmartCast_before.kt b/compiler/testData/codegen/bytecodeText/intrinsicsCompare/byteSmartCast_before.kt index a70dc5d717a..0564f0b291f 100644 --- a/compiler/testData/codegen/bytecodeText/intrinsicsCompare/byteSmartCast_before.kt +++ b/compiler/testData/codegen/bytecodeText/intrinsicsCompare/byteSmartCast_before.kt @@ -19,10 +19,10 @@ fun less5(a: Any?, b: Any?) = if (a is Byte && b is Byte) a < b else true // 0 IF_ICMPGE // JVM_IR_TEMPLATES -// 0 Intrinsics\.areEqual +// 3 Intrinsics\.areEqual // 0 Intrinsics\.compare -// 8 INVOKEVIRTUAL java/lang/Byte\.byteValue \(\)B -// 4 INVOKEVIRTUAL java/lang/Number\.byteValue \(\)B +// 4 INVOKEVIRTUAL java/lang/Byte\.byteValue \(\)B +// 2 INVOKEVIRTUAL java/lang/Number\.intValue \(\)I // 0 IFGE // 3 IF_ICMPGE -// 3 IF_ICMPNE \ No newline at end of file +// 0 IF_ICMPNE \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/intrinsicsCompare/shortSmartCast_after.kt b/compiler/testData/codegen/bytecodeText/intrinsicsCompare/shortSmartCast_after.kt index 2a16f59605b..066fa95f060 100644 --- a/compiler/testData/codegen/bytecodeText/intrinsicsCompare/shortSmartCast_after.kt +++ b/compiler/testData/codegen/bytecodeText/intrinsicsCompare/shortSmartCast_after.kt @@ -11,17 +11,10 @@ fun less4(a: Short?, b: Short?) = if (a is Short && b is Short) a < b else true fun less5(a: Any?, b: Any?) = if (a is Short && b is Short) a < b else true -// JVM_TEMPLATES // 3 Intrinsics\.areEqual // 0 Intrinsics\.compare +// 4 INVOKEVIRTUAL java/lang/Short\.shortValue \(\)S +// 2 INVOKEVIRTUAL java/lang/Number\.intValue \(\)I // 0 IFGE // 3 IF_ICMPGE - -// JVM_IR_TEMPLATES -// 0 Intrinsics\.areEqual -// 0 Intrinsics\.compare -// 8 INVOKEVIRTUAL java/lang/Short\.shortValue \(\)S -// 4 INVOKEVIRTUAL java/lang/Number\.shortValue \(\)S -// 0 IFGE -// 3 IF_ICMPGE -// 3 IF_ICMPNE +// 0 IF_ICMPNE diff --git a/compiler/testData/codegen/bytecodeText/intrinsicsCompare/shortSmartCast_before.kt b/compiler/testData/codegen/bytecodeText/intrinsicsCompare/shortSmartCast_before.kt index c63cfc86545..6b35e7f91c8 100644 --- a/compiler/testData/codegen/bytecodeText/intrinsicsCompare/shortSmartCast_before.kt +++ b/compiler/testData/codegen/bytecodeText/intrinsicsCompare/shortSmartCast_before.kt @@ -18,10 +18,10 @@ fun less5(a: Any?, b: Any?) = if (a is Short && b is Short) a < b else true // 0 IF_ICMPGE // JVM_IR_TEMPLATES -// 0 Intrinsics\.areEqual +// 3 Intrinsics\.areEqual // 0 Intrinsics\.compare -// 8 INVOKEVIRTUAL java/lang/Short\.shortValue \(\)S -// 4 INVOKEVIRTUAL java/lang/Number\.shortValue \(\)S +// 4 INVOKEVIRTUAL java/lang/Short\.shortValue \(\)S +// 2 INVOKEVIRTUAL java/lang/Number\.intValue \(\)I // 0 IFGE // 3 IF_ICMPGE -// 3 IF_ICMPNE \ No newline at end of file +// 0 IF_ICMPNE \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/when/noBoxingInDefaultWhenWithSpecialCases.kt b/compiler/testData/codegen/bytecodeText/when/noBoxingInDefaultWhenWithSpecialCases.kt index 04f2021cfd4..c07b3dd7fbf 100644 --- a/compiler/testData/codegen/bytecodeText/when/noBoxingInDefaultWhenWithSpecialCases.kt +++ b/compiler/testData/codegen/bytecodeText/when/noBoxingInDefaultWhenWithSpecialCases.kt @@ -1,6 +1,3 @@ -// IGNORE_BACKEND: JVM_IR -// TODO KT-36646 Don't box primitive values in equality comparison with objects in JVM_IR - fun testInt(i: Int?) = when (i) { 0 -> "zero" diff --git a/compiler/testData/ir/irText/classes/argumentReorderingInDelegatingConstructorCall.txt b/compiler/testData/ir/irText/classes/argumentReorderingInDelegatingConstructorCall.txt index 876e52f68fa..e24a29b3f5b 100644 --- a/compiler/testData/ir/irText/classes/argumentReorderingInDelegatingConstructorCall.txt +++ b/compiler/testData/ir/irText/classes/argumentReorderingInDelegatingConstructorCall.txt @@ -49,13 +49,9 @@ FILE fqName: fileName:/argumentReorderingInDelegatingConstructorCall.kt VALUE_PARAMETER name:yy index:1 type:kotlin.Int BLOCK_BODY BLOCK type=kotlin.Unit origin=ARGUMENTS_REORDERING_FOR_CALL - VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:kotlin.Int [val] - GET_VAR 'yy: kotlin.Int declared in .Test1.' type=kotlin.Int origin=null - VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:kotlin.Int [val] - GET_VAR 'xx: kotlin.Int declared in .Test1.' type=kotlin.Int origin=null DELEGATING_CONSTRUCTOR_CALL 'public constructor (x: kotlin.Int, y: kotlin.Int) [primary] declared in .Base' - x: GET_VAR 'val tmp_1: kotlin.Int [val] declared in .Test1.' type=kotlin.Int origin=null - y: GET_VAR 'val tmp_0: kotlin.Int [val] declared in .Test1.' type=kotlin.Int origin=null + x: GET_VAR 'xx: kotlin.Int declared in .Test1.' type=kotlin.Int origin=null + y: GET_VAR 'yy: kotlin.Int declared in .Test1.' type=kotlin.Int origin=null INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Test1 modality:FINAL visibility:public superTypes:[.Base]' PROPERTY FAKE_OVERRIDE name:x visibility:public modality:FINAL [fake_override,val] FUN FAKE_OVERRIDE name: visibility:public modality:FINAL <> ($this:.Base) returnType:kotlin.Int [fake_override] @@ -89,13 +85,9 @@ FILE fqName: fileName:/argumentReorderingInDelegatingConstructorCall.kt VALUE_PARAMETER name:yy index:1 type:kotlin.Int BLOCK_BODY BLOCK type=kotlin.Unit origin=ARGUMENTS_REORDERING_FOR_CALL - VAR IR_TEMPORARY_VARIABLE name:tmp_2 type:kotlin.Int [val] - GET_VAR 'yy: kotlin.Int declared in .Test2.' type=kotlin.Int origin=null - VAR IR_TEMPORARY_VARIABLE name:tmp_3 type:kotlin.Int [val] - GET_VAR 'xx: kotlin.Int declared in .Test2.' type=kotlin.Int origin=null DELEGATING_CONSTRUCTOR_CALL 'public constructor (x: kotlin.Int, y: kotlin.Int) [primary] declared in .Base' - x: GET_VAR 'val tmp_3: kotlin.Int [val] declared in .Test2.' type=kotlin.Int origin=null - y: GET_VAR 'val tmp_2: kotlin.Int [val] declared in .Test2.' type=kotlin.Int origin=null + x: GET_VAR 'xx: kotlin.Int declared in .Test2.' type=kotlin.Int origin=null + y: GET_VAR 'yy: kotlin.Int declared in .Test2.' type=kotlin.Int origin=null INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:Test2 modality:FINAL visibility:public superTypes:[.Base]' CONSTRUCTOR visibility:public <> (xxx:kotlin.Int, yyy:kotlin.Int, a:kotlin.Any) returnType:.Test2 VALUE_PARAMETER name:xxx index:0 type:kotlin.Int @@ -103,13 +95,9 @@ FILE fqName: fileName:/argumentReorderingInDelegatingConstructorCall.kt VALUE_PARAMETER name:a index:2 type:kotlin.Any BLOCK_BODY BLOCK type=kotlin.Unit origin=ARGUMENTS_REORDERING_FOR_CALL - VAR IR_TEMPORARY_VARIABLE name:tmp_4 type:kotlin.Int [val] - GET_VAR 'yyy: kotlin.Int declared in .Test2.' type=kotlin.Int origin=null - VAR IR_TEMPORARY_VARIABLE name:tmp_5 type:kotlin.Int [val] - GET_VAR 'xxx: kotlin.Int declared in .Test2.' type=kotlin.Int origin=null DELEGATING_CONSTRUCTOR_CALL 'public constructor (xx: kotlin.Int, yy: kotlin.Int) declared in .Test2' - xx: GET_VAR 'val tmp_5: kotlin.Int [val] declared in .Test2.' type=kotlin.Int origin=null - yy: GET_VAR 'val tmp_4: kotlin.Int [val] declared in .Test2.' type=kotlin.Int origin=null + xx: GET_VAR 'xxx: kotlin.Int declared in .Test2.' type=kotlin.Int origin=null + yy: GET_VAR 'yyy: kotlin.Int declared in .Test2.' type=kotlin.Int origin=null PROPERTY FAKE_OVERRIDE name:x visibility:public modality:FINAL [fake_override,val] FUN FAKE_OVERRIDE name: visibility:public modality:FINAL <> ($this:.Base) returnType:kotlin.Int [fake_override] correspondingProperty: PROPERTY FAKE_OVERRIDE name:x visibility:public modality:FINAL [fake_override,val] diff --git a/compiler/testData/ir/irText/expressions/primitiveComparisons.txt b/compiler/testData/ir/irText/expressions/primitiveComparisons.txt index dda66849909..6ac3f6799de 100644 --- a/compiler/testData/ir/irText/expressions/primitiveComparisons.txt +++ b/compiler/testData/ir/irText/expressions/primitiveComparisons.txt @@ -5,80 +5,80 @@ FILE fqName: fileName:/primitiveComparisons.kt BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun btest1 (a: kotlin.Byte, b: kotlin.Byte): kotlin.Boolean declared in ' CALL 'public final fun greater (arg0: kotlin.Int, arg1: kotlin.Int): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=GT - arg0: CALL 'public open fun toInt (): kotlin.Int declared in kotlin.Byte' type=kotlin.Int origin=null - $this: GET_VAR 'a: kotlin.Byte declared in .btest1' type=kotlin.Byte origin=null - arg1: CALL 'public open fun toInt (): kotlin.Int declared in kotlin.Byte' type=kotlin.Int origin=null - $this: GET_VAR 'b: kotlin.Byte declared in .btest1' type=kotlin.Byte origin=null + arg0: TYPE_OP type=kotlin.Int origin=IMPLICIT_CAST typeOperand=kotlin.Int + GET_VAR 'a: kotlin.Byte declared in .btest1' type=kotlin.Byte origin=null + arg1: TYPE_OP type=kotlin.Int origin=IMPLICIT_CAST typeOperand=kotlin.Int + GET_VAR 'b: kotlin.Byte declared in .btest1' type=kotlin.Byte origin=null FUN name:btest2 visibility:public modality:FINAL <> (a:kotlin.Byte, b:kotlin.Byte) returnType:kotlin.Boolean VALUE_PARAMETER name:a index:0 type:kotlin.Byte VALUE_PARAMETER name:b index:1 type:kotlin.Byte BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun btest2 (a: kotlin.Byte, b: kotlin.Byte): kotlin.Boolean declared in ' CALL 'public final fun less (arg0: kotlin.Int, arg1: kotlin.Int): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=LT - arg0: CALL 'public open fun toInt (): kotlin.Int declared in kotlin.Byte' type=kotlin.Int origin=null - $this: GET_VAR 'a: kotlin.Byte declared in .btest2' type=kotlin.Byte origin=null - arg1: CALL 'public open fun toInt (): kotlin.Int declared in kotlin.Byte' type=kotlin.Int origin=null - $this: GET_VAR 'b: kotlin.Byte declared in .btest2' type=kotlin.Byte origin=null + arg0: TYPE_OP type=kotlin.Int origin=IMPLICIT_CAST typeOperand=kotlin.Int + GET_VAR 'a: kotlin.Byte declared in .btest2' type=kotlin.Byte origin=null + arg1: TYPE_OP type=kotlin.Int origin=IMPLICIT_CAST typeOperand=kotlin.Int + GET_VAR 'b: kotlin.Byte declared in .btest2' type=kotlin.Byte origin=null FUN name:btest3 visibility:public modality:FINAL <> (a:kotlin.Byte, b:kotlin.Byte) returnType:kotlin.Boolean VALUE_PARAMETER name:a index:0 type:kotlin.Byte VALUE_PARAMETER name:b index:1 type:kotlin.Byte BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun btest3 (a: kotlin.Byte, b: kotlin.Byte): kotlin.Boolean declared in ' CALL 'public final fun greaterOrEqual (arg0: kotlin.Int, arg1: kotlin.Int): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=GTEQ - arg0: CALL 'public open fun toInt (): kotlin.Int declared in kotlin.Byte' type=kotlin.Int origin=null - $this: GET_VAR 'a: kotlin.Byte declared in .btest3' type=kotlin.Byte origin=null - arg1: CALL 'public open fun toInt (): kotlin.Int declared in kotlin.Byte' type=kotlin.Int origin=null - $this: GET_VAR 'b: kotlin.Byte declared in .btest3' type=kotlin.Byte origin=null + arg0: TYPE_OP type=kotlin.Int origin=IMPLICIT_CAST typeOperand=kotlin.Int + GET_VAR 'a: kotlin.Byte declared in .btest3' type=kotlin.Byte origin=null + arg1: TYPE_OP type=kotlin.Int origin=IMPLICIT_CAST typeOperand=kotlin.Int + GET_VAR 'b: kotlin.Byte declared in .btest3' type=kotlin.Byte origin=null FUN name:btest4 visibility:public modality:FINAL <> (a:kotlin.Byte, b:kotlin.Byte) returnType:kotlin.Boolean VALUE_PARAMETER name:a index:0 type:kotlin.Byte VALUE_PARAMETER name:b index:1 type:kotlin.Byte BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun btest4 (a: kotlin.Byte, b: kotlin.Byte): kotlin.Boolean declared in ' CALL 'public final fun lessOrEqual (arg0: kotlin.Int, arg1: kotlin.Int): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=LTEQ - arg0: CALL 'public open fun toInt (): kotlin.Int declared in kotlin.Byte' type=kotlin.Int origin=null - $this: GET_VAR 'a: kotlin.Byte declared in .btest4' type=kotlin.Byte origin=null - arg1: CALL 'public open fun toInt (): kotlin.Int declared in kotlin.Byte' type=kotlin.Int origin=null - $this: GET_VAR 'b: kotlin.Byte declared in .btest4' type=kotlin.Byte origin=null + arg0: TYPE_OP type=kotlin.Int origin=IMPLICIT_CAST typeOperand=kotlin.Int + GET_VAR 'a: kotlin.Byte declared in .btest4' type=kotlin.Byte origin=null + arg1: TYPE_OP type=kotlin.Int origin=IMPLICIT_CAST typeOperand=kotlin.Int + GET_VAR 'b: kotlin.Byte declared in .btest4' type=kotlin.Byte origin=null FUN name:stest1 visibility:public modality:FINAL <> (a:kotlin.Short, b:kotlin.Short) returnType:kotlin.Boolean VALUE_PARAMETER name:a index:0 type:kotlin.Short VALUE_PARAMETER name:b index:1 type:kotlin.Short BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun stest1 (a: kotlin.Short, b: kotlin.Short): kotlin.Boolean declared in ' CALL 'public final fun greater (arg0: kotlin.Int, arg1: kotlin.Int): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=GT - arg0: CALL 'public open fun toInt (): kotlin.Int declared in kotlin.Short' type=kotlin.Int origin=null - $this: GET_VAR 'a: kotlin.Short declared in .stest1' type=kotlin.Short origin=null - arg1: CALL 'public open fun toInt (): kotlin.Int declared in kotlin.Short' type=kotlin.Int origin=null - $this: GET_VAR 'b: kotlin.Short declared in .stest1' type=kotlin.Short origin=null + arg0: TYPE_OP type=kotlin.Int origin=IMPLICIT_CAST typeOperand=kotlin.Int + GET_VAR 'a: kotlin.Short declared in .stest1' type=kotlin.Short origin=null + arg1: TYPE_OP type=kotlin.Int origin=IMPLICIT_CAST typeOperand=kotlin.Int + GET_VAR 'b: kotlin.Short declared in .stest1' type=kotlin.Short origin=null FUN name:stest2 visibility:public modality:FINAL <> (a:kotlin.Short, b:kotlin.Short) returnType:kotlin.Boolean VALUE_PARAMETER name:a index:0 type:kotlin.Short VALUE_PARAMETER name:b index:1 type:kotlin.Short BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun stest2 (a: kotlin.Short, b: kotlin.Short): kotlin.Boolean declared in ' CALL 'public final fun less (arg0: kotlin.Int, arg1: kotlin.Int): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=LT - arg0: CALL 'public open fun toInt (): kotlin.Int declared in kotlin.Short' type=kotlin.Int origin=null - $this: GET_VAR 'a: kotlin.Short declared in .stest2' type=kotlin.Short origin=null - arg1: CALL 'public open fun toInt (): kotlin.Int declared in kotlin.Short' type=kotlin.Int origin=null - $this: GET_VAR 'b: kotlin.Short declared in .stest2' type=kotlin.Short origin=null + arg0: TYPE_OP type=kotlin.Int origin=IMPLICIT_CAST typeOperand=kotlin.Int + GET_VAR 'a: kotlin.Short declared in .stest2' type=kotlin.Short origin=null + arg1: TYPE_OP type=kotlin.Int origin=IMPLICIT_CAST typeOperand=kotlin.Int + GET_VAR 'b: kotlin.Short declared in .stest2' type=kotlin.Short origin=null FUN name:stest3 visibility:public modality:FINAL <> (a:kotlin.Short, b:kotlin.Short) returnType:kotlin.Boolean VALUE_PARAMETER name:a index:0 type:kotlin.Short VALUE_PARAMETER name:b index:1 type:kotlin.Short BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun stest3 (a: kotlin.Short, b: kotlin.Short): kotlin.Boolean declared in ' CALL 'public final fun greaterOrEqual (arg0: kotlin.Int, arg1: kotlin.Int): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=GTEQ - arg0: CALL 'public open fun toInt (): kotlin.Int declared in kotlin.Short' type=kotlin.Int origin=null - $this: GET_VAR 'a: kotlin.Short declared in .stest3' type=kotlin.Short origin=null - arg1: CALL 'public open fun toInt (): kotlin.Int declared in kotlin.Short' type=kotlin.Int origin=null - $this: GET_VAR 'b: kotlin.Short declared in .stest3' type=kotlin.Short origin=null + arg0: TYPE_OP type=kotlin.Int origin=IMPLICIT_CAST typeOperand=kotlin.Int + GET_VAR 'a: kotlin.Short declared in .stest3' type=kotlin.Short origin=null + arg1: TYPE_OP type=kotlin.Int origin=IMPLICIT_CAST typeOperand=kotlin.Int + GET_VAR 'b: kotlin.Short declared in .stest3' type=kotlin.Short origin=null FUN name:stest4 visibility:public modality:FINAL <> (a:kotlin.Short, b:kotlin.Short) returnType:kotlin.Boolean VALUE_PARAMETER name:a index:0 type:kotlin.Short VALUE_PARAMETER name:b index:1 type:kotlin.Short BLOCK_BODY RETURN type=kotlin.Nothing from='public final fun stest4 (a: kotlin.Short, b: kotlin.Short): kotlin.Boolean declared in ' CALL 'public final fun lessOrEqual (arg0: kotlin.Int, arg1: kotlin.Int): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=LTEQ - arg0: CALL 'public open fun toInt (): kotlin.Int declared in kotlin.Short' type=kotlin.Int origin=null - $this: GET_VAR 'a: kotlin.Short declared in .stest4' type=kotlin.Short origin=null - arg1: CALL 'public open fun toInt (): kotlin.Int declared in kotlin.Short' type=kotlin.Int origin=null - $this: GET_VAR 'b: kotlin.Short declared in .stest4' type=kotlin.Short origin=null + arg0: TYPE_OP type=kotlin.Int origin=IMPLICIT_CAST typeOperand=kotlin.Int + GET_VAR 'a: kotlin.Short declared in .stest4' type=kotlin.Short origin=null + arg1: TYPE_OP type=kotlin.Int origin=IMPLICIT_CAST typeOperand=kotlin.Int + GET_VAR 'b: kotlin.Short declared in .stest4' type=kotlin.Short origin=null FUN name:itest1 visibility:public modality:FINAL <> (a:kotlin.Int, b:kotlin.Int) returnType:kotlin.Boolean VALUE_PARAMETER name:a index:0 type:kotlin.Int VALUE_PARAMETER name:b index:1 type:kotlin.Int