Skip to content

Commit

Permalink
don't remove consecutive assigns to IO space location
Browse files Browse the repository at this point in the history
  • Loading branch information
irmen committed Dec 24, 2022
1 parent b526e13 commit 81bd5c7
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 6 deletions.
16 changes: 12 additions & 4 deletions compiler/src/prog8/compiler/astprocessing/VariousCleanups.kt
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,18 @@ internal class VariousCleanups(val program: Program, val errors: IErrorReporter,
}

override fun after(assignment: Assignment, parent: Node): Iterable<IAstModification> {
val nextAssign = assignment.nextSibling() as? Assignment
if(nextAssign!=null && nextAssign.target.isSameAs(assignment.target, program)) {
if(!nextAssign.isAugmentable && nextAssign.value isSameAs assignment.value && assignment.value !is IFunctionCall) // don't remove function calls even when they're duplicates
return listOf(IAstModification.Remove(assignment, parent as IStatementContainer))
// remove duplicated assignments, but not if it's a memory mapped IO register
val isIO = try {
assignment.target.isIOAddress(options.compTarget.machine)
} catch (_: FatalAstException) {
false
}
if(!isIO) {
val nextAssign = assignment.nextSibling() as? Assignment
if (nextAssign != null && nextAssign.target.isSameAs(assignment.target, program)) {
if (!nextAssign.isAugmentable && nextAssign.value isSameAs assignment.value && assignment.value !is IFunctionCall) // don't remove function calls even when they're duplicates
return listOf(IAstModification.Remove(assignment, parent as IStatementContainer))
}
}

return noModifications
Expand Down
57 changes: 57 additions & 0 deletions compiler/test/TestOptimization.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import prog8.ast.statements.*
import prog8.code.core.DataType
import prog8.code.core.Position
import prog8.code.target.C64Target
import prog8.code.target.Cx16Target
import prog8.compiler.printProgram
import prog8tests.helpers.*

Expand Down Expand Up @@ -736,4 +737,60 @@ class TestOptimization: FunSpec({
val stmts = result.program.entrypoint.statements
stmts.size shouldBe 3
}

test("repeated assignments to IO register should remain") {
val srcX16="""
main {
sub start() {
ubyte @shared xx
xx = 42
xx = 42 ; removed
xx = 42 ; removed
cx16.VERA_DATA0 = 0
cx16.VERA_DATA0 = 0
cx16.VERA_DATA0 = 0
@($9fff) = 0
@($9fff) = 0
@($9fff) = 0
return
}
}"""
var result = compileText(Cx16Target(), true, srcX16, writeAssembly = true)!!
var statements = result.program.entrypoint.statements
statements.size shouldBe 9
(statements[1] as Assignment).target.identifier!!.nameInSource shouldBe listOf("xx")
(statements[2] as Assignment).target.identifier!!.nameInSource shouldBe listOf("cx16", "VERA_DATA0")
(statements[3] as Assignment).target.identifier!!.nameInSource shouldBe listOf("cx16", "VERA_DATA0")
(statements[4] as Assignment).target.identifier!!.nameInSource shouldBe listOf("cx16", "VERA_DATA0")
(statements[5] as Assignment).target.memoryAddress!!.addressExpression.constValue(result.program)!!.number shouldBe 0x9fff
(statements[6] as Assignment).target.memoryAddress!!.addressExpression.constValue(result.program)!!.number shouldBe 0x9fff
(statements[7] as Assignment).target.memoryAddress!!.addressExpression.constValue(result.program)!!.number shouldBe 0x9fff

val srcC64="""
main {
sub start() {
ubyte @shared xx
xx = 42
xx = 42 ;removed
xx = 42 ;removed
c64.EXTCOL = 0
c64.EXTCOL = 0
c64.EXTCOL = 0
@(53281) = 0
@(53281) = 0
@(53281) = 0
return
}
}"""
result = compileText(C64Target(), true, srcC64, writeAssembly = true)!!
statements = result.program.entrypoint.statements
statements.size shouldBe 9
(statements[1] as Assignment).target.identifier!!.nameInSource shouldBe listOf("xx")
(statements[2] as Assignment).target.identifier!!.nameInSource shouldBe listOf("c64", "EXTCOL")
(statements[3] as Assignment).target.identifier!!.nameInSource shouldBe listOf("c64", "EXTCOL")
(statements[4] as Assignment).target.identifier!!.nameInSource shouldBe listOf("c64", "EXTCOL")
(statements[5] as Assignment).target.memoryAddress!!.addressExpression.constValue(result.program)!!.number shouldBe 53281.0
(statements[6] as Assignment).target.memoryAddress!!.addressExpression.constValue(result.program)!!.number shouldBe 53281.0
(statements[7] as Assignment).target.memoryAddress!!.addressExpression.constValue(result.program)!!.number shouldBe 53281.0
}
})
3 changes: 1 addition & 2 deletions compilerAst/src/prog8/ast/statements/AstStatements.kt
Original file line number Diff line number Diff line change
Expand Up @@ -532,8 +532,7 @@ data class AssignTarget(var identifier: IdentifierReference?,
} else false
}
ident != null -> {
val decl = ident.targetVarDecl(definingModule.program) ?:
throw FatalAstException("invalid identifier ${ident.nameInSource}")
val decl = ident.targetVarDecl(definingModule.program) ?: throw FatalAstException("invalid identifier ${ident.nameInSource}")
return if (decl.type == VarDeclType.MEMORY && decl.value is NumericLiteral)
machine.isIOAddress((decl.value as NumericLiteral).number.toUInt())
else
Expand Down

0 comments on commit 81bd5c7

Please sign in to comment.