ir: fix too greedy chunk removal

This commit is contained in:
Irmen de Jong 2022-11-12 19:56:54 +01:00
parent 267b6f49b5
commit d8e785aed0
2 changed files with 27 additions and 6 deletions

View File

@ -7,7 +7,15 @@ import prog8.intermediate.*
internal class IRUnusedCodeRemover(private val irprog: IRProgram, private val errors: IErrorReporter) { internal class IRUnusedCodeRemover(private val irprog: IRProgram, private val errors: IErrorReporter) {
fun optimize(): Int { fun optimize(): Int {
var numRemoved = removeSimpleUnlinked() + removeUnreachable() val allLabeledChunks = mutableMapOf<String, IRCodeChunkBase>()
irprog.blocks.asSequence().flatMap { it.subroutines }.forEach { sub ->
sub.chunks.forEach { chunk ->
chunk.label?.let { allLabeledChunks[it] = chunk }
}
}
var numRemoved = removeSimpleUnlinked(allLabeledChunks) + removeUnreachable(allLabeledChunks)
// remove empty subs // remove empty subs
irprog.blocks.forEach { block -> irprog.blocks.forEach { block ->
@ -32,14 +40,19 @@ internal class IRUnusedCodeRemover(private val irprog: IRProgram, private val er
return numRemoved return numRemoved
} }
private fun removeUnreachable(): Int { private fun removeUnreachable(allLabeledChunks: MutableMap<String, IRCodeChunkBase>): Int {
val reachable = mutableSetOf(irprog.blocks.single { it.name=="main" }.subroutines.single { it.name=="main.start" }.chunks.first()) val reachable = mutableSetOf(irprog.blocks.single { it.name=="main" }.subroutines.single { it.name=="main.start" }.chunks.first())
fun grow() { fun grow() {
val new = mutableSetOf<IRCodeChunkBase>() val new = mutableSetOf<IRCodeChunkBase>()
reachable.forEach { reachable.forEach {
it.next?.let { next -> new += next } it.next?.let { next -> new += next }
it.instructions.forEach { instr -> instr.branchTarget?.let { target -> new += target} } it.instructions.forEach { instr ->
if (instr.branchTarget == null)
instr.labelSymbol?.let { label -> allLabeledChunks[label]?.let { chunk -> new += chunk } }
else
new += instr.branchTarget!!
}
} }
reachable += new reachable += new
} }
@ -55,13 +68,19 @@ internal class IRUnusedCodeRemover(private val irprog: IRProgram, private val er
return removeUnlinkedChunks(reachable) return removeUnlinkedChunks(reachable)
} }
private fun removeSimpleUnlinked(): Int { private fun removeSimpleUnlinked(allLabeledChunks: Map<String, IRCodeChunkBase>): Int {
val linkedChunks = mutableSetOf<IRCodeChunkBase>() val linkedChunks = mutableSetOf<IRCodeChunkBase>()
irprog.blocks.asSequence().flatMap { it.subroutines }.forEach { sub -> irprog.blocks.asSequence().flatMap { it.subroutines }.forEach { sub ->
sub.chunks.forEach { chunk -> sub.chunks.forEach { chunk ->
chunk.next?.let { next -> linkedChunks += next } chunk.next?.let { next -> linkedChunks += next }
chunk.instructions.forEach { it.branchTarget?.let { target -> linkedChunks += target } } chunk.instructions.forEach {
if(it.branchTarget==null) {
it.labelSymbol?.let { label -> allLabeledChunks[label]?.let { cc -> linkedChunks += cc } }
} else {
linkedChunks += it.branchTarget!!
}
}
if (chunk.label == "main.start") if (chunk.label == "main.start")
linkedChunks += chunk linkedChunks += chunk
} }

View File

@ -109,8 +109,10 @@ class IRProgram(val name: String,
chunk.next = next chunk.next = next
else if(next is IRInlineAsmChunk) else if(next is IRInlineAsmChunk)
chunk.next = next chunk.next = next
else if(next is IRInlineBinaryChunk)
chunk.next =next
else else
throw AssemblyError("code chunk flows into following non-executable chunk") throw AssemblyError("code chunk followed by invalid chunk type $next")
} }
} }