mirror of
https://github.com/irmen/prog8.git
synced 2024-11-26 11:49:22 +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)
|
||||
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)
|
||||
tempvar.parent = stmtContainer
|
||||
|
||||
|
@ -1192,7 +1192,7 @@ $repeatLabel""")
|
||||
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
|
||||
|
||||
fun evalBytevalueWillClobberA(expr: PtExpression): Boolean {
|
||||
@ -1208,7 +1208,7 @@ $repeatLabel""")
|
||||
}
|
||||
}
|
||||
|
||||
if(operator=="+") {
|
||||
if(addressExpr.operator=="+") {
|
||||
val ptrAndIndex = pointerViaIndexRegisterPossible(addressExpr)
|
||||
if(ptrAndIndex!=null) {
|
||||
val pointervar = ptrAndIndex.first as? PtIdentifier
|
||||
@ -2919,7 +2919,7 @@ $repeatLabel""")
|
||||
}
|
||||
is PtBinaryExpression -> {
|
||||
val addrExpr = expr.address as PtBinaryExpression
|
||||
if(!tryOptimizedPointerAccessWithA(addrExpr, addrExpr.operator, false)) {
|
||||
if(!tryOptimizedPointerAccessWithA(addrExpr, false)) {
|
||||
assignViaExprEval()
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,6 @@
|
||||
package prog8.codegen.cpu6502
|
||||
|
||||
import prog8.code.ast.PtIdentifier
|
||||
import prog8.code.ast.PtNumber
|
||||
import prog8.code.ast.PtPostIncrDecr
|
||||
import prog8.code.ast.PtProgram
|
||||
import prog8.code.ast.*
|
||||
import prog8.code.core.*
|
||||
|
||||
|
||||
@ -37,6 +34,55 @@ internal class PostIncrDecrAsmGen(private val program: PtProgram, private val as
|
||||
}
|
||||
}
|
||||
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) {
|
||||
is PtNumber -> {
|
||||
val what = addressExpr.number.toHex()
|
||||
@ -50,13 +96,13 @@ internal class PostIncrDecrAsmGen(private val program: PtProgram, private val as
|
||||
else
|
||||
asmgen.out("+\tdec ${'$'}ffff\t; modified")
|
||||
}
|
||||
is PtBinaryExpression -> {
|
||||
if(!tryOptimizedPointerIncDec(addressExpr)) {
|
||||
incDecViaExprEval()
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
asmgen.assignExpressionToRegister(addressExpr, RegisterOrPair.AY)
|
||||
asmgen.out(" sta (+) + 1 | sty (+) + 2")
|
||||
if(incr)
|
||||
asmgen.out("+\tinc ${'$'}ffff\t; modified")
|
||||
else
|
||||
asmgen.out("+\tdec ${'$'}ffff\t; modified")
|
||||
incDecViaExprEval()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -144,7 +144,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
}
|
||||
is 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)
|
||||
} else {
|
||||
assignViaExprEval(value.address)
|
||||
@ -772,9 +772,21 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
return true
|
||||
}
|
||||
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
|
||||
if(rightArrayIndexer!=null && rightArrayIndexer.type in ByteDatatypes && left.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
|
||||
if(expr.operator=="+" && leftArrayIndexer!=null && leftArrayIndexer.type in ByteDatatypes && right.type in ByteDatatypes) {
|
||||
// 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)
|
||||
if(!rightArrayIndexer.index.isSimple()) asmgen.out(" pha")
|
||||
asmgen.assignExpressionToRegister(rightArrayIndexer.index, RegisterOrPair.Y, false)
|
||||
@ -785,6 +797,12 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
else
|
||||
asmgen.out(" sec | sbc $arrayvarname,y")
|
||||
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 {
|
||||
assignExpressionToRegister(left, RegisterOrPair.A, left.type==DataType.BYTE)
|
||||
if(directIntoY(right)) {
|
||||
@ -969,6 +987,32 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
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 {
|
||||
if (expr.left.type in ByteDatatypes && expr.right.type in ByteDatatypes) {
|
||||
if (expr.right.isSimple()) {
|
||||
@ -1993,7 +2037,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
}
|
||||
is PtBinaryExpression -> {
|
||||
val addrExpr = value.address as PtBinaryExpression
|
||||
if(asmgen.tryOptimizedPointerAccessWithA(addrExpr, addrExpr.operator, false)) {
|
||||
if(asmgen.tryOptimizedPointerAccessWithA(addrExpr, false)) {
|
||||
asmgen.out(" ldy #0")
|
||||
assignRegisterpairWord(target, RegisterOrPair.AY)
|
||||
} 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()
|
||||
}
|
||||
else -> storeViaExprEval()
|
||||
|
@ -197,19 +197,16 @@ _after:
|
||||
val indexExpr = arrayIndexedExpression.indexer.indexExpr
|
||||
val arrayVar = arrayIndexedExpression.arrayvar.targetVarDecl(program)
|
||||
if(arrayVar!=null && arrayVar.datatype==DataType.UWORD) {
|
||||
val add: Expression =
|
||||
if(indexExpr.constValue(program)?.number==0.0)
|
||||
arrayIndexedExpression.arrayvar.copy()
|
||||
else
|
||||
BinaryExpression(arrayIndexedExpression.arrayvar.copy(), "+", indexExpr, arrayIndexedExpression.position)
|
||||
val wordIndex = TypecastExpression(indexExpr, DataType.UWORD, true, indexExpr.position)
|
||||
val address = BinaryExpression(arrayIndexedExpression.arrayvar.copy(), "+", wordIndex, arrayIndexedExpression.position)
|
||||
return if(parent is AssignTarget) {
|
||||
// assignment to array
|
||||
val memwrite = DirectMemoryWrite(add, arrayIndexedExpression.position)
|
||||
val memwrite = DirectMemoryWrite(address, arrayIndexedExpression.position)
|
||||
val newtarget = AssignTarget(null, null, memwrite, arrayIndexedExpression.position)
|
||||
listOf(IAstModification.ReplaceNode(parent, newtarget, parent.parent))
|
||||
} else {
|
||||
// read from array
|
||||
val memread = DirectMemoryRead(add, arrayIndexedExpression.position)
|
||||
val memread = DirectMemoryRead(address, arrayIndexedExpression.position)
|
||||
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 {
|
||||
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 array = PtArrayIndexer(eltType, srcArr.position)
|
||||
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?
|
||||
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.
|
||||
|
||||
...
|
||||
|
@ -5,25 +5,22 @@
|
||||
%option no_sysinit
|
||||
|
||||
main {
|
||||
sub derp(str arg) {
|
||||
arg[4] = '?'
|
||||
}
|
||||
|
||||
sub start() {
|
||||
str msg = "hello"
|
||||
derp(msg)
|
||||
txt.chrout(msg[4]) ; ?
|
||||
txt.nl()
|
||||
; ubyte[10] az
|
||||
ubyte @shared offset=4
|
||||
uword @shared az = $4000
|
||||
@($4004) = 0
|
||||
az[4] |= $40
|
||||
txt.print_ub(@($4004)) ; 64
|
||||
ubyte @shared value = 22
|
||||
@($4004) = 99
|
||||
az[4]--
|
||||
@(az + offset)--
|
||||
txt.print_ub(@($4004))
|
||||
txt.nl()
|
||||
@(az+4) = 0
|
||||
@(az+4) |= $4f
|
||||
txt.print_ub(@($4004)) ; 79
|
||||
az[4]++
|
||||
@(az+offset)++
|
||||
txt.print_ub(@($4004))
|
||||
txt.nl()
|
||||
|
||||
; cx16.r0L = az[4] + value*5
|
||||
; cx16.r1L = value*5 + az[4]
|
||||
|
||||
; ubyte @shared idx = 1
|
||||
; txt.print_w(array[idx])
|
||||
|
Loading…
Reference in New Issue
Block a user