[IR] Optimize a few hot spots to reduce total CPU time

^KT-61121
This commit is contained in:
Mark Mann
2023-08-09 18:35:45 +02:00
committed by Space Team
parent 83a70ddf8b
commit 8a31e2ed82
12 changed files with 53 additions and 30 deletions
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.konan.ir.konanLibrary
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.util.fileOrNull
import org.jetbrains.kotlin.backend.konan.llvm.KonanMetadata
import org.jetbrains.kotlin.ir.util.getPackageFragment
import org.jetbrains.kotlin.library.KotlinLibrary
@@ -28,10 +29,20 @@ internal abstract class LlvmModuleSpecificationBase(protected val cachedLibrarie
override fun containsPackageFragment(packageFragment: IrPackageFragment): Boolean =
packageFragment.konanLibrary.let { it == null || containsLibrary(it) }
override fun containsDeclaration(declaration: IrDeclaration): Boolean =
declaration.konanLibrary.let { it == null || containsLibrary(it) }
// When producing per-file caches, some declarations might be generated by the stub generator.
&& declaration.getPackageFragment() !is IrExternalPackageFragment
private val containsCache = mutableMapOf<IrDeclaration, Boolean>()
// This is essentially memoizing the IrDeclaration.konanLibrary property -- so much of the implementation
// is inlined here to take greater advantage of the cache.
override fun containsDeclaration(declaration: IrDeclaration): Boolean = containsCache.getOrPut(declaration) {
val metadata = ((declaration as? IrMetadataSourceOwner)?.metadata as? KonanMetadata)
if (metadata != null) {
(metadata.konanLibrary == null || containsLibrary(metadata.konanLibrary)) && declaration.getPackageFragment() !is IrExternalPackageFragment
} else when (val parent = declaration.parent) {
is IrPackageFragment -> parent.konanLibrary.let { it == null || containsLibrary(it) } && parent !is IrExternalPackageFragment
is IrDeclaration -> containsDeclaration(parent)
else -> TODO("Unexpected declaration parent: $parent")
}
}
}
internal class DefaultLlvmModuleSpecification(cachedLibraries: CachedLibraries)
@@ -163,8 +163,9 @@ internal fun PsiToIrContext.psiToIr(
var dependenciesCount = 0
while (true) {
// context.config.librariesWithDependencies could change at each iteration.
val libsWithDeps = config.librariesWithDependencies().toSet()
val dependencies = moduleDescriptor.allDependencyModules.filter {
config.librariesWithDependencies().contains(it.konanLibrary)
libsWithDeps.contains(it.konanLibrary)
}
fun sortDependencies(dependencies: List<ModuleDescriptor>): Collection<ModuleDescriptor> {
@@ -110,6 +110,8 @@ val IrPackageFragment.konanLibrary : KotlinLibrary?
}
return this.packageFragmentDescriptor.containingDeclaration.konanLibrary
}
// Any changes made to konanLibrary here should be ported to the containsDeclaration
// function in LlvmModuleSpecificationBase in LlvmModuleSpecificationImpl.kt
val IrDeclaration.konanLibrary: KotlinLibrary?
get() {
((this as? IrMetadataSourceOwner)?.metadata as? KonanMetadata)?.let { return it.konanLibrary }
@@ -1785,7 +1785,7 @@ private fun ObjCExportCodeGenerator.createDirectAdapters(
)
}
val inheritedAdapters = superClass?.getAllRequiredDirectAdapters().orEmpty()
val inheritedAdapters = superClass?.getAllRequiredDirectAdapters().orEmpty().toSet()
val requiredAdapters = typeDeclaration.getAllRequiredDirectAdapters() - inheritedAdapters
return requiredAdapters.distinctBy { it.base.selector }.map { createMethodAdapter(it) }
@@ -43,7 +43,7 @@ internal class BuiltinOperatorLowering(val context: Context) : FileLoweringPass,
expression.transformChildrenVoid(this)
return when (expression.symbol) {
irBuiltins.eqeqSymbol, in ieee754EqualsSymbols() -> lowerEqeq(expression)
irBuiltins.eqeqSymbol, in ieee754EqualsSymbols -> lowerEqeq(expression)
irBuiltins.eqeqeqSymbol -> lowerEqeqeq(expression)
@@ -70,8 +70,8 @@ internal class BuiltinOperatorLowering(val context: Context) : FileLoweringPass,
return expression
}
private fun ieee754EqualsSymbols(): List<IrSimpleFunctionSymbol> =
irBuiltins.ieee754equalsFunByOperandType.values.toList()
private val ieee754EqualsSymbols: Set<IrSimpleFunctionSymbol> =
irBuiltins.ieee754equalsFunByOperandType.values.toSet()
private fun lowerEqeqeq(expression: IrCall): IrExpression {
val lhs = expression.getValueArgument(0)!!
@@ -191,7 +191,7 @@ internal class BuiltinOperatorLowering(val context: Context) : FileLoweringPass,
// TODO: areEqualByValue and ieee754Equals intrinsics are specially treated by code generator
// and thus can be declared synthetically in the compiler instead of explicitly in the runtime.
fun callEquals(lhs: IrExpression, rhs: IrExpression) =
if (symbol in ieee754EqualsSymbols())
if (symbol in ieee754EqualsSymbols)
// Find a type-compatible `konan.internal.ieee754Equals` intrinsic:
irCall(selectIntrinsic(symbols.ieee754Equals, lhs.type, rhs.type, true)!!).apply {
putValueArgument(0, lhs)
@@ -206,7 +206,7 @@ internal class BuiltinOperatorLowering(val context: Context) : FileLoweringPass,
val lhsIsNotNullable = !lhs.type.isNullable()
val rhsIsNotNullable = !rhs.type.isNullable()
return if (symbol in ieee754EqualsSymbols()) {
return if (symbol in ieee754EqualsSymbols) {
if (lhsIsNotNullable && rhsIsNotNullable)
callEquals(lhs, rhs)
else irBlock {
@@ -33,7 +33,7 @@ internal class PreInlineLowering(val context: Context) : BodyLoweringPass {
private val symbols get() = context.ir.symbols
private val asserts = symbols.asserts
private val asserts = symbols.asserts.toSet()
private val enableAssertions = context.config.configuration.getBoolean(KonanConfigKeys.ENABLE_ASSERTIONS)
override fun lower(irBody: IrBody, container: IrDeclaration) = lower(irBody, container, container.file)
@@ -179,12 +179,12 @@ internal object StaticInitializersOptimization {
val functionsRequiringGlobalInitializerCall = collectFunctionsRequiringInitializerCall(
initializedFiles.beforeCallGlobal,
callSitesRequiringGlobalInitializerCall.map { it.actualCallee }
.toMutableSet().intersect(callSitesNotRequiringGlobalInitializerCall.map { it.actualCallee })
.intersect(callSitesNotRequiringGlobalInitializerCall.mapTo(mutableSetOf()) { it.actualCallee })
)
val functionsRequiringThreadLocalInitializerCall = collectFunctionsRequiringInitializerCall(
initializedFiles.beforeCallThreadLocal,
callSitesRequiringThreadLocalInitializerCall.map { it.actualCallee }
.toMutableSet().intersect(callSitesNotRequiringThreadLocalInitializerCall.map { it.actualCallee })
.intersect(callSitesNotRequiringThreadLocalInitializerCall.mapTo(mutableSetOf()) { it.actualCallee })
)
return AnalysisResult(functionsRequiringGlobalInitializerCall, functionsRequiringThreadLocalInitializerCall,