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:
@@ -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
|
||||
Reference in New Issue
Block a user