optimize asm: don't use temp var for some additions

This commit is contained in:
Irmen de Jong 2023-09-01 22:24:17 +02:00
parent 5cd4b874ea
commit 04959dbd8b
4 changed files with 48 additions and 40 deletions

View File

@ -43,6 +43,13 @@ internal fun optimizeAssembly(lines: MutableList<String>, machine: IMachineDefin
numberOfOptimizations++ numberOfOptimizations++
} }
mods = optimizeUnneededTempvarInAdd(linesByFour)
if(mods.isNotEmpty()) {
apply(mods, lines)
linesByFour = getLinesBy(lines, 4)
numberOfOptimizations++
}
var linesByFourteen = getLinesBy(lines, 14) var linesByFourteen = getLinesBy(lines, 14)
mods = optimizeSameAssignments(linesByFourteen, machine, symbolTable) mods = optimizeSameAssignments(linesByFourteen, machine, symbolTable)
if(mods.isNotEmpty()) { if(mods.isNotEmpty()) {
@ -509,3 +516,26 @@ private fun optimizeUselessPushPopStack(linesByFour: List<List<IndexedValue<Stri
} }
return mods return mods
} }
private fun optimizeUnneededTempvarInAdd(linesByFour: List<List<IndexedValue<String>>>): List<Modification> {
// sequence: sta P8ZP_SCRATCH_XX / lda something / clc / adc P8ZP_SCRATCH_XX
// this can be performed without the scratch variable: clc / adc something
val mods = mutableListOf<Modification>()
for(lines in linesByFour) {
val first = lines[0].value.trimStart()
val second = lines[1].value.trimStart()
val third = lines[2].value.trimStart()
val fourth = lines[3].value.trimStart()
if(first.startsWith("sta P8ZP_SCRATCH_") && second.startsWith("lda") && third.startsWith("clc") && fourth.startsWith("adc P8ZP_SCRATCH_") ) {
if(fourth.substring(4)==first.substring(4)) {
mods.add(Modification(lines[0].index, false, " clc"))
mods.add(Modification(lines[1].index, false, " adc ${second.substring(3).trimStart()}"))
mods.add(Modification(lines[2].index, true, null))
mods.add(Modification(lines[3].index, true, null))
}
}
}
return mods
}

View File

@ -707,6 +707,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
} }
private fun inplacemodificationByteVariableWithValue(name: String, dt: DataType, operator: String, value: PtExpression) { private fun inplacemodificationByteVariableWithValue(name: String, dt: DataType, operator: String, value: PtExpression) {
// TODO optimize: don't use scratch var if possible
val tmpVar = if(name!="P8ZP_SCRATCH_B1") "P8ZP_SCRATCH_B1" else "P8ZP_SCRATCH_REG" val tmpVar = if(name!="P8ZP_SCRATCH_B1") "P8ZP_SCRATCH_B1" else "P8ZP_SCRATCH_REG"
asmgen.assignExpressionToVariable(value, tmpVar, value.type) asmgen.assignExpressionToVariable(value, tmpVar, value.type)
asmgen.out(" lda $name") asmgen.out(" lda $name")
@ -1080,6 +1081,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
} }
"-" -> { "-" -> {
asmgen.translateDirectMemReadExpressionToRegA(memread) asmgen.translateDirectMemReadExpressionToRegA(memread)
// TODO optimize: don't use scratch var if possible
val tmpByte = if(name!="P8ZP_SCRATCH_B1") "P8ZP_SCRATCH_B1" else "P8ZP_SCRATCH_REG" val tmpByte = if(name!="P8ZP_SCRATCH_B1") "P8ZP_SCRATCH_B1" else "P8ZP_SCRATCH_REG"
asmgen.out(""" asmgen.out("""
sta $tmpByte sta $tmpByte
@ -2025,8 +2027,9 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
// the other variable is a BYTE type so optimize for that // the other variable is a BYTE type so optimize for that
when (operator) { when (operator) {
"+" -> { "+" -> {
asmgen.assignExpressionToVariable(value, "P8ZP_SCRATCH_B1", valueDt) if(valueDt==DataType.UBYTE) {
if(valueDt==DataType.UBYTE) // TODO optimize: don't use scratch var
asmgen.assignExpressionToVariable(value, "P8ZP_SCRATCH_B1", valueDt)
asmgen.out(""" asmgen.out("""
lda $name lda $name
clc clc
@ -2035,7 +2038,9 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
bcc + bcc +
inc $name+1 inc $name+1
+""") +""")
else } else {
// TODO optimize: don't use scratch var
asmgen.assignExpressionToVariable(value, "P8ZP_SCRATCH_B1", valueDt)
asmgen.out(""" asmgen.out("""
ldy #0 ldy #0
lda P8ZP_SCRATCH_B1 lda P8ZP_SCRATCH_B1
@ -2047,8 +2052,10 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
tya tya
adc $name+1 adc $name+1
sta $name+1""") sta $name+1""")
}
} }
"-" -> { "-" -> {
// TODO optimize: don't use scratch var
asmgen.assignExpressionToVariable(value, "P8ZP_SCRATCH_B1", valueDt) asmgen.assignExpressionToVariable(value, "P8ZP_SCRATCH_B1", valueDt)
if(valueDt==DataType.UBYTE) if(valueDt==DataType.UBYTE)
asmgen.out(""" asmgen.out("""

View File

@ -1,5 +1,7 @@
TODO TODO
==== ====
- optimize: search for TODO optimize: don't use scratch var
- prefix prog8 subroutines with p8s_ instead of p8_ to not let them clash with variables in the asm? - prefix prog8 subroutines with p8s_ instead of p8_ to not let them clash with variables in the asm?
- allow 'chained' array indexing for expressions: value = ptrarray[0][0] - allow 'chained' array indexing for expressions: value = ptrarray[0][0]
- allow 'chained' array indexing for assign targets: ptrarray[0][0] = 42 this is just evaluating the lhs as a uword pointer expression - allow 'chained' array indexing for assign targets: ptrarray[0][0] = 42 this is just evaluating the lhs as a uword pointer expression

View File

@ -4,42 +4,11 @@
main { main {
sub start() { sub start() {
uword w1 ubyte index
uword w2 ubyte[] t_index = [1,2,3,4,5]
ubyte nibble = 0
ubyte b1 index -= t_index[4]
ubyte b2 index -= t_index[nibble]
b1 = 255
b2 = 1
txt.print_ub(b1&b2!=0) ; true
txt.spc()
txt.print_ub(b1&b2==0) ; false
txt.nl()
b1 = 255
b2 = 0
txt.print_ub(b1&b2!=0) ; false
txt.spc()
txt.print_ub(b1&b2==0) ; true
txt.nl()
w1 = $ff0f
w2 = $0101
txt.print_ub(w1&w2!=0) ; true
txt.spc()
txt.print_ub(w1&w2==0) ; false
txt.nl()
w1 = $ff0f
w2 = $00f0
txt.print_ub(w1&w2!=0) ; false
txt.spc()
txt.print_ub(w1&w2==0) ; true
txt.nl()
; if w1 & w2
; cx16.r0++
} }
} }