Specialize Comparable#compareTo for boxed primitives

Support Comparable#compareTo for boxed primitive in redundant
boxing/unboxing analysis, along with CHECKCAST to java.lang.Comparable.

Note that we can do that for Float and Double, too, because
Float#compareTo(Float) and Double#compareTo(Double) are delegated to
Float#compare(float, float) and Double#compare(double, double),
respectively.

Fuse specialized comparison for integers with conditional jumps
if possible (both for Comparable#compareTo and Intrinsics#areEqual).

 #KT-11959 Fixed
This commit is contained in:
Dmitry Petrov
2017-05-19 10:34:15 +03:00
parent bd5b984da9
commit e1b41eee15
14 changed files with 526 additions and 30 deletions
@@ -75,6 +75,10 @@ open class BoxingInterpreter(private val insnList: InsnList) : OptimizationBasic
onAreEqual(insn, values[0] as BoxedBasicValue, values[1] as BoxedBasicValue)
value
}
insn.isJavaLangComparableCompareToForSameTypedBoxedValues(values) -> {
onCompareTo(insn, values[0] as BoxedBasicValue, values[1] as BoxedBasicValue)
value
}
else -> {
// N-ary operation should be a method call or multinewarray.
// Arguments for multinewarray could be only numeric,
@@ -127,6 +131,7 @@ open class BoxingInterpreter(private val insnList: InsnList) : OptimizationBasic
protected open fun onNewBoxedValue(value: BoxedBasicValue) {}
protected open fun onUnboxing(insn: AbstractInsnNode, value: BoxedBasicValue, resultType: Type) {}
protected open fun onAreEqual(insn: AbstractInsnNode, value1: BoxedBasicValue, value2: BoxedBasicValue) {}
protected open fun onCompareTo(insn: AbstractInsnNode, value1: BoxedBasicValue, value2: BoxedBasicValue) {}
protected open fun onMethodCallWithBoxedValue(value: BoxedBasicValue) {}
protected open fun onMergeFail(value: BoxedBasicValue) {}
protected open fun onMergeSuccess(v: BoxedBasicValue, w: BoxedBasicValue) {}
@@ -150,7 +155,7 @@ fun AbstractInsnNode.isPrimitiveUnboxing() =
isWrapperClassNameOrNumber(owner) && isUnboxingMethodName(name)
}
private fun AbstractInsnNode.isJavaLangClassUnboxing() =
fun AbstractInsnNode.isJavaLangClassUnboxing() =
isMethodInsnWith(Opcodes.INVOKESTATIC) {
owner == "kotlin/jvm/JvmClassMappingKt" &&
name == "getJavaClass" &&
@@ -185,7 +190,7 @@ private fun MethodInsnNode.isBoxingMethodDescriptor(): Boolean {
return desc == Type.getMethodDescriptor(ownerType, AsmUtil.unboxType(ownerType))
}
private fun AbstractInsnNode.isJavaLangClassBoxing() =
fun AbstractInsnNode.isJavaLangClassBoxing() =
isMethodInsnWith(Opcodes.INVOKESTATIC) {
owner == AsmTypes.REFLECTION &&
name == "getOrCreateKotlinClass" &&
@@ -210,16 +215,15 @@ fun isProgressionClass(type: Type) =
RangeCodegenUtil.isRangeOrProgression(buildFqNameByInternal(type.internalName))
fun AbstractInsnNode.isAreEqualIntrinsicForSameTypedBoxedValues(values: List<BasicValue>) =
isAreEqualIntrinsic() && run {
if (values.size != 2) return false
isAreEqualIntrinsic() && areSameTypedBoxedValues(values)
val (v1, v2) = values
if (v1 !is BoxedBasicValue || v2 !is BoxedBasicValue) return false
val d1 = v1.descriptor
val d2 = v2.descriptor
d1.unboxedType == d2.unboxedType
}
fun areSameTypedBoxedValues(values: List<BasicValue>): Boolean {
if (values.size != 2) return false
val (v1, v2) = values
return v1 is BoxedBasicValue &&
v2 is BoxedBasicValue &&
v1.descriptor.unboxedType == v2.descriptor.unboxedType
}
fun AbstractInsnNode.isAreEqualIntrinsic() =
isMethodInsnWith(Opcodes.INVOKESTATIC) {
@@ -232,4 +236,14 @@ fun canValuesBeUnboxedForAreEqual(values: List<BasicValue>): Boolean =
!values.any {
val unboxedType = getUnboxedType(it.type)
unboxedType == Type.DOUBLE_TYPE || unboxedType == Type.FLOAT_TYPE
}
}
fun AbstractInsnNode.isJavaLangComparableCompareToForSameTypedBoxedValues(values: List<BasicValue>) =
isJavaLangComparableCompareTo() && areSameTypedBoxedValues(values)
fun AbstractInsnNode.isJavaLangComparableCompareTo() =
isMethodInsnWith(Opcodes.INVOKEINTERFACE) {
name == "compareTo" &&
owner == "java/lang/Comparable" &&
desc == "(Ljava/lang/Object;)I"
}
@@ -91,6 +91,13 @@ internal class RedundantBoxingInterpreter(insnList: InsnList) : BoxingInterprete
descriptor1.addInsn(insn)
}
override fun onCompareTo(insn: AbstractInsnNode, value1: BoxedBasicValue, value2: BoxedBasicValue) {
val descriptor1 = value1.descriptor
val descriptor2 = value2.descriptor
candidatesBoxedValues.merge(descriptor1, descriptor2)
descriptor1.addInsn(insn)
}
override fun onMethodCallWithBoxedValue(value: BoxedBasicValue) {
markValueAsDirty(value)
}
@@ -133,6 +140,8 @@ internal class RedundantBoxingInterpreter(insnList: InsnList) : BoxingInterprete
true
Type.getInternalName(Number::class.java) ->
PRIMITIVE_TYPES_SORTS_WITH_WRAPPER_EXTENDS_NUMBER.contains(value.descriptor.unboxedType.sort)
"java/lang/Comparable" ->
true
else ->
value.type.internalName == targetInternalName
}
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.codegen.optimization.boxing;
import com.intellij.openapi.util.Pair;
import kotlin.collections.CollectionsKt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil;
import org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue;
import org.jetbrains.kotlin.codegen.optimization.common.UtilKt;
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer;
@@ -324,16 +325,40 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
adaptAreEqualIntrinsic(node, insn, value);
break;
}
else {
// fall-through to default
else if (BoxingInterpreterKt.isJavaLangClassBoxing(insn) || BoxingInterpreterKt.isJavaLangClassUnboxing(insn)) {
node.instructions.remove(insn);
break;
}
default:
else {
throwCannotAdaptInstruction(insn);
}
case Opcodes.INVOKEINTERFACE:
if (BoxingInterpreterKt.isJavaLangComparableCompareTo(insn)) {
adaptJavaLangComparableCompareTo(node, insn, value);
break;
}
else {
throwCannotAdaptInstruction(insn);
}
case Opcodes.CHECKCAST:
case Opcodes.INVOKEVIRTUAL:
// CHECKCAST or unboxing-method call
node.instructions.remove(insn);
break;
default:
throwCannotAdaptInstruction(insn);
}
}
private static void adaptAreEqualIntrinsic(@NotNull MethodNode node, @NotNull AbstractInsnNode insn, @NotNull BoxedValueDescriptor value) {
private static void throwCannotAdaptInstruction(@NotNull AbstractInsnNode insn) {
throw new AssertionError("Cannot adapt instruction: " + InlineCodegenUtil.getInsnText(insn));
}
private static void adaptAreEqualIntrinsic(
@NotNull MethodNode node,
@NotNull AbstractInsnNode insn,
@NotNull BoxedValueDescriptor value
) {
Type unboxedType = value.getUnboxedType();
switch (unboxedType.getSort()) {
@@ -355,32 +380,137 @@ public class RedundantBoxingMethodTransformer extends MethodTransformer {
}
private static void adaptAreEqualIntrinsicForInt(@NotNull MethodNode node, @NotNull AbstractInsnNode insn) {
LabelNode lNotEqual = new LabelNode(new Label());
LabelNode lDone = new LabelNode(new Label());
node.instructions.insertBefore(insn, new JumpInsnNode(Opcodes.IF_ICMPNE, lNotEqual));
node.instructions.insertBefore(insn, new InsnNode(Opcodes.ICONST_1));
node.instructions.insertBefore(insn, new JumpInsnNode(Opcodes.GOTO, lDone));
node.instructions.insertBefore(insn, lNotEqual);
node.instructions.insertBefore(insn, new InsnNode(Opcodes.ICONST_0));
node.instructions.insertBefore(insn, lDone);
node.instructions.remove(insn);
AbstractInsnNode next = insn.getNext();
if (next != null && (next.getOpcode() == Opcodes.IFEQ || next.getOpcode() == Opcodes.IFNE)) {
fuseAreEqualWithBranch(node, insn, Opcodes.IF_ICMPNE, Opcodes.IF_ICMPEQ);
node.instructions.remove(insn);
node.instructions.remove(next);
}
else {
ifEqual1Else0(node, insn, Opcodes.IF_ICMPNE);
node.instructions.remove(insn);
}
}
private static void adaptAreEqualIntrinsicForLong(@NotNull MethodNode node, @NotNull AbstractInsnNode insn) {
node.instructions.insertBefore(insn, new InsnNode(Opcodes.LCMP));
ifEqual1Else0(node, insn);
node.instructions.remove(insn);
AbstractInsnNode next = insn.getNext();
if (next != null && (next.getOpcode() == Opcodes.IFEQ || next.getOpcode() == Opcodes.IFNE)) {
fuseAreEqualWithBranch(node, insn, Opcodes.IFNE, Opcodes.IFEQ);
node.instructions.remove(insn);
node.instructions.remove(next);
}
else {
ifEqual1Else0(node, insn, Opcodes.IFNE);
node.instructions.remove(insn);
}
}
private static void ifEqual1Else0(@NotNull MethodNode node, @NotNull AbstractInsnNode insn) {
private static void fuseAreEqualWithBranch(
@NotNull MethodNode node,
@NotNull AbstractInsnNode insn,
int ifEqualOpcode,
int ifNotEqualOpcode
) {
AbstractInsnNode next = insn.getNext();
assert next instanceof JumpInsnNode : "JumpInsnNode expected: " + next;
LabelNode nextLabel = ((JumpInsnNode) next).label;
if (next.getOpcode() == Opcodes.IFEQ) {
node.instructions.insertBefore(insn, new JumpInsnNode(ifEqualOpcode, nextLabel));
}
else if (next.getOpcode() == Opcodes.IFNE) {
node.instructions.insertBefore(insn, new JumpInsnNode(ifNotEqualOpcode, nextLabel));
}
else {
throw new AssertionError("IFEQ or IFNE expected: " + InlineCodegenUtil.getInsnOpcodeText(next));
}
}
private static void ifEqual1Else0(@NotNull MethodNode node, @NotNull AbstractInsnNode insn, int ifneOpcode) {
LabelNode lNotEqual = new LabelNode(new Label());
LabelNode lDone = new LabelNode(new Label());
node.instructions.insertBefore(insn, new JumpInsnNode(Opcodes.IFNE, lNotEqual));
node.instructions.insertBefore(insn, new JumpInsnNode(ifneOpcode, lNotEqual));
node.instructions.insertBefore(insn, new InsnNode(Opcodes.ICONST_1));
node.instructions.insertBefore(insn, new JumpInsnNode(Opcodes.GOTO, lDone));
node.instructions.insertBefore(insn, lNotEqual);
node.instructions.insertBefore(insn, new InsnNode(Opcodes.ICONST_0));
node.instructions.insertBefore(insn, lDone);
}
private static void adaptJavaLangComparableCompareTo(
@NotNull MethodNode node,
@NotNull AbstractInsnNode insn,
@NotNull BoxedValueDescriptor value
) {
Type unboxedType = value.getUnboxedType();
switch (unboxedType.getSort()) {
case Type.BOOLEAN:
case Type.BYTE:
case Type.SHORT:
case Type.INT:
case Type.CHAR:
adaptJavaLangComparableCompareToForInt(node, insn);
break;
case Type.LONG:
adaptJavaLangComparableCompareToForLong(node, insn);
break;
case Type.FLOAT:
adaptJavaLangComparableCompareToForFloat(node, insn);
break;
case Type.DOUBLE:
adaptJavaLangComparableCompareToForDouble(node, insn);
break;
default:
throw new AssertionError("Unexpected unboxed type kind: " + unboxedType);
}
}
private static void adaptJavaLangComparableCompareToForInt(@NotNull MethodNode node, @NotNull AbstractInsnNode insn) {
AbstractInsnNode next = insn.getNext();
AbstractInsnNode next2 = next == null ? null : next.getNext();
if (next != null && next2 != null &&
next.getOpcode() == Opcodes.ICONST_0 &&
next2.getOpcode() >= Opcodes.IF_ICMPEQ && next2.getOpcode() <= Opcodes.IF_ICMPLE) {
// Fuse: compareTo + ICONST_0 + IF_ICMPxx -> IF_ICMPxx
node.instructions.remove(insn);
node.instructions.remove(next);
}
else if (next != null &&
next.getOpcode() >= Opcodes.IFEQ && next.getOpcode() <= Opcodes.IFLE) {
// Fuse: compareTo + IFxx -> IF_ICMPxx
LabelNode nextLabel = ((JumpInsnNode) next).label;
int ifCmpOpcode = next.getOpcode() - Opcodes.IFEQ + Opcodes.IF_ICMPEQ;
node.instructions.insertBefore(insn, new JumpInsnNode(ifCmpOpcode, nextLabel));
node.instructions.remove(insn);
node.instructions.remove(next);
}
else {
// Can't fuse with branching instruction.
// Trick: convert I, I on stack to L, L and use LCMP.
// This is more compact than explicit branching.
// TODO Generate 'java.lang.Integer#compare(int, int)' in targets >= JVM 1.7
// Initial stack: I1 I2
node.instructions.insertBefore(insn, new InsnNode(Opcodes.SWAP)); // I2 I1
node.instructions.insertBefore(insn, new InsnNode(Opcodes.I2L)); // L2 I1
node.instructions.insertBefore(insn, new InsnNode(Opcodes.DUP2_X1)); // L2 I1 L2
node.instructions.insertBefore(insn, new InsnNode(Opcodes.POP2)); // I1 L2
node.instructions.insertBefore(insn, new InsnNode(Opcodes.I2L)); // L1 L2
node.instructions.insertBefore(insn, new InsnNode(Opcodes.LCMP)); // compare(L1, L2)
node.instructions.remove(insn);
}
}
private static void adaptJavaLangComparableCompareToForLong(@NotNull MethodNode node, @NotNull AbstractInsnNode insn) {
node.instructions.set(insn, new InsnNode(Opcodes.LCMP));
}
private static void adaptJavaLangComparableCompareToForFloat(@NotNull MethodNode node, @NotNull AbstractInsnNode insn) {
node.instructions.set(insn, new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Float", "compare", "(FF)I", false));
}
private static void adaptJavaLangComparableCompareToForDouble(@NotNull MethodNode node, @NotNull AbstractInsnNode insn) {
node.instructions.set(insn, new MethodInsnNode(Opcodes.INVOKESTATIC, "java/lang/Double", "compare", "(DD)I", false));
}
}
@@ -0,0 +1,46 @@
inline fun ltx(a: Comparable<Any>, b: Any) = a < b
inline fun lex(a: Comparable<Any>, b: Any) = a <= b
inline fun gex(a: Comparable<Any>, b: Any) = a >= b
inline fun gtx(a: Comparable<Any>, b: Any) = a > b
inline fun lt(a: Any, b: Any) = ltx(a as Comparable<Any>, b)
inline fun le(a: Any, b: Any) = lex(a as Comparable<Any>, b)
inline fun ge(a: Any, b: Any) = gex(a as Comparable<Any>, b)
inline fun gt(a: Any, b: Any) = gtx(a as Comparable<Any>, b)
val ONE = 1
val ONEL = 1L
fun box(): String {
return when {
!lt(ONE, 42) -> "Fail 1 LT"
lt(42, ONE) -> "Fail 2 LT"
!le(ONE, 42) -> "Fail 1 LE"
le(42, ONE) -> "Fail 2 LE"
!le(1, ONE) -> "Fail 3 LE"
!ge(42, ONE) -> "Fail 1 GE"
ge(ONE, 42) -> "Fail 2 GE"
!ge(1, ONE) -> "Fail 3 GE"
gt(ONE, 42) -> "Fail 1 GT"
!gt(42, ONE) -> "Fail 2 GT"
!lt(ONEL, 42L) -> "Fail 1 LT L"
lt(42L, ONEL) -> "Fail 2 LT L"
!le(ONEL, 42L) -> "Fail 1 LE L"
le(42L, ONEL) -> "Fail 2 LE L"
!le(ONEL, 1L) -> "Fail 3 LE L"
!ge(42L, ONEL) -> "Fail 1 GE L"
ge(ONEL, 42L) -> "Fail 2 GE L"
!ge(ONEL, 1L) -> "Fail 3 GE L"
gt(ONEL, 42L) -> "Fail 1 GT L"
!gt(42L, ONEL) -> "Fail 2 GT L"
else -> "OK"
}
}
@@ -0,0 +1,21 @@
inline fun eq(a: Any, b: Any) = a == b
inline fun ne(a: Any, b: Any) = a != b
val ONE = 1
val ONEL = 1L
fun box(): String {
return when {
eq(ONE, 2) -> "Fail 1"
!eq(ONE, 1) -> "Fail 2"
!ne(ONE, 2) -> "Fail 3"
ne(ONE, 1) -> "Fail 4"
eq(ONEL, 42L) -> "Fail 1L"
!eq(ONEL, 1L) -> "Fail 2L"
!ne(ONEL, 42L) -> "Fail 3L"
ne(ONEL, 1L) -> "Fail 4L"
else -> "OK"
}
}
@@ -0,0 +1,82 @@
// IGNORE_BACKEND: JS, NATIVE
inline fun ltx(a: Comparable<Any>, b: Any) = a < b
inline fun lex(a: Comparable<Any>, b: Any) = a <= b
inline fun gex(a: Comparable<Any>, b: Any) = a >= b
inline fun gtx(a: Comparable<Any>, b: Any) = a > b
inline fun lt(a: Any, b: Any) = ltx(a as Comparable<Any>, b)
inline fun le(a: Any, b: Any) = lex(a as Comparable<Any>, b)
inline fun ge(a: Any, b: Any) = gex(a as Comparable<Any>, b)
inline fun gt(a: Any, b: Any) = gtx(a as Comparable<Any>, b)
val PLUS0F = 0.0F
val MINUS0F = -0.0F
val PLUS0D = 0.0
val MINUS0D = -0.0
fun box(): String {
return when {
!lt(1.0F, 42.0F) -> "Fail 1 LT F"
lt(42.0F, 1.0F) -> "Fail 2 LT F"
!le(1.0F, 42.0F) -> "Fail 1 LE F"
le(42.0F, 1.0F) -> "Fail 2 LE F"
!le(1.0F, 1.0F) -> "Fail 3 LE F"
!ge(42.0F, 1.0F) -> "Fail 1 GE F"
ge(1.0F, 42.0F) -> "Fail 2 GE F"
!ge(1.0F, 1.0F) -> "Fail 3 GE F"
gt(1.0F, 42.0F) -> "Fail 1 GT F"
!gt(42.0F, 1.0F) -> "Fail 2 GT F"
!lt(1.0, 42.0) -> "Fail 1 LT D"
lt(42.0, 1.0) -> "Fail 2 LT D"
!le(1.0, 42.0) -> "Fail 1 LE D"
le(42.0, 1.0) -> "Fail 2 LE D"
!le(1.0, 1.0) -> "Fail 3 LE D"
!ge(42.0, 1.0) -> "Fail 1 GE D"
ge(1.0, 42.0) -> "Fail 2 GE D"
!ge(1.0, 1.0) -> "Fail 3 GE D"
gt(1.0, 42.0) -> "Fail 1 GT D"
!gt(42.0, 1.0) -> "Fail 2 GT D"
!lt(MINUS0F, PLUS0F) -> "Fail 1 LT +-0 F"
lt(PLUS0F, MINUS0F) -> "Fail 2 LT +-0 F"
!le(MINUS0F, PLUS0F) -> "Fail 1 LE +-0 F"
le(PLUS0F, MINUS0F) -> "Fail 2 LE +-0 F"
!le(MINUS0F, MINUS0F) -> "Fail 3 LE +-0 F"
!le(PLUS0F, PLUS0F) -> "Fail 3 LE +-0 F"
ge(MINUS0F, PLUS0F) -> "Fail 1 GE +-0 F"
!ge(PLUS0F, MINUS0F) -> "Fail 2 GE +-0 F"
!ge(MINUS0F, MINUS0F) -> "Fail 3 GE +-0 F"
!ge(PLUS0F, PLUS0F) -> "Fail 3 GE +-0 F"
gt(MINUS0F, PLUS0F) -> "Fail 1 GT +-0 F"
!gt(PLUS0F, MINUS0F) -> "Fail 2 GT +-0 F"
!lt(MINUS0D, PLUS0D) -> "Fail 1 LT +-0 D"
lt(PLUS0D, MINUS0D) -> "Fail 2 LT +-0 D"
!le(MINUS0D, PLUS0D) -> "Fail 1 LE +-0 D"
le(PLUS0D, MINUS0D) -> "Fail 2 LE +-0 D"
!le(MINUS0D, MINUS0D) -> "Fail 3 LE +-0 D"
!le(PLUS0D, PLUS0D) -> "Fail 3 LE +-0 D"
ge(MINUS0D, PLUS0D) -> "Fail 1 GE +-0 D"
!ge(PLUS0D, MINUS0D) -> "Fail 2 GE +-0 D"
!ge(MINUS0D, MINUS0D) -> "Fail 3 GE +-0 D"
!ge(PLUS0D, PLUS0D) -> "Fail 3 GE +-0 D"
gt(MINUS0D, PLUS0D) -> "Fail 1 GT +-0 D"
!gt(PLUS0D, MINUS0D) -> "Fail 2 GT +-0 D"
else -> "OK"
}
}
@@ -0,0 +1,8 @@
fun box(): String {
val a: Any = 1
val b: Any = 42
val test = (a as Comparable<Any>).compareTo(b)
if (test != -1) return "Fail: $test"
return "OK"
}
@@ -0,0 +1,20 @@
// WITH_RUNTIME
fun box(): String {
val intList = listOf(1, 2, 3)
val longList = listOf(1L, 2L, 3L)
val intListMin = intList.minBy { it }
if (intListMin != 1) return "Fail intListMin=$intListMin"
val intListMax = intList.maxBy { it }
if (intListMax != 3) return "Fail intListMax=$intListMax"
val longListMin = longList.minBy { it }
if (longListMin != 1L) return "Fail longListMin=$longListMin"
val longListMax = longList.maxBy { it }
if (longListMax != 3L) return "Fail longListMax=$longListMax"
return "OK"
}
@@ -0,0 +1,34 @@
// WITH_RUNTIME
// FILE: list.kt
val intList = listOf(1, 2, 3)
val longList = listOf(1L, 2L, 3L)
// FILE: box.kt
fun box(): String {
val intListMin = intList.minBy { it } ?: -1
if (intListMin != 1) return "Fail intListMin=$intListMin"
val intListMax = intList.maxBy { it } ?: -1
if (intListMax != 3) return "Fail intListMax=$intListMax"
val longListMin = longList.minBy { it } ?: -1
if (longListMin != 1L) return "Fail longListMin=$longListMin"
val longListMax = longList.maxBy { it } ?: -1
if (longListMax != 3L) return "Fail longListMax=$longListMax"
return "OK"
}
// @BoxKt.class:
// -- no boxing
// 0 valueOf
// -- no compareTo
// 0 compareTo
// -- comparisons are properly fused with conditional jumps
// 0 ICONST_0
// 1 IF_ICMPGE
// 1 IF_ICMPLE
// 4 LCMP
// 1 IFGE
// 1 IFLE
@@ -896,6 +896,24 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/boxingOptimization"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
@TestMetadata("boxedIntegersCmp.kt")
public void testBoxedIntegersCmp() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/boxedIntegersCmp.kt");
doTest(fileName);
}
@TestMetadata("boxedPrimitivesAreEqual.kt")
public void testBoxedPrimitivesAreEqual() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/boxedPrimitivesAreEqual.kt");
doTest(fileName);
}
@TestMetadata("boxedRealsCmp.kt")
public void testBoxedRealsCmp() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/boxedRealsCmp.kt");
doTest(fileName);
}
@TestMetadata("casts.kt")
public void testCasts() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/casts.kt");
@@ -926,6 +944,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
doTest(fileName);
}
@TestMetadata("intCompareTo.kt")
public void testIntCompareTo() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/intCompareTo.kt");
doTest(fileName);
}
@TestMetadata("kt15871.kt")
public void testKt15871() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/kt15871.kt");
@@ -962,6 +986,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
doTest(fileName);
}
@TestMetadata("maxMinBy.kt")
public void testMaxMinBy() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/maxMinBy.kt");
doTest(fileName);
}
@TestMetadata("nullCheck.kt")
public void testNullCheck() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/nullCheck.kt");
@@ -896,6 +896,24 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/boxingOptimization"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
@TestMetadata("boxedIntegersCmp.kt")
public void testBoxedIntegersCmp() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/boxedIntegersCmp.kt");
doTest(fileName);
}
@TestMetadata("boxedPrimitivesAreEqual.kt")
public void testBoxedPrimitivesAreEqual() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/boxedPrimitivesAreEqual.kt");
doTest(fileName);
}
@TestMetadata("boxedRealsCmp.kt")
public void testBoxedRealsCmp() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/boxedRealsCmp.kt");
doTest(fileName);
}
@TestMetadata("casts.kt")
public void testCasts() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/casts.kt");
@@ -926,6 +944,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest(fileName);
}
@TestMetadata("intCompareTo.kt")
public void testIntCompareTo() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/intCompareTo.kt");
doTest(fileName);
}
@TestMetadata("kt15871.kt")
public void testKt15871() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/kt15871.kt");
@@ -962,6 +986,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest(fileName);
}
@TestMetadata("maxMinBy.kt")
public void testMaxMinBy() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/maxMinBy.kt");
doTest(fileName);
}
@TestMetadata("nullCheck.kt")
public void testNullCheck() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/nullCheck.kt");
@@ -515,6 +515,12 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
doTest(fileName);
}
@TestMetadata("maxMinBy.kt")
public void testMaxMinBy() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/boxingOptimization/maxMinBy.kt");
doTest(fileName);
}
@TestMetadata("nullCheck.kt")
public void testNullCheck() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/boxingOptimization/nullCheck.kt");
@@ -896,6 +896,24 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/boxingOptimization"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
@TestMetadata("boxedIntegersCmp.kt")
public void testBoxedIntegersCmp() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/boxedIntegersCmp.kt");
doTest(fileName);
}
@TestMetadata("boxedPrimitivesAreEqual.kt")
public void testBoxedPrimitivesAreEqual() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/boxedPrimitivesAreEqual.kt");
doTest(fileName);
}
@TestMetadata("boxedRealsCmp.kt")
public void testBoxedRealsCmp() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/boxedRealsCmp.kt");
doTest(fileName);
}
@TestMetadata("casts.kt")
public void testCasts() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/casts.kt");
@@ -926,6 +944,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
doTest(fileName);
}
@TestMetadata("intCompareTo.kt")
public void testIntCompareTo() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/intCompareTo.kt");
doTest(fileName);
}
@TestMetadata("kt15871.kt")
public void testKt15871() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/kt15871.kt");
@@ -962,6 +986,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
doTest(fileName);
}
@TestMetadata("maxMinBy.kt")
public void testMaxMinBy() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/maxMinBy.kt");
doTest(fileName);
}
@TestMetadata("nullCheck.kt")
public void testNullCheck() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/nullCheck.kt");
@@ -1076,6 +1076,30 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/boxingOptimization"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
}
@TestMetadata("boxedIntegersCmp.kt")
public void testBoxedIntegersCmp() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/boxedIntegersCmp.kt");
doTest(fileName);
}
@TestMetadata("boxedPrimitivesAreEqual.kt")
public void testBoxedPrimitivesAreEqual() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/boxedPrimitivesAreEqual.kt");
doTest(fileName);
}
@TestMetadata("boxedRealsCmp.kt")
public void testBoxedRealsCmp() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/boxedRealsCmp.kt");
try {
doTest(fileName);
}
catch (Throwable ignore) {
return;
}
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
}
@TestMetadata("casts.kt")
public void testCasts() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/casts.kt");
@@ -1118,6 +1142,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
doTest(fileName);
}
@TestMetadata("intCompareTo.kt")
public void testIntCompareTo() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/intCompareTo.kt");
doTest(fileName);
}
@TestMetadata("kt15871.kt")
public void testKt15871() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/kt15871.kt");
@@ -1160,6 +1190,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
doTest(fileName);
}
@TestMetadata("maxMinBy.kt")
public void testMaxMinBy() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/maxMinBy.kt");
doTest(fileName);
}
@TestMetadata("nullCheck.kt")
public void testNullCheck() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/boxingOptimization/nullCheck.kt");