Added Global hierarchy analysis phase
This commit is contained in:
committed by
Igor Chevdar
parent
2195687f63
commit
afe9f07cbc
+1
@@ -435,6 +435,7 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
|
|||||||
fun shouldContainAnyDebugInfo() = shouldContainDebugInfo() || shouldContainLocationDebugInfo()
|
fun shouldContainAnyDebugInfo() = shouldContainDebugInfo() || shouldContainLocationDebugInfo()
|
||||||
|
|
||||||
fun shouldOptimize() = config.configuration.getBoolean(KonanConfigKeys.OPTIMIZATION)
|
fun shouldOptimize() = config.configuration.getBoolean(KonanConfigKeys.OPTIMIZATION)
|
||||||
|
fun ghaEnabled() = ::globalHierarchyAnalysisResult.isInitialized
|
||||||
|
|
||||||
val memoryModel = config.memoryModel
|
val memoryModel = config.memoryModel
|
||||||
|
|
||||||
|
|||||||
+2
@@ -361,6 +361,7 @@ internal val bitcodePhase = namedIrModulePhase(
|
|||||||
devirtualizationPhase then
|
devirtualizationPhase then
|
||||||
dcePhase then
|
dcePhase then
|
||||||
contextLLVMSetupPhase then
|
contextLLVMSetupPhase then
|
||||||
|
ghaPhase then
|
||||||
RTTIPhase then
|
RTTIPhase then
|
||||||
generateDebugInfoHeaderPhase then
|
generateDebugInfoHeaderPhase then
|
||||||
escapeAnalysisPhase then
|
escapeAnalysisPhase then
|
||||||
@@ -424,6 +425,7 @@ internal fun PhaseConfig.konanPhasesConfig(config: KonanConfig) {
|
|||||||
disableUnless(buildDFGPhase, getBoolean(KonanConfigKeys.OPTIMIZATION))
|
disableUnless(buildDFGPhase, getBoolean(KonanConfigKeys.OPTIMIZATION))
|
||||||
disableUnless(devirtualizationPhase, getBoolean(KonanConfigKeys.OPTIMIZATION))
|
disableUnless(devirtualizationPhase, getBoolean(KonanConfigKeys.OPTIMIZATION))
|
||||||
disableUnless(dcePhase, getBoolean(KonanConfigKeys.OPTIMIZATION))
|
disableUnless(dcePhase, getBoolean(KonanConfigKeys.OPTIMIZATION))
|
||||||
|
disableUnless(ghaPhase, getBoolean(KonanConfigKeys.OPTIMIZATION))
|
||||||
disableUnless(verifyBitcodePhase, config.needCompilerVerification || getBoolean(KonanConfigKeys.VERIFY_BITCODE))
|
disableUnless(verifyBitcodePhase, config.needCompilerVerification || getBoolean(KonanConfigKeys.VERIFY_BITCODE))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+3
-3
@@ -93,7 +93,7 @@ internal class ClassGlobalHierarchyInfo(val classIdLo: Int, val classIdHi: Int,
|
|||||||
|
|
||||||
internal class GlobalHierarchyAnalysisResult(val bitsPerColor: Int)
|
internal class GlobalHierarchyAnalysisResult(val bitsPerColor: Int)
|
||||||
|
|
||||||
internal class GlobalHierarchyAnalysis(val context: Context) {
|
internal class GlobalHierarchyAnalysis(val context: Context, val irModule: IrModuleFragment) {
|
||||||
fun run() {
|
fun run() {
|
||||||
/*
|
/*
|
||||||
* The algorithm for fast interface call and check:
|
* The algorithm for fast interface call and check:
|
||||||
@@ -142,7 +142,7 @@ internal class GlobalHierarchyAnalysis(val context: Context) {
|
|||||||
val root = context.irBuiltIns.anyClass.owner
|
val root = context.irBuiltIns.anyClass.owner
|
||||||
val immediateInheritors = mutableMapOf<IrClass, MutableList<IrClass>>()
|
val immediateInheritors = mutableMapOf<IrClass, MutableList<IrClass>>()
|
||||||
val allClasses = mutableListOf<IrClass>()
|
val allClasses = mutableListOf<IrClass>()
|
||||||
context.irModule!!.acceptVoid(object: IrElementVisitorVoid {
|
irModule.acceptVoid(object: IrElementVisitorVoid {
|
||||||
override fun visitElement(element: IrElement) {
|
override fun visitElement(element: IrElement) {
|
||||||
element.acceptChildrenVoid(this)
|
element.acceptChildrenVoid(this)
|
||||||
}
|
}
|
||||||
@@ -251,7 +251,7 @@ internal class GlobalHierarchyAnalysis(val context: Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun assignColorsToInterfaces(): Map<IrClass, Int> {
|
private fun assignColorsToInterfaces(): Map<IrClass, Int> {
|
||||||
val graph = InterfacesForbiddennessGraph.build(context.irModule!!)
|
val graph = InterfacesForbiddennessGraph.build(irModule)
|
||||||
val coloring = graph.computeColoringGreedy()
|
val coloring = graph.computeColoringGreedy()
|
||||||
return graph.nodes.mapIndexed { v, irClass -> irClass to coloring[v] }.toMap()
|
return graph.nodes.mapIndexed { v, irClass -> irClass to coloring[v] }.toMap()
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-5
@@ -38,11 +38,7 @@ internal val contextLLVMSetupPhase = makeKonanModuleOpPhase(
|
|||||||
internal val RTTIPhase = makeKonanModuleOpPhase(
|
internal val RTTIPhase = makeKonanModuleOpPhase(
|
||||||
name = "RTTI",
|
name = "RTTI",
|
||||||
description = "RTTI generation",
|
description = "RTTI generation",
|
||||||
op = { context, irModule ->
|
op = { context, irModule -> irModule.acceptVoid(RTTIGeneratorVisitor(context)) }
|
||||||
if (context.shouldOptimize())
|
|
||||||
GlobalHierarchyAnalysis(context).run()
|
|
||||||
irModule.acceptVoid(RTTIGeneratorVisitor(context))
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
internal val generateDebugInfoHeaderPhase = makeKonanModuleOpPhase(
|
internal val generateDebugInfoHeaderPhase = makeKonanModuleOpPhase(
|
||||||
@@ -82,6 +78,12 @@ internal val devirtualizationPhase = makeKonanModuleOpPhase(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
internal val ghaPhase = makeKonanModuleOpPhase(
|
||||||
|
name = "GHAPhase",
|
||||||
|
description = "Global hierarchy analysis",
|
||||||
|
op = { context, irModule -> GlobalHierarchyAnalysis(context, irModule).run() }
|
||||||
|
)
|
||||||
|
|
||||||
internal val IrFunction.longName: String
|
internal val IrFunction.longName: String
|
||||||
get() = "${(parent as? IrClass)?.name?.asString() ?: "<root>"}.${(this as? IrSimpleFunction)?.name ?: "<init>"}"
|
get() = "${(parent as? IrClass)?.name?.asString() ?: "<root>"}.${(this as? IrSimpleFunction)?.name ?: "<init>"}"
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -779,7 +779,7 @@ internal class FunctionGenerationContext(val function: LLVMValueRef,
|
|||||||
load(slot)
|
load(slot)
|
||||||
}
|
}
|
||||||
|
|
||||||
!context.shouldOptimize() -> call(context.llvm.lookupOpenMethodFunction, listOf(typeInfoPtr, methodHash))
|
!context.ghaEnabled() -> call(context.llvm.lookupOpenMethodFunction, listOf(typeInfoPtr, methodHash))
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
// Essentially: typeInfo.itable[place(interfaceId)].vtable[method]
|
// Essentially: typeInfo.itable[place(interfaceId)].vtable[method]
|
||||||
|
|||||||
+1
-1
@@ -1392,7 +1392,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
|||||||
|
|
||||||
val srcObjInfoPtr = functionGenerationContext.bitcast(codegen.kObjHeaderPtr, obj)
|
val srcObjInfoPtr = functionGenerationContext.bitcast(codegen.kObjHeaderPtr, obj)
|
||||||
|
|
||||||
return if (!context.shouldOptimize()) {
|
return if (!context.ghaEnabled()) {
|
||||||
call(context.llvm.isInstanceFunction, listOf(srcObjInfoPtr, codegen.typeInfoValue(dstClass)))
|
call(context.llvm.isInstanceFunction, listOf(srcObjInfoPtr, codegen.typeInfoValue(dstClass)))
|
||||||
} else {
|
} else {
|
||||||
val dstHierarchyInfo = context.getLayoutBuilder(dstClass).hierarchyInfo
|
val dstHierarchyInfo = context.getLayoutBuilder(dstClass).hierarchyInfo
|
||||||
|
|||||||
+4
-4
@@ -225,7 +225,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
|||||||
val reflectionInfo = getReflectionInfo(irClass)
|
val reflectionInfo = getReflectionInfo(irClass)
|
||||||
val typeInfoGlobal = llvmDeclarations.typeInfoGlobal
|
val typeInfoGlobal = llvmDeclarations.typeInfoGlobal
|
||||||
val hierarchyInfo =
|
val hierarchyInfo =
|
||||||
if (context.shouldOptimize())
|
if (context.ghaEnabled())
|
||||||
context.getLayoutBuilder(irClass).hierarchyInfo
|
context.getLayoutBuilder(irClass).hierarchyInfo
|
||||||
else ClassGlobalHierarchyInfo.DUMMY
|
else ClassGlobalHierarchyInfo.DUMMY
|
||||||
val typeInfo = TypeInfo(
|
val typeInfo = TypeInfo(
|
||||||
@@ -302,7 +302,7 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun interfaceTable(irClass: IrClass): Pair<ConstPointer?, Int> {
|
private fun interfaceTable(irClass: IrClass): Pair<ConstPointer?, Int> {
|
||||||
val needInterfaceTable = context.shouldOptimize() && !irClass.isInterface
|
val needInterfaceTable = context.ghaEnabled() && !irClass.isInterface
|
||||||
&& !irClass.isAbstract() && !irClass.isObjCClass()
|
&& !irClass.isAbstract() && !irClass.isObjCClass()
|
||||||
if (!needInterfaceTable) return Pair(null, 0)
|
if (!needInterfaceTable) return Pair(null, 0)
|
||||||
// The details are in ClassLayoutBuilder.
|
// The details are in ClassLayoutBuilder.
|
||||||
@@ -484,12 +484,12 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
|||||||
val typeInfoWithVtableType = structType(runtime.typeInfoType, vtable.llvmType)
|
val typeInfoWithVtableType = structType(runtime.typeInfoType, vtable.llvmType)
|
||||||
val typeInfoWithVtableGlobal = staticData.createGlobal(typeInfoWithVtableType, "", isExported = false)
|
val typeInfoWithVtableGlobal = staticData.createGlobal(typeInfoWithVtableType, "", isExported = false)
|
||||||
val result = typeInfoWithVtableGlobal.pointer.getElementPtr(0)
|
val result = typeInfoWithVtableGlobal.pointer.getElementPtr(0)
|
||||||
val typeHierarchyInfo = if (!context.shouldOptimize())
|
val typeHierarchyInfo = if (!context.ghaEnabled())
|
||||||
ClassGlobalHierarchyInfo.DUMMY
|
ClassGlobalHierarchyInfo.DUMMY
|
||||||
else
|
else
|
||||||
ClassGlobalHierarchyInfo(-1, -1, 0, 0)
|
ClassGlobalHierarchyInfo(-1, -1, 0, 0)
|
||||||
|
|
||||||
val interfaceTable = if (!context.shouldOptimize()) null else {
|
val interfaceTable = if (!context.ghaEnabled()) null else {
|
||||||
val layoutBuilder = context.getLayoutBuilder(irClass)
|
val layoutBuilder = context.getLayoutBuilder(irClass)
|
||||||
val vtableEntries = layoutBuilder.interfaceTableEntries.map { methodImpls[it]!!.bitcast(int8TypePtr) }
|
val vtableEntries = layoutBuilder.interfaceTableEntries.map { methodImpls[it]!!.bitcast(int8TypePtr) }
|
||||||
val interfaceVTable = staticData.placeGlobalArray("", kInt8Ptr, vtableEntries)
|
val interfaceVTable = staticData.placeGlobalArray("", kInt8Ptr, vtableEntries)
|
||||||
|
|||||||
+1
-1
@@ -932,7 +932,7 @@ private fun ObjCExportCodeGenerator.vtableIndex(irFunction: IrSimpleFunction): I
|
|||||||
private fun ObjCExportCodeGenerator.itablePlace(irFunction: IrSimpleFunction): ClassLayoutBuilder.InterfaceTablePlace? {
|
private fun ObjCExportCodeGenerator.itablePlace(irFunction: IrSimpleFunction): ClassLayoutBuilder.InterfaceTablePlace? {
|
||||||
assert(irFunction.isOverridable)
|
assert(irFunction.isOverridable)
|
||||||
val irClass = irFunction.parentAsClass
|
val irClass = irFunction.parentAsClass
|
||||||
return if (irClass.isInterface && context.shouldOptimize()
|
return if (irClass.isInterface && context.ghaEnabled()
|
||||||
&& (irFunction.isReal || irFunction.resolveFakeOverrideMaybeAbstract().parent != context.irBuiltIns.anyClass.owner)) {
|
&& (irFunction.isReal || irFunction.resolveFakeOverrideMaybeAbstract().parent != context.irBuiltIns.anyClass.owner)) {
|
||||||
context.getLayoutBuilder(irClass).itablePlace(irFunction)
|
context.getLayoutBuilder(irClass).itablePlace(irFunction)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user