improved repeat counter vars allocation (re-use var if possible)

This commit is contained in:
Irmen de Jong 2021-05-30 15:30:34 +02:00
parent e61a2d7083
commit d4b69ac79c
4 changed files with 26 additions and 23 deletions

View File

@ -880,11 +880,10 @@ internal class AsmGen(private val program: Program,
}
out("; variables")
for((name, addr) in sub.asmGenInfo.extraVarsZP) {
out("$name = $addr")
}
for((dt, name) in sub.asmGenInfo.extraVars) {
when(dt) {
for((dt, name, addr) in sub.asmGenInfo.extraVars) {
if(addr!=null)
out("$name = $addr")
else when(dt) {
DataType.UBYTE -> out("$name .byte 0")
DataType.UWORD -> out("$name .word 0")
else -> throw AssemblyError("weird dt")
@ -1069,33 +1068,40 @@ $repeatLabel lda $counterVar
}
private fun createRepeatCounterVar(dt: DataType, constIterations: Int?, stmt: RepeatLoop): String {
// TODO share counter variables between subroutines or even between repeat loops as long as they're not nested
// var parent = stmt.parent
// while(parent !is ParentSentinel) {
// if(parent is RepeatLoop)
// break
// parent = parent.parent
// }
// val isNested = parent is RepeatLoop
val counterVar = makeLabel("repeatcounter")
val asmInfo = stmt.definingSubroutine()!!.asmGenInfo
var parent = stmt.parent
while(parent !is ParentSentinel) {
if(parent is RepeatLoop)
break
parent = parent.parent
}
val isNested = parent is RepeatLoop
if(!isNested) {
// we can re-use a counter var from the subroutine if it already has one for that datatype
val existingVar = asmInfo.extraVars.firstOrNull { it.first==dt }
if(existingVar!=null)
return existingVar.second
}
val counterVar = makeLabel("repeatcounter")
when(dt) {
DataType.UBYTE -> {
if(constIterations!=null && constIterations>=16 && zeropage.hasByteAvailable()) {
// allocate count var on ZP
val zpAddr = zeropage.allocate(counterVar, DataType.UBYTE, stmt.position, errors)
asmInfo.extraVarsZP.add(Pair(counterVar, zpAddr))
asmInfo.extraVars.add(Triple(DataType.UBYTE, counterVar, zpAddr))
} else {
asmInfo.extraVars.add(Pair(DataType.UBYTE, counterVar))
asmInfo.extraVars.add(Triple(DataType.UBYTE, counterVar, null))
}
}
DataType.UWORD -> {
if(constIterations!=null && constIterations>=16 && zeropage.hasWordAvailable()) {
// allocate count var on ZP
val zpAddr = zeropage.allocate(counterVar, DataType.UWORD, stmt.position, errors)
asmInfo.extraVarsZP.add(Pair(counterVar, zpAddr))
asmInfo.extraVars.add(Triple(DataType.UWORD, counterVar, zpAddr))
} else {
asmInfo.extraVars.add(Pair(DataType.UWORD, counterVar))
asmInfo.extraVars.add(Triple(DataType.UWORD, counterVar, null))
}
}
else -> throw AssemblyError("invalidt dt")

View File

@ -589,8 +589,7 @@ class AsmGenInfo {
var usedFloatEvalResultVar1 = false
var usedFloatEvalResultVar2 = false
val extraVars = mutableListOf<Pair<DataType, String>>()
val extraVarsZP = mutableListOf<Pair<String, Int>>()
val extraVars = mutableListOf<Triple<DataType, String, Int?>>()
}
// the subroutine class covers both the normal user-defined subroutines,

View File

@ -5,7 +5,6 @@ TODO
- test all examples (including imgviewer, assembler and petaxian) before release of the new version
- simplify cx16.joystick_get2() once this cx16 rom issue is resolved: https://github.com/commanderx16/x16-rom/issues/203
- improve repeat counter vars allocation in asmgen.createRepeatCounterVar()
- c64: make the graphics.BITMAP_ADDRESS configurable (VIC banking)
- get rid of all other TODO's in the code ;-)

View File

@ -1,11 +1,10 @@
%import textio ; txt.*
%import textio
%zeropage basicsafe
main {
; test program for the optimization of repeat var allocation (asmgen.createRepeatCounterVar)
; output must be: 60 6164 6224 12328
; original program size: $046b
uword xx