reducing dependencies

This commit is contained in:
Irmen de Jong 2021-02-20 17:33:45 +01:00
parent f4cef3eaf2
commit 781915d2cf
6 changed files with 24 additions and 14 deletions

View File

@ -267,14 +267,14 @@ private fun optimizeAst(programAst: Program, errors: IErrorReporter, functions:
// keep optimizing expressions and statements until no more steps remain
val optsDone1 = programAst.simplifyExpressions()
val optsDone2 = programAst.splitBinaryExpressions(compTarget)
val optsDone3 = programAst.optimizeStatements(errors, functions, compTarget)
val optsDone3 = programAst.optimizeStatements(errors, functions, compTarget, ::loadAsmIncludeFile)
programAst.constantFold(errors, compTarget) // because simplified statements and expressions can result in more constants that can be folded away
errors.report()
if (optsDone1 + optsDone2 + optsDone3 == 0)
break
}
val remover = UnusedCodeRemover(programAst, errors, compTarget)
val remover = UnusedCodeRemover(programAst, errors, compTarget, ::loadAsmIncludeFile)
remover.visit(programAst)
remover.applyModifications()
errors.report()
@ -286,7 +286,7 @@ private fun postprocessAst(programAst: Program, errors: IErrorReporter, compiler
programAst.variousCleanups()
programAst.checkValid(compilerOptions, errors, compilerOptions.compTarget) // check if final tree is still valid
errors.report()
val callGraph = CallGraph(programAst)
val callGraph = CallGraph(programAst, ::loadAsmIncludeFile)
callGraph.checkRecursiveCalls(errors)
errors.report()
programAst.verifyFunctionArgTypes()

View File

@ -12,7 +12,7 @@ import prog8.ast.expressions.IdentifierReference
import prog8.ast.statements.*
import prog8.ast.walk.IAstVisitor
import prog8.compiler.IErrorReporter
import prog8.compiler.loadAsmIncludeFile
import java.nio.file.Path
private val alwaysKeepSubroutines = setOf(
Pair("main", "start"),
@ -23,7 +23,7 @@ private val asmJumpRx = Regex("""[\-+a-zA-Z0-9_ \t]+(jmp|jsr)[ \t]+(\S+).*""", R
private val asmRefRx = Regex("""[\-+a-zA-Z0-9_ \t]+(...)[ \t]+(\S+).*""", RegexOption.IGNORE_CASE)
class CallGraph(private val program: Program) : IAstVisitor {
class CallGraph(private val program: Program, private val asmFileLoader: (filename: String, source: Path)->String) : IAstVisitor {
val imports = mutableMapOf<Module, List<Module>>().withDefault { mutableListOf() }
val importedBy = mutableMapOf<Module, List<Module>>().withDefault { mutableListOf() }
@ -80,7 +80,7 @@ class CallGraph(private val program: Program) : IAstVisitor {
imports[thisModule] = imports.getValue(thisModule).plus(importedModule)
importedBy[importedModule] = importedBy.getValue(importedModule).plus(thisModule)
} else if (directive.directive == "%asminclude") {
val asm = loadAsmIncludeFile(directive.args[0].str!!, thisModule.source)
val asm = asmFileLoader(directive.args[0].str!!, thisModule.source)
val scope = directive.definingSubroutine()
if(scope!=null) {
scanAssemblyCode(asm, directive, scope)

View File

@ -4,6 +4,7 @@ import prog8.ast.IBuiltinFunctions
import prog8.ast.Program
import prog8.compiler.IErrorReporter
import prog8.compiler.target.ICompilationTarget
import java.nio.file.Path
internal fun Program.constantFold(errors: IErrorReporter, compTarget: ICompilationTarget) {
@ -40,8 +41,11 @@ internal fun Program.constantFold(errors: IErrorReporter, compTarget: ICompilati
}
internal fun Program.optimizeStatements(errors: IErrorReporter, functions: IBuiltinFunctions, compTarget: ICompilationTarget): Int {
val optimizer = StatementOptimizer(this, errors, functions, compTarget)
internal fun Program.optimizeStatements(errors: IErrorReporter,
functions: IBuiltinFunctions,
compTarget: ICompilationTarget,
asmFileLoader: (filename: String, source: Path)->String): Int {
val optimizer = StatementOptimizer(this, errors, functions, compTarget, asmFileLoader)
optimizer.visit(this)
val optimizationCount = optimizer.applyModifications()

View File

@ -12,17 +12,19 @@ import prog8.ast.walk.IAstModification
import prog8.ast.walk.IAstVisitor
import prog8.compiler.IErrorReporter
import prog8.compiler.target.ICompilationTarget
import java.nio.file.Path
import kotlin.math.floor
internal class StatementOptimizer(private val program: Program,
private val errors: IErrorReporter,
private val functions: IBuiltinFunctions,
private val compTarget: ICompilationTarget
private val compTarget: ICompilationTarget,
private val asmFileLoader: (filename: String, source: Path)->String
) : AstWalker() {
private val noModifications = emptyList<IAstModification>()
private val callgraph = CallGraph(program)
private val callgraph = CallGraph(program, asmFileLoader)
override fun after(block: Block, parent: Node): Iterable<IAstModification> {
if("force_output" !in block.options()) {

View File

@ -12,12 +12,16 @@ import prog8.ast.walk.AstWalker
import prog8.ast.walk.IAstModification
import prog8.compiler.IErrorReporter
import prog8.compiler.target.ICompilationTarget
import java.nio.file.Path
internal class UnusedCodeRemover(private val program: Program, private val errors: IErrorReporter, private val compTarget: ICompilationTarget): AstWalker() {
internal class UnusedCodeRemover(private val program: Program,
private val errors: IErrorReporter,
private val compTarget: ICompilationTarget,
private val asmFileLoader: (filename: String, source: Path)->String): AstWalker() {
override fun before(program: Program, parent: Node): Iterable<IAstModification> {
val callgraph = CallGraph(program)
val callgraph = CallGraph(program, asmFileLoader)
val removals = mutableListOf<IAstModification>()
// remove all subroutines that aren't called, or are empty

View File

@ -5,8 +5,6 @@ TODO
- add sound to the cx16 tehtriz
- hoist all variable declarations up to the subroutine scope *before* even the constant folding takes place (to avoid undefined symbol errors when referring to a variable from another nested scope in the subroutine)
- refactor the asmgen into their own submodule?
- refactor the compiler optimizers into their own submodule?
- optimize swap of two memread values with index, using the same pointer expression/variable, like swap(@(ptr+1), @(ptr+2))
- optimize several inner loops in gfx2 (highres 4 color mode)
- use the 65c02 bit clear/set/test instructions for single-bit operations
@ -14,6 +12,8 @@ TODO
- add modes 2 and 3 to gfx2 (lowres 4 color and 16 color)
- add a flood fill routine to gfx2?
- add a f_seek() routine for the Cx16 that uses its seek dos api?
- refactor the asmgen into their own submodule?
- refactor the compiler optimizers into their own submodule?
- optimizer: detect variables that are written but never read - mark those as unused too and remove them, such as uword unused = memory("unused222", 20) - also remove the memory slab allocation
- add a compiler option to not remove unused subroutines. this allows for building library programs
- make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as 'v_'