[K/N] Run inline property accessors later to inline all cases including devirtualized
This commit is contained in:
+9
-2
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl
|
||||
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
|
||||
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
|
||||
import org.jetbrains.kotlin.backend.common.ir.isPure
|
||||
import org.jetbrains.kotlin.ir.types.isUnit
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
|
||||
@@ -127,8 +128,14 @@ class PropertyAccessorInlineLowering(private val context: CommonBackendContext)
|
||||
|
||||
private fun isSimpleSetter(callee: IrSimpleFunction, backingField: IrField): Boolean {
|
||||
val body = callee.body?.let { it as IrBlockBody } ?: return false
|
||||
|
||||
val stmt = body.statements.singleOrNull() ?: return false
|
||||
val statementsSizeCheck = when (body.statements.size) {
|
||||
1 -> true
|
||||
// In K/N backend this lowering should be called after devirtualization. At this point IrReturns are already added.
|
||||
2 -> (body.statements[1] as? IrReturn)?.value?.type?.isUnit() == true
|
||||
else -> false
|
||||
}
|
||||
if (!statementsSizeCheck) return false
|
||||
val stmt = body.statements[0]
|
||||
val setFieldStmt = stmt as? IrSetField ?: return false
|
||||
if (setFieldStmt.symbol !== backingField.symbol) return false
|
||||
|
||||
|
||||
+4
-2
@@ -394,14 +394,15 @@ internal val bitcodePhase = NamedCompilerPhase(
|
||||
name = "Bitcode",
|
||||
description = "LLVM Bitcode generation",
|
||||
lower = contextLLVMSetupPhase then
|
||||
propertyAccessorInlinePhase then // Have to run after link dependencies phase, because fields
|
||||
// from dependencies can be changed during lowerings.
|
||||
returnsInsertionPhase then
|
||||
buildDFGPhase then
|
||||
devirtualizationAnalysisPhase then
|
||||
dcePhase then
|
||||
removeRedundantCallsToFileInitializersPhase then
|
||||
devirtualizationPhase then
|
||||
propertyAccessorInlinePhase then // Have to run after link dependencies phase, because fields
|
||||
// from dependencies can be changed during lowerings.
|
||||
inlineClassPropertyAccessorsPhase then
|
||||
redundantCoercionsCleaningPhase then
|
||||
createLLVMDeclarationsPhase then
|
||||
ghaPhase then
|
||||
@@ -493,6 +494,7 @@ internal fun PhaseConfig.konanPhasesConfig(config: KonanConfig) {
|
||||
// Inline accessors only in optimized builds due to separate compilation and possibility to get broken
|
||||
// debug information.
|
||||
disableUnless(propertyAccessorInlinePhase, getBoolean(KonanConfigKeys.OPTIMIZATION))
|
||||
disableUnless(inlineClassPropertyAccessorsPhase, getBoolean(KonanConfigKeys.OPTIMIZATION))
|
||||
disableUnless(dcePhase, getBoolean(KonanConfigKeys.OPTIMIZATION))
|
||||
disableUnless(removeRedundantCallsToFileInitializersPhase, getBoolean(KonanConfigKeys.OPTIMIZATION))
|
||||
disableUnless(ghaPhase, getBoolean(KonanConfigKeys.OPTIMIZATION))
|
||||
|
||||
+7
-5
@@ -13,6 +13,7 @@ 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.InlineClassPropertyAccessorsLowering
|
||||
import org.jetbrains.kotlin.backend.konan.lower.RedundantCoercionsCleaner
|
||||
import org.jetbrains.kotlin.backend.konan.lower.ReturnsInsertionLowering
|
||||
import org.jetbrains.kotlin.backend.konan.optimizations.*
|
||||
@@ -121,6 +122,12 @@ internal val returnsInsertionPhase = makeKonanModuleOpPhase(
|
||||
op = { context, irModule -> irModule.files.forEach { ReturnsInsertionLowering(context).lower(it) } }
|
||||
)
|
||||
|
||||
internal val inlineClassPropertyAccessorsPhase = makeKonanModuleOpPhase(
|
||||
name = "InlineClassPropertyAccessorsLowering",
|
||||
description = "Inline class property accessors",
|
||||
op = { context, irModule -> irModule.files.forEach { InlineClassPropertyAccessorsLowering(context).lower(it) } }
|
||||
)
|
||||
|
||||
internal val devirtualizationAnalysisPhase = makeKonanModuleOpPhase(
|
||||
name = "DevirtualizationAnalysis",
|
||||
description = "Devirtualization analysis",
|
||||
@@ -201,11 +208,6 @@ 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 {
|
||||
|
||||
-24
@@ -311,30 +311,6 @@ private class InlineClassTransformer(private val context: Context) : IrBuildingT
|
||||
return declaration
|
||||
}
|
||||
|
||||
override fun visitCall(expression: IrCall): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
// Make replacement only in optimized builds due to separate compilation and possibility to get broken
|
||||
// debug information.
|
||||
if (!context.shouldOptimize())
|
||||
return expression
|
||||
|
||||
val property = expression.symbol.owner.correspondingPropertySymbol?.owner ?: return expression
|
||||
|
||||
property.parent.let {
|
||||
if (it is IrClass && it.isInline && property.backingField != null) {
|
||||
expression.dispatchReceiver?.let { receiver ->
|
||||
return builder.at(expression)
|
||||
.irCall(symbols.reinterpret, expression.type, listOf(receiver.type, expression.type))
|
||||
.apply {
|
||||
extensionReceiver = receiver
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return expression
|
||||
}
|
||||
|
||||
private fun IrBuilderWithScope.irIsNull(expression: IrExpression): IrExpression {
|
||||
val binary = expression.type.computeBinaryType()
|
||||
return when (binary) {
|
||||
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan.lower
|
||||
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.lower.*
|
||||
import org.jetbrains.kotlin.backend.konan.*
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.visitors.*
|
||||
|
||||
|
||||
/**
|
||||
* Boxes and unboxes values of value types when necessary.
|
||||
*/
|
||||
internal class InlineClassPropertyAccessorsLowering(val context: Context) : FileLoweringPass {
|
||||
|
||||
private val transformer = InlineClassAccessorsTransformer(context)
|
||||
|
||||
override fun lower(irFile: IrFile) {
|
||||
irFile.transformChildrenVoid(transformer)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class InlineClassAccessorsTransformer(private val context: Context) : IrBuildingTransformer(context) {
|
||||
|
||||
private val symbols = context.ir.symbols
|
||||
|
||||
override fun visitCall(expression: IrCall): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
val property = expression.symbol.owner.correspondingPropertySymbol?.owner ?: return expression
|
||||
|
||||
property.parent.let {
|
||||
if (it is IrClass && it.isInline && property.backingField != null) {
|
||||
expression.dispatchReceiver?.let { receiver ->
|
||||
return builder.at(expression)
|
||||
.irCall(symbols.reinterpret, expression.type, listOf(receiver.type, expression.type))
|
||||
.apply {
|
||||
extensionReceiver = receiver
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return expression
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user