mirror of
https://github.com/irmen/prog8.git
synced 2025-01-10 20:30:23 +00:00
optimize postincrdecr on memory a bit
This commit is contained in:
parent
b0f5b6925d
commit
abcdfd8e28
@ -98,7 +98,7 @@ private fun optimizeCommonSubExpressions(program: PtProgram, errors: IErrorRepor
|
|||||||
stmtContainer.children.add(stmtContainer.children.indexOf(stmt), tempassign)
|
stmtContainer.children.add(stmtContainer.children.indexOf(stmt), tempassign)
|
||||||
tempassign.parent = stmtContainer
|
tempassign.parent = stmtContainer
|
||||||
|
|
||||||
val tempvar = PtVariable(tempvarName, datatype, ZeropageWish.DONTCARE, null, null, binexpr.position)
|
val tempvar = PtVariable(tempvarName, datatype, ZeropageWish.NOT_IN_ZEROPAGE, null, null, binexpr.position)
|
||||||
stmtContainer.add(0, tempvar)
|
stmtContainer.add(0, tempvar)
|
||||||
tempvar.parent = stmtContainer
|
tempvar.parent = stmtContainer
|
||||||
|
|
||||||
|
@ -1192,7 +1192,7 @@ $repeatLabel""")
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun tryOptimizedPointerAccessWithA(addressExpr: PtExpression, operator: String, write: Boolean): Boolean {
|
internal fun tryOptimizedPointerAccessWithA(addressExpr: PtBinaryExpression, write: Boolean): Boolean {
|
||||||
// optimize pointer,indexregister if possible
|
// optimize pointer,indexregister if possible
|
||||||
|
|
||||||
fun evalBytevalueWillClobberA(expr: PtExpression): Boolean {
|
fun evalBytevalueWillClobberA(expr: PtExpression): Boolean {
|
||||||
@ -1208,7 +1208,7 @@ $repeatLabel""")
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(operator=="+") {
|
if(addressExpr.operator=="+") {
|
||||||
val ptrAndIndex = pointerViaIndexRegisterPossible(addressExpr)
|
val ptrAndIndex = pointerViaIndexRegisterPossible(addressExpr)
|
||||||
if(ptrAndIndex!=null) {
|
if(ptrAndIndex!=null) {
|
||||||
val pointervar = ptrAndIndex.first as? PtIdentifier
|
val pointervar = ptrAndIndex.first as? PtIdentifier
|
||||||
@ -2919,7 +2919,7 @@ $repeatLabel""")
|
|||||||
}
|
}
|
||||||
is PtBinaryExpression -> {
|
is PtBinaryExpression -> {
|
||||||
val addrExpr = expr.address as PtBinaryExpression
|
val addrExpr = expr.address as PtBinaryExpression
|
||||||
if(!tryOptimizedPointerAccessWithA(addrExpr, addrExpr.operator, false)) {
|
if(!tryOptimizedPointerAccessWithA(addrExpr, false)) {
|
||||||
assignViaExprEval()
|
assignViaExprEval()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
package prog8.codegen.cpu6502
|
package prog8.codegen.cpu6502
|
||||||
|
|
||||||
import prog8.code.ast.PtIdentifier
|
import prog8.code.ast.*
|
||||||
import prog8.code.ast.PtNumber
|
|
||||||
import prog8.code.ast.PtPostIncrDecr
|
|
||||||
import prog8.code.ast.PtProgram
|
|
||||||
import prog8.code.core.*
|
import prog8.code.core.*
|
||||||
|
|
||||||
|
|
||||||
@ -37,6 +34,55 @@ internal class PostIncrDecrAsmGen(private val program: PtProgram, private val as
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
targetMemory!=null -> {
|
targetMemory!=null -> {
|
||||||
|
fun incDecViaExprEval() {
|
||||||
|
asmgen.assignExpressionToRegister(targetMemory.address, RegisterOrPair.AY)
|
||||||
|
asmgen.out(" sta (+) + 1 | sty (+) + 2")
|
||||||
|
if(incr)
|
||||||
|
asmgen.out("+\tinc ${'$'}ffff\t; modified")
|
||||||
|
else
|
||||||
|
asmgen.out("+\tdec ${'$'}ffff\t; modified")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun tryOptimizedPointerIncDec(address: PtBinaryExpression): Boolean {
|
||||||
|
if(address.operator=="+") {
|
||||||
|
val offset = address.right.asConstInteger()
|
||||||
|
if(offset!=null && offset<256) {
|
||||||
|
// we have @(ptr + 255) ++ , or @(ptr+255)--
|
||||||
|
asmgen.assignExpressionToRegister(address.left, RegisterOrPair.AY, false)
|
||||||
|
asmgen.out("""
|
||||||
|
sta (+) + 1
|
||||||
|
sty (+) + 2
|
||||||
|
ldx #$offset""")
|
||||||
|
if(incr)
|
||||||
|
asmgen.out("+\tinc ${'$'}ffff,x\t; modified")
|
||||||
|
else
|
||||||
|
asmgen.out("+\tdec ${'$'}ffff,x\t; modified")
|
||||||
|
return true
|
||||||
|
} else if(address.right.type in ByteDatatypes) {
|
||||||
|
// we have @(ptr + bytevar) ++ , or @(ptr+bytevar)--
|
||||||
|
asmgen.assignExpressionToRegister(address.left, RegisterOrPair.AY, false)
|
||||||
|
asmgen.out(" sta (+) + 1 | sty (+) + 2")
|
||||||
|
asmgen.assignExpressionToRegister(address.right, RegisterOrPair.X, false)
|
||||||
|
if(incr)
|
||||||
|
asmgen.out("+\tinc ${'$'}ffff,x\t; modified")
|
||||||
|
else
|
||||||
|
asmgen.out("+\tdec ${'$'}ffff,x\t; modified")
|
||||||
|
return true
|
||||||
|
} else if((address.right as? PtTypeCast)?.value?.type in ByteDatatypes) {
|
||||||
|
// we have @(ptr + bytevar) ++ , or @(ptr+bytevar)--
|
||||||
|
asmgen.assignExpressionToRegister(address.left, RegisterOrPair.AY, false)
|
||||||
|
asmgen.out(" sta (+) + 1 | sty (+) + 2")
|
||||||
|
asmgen.assignExpressionToRegister((address.right as PtTypeCast).value, RegisterOrPair.X, false)
|
||||||
|
if(incr)
|
||||||
|
asmgen.out("+\tinc ${'$'}ffff,x\t; modified")
|
||||||
|
else
|
||||||
|
asmgen.out("+\tdec ${'$'}ffff,x\t; modified")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
when (val addressExpr = targetMemory.address) {
|
when (val addressExpr = targetMemory.address) {
|
||||||
is PtNumber -> {
|
is PtNumber -> {
|
||||||
val what = addressExpr.number.toHex()
|
val what = addressExpr.number.toHex()
|
||||||
@ -50,13 +96,13 @@ internal class PostIncrDecrAsmGen(private val program: PtProgram, private val as
|
|||||||
else
|
else
|
||||||
asmgen.out("+\tdec ${'$'}ffff\t; modified")
|
asmgen.out("+\tdec ${'$'}ffff\t; modified")
|
||||||
}
|
}
|
||||||
|
is PtBinaryExpression -> {
|
||||||
|
if(!tryOptimizedPointerIncDec(addressExpr)) {
|
||||||
|
incDecViaExprEval()
|
||||||
|
}
|
||||||
|
}
|
||||||
else -> {
|
else -> {
|
||||||
asmgen.assignExpressionToRegister(addressExpr, RegisterOrPair.AY)
|
incDecViaExprEval()
|
||||||
asmgen.out(" sta (+) + 1 | sty (+) + 2")
|
|
||||||
if(incr)
|
|
||||||
asmgen.out("+\tinc ${'$'}ffff\t; modified")
|
|
||||||
else
|
|
||||||
asmgen.out("+\tdec ${'$'}ffff\t; modified")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,7 +144,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
|||||||
}
|
}
|
||||||
is PtBinaryExpression -> {
|
is PtBinaryExpression -> {
|
||||||
val addrExpr = value.address as PtBinaryExpression
|
val addrExpr = value.address as PtBinaryExpression
|
||||||
if(asmgen.tryOptimizedPointerAccessWithA(addrExpr, addrExpr.operator, false)) {
|
if(asmgen.tryOptimizedPointerAccessWithA(addrExpr, false)) {
|
||||||
assignRegisterByte(assign.target, CpuRegister.A, false, true)
|
assignRegisterByte(assign.target, CpuRegister.A, false, true)
|
||||||
} else {
|
} else {
|
||||||
assignViaExprEval(value.address)
|
assignViaExprEval(value.address)
|
||||||
@ -772,9 +772,21 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
|
val leftMemByte = expr.left as? PtMemoryByte
|
||||||
|
val rightMemByte = expr.right as? PtMemoryByte
|
||||||
|
val leftArrayIndexer = expr.left as? PtArrayIndexer
|
||||||
val rightArrayIndexer = expr.right as? PtArrayIndexer
|
val rightArrayIndexer = expr.right as? PtArrayIndexer
|
||||||
if(rightArrayIndexer!=null && rightArrayIndexer.type in ByteDatatypes && left.type in ByteDatatypes) {
|
if(expr.operator=="+" && leftArrayIndexer!=null && leftArrayIndexer.type in ByteDatatypes && right.type in ByteDatatypes) {
|
||||||
// special optimization for bytevalue +/- bytearr[y] : no need to use a tempvar, just use adc array,y or sbc array,y or adc (ptr),y / sbc (ptr),y
|
// special optimization for bytearray[y] + bytevalue : no need to use a tempvar, just use adc array,y
|
||||||
|
assignExpressionToRegister(right, RegisterOrPair.A, right.type==DataType.BYTE)
|
||||||
|
if(!leftArrayIndexer.index.isSimple()) asmgen.out(" pha")
|
||||||
|
asmgen.assignExpressionToRegister(leftArrayIndexer.index, RegisterOrPair.Y, false)
|
||||||
|
if(!leftArrayIndexer.index.isSimple()) asmgen.out(" pla")
|
||||||
|
val arrayvarname = asmgen.asmSymbolName(leftArrayIndexer.variable)
|
||||||
|
asmgen.out(" clc | adc $arrayvarname,y")
|
||||||
|
assignRegisterByte(target, CpuRegister.A, dt in SignedDatatypes, true)
|
||||||
|
} else if(rightArrayIndexer!=null && rightArrayIndexer.type in ByteDatatypes && left.type in ByteDatatypes) {
|
||||||
|
// special optimization for bytevalue +/- bytearray[y] : no need to use a tempvar, just use adc array,y or sbc array,y
|
||||||
assignExpressionToRegister(left, RegisterOrPair.A, left.type==DataType.BYTE)
|
assignExpressionToRegister(left, RegisterOrPair.A, left.type==DataType.BYTE)
|
||||||
if(!rightArrayIndexer.index.isSimple()) asmgen.out(" pha")
|
if(!rightArrayIndexer.index.isSimple()) asmgen.out(" pha")
|
||||||
asmgen.assignExpressionToRegister(rightArrayIndexer.index, RegisterOrPair.Y, false)
|
asmgen.assignExpressionToRegister(rightArrayIndexer.index, RegisterOrPair.Y, false)
|
||||||
@ -785,6 +797,12 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
|||||||
else
|
else
|
||||||
asmgen.out(" sec | sbc $arrayvarname,y")
|
asmgen.out(" sec | sbc $arrayvarname,y")
|
||||||
assignRegisterByte(target, CpuRegister.A, dt in SignedDatatypes, true)
|
assignRegisterByte(target, CpuRegister.A, dt in SignedDatatypes, true)
|
||||||
|
} else if(expr.operator=="+" && leftMemByte!=null && right.type in ByteDatatypes && optimizedPointerIndexPlusByteIntoA(leftMemByte, right)) {
|
||||||
|
assignRegisterByte(target, CpuRegister.A, dt in SignedDatatypes, true)
|
||||||
|
return true
|
||||||
|
} else if(rightMemByte!=null && left.type in ByteDatatypes && optimizedPointerIndexPlusMinusByteIntoA(left, expr.operator, rightMemByte)) {
|
||||||
|
assignRegisterByte(target, CpuRegister.A, dt in SignedDatatypes, true)
|
||||||
|
return true
|
||||||
} else {
|
} else {
|
||||||
assignExpressionToRegister(left, RegisterOrPair.A, left.type==DataType.BYTE)
|
assignExpressionToRegister(left, RegisterOrPair.A, left.type==DataType.BYTE)
|
||||||
if(directIntoY(right)) {
|
if(directIntoY(right)) {
|
||||||
@ -969,6 +987,32 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun optimizedPointerIndexPlusByteIntoA(mem: PtMemoryByte, value: PtExpression): Boolean {
|
||||||
|
// special optimization for pointervar[y] + bytevalue (actually: @(address) + value)
|
||||||
|
return false // TODO implement this optimization?
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun optimizedPointerIndexPlusMinusByteIntoA(value: PtExpression, operator: String, mem: PtMemoryByte): Boolean {
|
||||||
|
// special optimization for bytevalue +/- pointervar[y] (actually: bytevalue +/- @(address) )
|
||||||
|
val address = mem.address as? PtBinaryExpression
|
||||||
|
|
||||||
|
if(address is PtBinaryExpression) {
|
||||||
|
val offset = address.right.asConstInteger()
|
||||||
|
if(offset!=null && offset<256) {
|
||||||
|
// we have value + @(ptr + 255), or value - @(ptr+255)
|
||||||
|
// TODO()
|
||||||
|
} else if(address.right.type in ByteDatatypes) {
|
||||||
|
// we have @(ptr + bytevar) ++ , or @(ptr+bytevar)--
|
||||||
|
// TODO()
|
||||||
|
} else if((address.right as? PtTypeCast)?.value?.type in ByteDatatypes) {
|
||||||
|
// we have @(ptr + bytevar) ++ , or @(ptr+bytevar)--
|
||||||
|
// TODO()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println("TODO: OPTIMIZE POINTER PLUSMINUS ${value.position}")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
private fun optimizedBitwiseExpr(expr: PtBinaryExpression, target: AsmAssignTarget): Boolean {
|
private fun optimizedBitwiseExpr(expr: PtBinaryExpression, target: AsmAssignTarget): Boolean {
|
||||||
if (expr.left.type in ByteDatatypes && expr.right.type in ByteDatatypes) {
|
if (expr.left.type in ByteDatatypes && expr.right.type in ByteDatatypes) {
|
||||||
if (expr.right.isSimple()) {
|
if (expr.right.isSimple()) {
|
||||||
@ -1993,7 +2037,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
|||||||
}
|
}
|
||||||
is PtBinaryExpression -> {
|
is PtBinaryExpression -> {
|
||||||
val addrExpr = value.address as PtBinaryExpression
|
val addrExpr = value.address as PtBinaryExpression
|
||||||
if(asmgen.tryOptimizedPointerAccessWithA(addrExpr, addrExpr.operator, false)) {
|
if(asmgen.tryOptimizedPointerAccessWithA(addrExpr, false)) {
|
||||||
asmgen.out(" ldy #0")
|
asmgen.out(" ldy #0")
|
||||||
assignRegisterpairWord(target, RegisterOrPair.AY)
|
assignRegisterpairWord(target, RegisterOrPair.AY)
|
||||||
} else {
|
} else {
|
||||||
@ -3860,7 +3904,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!asmgen.tryOptimizedPointerAccessWithA(addressExpr, addressExpr.operator, true))
|
if(!asmgen.tryOptimizedPointerAccessWithA(addressExpr, true))
|
||||||
storeViaExprEval()
|
storeViaExprEval()
|
||||||
}
|
}
|
||||||
else -> storeViaExprEval()
|
else -> storeViaExprEval()
|
||||||
|
@ -197,19 +197,16 @@ _after:
|
|||||||
val indexExpr = arrayIndexedExpression.indexer.indexExpr
|
val indexExpr = arrayIndexedExpression.indexer.indexExpr
|
||||||
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) {
|
||||||
val add: Expression =
|
val wordIndex = TypecastExpression(indexExpr, DataType.UWORD, true, indexExpr.position)
|
||||||
if(indexExpr.constValue(program)?.number==0.0)
|
val address = BinaryExpression(arrayIndexedExpression.arrayvar.copy(), "+", wordIndex, arrayIndexedExpression.position)
|
||||||
arrayIndexedExpression.arrayvar.copy()
|
|
||||||
else
|
|
||||||
BinaryExpression(arrayIndexedExpression.arrayvar.copy(), "+", indexExpr, arrayIndexedExpression.position)
|
|
||||||
return if(parent is AssignTarget) {
|
return if(parent is AssignTarget) {
|
||||||
// assignment to array
|
// assignment to array
|
||||||
val memwrite = DirectMemoryWrite(add, arrayIndexedExpression.position)
|
val memwrite = DirectMemoryWrite(address, arrayIndexedExpression.position)
|
||||||
val newtarget = AssignTarget(null, null, memwrite, arrayIndexedExpression.position)
|
val newtarget = AssignTarget(null, null, memwrite, arrayIndexedExpression.position)
|
||||||
listOf(IAstModification.ReplaceNode(parent, newtarget, parent.parent))
|
listOf(IAstModification.ReplaceNode(parent, newtarget, parent.parent))
|
||||||
} else {
|
} else {
|
||||||
// read from array
|
// read from array
|
||||||
val memread = DirectMemoryRead(add, arrayIndexedExpression.position)
|
val memread = DirectMemoryRead(address, arrayIndexedExpression.position)
|
||||||
listOf(IAstModification.ReplaceNode(arrayIndexedExpression, memread, parent))
|
listOf(IAstModification.ReplaceNode(arrayIndexedExpression, memread, parent))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -552,7 +552,7 @@ class IntermediateAstMaker(private val program: Program, private val errors: IEr
|
|||||||
|
|
||||||
private fun transform(srcArr: ArrayIndexedExpression): PtArrayIndexer {
|
private fun transform(srcArr: ArrayIndexedExpression): PtArrayIndexer {
|
||||||
if(srcArr.arrayvar.targetVarDecl(program)!!.datatype !in ArrayDatatypes + DataType.STR)
|
if(srcArr.arrayvar.targetVarDecl(program)!!.datatype !in ArrayDatatypes + DataType.STR)
|
||||||
throw FatalAstException("array indexing can be used on array or string variables ${srcArr.position}")
|
throw FatalAstException("array indexing can only be used on array or string variables ${srcArr.position}")
|
||||||
val eltType = srcArr.inferType(program).getOrElse { throw FatalAstException("unknown dt") }
|
val eltType = srcArr.inferType(program).getOrElse { throw FatalAstException("unknown dt") }
|
||||||
val array = PtArrayIndexer(eltType, srcArr.position)
|
val array = PtArrayIndexer(eltType, srcArr.position)
|
||||||
array.add(transform(srcArr.arrayvar))
|
array.add(transform(srcArr.arrayvar))
|
||||||
|
@ -4,6 +4,8 @@ TODO
|
|||||||
petaxian is now a lot larger since pointer[idx] is rewritten into @(ptr+idx). Missing some optimized code somewhere now?
|
petaxian is now a lot larger since pointer[idx] is rewritten into @(ptr+idx). Missing some optimized code somewhere now?
|
||||||
VM textelite is now a lot larger too
|
VM textelite is now a lot larger too
|
||||||
|
|
||||||
|
DO: "TODO implement this optimization"
|
||||||
|
|
||||||
(after merge in boolean): move all "OperatorXinplace" from expressionGen to AssignmentGen, see if we can get rid of the Result return type.
|
(after merge in boolean): move all "OperatorXinplace" from expressionGen to AssignmentGen, see if we can get rid of the Result return type.
|
||||||
|
|
||||||
...
|
...
|
||||||
|
@ -5,25 +5,22 @@
|
|||||||
%option no_sysinit
|
%option no_sysinit
|
||||||
|
|
||||||
main {
|
main {
|
||||||
sub derp(str arg) {
|
|
||||||
arg[4] = '?'
|
|
||||||
}
|
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
str msg = "hello"
|
; ubyte[10] az
|
||||||
derp(msg)
|
ubyte @shared offset=4
|
||||||
txt.chrout(msg[4]) ; ?
|
|
||||||
txt.nl()
|
|
||||||
uword @shared az = $4000
|
uword @shared az = $4000
|
||||||
@($4004) = 0
|
ubyte @shared value = 22
|
||||||
az[4] |= $40
|
@($4004) = 99
|
||||||
txt.print_ub(@($4004)) ; 64
|
az[4]--
|
||||||
|
@(az + offset)--
|
||||||
|
txt.print_ub(@($4004))
|
||||||
txt.nl()
|
txt.nl()
|
||||||
@(az+4) = 0
|
az[4]++
|
||||||
@(az+4) |= $4f
|
@(az+offset)++
|
||||||
txt.print_ub(@($4004)) ; 79
|
txt.print_ub(@($4004))
|
||||||
txt.nl()
|
txt.nl()
|
||||||
|
; cx16.r0L = az[4] + value*5
|
||||||
|
; cx16.r1L = value*5 + az[4]
|
||||||
|
|
||||||
; ubyte @shared idx = 1
|
; ubyte @shared idx = 1
|
||||||
; txt.print_w(array[idx])
|
; txt.print_w(array[idx])
|
||||||
|
Loading…
x
Reference in New Issue
Block a user