Devirtualization fails to eliminate boxing in function reference context

^KT-49847 Fixed

Merge-request: KT-MR-6460
Merged-by: Vladimir Sukharev <Vladimir.Sukharev@jetbrains.com>
This commit is contained in:
Vladimir Sukharev
2022-07-12 08:26:27 +00:00
committed by Space
parent 5013988dbb
commit fd52f475cb
19 changed files with 289 additions and 8 deletions
@@ -0,0 +1,21 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
class C {
fun foo(x: Int) = x
}
// CHECK: define void @"kfun:#main(){}"()
// CHECK-NOT: Int-box
// TODO Remove next check after fix of https://youtrack.jetbrains.com/issue/KT-53100/Optimization-needed-T-unboxCONSTANTPRIMITIVEx-T-x
// CHECK: Int-unbox
// CHECK-NOT: Int-unbox
// CHECK: ret void
fun main() {
val c = C()
val fooref = c::foo
if( fooref(42) == 42)
println("ok")
}
@@ -0,0 +1,21 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
class C<T> {
fun foo(x: T) = x
}
// CHECK: define void @"kfun:#main(){}"()
// CHECK-NOT: Int-box
// TODO Remove next check after fix of https://youtrack.jetbrains.com/issue/KT-53100/Optimization-needed-T-unboxCONSTANTPRIMITIVEx-T-x
// CHECK: Int-unbox
// CHECK-NOT: Int-unbox
// CHECK: ret void
fun main() {
val c = C<Int>()
val fooref = c::foo
if( fooref(42) == 42)
println("ok")
}
@@ -0,0 +1,13 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
// CHECK: define internal void @"kfun:$foo$FUNCTION_REFERENCE$0.<init>#internal"
// CHECK-SAME: i32
fun <T> T.foo() { println(this) }
fun main() {
println(5::foo)
}
@@ -0,0 +1,34 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
fun interface Foo {
fun bar(x: Int): Any
}
fun baz(x: Any): Int = x.hashCode()
// CHECK: define void @"kfun:#main(){}"()
// Boxing/unboxing need to be used now due to non-devirtualized call
// CHECK: Int-box
// TODO Remove two next checks, when advanced optimization of Int-unbox(Int-box(x)) would be done for snippet like:
// TODO VAR IR_TEMPORARY_VARIABLE name:arg0 type:kotlin.Any [val]
// TODO BLOCK type=kotlin.Any origin=null
// TODO CALL <Int-box>
// TODO GET_VAR 'val arg1: kotlin.Int [val]'
// TODO CALL <Int-unbox>
// TODO GET_VAR 'val arg0: kotlin.Any [val]'
// CHECK: Int-box
// CHECK: Int-unbox
// CHECK-NOT: Int-box
// CHECK-NOT: Int-unbox
// CHECK: ret void
fun main() {
val foo: Foo = Foo(::baz)
if( foo.bar(42) == 42 )
println("passed")
}
@@ -0,0 +1,24 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
fun interface Foo<T> {
fun bar(x: T): Any
}
fun baz(x: Any): Int = x.hashCode()
// CHECK: define void @"kfun:#main(){}"()
// Boxing/unboxing need to be used now due to non-devirtualized call
// CHECK: Int-box
// CHECK-NOT: Int-box
// CHECK: Int-unbox
// CHECK-NOT: Int-unbox
// CHECK-NOT: Int-box
// CHECK: ret void
fun main() {
val foo: Foo<Int> = Foo(::baz)
if( foo.bar(42) == 42 )
println("passed")
}
@@ -0,0 +1,20 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
fun interface Foo {
fun bar(x: Int): Int
}
fun baz(x: Int): Int = x.hashCode()
// CHECK: define void @"kfun:#main(){}"()
// CHECK-NOT: Int-box
// CHECK-NOT: Int-unbox
// CHECK: ret void
fun main() {
val foo: Foo = Foo(::baz)
if( foo.bar(42) == 42 )
println("passed")
}
@@ -0,0 +1,20 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
fun interface Foo<T> {
fun bar(x: T): Int
}
fun baz(x: Any): Int = x.hashCode()
// CHECK: define void @"kfun:#main(){}"()
// CHECK-NOT: Int-box
// CHECK-NOT: Int-unbox
// CHECK: ret void
fun main() {
val foo: Foo<Int> = Foo(::baz)
if( foo.bar(42) == 42 )
println("passed")
}
@@ -0,0 +1,20 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
fun plus1(x: Int) = x + 1
// CHECK: define void @"kfun:#main(){}"()
// CHECK-NOT: Int-box
// CHECK-NOT: Int-unbox
// CHECK: ret void
fun main() {
val ref = ::plus1
var y = 0
repeat(100000) {
y += ref(it) // Should be devirtualized and invoked without boxing/unboxing (`Int-box`/`Int-unbox`)
}
if (y > 999999)
println("y > 999999")
}