Added Global hierarchy analysis phase

This commit is contained in:
Igor Chevdar
2019-09-24 13:57:36 +03:00
committed by Igor Chevdar
parent 2195687f63
commit afe9f07cbc
8 changed files with 20 additions and 15 deletions
@@ -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
@@ -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))
} }
} }
@@ -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()
} }
@@ -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>"}"
@@ -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]
@@ -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
@@ -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)
@@ -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 {