mirror of
https://github.com/irmen/prog8.git
synced 2025-01-10 20:30:23 +00:00
IR: optimize redundant labels
This commit is contained in:
parent
6a40f23578
commit
9ef9c24388
@ -87,7 +87,7 @@ class IRPeepholeOptimizer(private val irprog: IRProgram) {
|
||||
/*
|
||||
Empty Code chunk with label ->
|
||||
If next chunk has no label -> move label to next chunk, remove original
|
||||
If next chunk has label -> label name should be the same, remove original. Otherwise FOR NOW leave it in place. (TODO: merge both labels into 1)
|
||||
If next chunk has label -> label name should be the same, remove original. Otherwise merge both labels into 1.
|
||||
If is last chunk -> keep chunk in place because of the label.
|
||||
Empty Code chunk without label ->
|
||||
should not have been generated! ERROR.
|
||||
@ -96,6 +96,7 @@ class IRPeepholeOptimizer(private val irprog: IRProgram) {
|
||||
|
||||
val relabelChunks = mutableListOf<Pair<Int, String>>()
|
||||
val removeChunks = mutableListOf<Int>()
|
||||
val replaceLabels = mutableMapOf<String, String>()
|
||||
|
||||
sub.chunks.withIndex().forEach { (index, chunk) ->
|
||||
if(chunk is IRCodeChunk && chunk.instructions.isEmpty()) {
|
||||
@ -109,10 +110,18 @@ class IRPeepholeOptimizer(private val irprog: IRProgram) {
|
||||
relabelChunks += Pair(index + 1, chunk.label!!)
|
||||
removeChunks += index
|
||||
} else {
|
||||
if (chunk.label == nextchunk.label)
|
||||
removeChunks += index
|
||||
else {
|
||||
// TODO: merge labels on same chunk
|
||||
// merge both labels into 1 except if this is the label chunk at the start of the subroutine
|
||||
if(index>0) {
|
||||
if (chunk.label == nextchunk.label)
|
||||
removeChunks += index
|
||||
else {
|
||||
removeChunks += index
|
||||
replaceLabels[chunk.label!!] = nextchunk.label!!
|
||||
replaceLabels.entries.forEach { (key, value) ->
|
||||
if (value == chunk.label)
|
||||
replaceLabels[key] = nextchunk.label!!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -129,6 +138,25 @@ class IRPeepholeOptimizer(private val irprog: IRProgram) {
|
||||
sub.chunks[index] = chunk
|
||||
}
|
||||
removeChunks.reversed().forEach { index -> sub.chunks.removeAt(index) }
|
||||
|
||||
sub.chunks.forEach { chunk ->
|
||||
chunk.instructions.withIndex().forEach { (idx, instr) ->
|
||||
instr.labelSymbol?.let {
|
||||
if(instr.opcode in OpcodesThatBranch) {
|
||||
replaceLabels.forEach { (from, to) ->
|
||||
if (it == from) {
|
||||
chunk.instructions[idx] = instr.copy(labelSymbol = to)
|
||||
}
|
||||
else {
|
||||
val actualPrefix = "$from."
|
||||
if (it.startsWith(actualPrefix))
|
||||
chunk.instructions[idx] = instr.copy(labelSymbol = "$to.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun joinChunks(sub: IRSubroutine) {
|
||||
|
@ -53,9 +53,9 @@ class TestIRPeepholeOpt: FunSpec({
|
||||
|
||||
test("remove jmp to label below") {
|
||||
val c1 = IRCodeChunk("main.start", null)
|
||||
c1 += IRInstruction(Opcode.JUMP, labelSymbol = "label") // removed, but chunk stays because of label
|
||||
c1 += IRInstruction(Opcode.JUMP, labelSymbol = "label")
|
||||
val c2 = IRCodeChunk("label", null)
|
||||
c2 += IRInstruction(Opcode.JUMP, labelSymbol = "label2") // removed, but chunk stays because of label
|
||||
c2 += IRInstruction(Opcode.JUMP, labelSymbol = "label2")
|
||||
c2 += IRInstruction(Opcode.NOP) // removed
|
||||
val c3 = IRCodeChunk("label2", null)
|
||||
c3 += IRInstruction(Opcode.JUMP, labelSymbol = "label3")
|
||||
@ -67,15 +67,13 @@ class TestIRPeepholeOpt: FunSpec({
|
||||
irProg.chunks().flatMap { it.instructions }.size shouldBe 5
|
||||
val opt = IRPeepholeOptimizer(irProg)
|
||||
opt.optimize(true, ErrorReporterForTests())
|
||||
irProg.chunks().size shouldBe 4
|
||||
irProg.chunks().size shouldBe 3
|
||||
irProg.chunks()[0].label shouldBe "main.start"
|
||||
irProg.chunks()[1].label shouldBe "label"
|
||||
irProg.chunks()[2].label shouldBe "label2"
|
||||
irProg.chunks()[3].label shouldBe "label3"
|
||||
irProg.chunks()[1].label shouldBe "label2"
|
||||
irProg.chunks()[2].label shouldBe "label3"
|
||||
irProg.chunks()[0].isEmpty() shouldBe true
|
||||
irProg.chunks()[1].isEmpty() shouldBe true
|
||||
irProg.chunks()[2].isEmpty() shouldBe false
|
||||
irProg.chunks()[3].isEmpty() shouldBe true
|
||||
irProg.chunks()[1].isEmpty() shouldBe false
|
||||
irProg.chunks()[2].isEmpty() shouldBe true
|
||||
val instr = irProg.chunks().flatMap { it.instructions }
|
||||
instr.size shouldBe 2
|
||||
instr[0].opcode shouldBe Opcode.JUMP
|
||||
|
@ -1,7 +1,7 @@
|
||||
; Routines to load and save "BMX" files (commander X16 bitmap format) Version 1.
|
||||
; Only uncompressed images are supported for now.
|
||||
; BMX Specification: https://cx16forum.com/forum/viewtopic.php?t=6945
|
||||
; TODO: make read_palette() and write_palette() use a palette_buffer_ptr to store palette into system ram instead of directly into vram.
|
||||
; TODO: make read_palette() and write_palette() use an optional palette_buffer_ptr to store palette into system ram instead of directly into vram.
|
||||
|
||||
%import diskio
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user