mirror of
https://github.com/irmen/prog8.git
synced 2024-12-26 14:29:35 +00:00
optimize memory read expression of ptr + constant index
This commit is contained in:
parent
76d54fbe5c
commit
1481f92cb0
@ -1457,6 +1457,45 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
|
||||
}
|
||||
|
||||
internal fun translateDirectMemReadExpression(expr: DirectMemoryRead, pushResultOnEstack: Boolean) {
|
||||
|
||||
fun assignViaExprEval() {
|
||||
asmgen.assignExpressionToVariable(expr.addressExpression, asmgen.asmVariableName("P8ZP_SCRATCH_W2"), DataType.UWORD, null)
|
||||
if (CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) {
|
||||
if (pushResultOnEstack) {
|
||||
asmgen.out(" dex | lda (P8ZP_SCRATCH_W2) | sta P8ESTACK_LO+1,x")
|
||||
} else {
|
||||
asmgen.out(" lda (P8ZP_SCRATCH_W2)")
|
||||
}
|
||||
} else {
|
||||
if (pushResultOnEstack) {
|
||||
asmgen.out(" dex | ldy #0 | lda (P8ZP_SCRATCH_W2),y | sta P8ESTACK_LO+1,x")
|
||||
} else {
|
||||
asmgen.out(" ldy #0 | lda (P8ZP_SCRATCH_W2),y")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun tryOptimizedPointerAccess(expr: BinaryExpression): Boolean {
|
||||
// try to optimize simple cases like assignment from ptr+1, ptr+2...
|
||||
if(expr.operator=="+") {
|
||||
// we can assume const operand has been moved to the right.
|
||||
val constOperand = expr.right.constValue(program)
|
||||
if(constOperand!=null) {
|
||||
val intIndex = constOperand.number.toInt()
|
||||
if(intIndex in 1..255) {
|
||||
asmgen.assignExpressionToVariable(expr.left, asmgen.asmVariableName("P8ZP_SCRATCH_W2"), DataType.UWORD, null)
|
||||
if (pushResultOnEstack) {
|
||||
asmgen.out(" dex | ldy #${intIndex} | lda (P8ZP_SCRATCH_W2),y | sta P8ESTACK_LO+1,x")
|
||||
} else {
|
||||
asmgen.out(" ldy #${intIndex} | lda (P8ZP_SCRATCH_W2),y")
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
when(expr.addressExpression) {
|
||||
is NumericLiteralValue -> {
|
||||
val address = (expr.addressExpression as NumericLiteralValue).number.toInt()
|
||||
@ -1470,22 +1509,11 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
|
||||
if(pushResultOnEstack)
|
||||
asmgen.out(" sta P8ESTACK_LO,x | dex")
|
||||
}
|
||||
else -> {
|
||||
asmgen.assignExpressionToVariable(expr.addressExpression, asmgen.asmVariableName("P8ZP_SCRATCH_W2"), DataType.UWORD, null)
|
||||
if (CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) {
|
||||
if (pushResultOnEstack) {
|
||||
asmgen.out(" dex | lda (P8ZP_SCRATCH_W2) | sta P8ESTACK_LO+1,x")
|
||||
} else {
|
||||
asmgen.out(" lda (P8ZP_SCRATCH_W2)")
|
||||
}
|
||||
} else {
|
||||
if (pushResultOnEstack) {
|
||||
asmgen.out(" dex | ldy #0 | lda (P8ZP_SCRATCH_W2),y | sta P8ESTACK_LO+1,x")
|
||||
} else {
|
||||
asmgen.out(" ldy #0 | lda (P8ZP_SCRATCH_W2),y")
|
||||
}
|
||||
}
|
||||
is BinaryExpression -> {
|
||||
if(!tryOptimizedPointerAccess(expr.addressExpression as BinaryExpression))
|
||||
assignViaExprEval()
|
||||
}
|
||||
else -> assignViaExprEval()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -121,6 +121,24 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
assignRegisterByte(assign.target, CpuRegister.A)
|
||||
}
|
||||
|
||||
fun tryOptimizedPointerAccess(expr: BinaryExpression): Boolean {
|
||||
// try to optimize simple cases like assignment from ptr+1, ptr+2...
|
||||
if(expr.operator=="+") {
|
||||
// we can assume const operand has been moved to the right.
|
||||
val constOperand = expr.right.constValue(program)
|
||||
if(constOperand!=null) {
|
||||
val intIndex = constOperand.number.toInt()
|
||||
if(intIndex in 1..255) {
|
||||
assignExpressionToVariable(expr.left, asmgen.asmVariableName("P8ZP_SCRATCH_W2"), DataType.UWORD, assign.target.scope)
|
||||
asmgen.out(" ldy #${intIndex} | lda (P8ZP_SCRATCH_W2),y")
|
||||
assignRegisterByte(assign.target, CpuRegister.A)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
val value = assign.source.memory!!
|
||||
when (value.addressExpression) {
|
||||
is NumericLiteralValue -> {
|
||||
@ -131,25 +149,8 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
assignMemoryByte(assign.target, null, value.addressExpression as IdentifierReference)
|
||||
}
|
||||
is BinaryExpression -> {
|
||||
// try to optimize simple cases like assignment from ptr+1, ptr+2...
|
||||
var optimized = false
|
||||
val expr = value.addressExpression as BinaryExpression
|
||||
if(expr.operator=="+") {
|
||||
// we can assume const operand has been moved to the right.
|
||||
val constOperand = expr.right.constValue(program)
|
||||
if(constOperand!=null) {
|
||||
val intIndex = constOperand.number.toInt()
|
||||
if(intIndex in 1..255) {
|
||||
assignExpressionToVariable(expr.left, asmgen.asmVariableName("P8ZP_SCRATCH_W2"), DataType.UWORD, assign.target.scope)
|
||||
asmgen.out(" ldy #${intIndex} | lda (P8ZP_SCRATCH_W2),y")
|
||||
assignRegisterByte(assign.target, CpuRegister.A)
|
||||
optimized = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!optimized)
|
||||
assignViaExprEval(expr)
|
||||
if(!tryOptimizedPointerAccess(value.addressExpression as BinaryExpression))
|
||||
assignViaExprEval(value.addressExpression)
|
||||
}
|
||||
else -> assignViaExprEval(value.addressExpression)
|
||||
}
|
||||
@ -1961,8 +1962,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
val addressExpr = memoryAddress.addressExpression
|
||||
val addressLv = addressExpr as? NumericLiteralValue
|
||||
|
||||
fun storeViaExprEval()
|
||||
{
|
||||
fun storeViaExprEval() {
|
||||
assignExpressionToVariable(addressExpr, asmgen.asmVariableName("P8ZP_SCRATCH_W2"), DataType.UWORD, null)
|
||||
if (CompilationTarget.instance.machine.cpu == CpuType.CPU65c02)
|
||||
asmgen.out(" lda $ldaInstructionArg | sta (P8ZP_SCRATCH_W2)")
|
||||
@ -1970,6 +1970,23 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
asmgen.out(" lda $ldaInstructionArg | ldy #0 | sta (P8ZP_SCRATCH_W2),y")
|
||||
}
|
||||
|
||||
fun tryOptimizedPointerAccess(expr: BinaryExpression): Boolean {
|
||||
// try to optimize simple cases like storing value to ptr+1, ptr+2...
|
||||
if(expr.operator=="+") {
|
||||
// we can assume const operand has been moved to the right.
|
||||
val constOperand = expr.right.constValue(program)
|
||||
if(constOperand!=null) {
|
||||
val intIndex = constOperand.number.toInt()
|
||||
if(intIndex in 1..255) {
|
||||
assignExpressionToVariable(expr.left, asmgen.asmVariableName("P8ZP_SCRATCH_W2"), DataType.UWORD, null)
|
||||
asmgen.out(" lda $ldaInstructionArg | ldy #${intIndex} | sta (P8ZP_SCRATCH_W2),y")
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
when {
|
||||
addressLv != null -> {
|
||||
asmgen.out(" lda $ldaInstructionArg | sta ${addressLv.number.toHex()}")
|
||||
@ -1978,22 +1995,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
asmgen.storeByteIntoPointer(addressExpr, ldaInstructionArg)
|
||||
}
|
||||
addressExpr is BinaryExpression -> {
|
||||
// try to optimize simple cases like storing value to ptr+1, ptr+2...
|
||||
var optimized = false
|
||||
if(addressExpr.operator=="+") {
|
||||
// we can assume const operand has been moved to the right.
|
||||
val constOperand = addressExpr.right.constValue(program)
|
||||
if(constOperand!=null) {
|
||||
val intIndex = constOperand.number.toInt()
|
||||
if(intIndex in 1..255) {
|
||||
assignExpressionToVariable(addressExpr.left, asmgen.asmVariableName("P8ZP_SCRATCH_W2"), DataType.UWORD, null)
|
||||
asmgen.out(" lda $ldaInstructionArg | ldy #${intIndex} | sta (P8ZP_SCRATCH_W2),y")
|
||||
optimized = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!optimized)
|
||||
if(!tryOptimizedPointerAccess(addressExpr))
|
||||
storeViaExprEval()
|
||||
}
|
||||
else -> storeViaExprEval()
|
||||
@ -2006,8 +2008,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
val addressLv = addressExpr as? NumericLiteralValue
|
||||
val registerName = register.name.toLowerCase()
|
||||
|
||||
fun storeViaExprEval()
|
||||
{
|
||||
fun storeViaExprEval() {
|
||||
asmgen.saveRegisterStack(register, false)
|
||||
assignExpressionToVariable(addressExpr, asmgen.asmVariableName("P8ZP_SCRATCH_W2"), DataType.UWORD, null)
|
||||
asmgen.restoreRegisterStack(CpuRegister.A, false)
|
||||
@ -2017,6 +2018,25 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
asmgen.out(" ldy #0 | sta (P8ZP_SCRATCH_W2),y")
|
||||
}
|
||||
|
||||
fun tryOptimizedPointerAccess(expr: BinaryExpression): Boolean {
|
||||
// try to optimize simple cases like storing value to ptr+1, ptr+2...
|
||||
if(expr.operator=="+") {
|
||||
// we can assume const operand has been moved to the right.
|
||||
val constOperand = expr.right.constValue(program)
|
||||
if(constOperand!=null) {
|
||||
val intIndex = constOperand.number.toInt()
|
||||
if(intIndex in 1..255) {
|
||||
asmgen.saveRegisterStack(register, false)
|
||||
assignExpressionToVariable(expr.left, asmgen.asmVariableName("P8ZP_SCRATCH_W2"), DataType.UWORD, null)
|
||||
asmgen.restoreRegisterStack(CpuRegister.A, false)
|
||||
asmgen.out(" ldy #${intIndex} | sta (P8ZP_SCRATCH_W2),y")
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
when {
|
||||
addressLv != null -> {
|
||||
asmgen.out(" st$registerName ${addressLv.number.toHex()}")
|
||||
@ -2030,24 +2050,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
asmgen.storeByteIntoPointer(addressExpr, null)
|
||||
}
|
||||
addressExpr is BinaryExpression -> {
|
||||
// try to optimize simple cases like storing value to ptr+1, ptr+2...
|
||||
var optimized = false
|
||||
if(addressExpr.operator=="+") {
|
||||
// we can assume const operand has been moved to the right.
|
||||
val constOperand = addressExpr.right.constValue(program)
|
||||
if(constOperand!=null) {
|
||||
val intIndex = constOperand.number.toInt()
|
||||
if(intIndex in 1..255) {
|
||||
asmgen.saveRegisterStack(register, false)
|
||||
assignExpressionToVariable(addressExpr.left, asmgen.asmVariableName("P8ZP_SCRATCH_W2"), DataType.UWORD, null)
|
||||
asmgen.restoreRegisterStack(CpuRegister.A, false)
|
||||
asmgen.out(" ldy #${intIndex} | sta (P8ZP_SCRATCH_W2),y")
|
||||
optimized = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!optimized)
|
||||
if(!tryOptimizedPointerAccess(addressExpr))
|
||||
storeViaExprEval()
|
||||
}
|
||||
else -> storeViaExprEval()
|
||||
|
@ -2,7 +2,8 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
- optimize pointer access code @(pointer)? use a subroutine? macro? 65c02 vs 6502?
|
||||
- optimize pointer access if it's via a var that's already in ZP. in AssignmentAsmGen 3 times,
|
||||
and in translateDirectMemReadExpression. like loadByteFromPointerIntoA() is doing.
|
||||
- can we get rid of the --longOptionName command line options and only keep the short versions? https://github.com/Kotlin/kotlinx-cli/issues/50
|
||||
- add a compiler option to generate a symbol listing at the end
|
||||
- optimizer: detect variables that are written but never read - mark those as unused too and remove them, such as uword unused = memory("unused222", 20) - also remove the memory slab allocation
|
||||
|
@ -23,10 +23,11 @@ main {
|
||||
txt.nl()
|
||||
txt.nl()
|
||||
|
||||
cc=0
|
||||
|
||||
txt.chrout(@(ptr))
|
||||
txt.chrout(@(ptr+1))
|
||||
txt.chrout(@(ptr+2))
|
||||
txt.chrout(@(ptr)+cc)
|
||||
txt.chrout(@(ptr+1)+cc)
|
||||
txt.chrout(@(ptr+2)+cc)
|
||||
txt.nl()
|
||||
|
||||
@(ptr) = '1'
|
||||
|
Loading…
Reference in New Issue
Block a user