mirror of
https://github.com/irmen/prog8.git
synced 2024-11-27 03:50:27 +00:00
reduce slow estack usage by splitting up simple binary expressions
This commit is contained in:
parent
d020a7974a
commit
bda1c1c1eb
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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> {
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
|
Loading…
Reference in New Issue
Block a user