mirror of
https://github.com/irmen/prog8.git
synced 2025-02-21 10:29:03 +00:00
asm optimizer: don't remove labels. remove redundant cmp/cpx/cpy instructions.
This commit is contained in:
parent
ceaa4cd07d
commit
620ffe54ec
@ -75,23 +75,48 @@ private fun String.isStoreReg() = this.startsWith("sta") || this.startsWith("sty
|
|||||||
private fun String.isStoreRegOrZero() = this.isStoreReg() || this.startsWith("stz")
|
private fun String.isStoreRegOrZero() = this.isStoreReg() || this.startsWith("stz")
|
||||||
private fun String.isLoadReg() = this.startsWith("lda") || this.startsWith("ldy") || this.startsWith("ldx")
|
private fun String.isLoadReg() = this.startsWith("lda") || this.startsWith("ldy") || this.startsWith("ldx")
|
||||||
|
|
||||||
private class Modification(val lineIndex: Int, val remove: Boolean, val replacement: String?)
|
private class Modification(val lineIndex: Int, val remove: Boolean, val replacement: String?, val removeLabel: Boolean=false)
|
||||||
|
|
||||||
private fun apply(modifications: List<Modification>, lines: MutableList<String>) {
|
private fun apply(modifications: List<Modification>, lines: MutableList<String>) {
|
||||||
for (modification in modifications.sortedBy { it.lineIndex }.reversed()) {
|
for (modification in modifications.sortedBy { it.lineIndex }.reversed()) {
|
||||||
if(modification.remove)
|
if(modification.remove) {
|
||||||
lines.removeAt(modification.lineIndex)
|
if(modification.removeLabel)
|
||||||
|
lines.removeAt(modification.lineIndex)
|
||||||
|
else {
|
||||||
|
val line = lines[modification.lineIndex]
|
||||||
|
if (line.length < 2 || line[0] == ';' || line.trimStart()[0] == ';')
|
||||||
|
lines.removeAt(modification.lineIndex)
|
||||||
|
else if (haslabel(line)) {
|
||||||
|
val label = keeplabel(line)
|
||||||
|
if (label.isNotEmpty())
|
||||||
|
lines[modification.lineIndex] = label
|
||||||
|
else
|
||||||
|
lines.removeAt(modification.lineIndex)
|
||||||
|
} else lines.removeAt(modification.lineIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
lines[modification.lineIndex] = modification.replacement!!
|
lines[modification.lineIndex] = modification.replacement!!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun haslabel(line: String): Boolean {
|
||||||
|
return line.length>1 && line[0]!=';' && (!line[0].isWhitespace() || ':' in line)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun keeplabel(line: String): String {
|
||||||
|
if(':' in line)
|
||||||
|
return line.substringBefore(':') + ':'
|
||||||
|
val splits = line.split('\t', ' ', limit=2)
|
||||||
|
return if(splits.size>1) splits[0] + ':' else ""
|
||||||
|
}
|
||||||
|
|
||||||
private fun getLinesBy(lines: MutableList<String>, windowSize: Int) =
|
private fun getLinesBy(lines: MutableList<String>, windowSize: Int) =
|
||||||
// all lines (that aren't empty or comments) in sliding windows of certain size
|
// all lines (that aren't empty or comments) in sliding windows of certain size
|
||||||
lines.withIndex().filter { it.value.isNotBlank() && !it.value.trimStart().startsWith(';') }.windowed(windowSize, partialWindows = false)
|
lines.asSequence().withIndex().filter { it.value.isNotBlank() && !it.value.trimStart().startsWith(';') }.windowed(windowSize, partialWindows = false)
|
||||||
|
|
||||||
private fun optimizeSameAssignments(
|
private fun optimizeSameAssignments(
|
||||||
linesByFourteen: List<List<IndexedValue<String>>>,
|
linesByFourteen: Sequence<List<IndexedValue<String>>>,
|
||||||
machine: IMachineDefinition,
|
machine: IMachineDefinition,
|
||||||
symbolTable: SymbolTable
|
symbolTable: SymbolTable
|
||||||
): List<Modification> {
|
): List<Modification> {
|
||||||
@ -281,7 +306,7 @@ private fun optimizeSameAssignments(
|
|||||||
return mods
|
return mods
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun optimizeSamePointerIndexing(linesByFourteen: List<List<IndexedValue<String>>>): List<Modification> {
|
private fun optimizeSamePointerIndexing(linesByFourteen: Sequence<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
|
||||||
// if Y isn't modified in between we can omit the second LDY:
|
// if Y isn't modified in between we can omit the second LDY:
|
||||||
@ -324,7 +349,7 @@ private fun optimizeSamePointerIndexing(linesByFourteen: List<List<IndexedValue<
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun optimizeStoreLoadSame(
|
private fun optimizeStoreLoadSame(
|
||||||
linesByFour: List<List<IndexedValue<String>>>,
|
linesByFour: Sequence<List<IndexedValue<String>>>,
|
||||||
machine: IMachineDefinition,
|
machine: IMachineDefinition,
|
||||||
symbolTable: SymbolTable
|
symbolTable: SymbolTable
|
||||||
): List<Modification> {
|
): List<Modification> {
|
||||||
@ -414,7 +439,7 @@ private fun getAddressArg(line: String, symbolTable: SymbolTable): UInt? {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun optimizeIncDec(linesByFour: List<List<IndexedValue<String>>>): List<Modification> {
|
private fun optimizeIncDec(linesByFour: Sequence<List<IndexedValue<String>>>): List<Modification> {
|
||||||
// sometimes, iny+dey / inx+dex / dey+iny / dex+inx sequences are generated, these can be eliminated.
|
// sometimes, iny+dey / inx+dex / dey+iny / dex+inx sequences are generated, these can be eliminated.
|
||||||
val mods = mutableListOf<Modification>()
|
val mods = mutableListOf<Modification>()
|
||||||
for (lines in linesByFour) {
|
for (lines in linesByFour) {
|
||||||
@ -435,10 +460,11 @@ private fun optimizeIncDec(linesByFour: List<List<IndexedValue<String>>>): List<
|
|||||||
return mods
|
return mods
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun optimizeJsrRtsAndOtherCombinations(linesByFour: List<List<IndexedValue<String>>>): List<Modification> {
|
private fun optimizeJsrRtsAndOtherCombinations(linesByFour: Sequence<List<IndexedValue<String>>>): List<Modification> {
|
||||||
// jsr Sub + rts -> jmp Sub
|
// jsr Sub + rts -> jmp Sub
|
||||||
// rts + jmp -> remove jmp
|
// rts + jmp -> remove jmp
|
||||||
// rts + bxx -> remove bxx
|
// rts + bxx -> remove bxx
|
||||||
|
// lda + cmp #0 -> remove cmp, same for cpy and cpx.
|
||||||
// and some other optimizations.
|
// and some other optimizations.
|
||||||
|
|
||||||
val mods = mutableListOf<Modification>()
|
val mods = mutableListOf<Modification>()
|
||||||
@ -472,6 +498,23 @@ private fun optimizeJsrRtsAndOtherCombinations(linesByFour: List<List<IndexedVal
|
|||||||
mods += Modification(lines[1].index, true, null)
|
mods += Modification(lines[1].index, true, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!haslabel(second)) {
|
||||||
|
if ((" lda" in first || "\tlda" in first) && (" cmp #0" in second || "\tcmp #0" in second) ||
|
||||||
|
(" ldx" in first || "\tldx" in first) && (" cpx #0" in second || "\tcpx #0" in second) ||
|
||||||
|
(" ldy" in first || "\tldy" in first) && (" cpy #0" in second || "\tcpy #0" in second)
|
||||||
|
) {
|
||||||
|
mods.add(Modification(lines[1].index, true, null))
|
||||||
|
}
|
||||||
|
else if(" cmp #0" in second || "\tcmp #0" in second) {
|
||||||
|
// there are many instructions that modify A and set the bits...
|
||||||
|
for(instr in arrayOf("lda", "ora", "and", "eor", "adc", "sbc", "asl", "cmp", "inc a", "lsr", "pla", "rol", "ror", "txa", "tya")) {
|
||||||
|
if(" $instr" in first || "\t$instr" in first) {
|
||||||
|
mods.add(Modification(lines[1].index, true, null))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
LDA NUM1
|
LDA NUM1
|
||||||
CMP NUM2
|
CMP NUM2
|
||||||
@ -501,7 +544,7 @@ private fun optimizeJsrRtsAndOtherCombinations(linesByFour: List<List<IndexedVal
|
|||||||
return mods
|
return mods
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun optimizeUselessPushPopStack(linesByFour: List<List<IndexedValue<String>>>): List<Modification> {
|
private fun optimizeUselessPushPopStack(linesByFour: Sequence<List<IndexedValue<String>>>): List<Modification> {
|
||||||
val mods = mutableListOf<Modification>()
|
val mods = mutableListOf<Modification>()
|
||||||
|
|
||||||
fun optimize(register: Char, lines: List<IndexedValue<String>>) {
|
fun optimize(register: Char, lines: List<IndexedValue<String>>) {
|
||||||
@ -538,7 +581,7 @@ private fun optimizeUselessPushPopStack(linesByFour: List<List<IndexedValue<Stri
|
|||||||
return mods
|
return mods
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun optimizeUnneededTempvarInAdd(linesByFour: List<List<IndexedValue<String>>>): List<Modification> {
|
private fun optimizeUnneededTempvarInAdd(linesByFour: Sequence<List<IndexedValue<String>>>): List<Modification> {
|
||||||
// sequence: sta P8ZP_SCRATCH_XX / lda something / clc / adc P8ZP_SCRATCH_XX
|
// sequence: sta P8ZP_SCRATCH_XX / lda something / clc / adc P8ZP_SCRATCH_XX
|
||||||
// this can be performed without the scratch variable: clc / adc something
|
// this can be performed without the scratch variable: clc / adc something
|
||||||
val mods = mutableListOf<Modification>()
|
val mods = mutableListOf<Modification>()
|
||||||
|
@ -1,14 +1,9 @@
|
|||||||
TODO
|
TODO
|
||||||
====
|
====
|
||||||
|
|
||||||
add peephole asm optimizer that removes a cmp #0 directly after a lda (same for cpx cpy)
|
|
||||||
check all comparisons for split word arrays (signed+unsigned, all 4 variants)
|
check all comparisons for split word arrays (signed+unsigned, all 4 variants)
|
||||||
|
|
||||||
|
snow example is a lot larger!
|
||||||
floatparse is slightly larger
|
|
||||||
snow is a lot larger
|
|
||||||
neofetch is sligthly larger
|
|
||||||
|
|
||||||
|
|
||||||
explore possible optimizations for words when comparing to a constant number (BeforeAsmAstChanger)
|
explore possible optimizations for words when comparing to a constant number (BeforeAsmAstChanger)
|
||||||
|
|
||||||
|
@ -11,27 +11,27 @@ main {
|
|||||||
|
|
||||||
if any(barray)
|
if any(barray)
|
||||||
cx16.r0++
|
cx16.r0++
|
||||||
;
|
|
||||||
;
|
|
||||||
; if barray[2] == 33
|
if barray[2] == 33
|
||||||
; cx16.r0++
|
cx16.r0++
|
||||||
; else
|
else
|
||||||
; cx16.r1++
|
cx16.r1++
|
||||||
;
|
|
||||||
; if warray[2] == 3333
|
if warray[2] == 3333
|
||||||
; cx16.r0++
|
cx16.r0++
|
||||||
; else
|
else
|
||||||
; cx16.r1++
|
cx16.r1++
|
||||||
;
|
|
||||||
; if barray[cx16.r0L] == 33
|
if barray[cx16.r0L] == 33
|
||||||
; cx16.r0++
|
cx16.r0++
|
||||||
; else
|
else
|
||||||
; cx16.r1++
|
cx16.r1++
|
||||||
;
|
|
||||||
; if warray[cx16.r0L] == 3333
|
if warray[cx16.r0L] == 3333
|
||||||
; cx16.r0++
|
cx16.r0++
|
||||||
; else
|
else
|
||||||
; cx16.r1++
|
cx16.r1++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user