reduce slow estack usage by splitting up simple binary expressions

This commit is contained in:
Irmen de Jong 2020-09-30 19:57:16 +02:00
parent d020a7974a
commit bda1c1c1eb
7 changed files with 56 additions and 9 deletions

View File

@ -35,4 +35,5 @@ internal interface IMachineDefinition {
fun getFloatRomConst(number: Double): String?
fun importLibs(compilerOptions: CompilationOptions, importer: ModuleImporter, program: Program)
fun launchEmulator(programName: String)
fun isRAMaddress(address: Int): Boolean
}

View File

@ -89,6 +89,8 @@ internal object C64MachineDefinition: IMachineDefinition {
}
}
override fun isRAMaddress(address: Int): Boolean = (address<0xa000) || (address in 0xc000..0xd000)
override fun initializeZeropage(compilerOptions: CompilationOptions) {
zeropage = C64Zeropage(compilerOptions)
}

View File

@ -52,6 +52,10 @@ internal object CX16MachineDefinition: IMachineDefinition {
}
}
override fun isRAMaddress(address: Int): Boolean {
return address < 0x9000 // TODO put correct Cx16 mem ranges here
}
override fun initializeZeropage(compilerOptions: CompilationOptions) {
zeropage = CX16Zeropage(compilerOptions)
}

View File

@ -449,12 +449,34 @@ internal class StatementOptimizer(private val program: Program,
fun isSimpleTarget(target: AssignTarget): Boolean {
return when {
target.identifier!=null -> true
target.identifier!=null -> {
val decl = target.identifier!!.targetVarDecl(program.namespace)!!
return if(decl.type!=VarDeclType.MEMORY) {
if(decl.value is NumericLiteralValue) {
CompilationTarget.instance.machine.isRAMaddress((decl.value as NumericLiteralValue).number.toInt())
} else {
false
}
} else true
}
target.memoryAddress!=null -> {
target.memoryAddress.addressExpression is NumericLiteralValue || target.memoryAddress.addressExpression is IdentifierReference
return when (target.memoryAddress.addressExpression) {
is NumericLiteralValue -> {
CompilationTarget.instance.machine.isRAMaddress((target.memoryAddress.addressExpression as NumericLiteralValue).number.toInt())
}
is IdentifierReference -> {
val decl = (target.memoryAddress.addressExpression as IdentifierReference).targetVarDecl(program.namespace)!!
if(decl.value is NumericLiteralValue) {
CompilationTarget.instance.machine.isRAMaddress((decl.value as NumericLiteralValue).number.toInt())
} else {
false
}
}
else -> false
}
}
target.arrayindexed!=null -> {
target.arrayindexed!!.arrayspec.index is NumericLiteralValue || target.arrayindexed!!.arrayspec.index is IdentifierReference
target.arrayindexed!!.arrayspec.index is NumericLiteralValue
}
else -> false
}
@ -465,16 +487,14 @@ internal class StatementOptimizer(private val program: Program,
// X = <some-expression-not-X> <operator> <not-binary-expression>
// or X = <not-binary-expression> <associativeoperator> <some-expression-not-X>
// split that into X = <some-expression-not-X> ; X = X <operator> <not-binary-expression>
if(!assignment.isAugmentable && isSimpleTarget(assignment.target)) {
if(bexpr.operator !in comparisonOperators && !assignment.isAugmentable && isSimpleTarget(assignment.target)) {
if (bexpr.right !is BinaryExpression) {
println("SPLIT RIGHT ${bexpr.left}\n ${bexpr.operator}\n ${bexpr.right}")
val firstAssign = Assignment(assignment.target, bexpr.left, assignment.position)
val augExpr = BinaryExpression(assignment.target.toExpression(), bexpr.operator, bexpr.right, bexpr.position)
return listOf(
IAstModification.InsertBefore(assignment, firstAssign, parent),
IAstModification.ReplaceNode(assignment.value, augExpr, assignment))
} else if (bexpr.left !is BinaryExpression && bexpr.operator in associativeOperators) {
println("SPLIT LEFT ${bexpr.left}\n ${bexpr.operator}\n ${bexpr.right}")
val firstAssign = Assignment(assignment.target, bexpr.right, assignment.position)
val augExpr = BinaryExpression(assignment.target.toExpression(), bexpr.operator, bexpr.left, bexpr.position)
return listOf(

View File

@ -8,6 +8,9 @@ import prog8.ast.processing.AstWalker
import prog8.ast.processing.IAstModification
import prog8.ast.statements.*
// TODO remove unneeded assignments such as: cc = 0 ; cc= xbuf ; ... the first can be removed (unless target is not RAM)
internal class UnusedCodeRemover(private val errors: ErrorReporter): AstWalker() {
override fun before(program: Program, parent: Node): Iterable<IAstModification> {

View File

@ -74,13 +74,18 @@ main {
}
c2A += 2
c2B -= 3
ubyte cc
for y in 24 downto 0 {
for x in 39 downto 0 {
@(screen) = xbuf[x] + ybuf[y]
; using a temp var here to enable expression optimization that can't be done on a 'problematic' ROM/RAM memory location
ubyte cc = xbuf[x] + ybuf[y] ; TODO should be split!!
@(screen) = cc
; this is the fastest way to do this inner part:
; %asm {{
; ldy x
; ldy i
; lda xbuf,y
; ldy y
; ldy ii
; clc
; adc ybuf,y
; ldy #0

View File

@ -40,6 +40,18 @@ _saveX .byte 0
float ff1 = 1000
float ff2 = -1000
ubyte[10] xbuf
ubyte[10] ybuf
ubyte x
ubyte y
ubyte cc = xbuf[x] + ybuf[y] ; TODO should be split!!
ubyte cc2
cc2 = xbuf[x] + ybuf[y] ; will be split correctly?
return
ff1 = 1+((-ff1) *3)
floats.print_f(ff1)
floats.print_f(1+((-1000) *3))