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 getFloatRomConst(number: Double): String?
fun importLibs(compilerOptions: CompilationOptions, importer: ModuleImporter, program: Program) fun importLibs(compilerOptions: CompilationOptions, importer: ModuleImporter, program: Program)
fun launchEmulator(programName: String) 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) { override fun initializeZeropage(compilerOptions: CompilationOptions) {
zeropage = C64Zeropage(compilerOptions) 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) { override fun initializeZeropage(compilerOptions: CompilationOptions) {
zeropage = CX16Zeropage(compilerOptions) zeropage = CX16Zeropage(compilerOptions)
} }

View File

@ -449,12 +449,34 @@ internal class StatementOptimizer(private val program: Program,
fun isSimpleTarget(target: AssignTarget): Boolean { fun isSimpleTarget(target: AssignTarget): Boolean {
return when { 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!=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!=null -> {
target.arrayindexed!!.arrayspec.index is NumericLiteralValue || target.arrayindexed!!.arrayspec.index is IdentifierReference target.arrayindexed!!.arrayspec.index is NumericLiteralValue
} }
else -> false else -> false
} }
@ -465,16 +487,14 @@ internal class StatementOptimizer(private val program: Program,
// X = <some-expression-not-X> <operator> <not-binary-expression> // X = <some-expression-not-X> <operator> <not-binary-expression>
// or X = <not-binary-expression> <associativeoperator> <some-expression-not-X> // or X = <not-binary-expression> <associativeoperator> <some-expression-not-X>
// split that into X = <some-expression-not-X> ; X = X <operator> <not-binary-expression> // 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) { 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 firstAssign = Assignment(assignment.target, bexpr.left, assignment.position)
val augExpr = BinaryExpression(assignment.target.toExpression(), bexpr.operator, bexpr.right, bexpr.position) val augExpr = BinaryExpression(assignment.target.toExpression(), bexpr.operator, bexpr.right, bexpr.position)
return listOf( return listOf(
IAstModification.InsertBefore(assignment, firstAssign, parent), IAstModification.InsertBefore(assignment, firstAssign, parent),
IAstModification.ReplaceNode(assignment.value, augExpr, assignment)) IAstModification.ReplaceNode(assignment.value, augExpr, assignment))
} else if (bexpr.left !is BinaryExpression && bexpr.operator in associativeOperators) { } 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 firstAssign = Assignment(assignment.target, bexpr.right, assignment.position)
val augExpr = BinaryExpression(assignment.target.toExpression(), bexpr.operator, bexpr.left, bexpr.position) val augExpr = BinaryExpression(assignment.target.toExpression(), bexpr.operator, bexpr.left, bexpr.position)
return listOf( return listOf(

View File

@ -8,6 +8,9 @@ import prog8.ast.processing.AstWalker
import prog8.ast.processing.IAstModification import prog8.ast.processing.IAstModification
import prog8.ast.statements.* 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() { internal class UnusedCodeRemover(private val errors: ErrorReporter): AstWalker() {
override fun before(program: Program, parent: Node): Iterable<IAstModification> { override fun before(program: Program, parent: Node): Iterable<IAstModification> {

View File

@ -74,13 +74,18 @@ main {
} }
c2A += 2 c2A += 2
c2B -= 3 c2B -= 3
ubyte cc
for y in 24 downto 0 { for y in 24 downto 0 {
for x in 39 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 {{ ; %asm {{
; ldy x ; ldy i
; lda xbuf,y ; lda xbuf,y
; ldy y ; ldy ii
; clc ; clc
; adc ybuf,y ; adc ybuf,y
; ldy #0 ; ldy #0

View File

@ -40,6 +40,18 @@ _saveX .byte 0
float ff1 = 1000 float ff1 = 1000
float ff2 = -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) ff1 = 1+((-ff1) *3)
floats.print_f(ff1) floats.print_f(ff1)
floats.print_f(1+((-1000) *3)) floats.print_f(1+((-1000) *3))