From 7c69d38588c00b39e7f5e04641226bed83c899a6 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Mon, 7 Oct 2024 20:39:49 +0200 Subject: [PATCH] scan all asmsubs to see if another subroutine is referenced. Fixes #153 --- compiler/test/TestOptimization.kt | 24 +++++++++++++++++++++ compilerAst/src/prog8/compiler/CallGraph.kt | 18 +++++++++------- examples/test.p8 | 23 ++++++++++++++------ 3 files changed, 51 insertions(+), 14 deletions(-) diff --git a/compiler/test/TestOptimization.kt b/compiler/test/TestOptimization.kt index fb91af9d0..a9080013e 100644 --- a/compiler/test/TestOptimization.kt +++ b/compiler/test/TestOptimization.kt @@ -47,6 +47,30 @@ class TestOptimization: FunSpec({ } } + test("scan all asmsubs to see if another subroutine is referenced") { + val src=""" +main { + sub foo() { + cx16.r0++ + } + asmsub baz() { + %asm{{ + jsr p8s_foo + }} + } + asmsub bar() { + %asm{{ + inx + jmp p8s_foo + }} + } + sub start() { + bar() + } +}""" + compileText(C64Target(), true, src) shouldNotBe null + } + test("don't remove empty subroutine if it's referenced") { val sourcecode = """ main { diff --git a/compilerAst/src/prog8/compiler/CallGraph.kt b/compilerAst/src/prog8/compiler/CallGraph.kt index 8b5ec582d..9abb45f24 100644 --- a/compilerAst/src/prog8/compiler/CallGraph.kt +++ b/compilerAst/src/prog8/compiler/CallGraph.kt @@ -162,20 +162,22 @@ class CallGraph(private val program: Program) : IAstVisitor { fun unused(sub: Subroutine): Boolean { if(sub in usedSubroutines) return false - val asm = nameInAssemblyCode(sub.name, listOf("p8s_", "")) - if(asm!=null) { + val asms = nameInAssemblyCode(sub.name, listOf("p8s_", "")) + if(asms.isEmpty()) + return true + val allUnused = asms.all { asm-> // check that the asm block that calls us, is inside a subroutine that is unused or not val containingSub = asm.definingSubroutine - return if(containingSub != null && containingSub !== sub) + if(containingSub != null && containingSub !== sub) unused(containingSub) else false } - return true + return allUnused } fun unused(block: Block): Boolean { - return block !in usedBlocks && nameInAssemblyCode(block.name, listOf("p8b_", ""))==null + return block !in usedBlocks && nameInAssemblyCode(block.name, listOf("p8b_", "")).isEmpty() } fun unused(decl: VarDecl): Boolean { @@ -198,13 +200,13 @@ class CallGraph(private val program: Program) : IAstVisitor { } private val prefixes = listOf("p8b_", "p8v_", "p8s_", "p8c_", "p8l_", "p8_", "") - private fun nameInAssemblyCode(name: String, knownAsmPrefixes: List = emptyList()): InlineAssembly? { + private fun nameInAssemblyCode(name: String, knownAsmPrefixes: List = emptyList()): List { if(knownAsmPrefixes.isNotEmpty()) - return allAssemblyNodes.firstOrNull { + return allAssemblyNodes.filter { knownAsmPrefixes.any { prefix -> prefix+name in it.names } } - return allAssemblyNodes.firstOrNull { + return allAssemblyNodes.filter { prefixes.any { prefix -> prefix+name in it.names } } } diff --git a/examples/test.p8 b/examples/test.p8 index 3ec96ba43..36cd589af 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,8 +1,19 @@ -%import textio -%zeropage basicsafe - main { - sub foo() { foo() } - sub bar() -> ubyte { return bar() } - sub start() { } + sub foo() { + cx16.r0++ + } + asmsub baz() { + %asm{{ + jsr p8s_foo + }} + } + asmsub bar() { + %asm{{ + inx + jmp p8s_foo + }} + } + sub start() { + bar() + } }