[K/N] Safer handling of bridges function in dce

This commit is contained in:
Pavel Kunyavskiy
2021-09-08 17:10:44 +03:00
committed by Space
parent 007cf2ce7c
commit 51c85e7f86
4 changed files with 30 additions and 0 deletions
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.backend.common.phaser.PhaserState
import org.jetbrains.kotlin.backend.common.phaser.namedUnitPhase
import org.jetbrains.kotlin.backend.konan.*
import org.jetbrains.kotlin.backend.konan.descriptors.GlobalHierarchyAnalysis
import org.jetbrains.kotlin.backend.konan.lower.DECLARATION_ORIGIN_BRIDGE_METHOD
import org.jetbrains.kotlin.backend.konan.lower.RedundantCoercionsCleaner
import org.jetbrains.kotlin.backend.konan.lower.ReturnsInsertionLowering
import org.jetbrains.kotlin.backend.konan.optimizations.*
@@ -25,6 +26,7 @@ import org.jetbrains.kotlin.ir.util.parentAsClass
import org.jetbrains.kotlin.ir.visitors.*
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.addToStdlib.cast
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
internal val contextLLVMSetupPhase = makeKonanModuleOpPhase(
name = "ContextLLVMSetup",
@@ -199,6 +201,11 @@ internal val dcePhase = makeKonanModuleOpPhase(
}
})
// TODO: Bridge function normally calls it's target, but it could be optimized out by Autoboxing and InlinePropertyAccessor
// lowerings. But Devirtualization doesn't handle this correctly, and can replace bridge call with call of it's target.
// So it's safer not to remove target if bridge is preserved, even if target itself is not called directly
referencedFunctions.addAll(referencedFunctions.mapNotNull { it.origin.safeAs<DECLARATION_ORIGIN_BRIDGE_METHOD>()?.bridgeTarget })
context.irModule!!.transformChildrenVoid(object: IrElementTransformerVoid() {
override fun visitFile(declaration: IrFile): IrFile {
declaration.declarations.removeAll {
@@ -2955,6 +2955,14 @@ standaloneTest("devirtualization_getter_looking_as_box_function") {
source = "codegen/devirtualization/getter_looking_as_box_function.kt"
}
standaloneTest("devirtualization_inline_getter") {
disabled = (cacheTesting != null) // Cache is not compatible with -opt.
useGoldenData = true
flags = ["-opt"]
source = "codegen/devirtualization/inline_getter.kt"
}
standaloneTest("devirtualization_anonymousObject") {
disabled = (cacheTesting != null) // Cache is not compatible with -opt.
useGoldenData = true
@@ -0,0 +1,13 @@
interface Base { val id: Int }
inline class Child(override val id: Int = 1) : Base
interface Base2 { val prop: Base }
class Child2(override val prop: Child) : Base2
fun main() {
val x : Base = Child(5)
println(x.id)
val y : Base2 = Child2(Child(5))
println(y.prop)
}
@@ -0,0 +1,2 @@
5
Child(id=5)