mirror of
https://github.com/irmen/prog8.git
synced 2024-12-01 15:52:54 +00:00
removed a problematic asm optimization step that could result in dysfunctional code when writing to I/O addresses
This commit is contained in:
parent
92276b5769
commit
e2c101206c
@ -17,11 +17,13 @@ class SymbolTable(astProgram: PtProgram) : StNode(astProgram.name, StNodeType.GL
|
|||||||
|
|
||||||
val flat: Map<String, StNode> by lazy {
|
val flat: Map<String, StNode> by lazy {
|
||||||
val result = mutableMapOf<String, StNode>()
|
val result = mutableMapOf<String, StNode>()
|
||||||
fun flatten(node: StNode) {
|
fun collect(node: StNode) {
|
||||||
result[node.scopedName] = node
|
for(child in node.children) {
|
||||||
node.children.values.forEach { flatten(it) }
|
result[child.value.scopedName] = child.value
|
||||||
|
collect(child.value)
|
||||||
}
|
}
|
||||||
children.values.forEach { flatten(it) }
|
}
|
||||||
|
collect(this)
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,13 +51,6 @@ internal fun optimizeAssembly(lines: MutableList<String>, machine: IMachineDefin
|
|||||||
}
|
}
|
||||||
|
|
||||||
var linesByFourteen = getLinesBy(lines, 14)
|
var linesByFourteen = getLinesBy(lines, 14)
|
||||||
mods = optimizeSameAssignments(linesByFourteen, machine, symbolTable)
|
|
||||||
if(mods.isNotEmpty()) {
|
|
||||||
apply(mods, lines)
|
|
||||||
linesByFourteen = getLinesBy(lines, 14)
|
|
||||||
numberOfOptimizations++
|
|
||||||
}
|
|
||||||
|
|
||||||
mods = optimizeSamePointerIndexing(linesByFourteen)
|
mods = optimizeSamePointerIndexing(linesByFourteen)
|
||||||
if(mods.isNotEmpty()) {
|
if(mods.isNotEmpty()) {
|
||||||
apply(mods, lines)
|
apply(mods, lines)
|
||||||
@ -128,208 +121,6 @@ private fun optimizeUselessStackByteWrites(linesByFour: List<List<IndexedValue<S
|
|||||||
return mods
|
return mods
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun optimizeSameAssignments(
|
|
||||||
linesByFourteen: List<List<IndexedValue<String>>>,
|
|
||||||
machine: IMachineDefinition,
|
|
||||||
symbolTable: SymbolTable
|
|
||||||
): List<Modification> {
|
|
||||||
|
|
||||||
// Optimize sequential assignments of the same value to various targets (bytes, words, floats)
|
|
||||||
// the float one is the one that requires 2*7=14 lines of code to check...
|
|
||||||
// The better place to do this is in the Compiler instead and never create these types of assembly, but hey
|
|
||||||
|
|
||||||
val mods = mutableListOf<Modification>()
|
|
||||||
for (lines in linesByFourteen) {
|
|
||||||
val first = lines[0].value.trimStart()
|
|
||||||
val second = lines[1].value.trimStart()
|
|
||||||
val third = lines[2].value.trimStart()
|
|
||||||
val fourth = lines[3].value.trimStart()
|
|
||||||
val fifth = lines[4].value.trimStart()
|
|
||||||
val sixth = lines[5].value.trimStart()
|
|
||||||
val seventh = lines[6].value.trimStart()
|
|
||||||
val eighth = lines[7].value.trimStart()
|
|
||||||
|
|
||||||
if(first.startsWith("lda") && second.startsWith("ldy") && third.startsWith("sta") && fourth.startsWith("sty") &&
|
|
||||||
fifth.startsWith("lda") && sixth.startsWith("ldy") && seventh.startsWith("sta") && eighth.startsWith("sty")) {
|
|
||||||
val firstvalue = first.substring(4)
|
|
||||||
val secondvalue = second.substring(4)
|
|
||||||
val thirdvalue = fifth.substring(4)
|
|
||||||
val fourthvalue = sixth.substring(4)
|
|
||||||
if(firstvalue==thirdvalue && secondvalue==fourthvalue) {
|
|
||||||
// lda/ldy sta/sty twice the same word --> remove second lda/ldy pair (fifth and sixth lines)
|
|
||||||
val address1 = getAddressArg(first, symbolTable)
|
|
||||||
val address2 = getAddressArg(second, symbolTable)
|
|
||||||
if(address1==null || address2==null || (!machine.isIOAddress(address1) && !machine.isIOAddress(address2))) {
|
|
||||||
mods.add(Modification(lines[4].index, true, null))
|
|
||||||
mods.add(Modification(lines[5].index, true, null))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(first.startsWith("lda") && second.startsWith("sta") && third.startsWith("lda") && fourth.startsWith("sta")) {
|
|
||||||
val firstvalue = first.substring(4)
|
|
||||||
val secondvalue = third.substring(4)
|
|
||||||
if(firstvalue==secondvalue) {
|
|
||||||
// lda value / sta ? / lda same-value / sta ? -> remove second lda (third line)
|
|
||||||
val address = getAddressArg(first, symbolTable)
|
|
||||||
if(address==null || !machine.isIOAddress(address))
|
|
||||||
mods.add(Modification(lines[2].index, true, null))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(first.startsWith("lda") && second.startsWith("ldy") && third.startsWith("sta") && fourth.startsWith("sty") &&
|
|
||||||
fifth.startsWith("lda") && sixth.startsWith("ldy") &&
|
|
||||||
(seventh.startsWith("jsr floats.copy_float") || seventh.startsWith("jsr cx16flt.copy_float"))) {
|
|
||||||
|
|
||||||
val nineth = lines[8].value.trimStart()
|
|
||||||
val tenth = lines[9].value.trimStart()
|
|
||||||
val eleventh = lines[10].value.trimStart()
|
|
||||||
val twelveth = lines[11].value.trimStart()
|
|
||||||
val thirteenth = lines[12].value.trimStart()
|
|
||||||
val fourteenth = lines[13].value.trimStart()
|
|
||||||
|
|
||||||
if(eighth.startsWith("lda") && nineth.startsWith("ldy") && tenth.startsWith("sta") && eleventh.startsWith("sty") &&
|
|
||||||
twelveth.startsWith("lda") && thirteenth.startsWith("ldy") &&
|
|
||||||
(fourteenth.startsWith("jsr floats.copy_float") || fourteenth.startsWith("jsr cx16flt.copy_float"))) {
|
|
||||||
|
|
||||||
if(first.substring(4) == eighth.substring(4) && second.substring(4)==nineth.substring(4)) {
|
|
||||||
// identical float init
|
|
||||||
mods.add(Modification(lines[7].index, true, null))
|
|
||||||
mods.add(Modification(lines[8].index, true, null))
|
|
||||||
mods.add(Modification(lines[9].index, true, null))
|
|
||||||
mods.add(Modification(lines[10].index, true, null))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var overlappingMods = false
|
|
||||||
/*
|
|
||||||
sta prog8_lib.retval_intermX ; remove
|
|
||||||
sty prog8_lib.retval_intermY ; remove
|
|
||||||
lda prog8_lib.retval_intermX ; remove
|
|
||||||
ldy prog8_lib.retval_intermY ; remove
|
|
||||||
sta A1
|
|
||||||
sty A2
|
|
||||||
*/
|
|
||||||
if(first.isStoreReg() && second.isStoreReg()
|
|
||||||
&& third.isLoadReg() && fourth.isLoadReg()
|
|
||||||
&& fifth.isStoreReg() && sixth.isStoreReg()) {
|
|
||||||
val reg1 = first[2]
|
|
||||||
val reg2 = second[2]
|
|
||||||
val reg3 = third[2]
|
|
||||||
val reg4 = fourth[2]
|
|
||||||
val reg5 = fifth[2]
|
|
||||||
val reg6 = sixth[2]
|
|
||||||
if (reg1 == reg3 && reg1 == reg5 && reg2 == reg4 && reg2 == reg6) {
|
|
||||||
val firstvalue = first.substring(4)
|
|
||||||
val secondvalue = second.substring(4)
|
|
||||||
val thirdvalue = third.substring(4)
|
|
||||||
val fourthvalue = fourth.substring(4)
|
|
||||||
if(firstvalue.contains("prog8_lib.retval_interm") && secondvalue.contains("prog8_lib.retval_interm")
|
|
||||||
&& firstvalue==thirdvalue && secondvalue==fourthvalue) {
|
|
||||||
mods.add(Modification(lines[0].index, true, null))
|
|
||||||
mods.add(Modification(lines[1].index, true, null))
|
|
||||||
mods.add(Modification(lines[2].index, true, null))
|
|
||||||
mods.add(Modification(lines[3].index, true, null))
|
|
||||||
overlappingMods = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
sta A1
|
|
||||||
sty A2
|
|
||||||
lda A1 ; can be removed
|
|
||||||
ldy A2 ; can be removed if not followed by a branch instuction
|
|
||||||
*/
|
|
||||||
if(!overlappingMods && first.isStoreReg() && second.isStoreReg()
|
|
||||||
&& third.isLoadReg() && fourth.isLoadReg()) {
|
|
||||||
val reg1 = first[2]
|
|
||||||
val reg2 = second[2]
|
|
||||||
val reg3 = third[2]
|
|
||||||
val reg4 = fourth[2]
|
|
||||||
if(reg1==reg3 && reg2==reg4) {
|
|
||||||
val firstvalue = first.substring(4)
|
|
||||||
val secondvalue = second.substring(4)
|
|
||||||
val thirdvalue = third.substring(4)
|
|
||||||
val fourthvalue = fourth.substring(4)
|
|
||||||
if(firstvalue==thirdvalue && secondvalue == fourthvalue) {
|
|
||||||
val address = getAddressArg(first, symbolTable)
|
|
||||||
if(address==null || !machine.isIOAddress(address)) {
|
|
||||||
overlappingMods = true
|
|
||||||
mods.add(Modification(lines[2].index, true, null))
|
|
||||||
if (!fifth.startsWith('b'))
|
|
||||||
mods.add(Modification(lines[3].index, true, null))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
sta A1
|
|
||||||
sty A2 ; ... or stz
|
|
||||||
lda A1 ; can be removed if not followed by a branch instruction
|
|
||||||
*/
|
|
||||||
if(!overlappingMods && first.isStoreReg() && second.isStoreRegOrZero()
|
|
||||||
&& third.isLoadReg() && !fourth.isBranch()) {
|
|
||||||
val reg1 = first[2]
|
|
||||||
val reg3 = third[2]
|
|
||||||
if(reg1==reg3) {
|
|
||||||
val firstvalue = first.substring(4)
|
|
||||||
val thirdvalue = third.substring(4)
|
|
||||||
if(firstvalue==thirdvalue) {
|
|
||||||
val address = getAddressArg(first, symbolTable)
|
|
||||||
if(address==null || !machine.isIOAddress(address)) {
|
|
||||||
overlappingMods = true
|
|
||||||
mods.add(Modification(lines[2].index, true, null))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
sta A1
|
|
||||||
ldy A1 ; make tay
|
|
||||||
sta A1 ; remove
|
|
||||||
*/
|
|
||||||
if(!overlappingMods && first.startsWith("sta") && second.isLoadReg()
|
|
||||||
&& third.startsWith("sta") && second.length>4) {
|
|
||||||
val firstvalue = first.substring(4)
|
|
||||||
val secondvalue = second.substring(4)
|
|
||||||
val thirdvalue = third.substring(4)
|
|
||||||
if(firstvalue==secondvalue && firstvalue==thirdvalue) {
|
|
||||||
val address = getAddressArg(first, symbolTable)
|
|
||||||
if(address==null || !machine.isIOAddress(address)) {
|
|
||||||
overlappingMods = true
|
|
||||||
val reg2 = second[2]
|
|
||||||
mods.add(Modification(lines[1].index, false, " ta$reg2"))
|
|
||||||
mods.add(Modification(lines[2].index, true, null))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
sta A ; or stz double store, remove this first one
|
|
||||||
sta A ; or stz
|
|
||||||
*/
|
|
||||||
if(!overlappingMods && first.isStoreRegOrZero() && second.isStoreRegOrZero()) {
|
|
||||||
if(first[2]==second[2]) {
|
|
||||||
val firstvalue = first.substring(4)
|
|
||||||
val secondvalue = second.substring(4)
|
|
||||||
if(firstvalue==secondvalue) {
|
|
||||||
val address = getAddressArg(first, symbolTable)
|
|
||||||
if(address==null || !machine.isIOAddress(address)) {
|
|
||||||
overlappingMods = true
|
|
||||||
mods.add(Modification(lines[0].index, true, null))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return mods
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun optimizeSamePointerIndexing(linesByFourteen: List<List<IndexedValue<String>>>): List<Modification> {
|
private fun optimizeSamePointerIndexing(linesByFourteen: List<List<IndexedValue<String>>>): List<Modification> {
|
||||||
|
|
||||||
// Optimize same pointer indexing where for instance we load and store to the same ptr index in Y
|
// Optimize same pointer indexing where for instance we load and store to the same ptr index in Y
|
||||||
|
@ -3,8 +3,6 @@ TODO
|
|||||||
|
|
||||||
For next minor release
|
For next minor release
|
||||||
^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
- IR: animals and textelite take more registers now than with 8.10 (code *is* smaller) see test.p8
|
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user