sorting aligned vars to shrink prg size

This commit is contained in:
Irmen de Jong 2024-10-26 18:33:51 +02:00
parent 1cd754f05d
commit 9317cf8a35
4 changed files with 122 additions and 31 deletions

View File

@ -587,7 +587,16 @@ internal class ProgramAndVarsGen(
if(varsNoInit.isNotEmpty()) {
asmgen.out("; non-zeropage variables")
asmgen.out(" .section BSS")
varsNoInit.sortedWith(compareBy<StStaticVariable> { it.name }.thenBy { it.dt }).forEach {
val wordAligned = varsNoInit.filter { it.align==PtVariable.Alignment.WORD }
val pageAligned = varsNoInit.filter { it.align==PtVariable.Alignment.PAGE }
val notAligned = varsNoInit.filter { it.align==PtVariable.Alignment.NONE }
notAligned.sortedWith(compareBy<StStaticVariable> { it.name }.thenBy { it.dt }).forEach {
uninitializedVariable2asm(it)
}
wordAligned.sortedWith(compareBy<StStaticVariable> { it.name }.thenBy { it.dt }).forEach {
uninitializedVariable2asm(it)
}
pageAligned.sortedWith(compareBy<StStaticVariable> { it.name }.thenBy { it.dt }).forEach {
uninitializedVariable2asm(it)
}
asmgen.out(" .send BSS")
@ -596,7 +605,11 @@ internal class ProgramAndVarsGen(
if(varsWithInit.isNotEmpty()) {
asmgen.out("; non-zeropage variables with init value")
val (stringvars, othervars) = varsWithInit.sortedBy { it.name }.partition { it.dt == DataType.STR }
stringvars.forEach {
val stringsWordAligned = stringvars.filter { it.align==PtVariable.Alignment.WORD }
val stringsPageAligned = stringvars.filter { it.align==PtVariable.Alignment.PAGE }
val stringsNotAligned = stringvars.filter { it.align==PtVariable.Alignment.NONE }
stringsNotAligned.forEach {
outputStringvar(
it.name,
it.align,
@ -604,7 +617,33 @@ internal class ProgramAndVarsGen(
it.initializationStringValue!!.first
)
}
othervars.sortedBy { it.type }.forEach {
stringsWordAligned.forEach {
outputStringvar(
it.name,
it.align,
it.initializationStringValue!!.second,
it.initializationStringValue!!.first
)
}
stringsPageAligned.forEach {
outputStringvar(
it.name,
it.align,
it.initializationStringValue!!.second,
it.initializationStringValue!!.first
)
}
val wordAligned = othervars.filter { it.align==PtVariable.Alignment.WORD }
val pageAligned = othervars.filter { it.align==PtVariable.Alignment.PAGE }
val notAligned = othervars.filter { it.align==PtVariable.Alignment.NONE }
notAligned.sortedBy { it.type }.forEach {
staticVariable2asm(it)
}
wordAligned.sortedBy { it.type }.forEach {
staticVariable2asm(it)
}
pageAligned.sortedBy { it.type }.forEach {
staticVariable2asm(it)
}
}
@ -667,7 +706,9 @@ internal class ProgramAndVarsGen(
DataType.STR -> {
throw AssemblyError("all string vars should have been interned into prog")
}
in ArrayDatatypes -> arrayVariable2asm(variable.name, variable.dt, variable.align, variable.initializationArrayValue, variable.length)
in ArrayDatatypes -> {
arrayVariable2asm(variable.name, variable.dt, variable.align, variable.initializationArrayValue, variable.length)
}
else -> {
throw AssemblyError("weird dt")
}

View File

@ -1,8 +1,7 @@
TODO
====
- are uninitialized (bss) variables correctly @aligned now? (%option align docs say they're not, but maybe the new @align tag fixes this too)
- aligned vars codegen: sort to do all word alignments first then the page alignments
- add docs for @align. Note: uninitialized (bss) variables are also correctly aligned (%option align docs say they're not, but that is fixed)
- what to use to align a label ? (%align $100 ?) to support aligned asmincludes for example.
- remove %option align_xxx ? (block level alignment, as we now have individual variable alignments)
@ -44,6 +43,7 @@ Future Things and Ideas
- ir: add more optimizations in IRPeepholeOptimizer
- ir: the @split arrays are currently also split in _lsb/_msb arrays in the IR, and operations take multiple (byte) instructions that may lead to verbose and slow operation and machine code generation down the line.
maybe another representation is needed once actual codegeneration is done from the IR...?
- ir: split word arrays, both _msb and _lsb arrays are tagged with an alignment. This is not what's intended; only the one put in memory first should be aligned (the other one should follow straight after it)
- ir: getting it in shape for code generation...
- ir: make optimizeBitTest work for IR too to use the BIT instruction?
- ir: make sure that a 6502 codegen based off the IR, still generates BIT instructions when testing bit 7 or 6 of a byte var.

View File

@ -1,20 +1,45 @@
%option no_sysinit
%zeropage basicsafe
%zeropage dontuse
main {
sub start() {
str @alignword @shared name = "wordaligned"
str @alignpage @shared @nozp name2 = "pagealigned"
ubyte[20] @alignword @shared array1
ubyte[20] @alignword @shared array2
ubyte[20] @alignpage @shared array3
ubyte[20] @alignpage @shared array4
ubyte[] @alignword @shared array5 = [1,2,3,4]
ubyte[] @alignword @shared array6 = [1,2,3,4]
ubyte[] @alignpage @shared array7 = [1,2,3,4]
ubyte[] @alignpage @shared array8 = [1,2,3,4]
uword[20] @alignword @split @shared array9
uword[] @alignword @split @shared array10 = [1111,2222,3333,4444]
str @alignword @shared name1 = "abc123456789"
str @alignpage @shared name2 = "def123456789"
str @alignword @shared @nozp name3 = "ghi123456789"
str @alignword @shared @nozp name4 = "jkl123456789"
ubyte[9] @alignword @shared array1
ubyte[9] @alignword @shared array2
ubyte[9] @alignpage @shared array3
ubyte[9] @alignword @shared array4
ubyte[9] @alignword @shared array5
ubyte[9] @alignword @shared array6
ubyte[9] @alignword @shared array7
ubyte[9] @alignword @shared array8
ubyte[] @alignword @shared array9 = [1,2,3]
ubyte[] @alignword @shared array10 = [1,2,3]
ubyte[] @alignpage @shared array11 = [1,2,3]
ubyte[] @alignpage @shared array12 = [1,2,3]
ubyte[] @alignword @shared array13 = [1,2,3]
ubyte[] @alignword @shared array14 = [1,2,3]
ubyte[] @alignpage @shared array15 = [1,2,3]
ubyte[] @alignpage @shared array16 = [1,2,3]
uword[3] @alignword @split @shared array17
uword[] @alignword @split @shared array18 = [1111,2222,3333]
array9[2]++
array10[2]++
array11[2]++
array12[2]++
array13[2]++
array14[2]++
array15[2]++
array16[2]++
array17[2]++
array18[2]++
name1[2]++
name2[2]++
name3[2]++
name4[2]++
}
}

View File

@ -202,12 +202,7 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
}
private fun writeVariables() {
val (variablesNoInit, variablesWithInit) = irProgram.st.allVariables().partition { it.uninitialized }
xml.writeStartElement("VARIABLESNOINIT")
xml.writeCharacters("\n")
for (variable in variablesNoInit) {
fun writeNoInitVar(variable: IRStStaticVariable) {
if(variable.dt in SplitWordArrayTypes) {
// split into 2 ubyte arrays lsb+msb
xml.writeCharacters("ubyte[${variable.length}] ${variable.name}_lsb zp=${variable.zpwish} align=${variable.align}\n")
@ -217,12 +212,7 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
}
}
xml.writeEndElement()
xml.writeCharacters("\n")
xml.writeStartElement("VARIABLESWITHINIT")
xml.writeCharacters("\n")
for (variable in variablesWithInit) {
fun writeVarWithInit(variable: IRStStaticVariable) {
if(variable.dt in SplitWordArrayTypes) {
val lsbValue: String
val msbValue: String
@ -282,6 +272,41 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
xml.writeCharacters("${variable.typeString} ${variable.name}=$value zp=${variable.zpwish} align=${variable.align}\n")
}
}
val (variablesNoInit, variablesWithInit) = irProgram.st.allVariables().partition { it.uninitialized }
xml.writeStartElement("VARIABLESNOINIT")
xml.writeCharacters("\n")
val noinitNotAligned = variablesNoInit.filter { it.align==IRStStaticVariable.Alignment.NONE }
val noinitWordAligned = variablesNoInit.filter { it.align==IRStStaticVariable.Alignment.WORD }
val noinitPageAligned = variablesNoInit.filter { it.align==IRStStaticVariable.Alignment.PAGE }
for (variable in noinitNotAligned) {
writeNoInitVar(variable)
}
for (variable in noinitWordAligned) {
writeNoInitVar(variable)
}
for (variable in noinitPageAligned) {
writeNoInitVar(variable)
}
xml.writeEndElement()
xml.writeCharacters("\n")
xml.writeStartElement("VARIABLESWITHINIT")
xml.writeCharacters("\n")
val initNotAligned = variablesWithInit.filter { it.align==IRStStaticVariable.Alignment.NONE }
val initWordAligned = variablesWithInit.filter { it.align==IRStStaticVariable.Alignment.WORD }
val initPageAligned = variablesWithInit.filter { it.align==IRStStaticVariable.Alignment.PAGE }
for (variable in initNotAligned) {
writeVarWithInit(variable)
}
for (variable in initWordAligned) {
writeVarWithInit(variable)
}
for (variable in initPageAligned) {
writeVarWithInit(variable)
}
xml.writeEndElement()
xml.writeCharacters("\n")