optimized codegen for assigning value or variable to indexed pointer. (6502)

This commit is contained in:
Irmen de Jong 2022-06-06 18:30:19 +02:00
parent b042b7705e
commit 3075578245
4 changed files with 88 additions and 35 deletions

View File

@ -1384,6 +1384,22 @@ internal class AssignmentAsmGen(private val program: Program,
storeRegisterAInMemoryAddress(target.memory!!) storeRegisterAInMemoryAddress(target.memory!!)
} }
TargetStorageKind.ARRAY -> { TargetStorageKind.ARRAY -> {
if(target.origAstTarget?.arrayindexed?.arrayvar?.targetVarDecl(program)?.datatype==DataType.UWORD) {
// assigning an indexed pointer var
if (target.constArrayIndexValue==0u) {
asmgen.out(" lda $sourceName")
asmgen.storeAIntoPointerVar(target.origAstTarget.arrayindexed!!.arrayvar)
} else {
asmgen.loadScaledArrayIndexIntoRegister(target.array!!, DataType.UBYTE, CpuRegister.Y)
if (asmgen.isZpVar(target.origAstTarget.arrayindexed!!.arrayvar)) {
asmgen.out(" lda $sourceName | sta (${target.asmVarname}),y")
} else {
asmgen.out(" lda ${target.asmVarname} | sta P8ZP_SCRATCH_W2 | lda ${target.asmVarname}+1 | sta P8ZP_SCRATCH_W2+1")
asmgen.out(" lda $sourceName | sta (P8ZP_SCRATCH_W2),y")
}
}
return
}
if (target.constArrayIndexValue!=null) { if (target.constArrayIndexValue!=null) {
val scaledIdx = target.constArrayIndexValue!! * program.memsizer.memorySize(target.datatype).toUInt() val scaledIdx = target.constArrayIndexValue!! * program.memsizer.memorySize(target.datatype).toUInt()
asmgen.out(" lda $sourceName | sta ${target.asmVarname}+$scaledIdx") asmgen.out(" lda $sourceName | sta ${target.asmVarname}+$scaledIdx")
@ -1916,6 +1932,22 @@ internal class AssignmentAsmGen(private val program: Program,
storeRegisterAInMemoryAddress(target.memory!!) storeRegisterAInMemoryAddress(target.memory!!)
} }
TargetStorageKind.ARRAY -> { TargetStorageKind.ARRAY -> {
if(target.origAstTarget?.arrayindexed?.arrayvar?.targetVarDecl(program)?.datatype==DataType.UWORD) {
// assigning an indexed pointer var
if (target.constArrayIndexValue==0u) {
asmgen.out(" lda #0")
asmgen.storeAIntoPointerVar(target.origAstTarget.arrayindexed!!.arrayvar)
} else {
asmgen.loadScaledArrayIndexIntoRegister(target.array!!, DataType.UBYTE, CpuRegister.Y)
if (asmgen.isZpVar(target.origAstTarget.arrayindexed!!.arrayvar)) {
asmgen.out(" lda #0 | sta (${target.asmVarname}),y")
} else {
asmgen.out(" lda ${target.asmVarname} | sta P8ZP_SCRATCH_W2 | lda ${target.asmVarname}+1 | sta P8ZP_SCRATCH_W2+1")
asmgen.out(" lda #0 | sta (P8ZP_SCRATCH_W2),y")
}
}
return
}
if (target.constArrayIndexValue!=null) { if (target.constArrayIndexValue!=null) {
val indexValue = target.constArrayIndexValue!! val indexValue = target.constArrayIndexValue!!
asmgen.out(" stz ${target.asmVarname}+$indexValue") asmgen.out(" stz ${target.asmVarname}+$indexValue")
@ -1959,13 +1991,29 @@ internal class AssignmentAsmGen(private val program: Program,
storeRegisterAInMemoryAddress(target.memory!!) storeRegisterAInMemoryAddress(target.memory!!)
} }
TargetStorageKind.ARRAY -> { TargetStorageKind.ARRAY -> {
if(target.origAstTarget?.arrayindexed?.arrayvar?.targetVarDecl(program)?.datatype==DataType.UWORD) {
// assigning an indexed pointer var
if (target.constArrayIndexValue==0u) {
asmgen.out(" lda #${byte.toHex()}")
asmgen.storeAIntoPointerVar(target.origAstTarget.arrayindexed!!.arrayvar)
} else {
asmgen.loadScaledArrayIndexIntoRegister(target.array!!, DataType.UBYTE, CpuRegister.Y)
if (asmgen.isZpVar(target.origAstTarget.arrayindexed!!.arrayvar)) {
asmgen.out(" lda #${byte.toHex()} | sta (${target.asmVarname}),y")
} else {
asmgen.out(" lda ${target.asmVarname} | sta P8ZP_SCRATCH_W2 | lda ${target.asmVarname}+1 | sta P8ZP_SCRATCH_W2+1")
asmgen.out(" lda #${byte.toHex()} | sta (P8ZP_SCRATCH_W2),y")
}
}
return
}
if (target.constArrayIndexValue!=null) { if (target.constArrayIndexValue!=null) {
val indexValue = target.constArrayIndexValue!! val indexValue = target.constArrayIndexValue!!
asmgen.out(" lda #${byte.toHex()} | sta ${target.asmVarname}+$indexValue") asmgen.out(" lda #${byte.toHex()} | sta ${target.asmVarname}+$indexValue")
} }
else { else {
asmgen.loadScaledArrayIndexIntoRegister(target.array!!, DataType.UBYTE, CpuRegister.Y) asmgen.loadScaledArrayIndexIntoRegister(target.array!!, DataType.UBYTE, CpuRegister.Y)
asmgen.out(" lda #<${byte.toHex()} | sta ${target.asmVarname},y") asmgen.out(" lda #${byte.toHex()} | sta ${target.asmVarname},y")
} }
} }
TargetStorageKind.REGISTER -> when(target.register!!) { TargetStorageKind.REGISTER -> when(target.register!!) {

View File

@ -2,10 +2,9 @@ package prog8.compiler.astprocessing
import prog8.ast.Node import prog8.ast.Node
import prog8.ast.Program import prog8.ast.Program
import prog8.ast.expressions.ArrayIndexedExpression import prog8.ast.expressions.*
import prog8.ast.expressions.BinaryExpression
import prog8.ast.expressions.Expression
import prog8.ast.statements.AssignTarget import prog8.ast.statements.AssignTarget
import prog8.ast.statements.Assignment
import prog8.ast.statements.DirectMemoryWrite import prog8.ast.statements.DirectMemoryWrite
import prog8.ast.statements.VarDecl import prog8.ast.statements.VarDecl
import prog8.ast.walk.AstWalker import prog8.ast.walk.AstWalker
@ -31,13 +30,19 @@ internal class AstOnetimeTransforms(private val program: Program, private val op
private fun replacePointerVarIndexWithMemreadOrMemwrite(arrayIndexedExpression: ArrayIndexedExpression, parent: Node): Iterable<IAstModification> { private fun replacePointerVarIndexWithMemreadOrMemwrite(arrayIndexedExpression: ArrayIndexedExpression, parent: Node): Iterable<IAstModification> {
if(options.compTarget.name== VMTarget.NAME) if(options.compTarget.name== VMTarget.NAME)
return noModifications return noModifications // vm codegen deals correctly with all cases
val arrayVar = arrayIndexedExpression.arrayvar.targetVarDecl(program) val arrayVar = arrayIndexedExpression.arrayvar.targetVarDecl(program)
if(arrayVar!=null && arrayVar.datatype == DataType.UWORD) { if(arrayVar!=null && arrayVar.datatype == DataType.UWORD) {
if(parent is AssignTarget) { if(parent is AssignTarget) {
// rewrite assignment target pointervar[index] into @(pointervar+index) val assignment = parent.parent as? Assignment
//println("REWRITE POINTER INDEXED: ${arrayVar.name}[${arrayIndexedExpression.indexer.indexExpr}] as assignment target at ${parent.position}") // TODO if(assignment?.value is NumericLiteral || assignment?.value is IdentifierReference) {
// ONLY for a constant assignment, or direct variable assignment, the codegen contains correct optimized code.
return noModifications
}
// Other cases aren't covered correctly by the 6502 codegen, and there are a LOT of cases.
// So rewrite assignment target pointervar[index] into @(pointervar+index)
// (the 6502 codegen covers all cases correctly for a direct memory assignment).
val indexer = arrayIndexedExpression.indexer val indexer = arrayIndexedExpression.indexer
val add: Expression = val add: Expression =
if(indexer.indexExpr.constValue(program)?.number==0.0) if(indexer.indexExpr.constValue(program)?.number==0.0)

View File

@ -3,7 +3,6 @@ TODO
For next release For next release
^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^
- 6502: fix optimized pointervar indexing codegen when it is an assignment target (i.e. writing to ptr[ix])
- pipe operator: (targets other than 'Virtual'): allow non-unary function calls in the pipe that specify the other argument(s) in the calls. Already working for VM target. - pipe operator: (targets other than 'Virtual'): allow non-unary function calls in the pipe that specify the other argument(s) in the calls. Already working for VM target.
- add McCarthy evaluation to shortcircuit and/or expressions. First do ifs by splitting them up? Then do expressions that compute a value? - add McCarthy evaluation to shortcircuit and/or expressions. First do ifs by splitting them up? Then do expressions that compute a value?
- Inliner: also inline function call expressions, and remove it from the StatementOptimizer - Inliner: also inline function call expressions, and remove it from the StatementOptimizer

View File

@ -40,32 +40,32 @@ main {
uword bitmapbuf = &data uword bitmapbuf = &data
; 11 22 33 ; 11 22 33
; txt.print_ub(bitmapbuf[0]) txt.print_ub(bitmapbuf[0])
; txt.spc() txt.spc()
; txt.print_ub(bitmapbuf[1]) txt.print_ub(bitmapbuf[1])
; txt.spc() txt.spc()
; txt.print_ub(bitmapbuf[2]) txt.print_ub(bitmapbuf[2])
; txt.nl() txt.nl()
; rol(bitmapbuf[0]) rol(bitmapbuf[0])
; rol(bitmapbuf[0]) rol(bitmapbuf[0])
; txt.print_ub(bitmapbuf[0]) ; 44 txt.print_ub(bitmapbuf[0]) ; 44
; txt.spc() txt.spc()
; ror(bitmapbuf[0]) ror(bitmapbuf[0])
; ror(bitmapbuf[0]) ror(bitmapbuf[0])
; txt.print_ub(bitmapbuf[0]) ; 11 txt.print_ub(bitmapbuf[0]) ; 11
; txt.nl() txt.nl()
;
; ; 22 44 66 ; 22 44 66
; txt.print_ub(bitmapbuf[0]*2) txt.print_ub(bitmapbuf[0]*2)
; txt.spc() txt.spc()
; txt.print_ub(bitmapbuf[1]*2) txt.print_ub(bitmapbuf[1]*2)
; txt.spc() txt.spc()
; txt.print_ub(bitmapbuf[2]*2) txt.print_ub(bitmapbuf[2]*2)
; txt.nl() txt.nl()
;
; value = one+one+one+one+one value = one+one+one+one+one
; txt.print_ub(value) ; 5 txt.print_ub(value) ; 5
; txt.nl() txt.nl()
bitmapbuf[0] = one+one+one bitmapbuf[0] = one+one+one
bitmapbuf[0] = one+one+one bitmapbuf[0] = one+one+one
@ -76,6 +76,7 @@ main {
bitmapbuf[2] = one bitmapbuf[2] = one
bitmapbuf[2] = one bitmapbuf[2] = one
bitmapbuf[2] = one bitmapbuf[2] = one
bitmapbuf[3] = 42
bitmapbuf[2] += 100 bitmapbuf[2] += 100
bitmapbuf[2] -= 1 bitmapbuf[2] -= 1
bitmapbuf[2] -= 1 bitmapbuf[2] -= 1
@ -91,7 +92,7 @@ main {
txt.nl() txt.nl()
for value in data { for value in data {
txt.print_ub(value) ; 3 2 97 4 5 6 7 8 9 10 txt.print_ub(value) ; 3 2 97 42 5 6 7 8 9 10
txt.spc() txt.spc()
} }
txt.nl() txt.nl()