mirror of
https://github.com/irmen/prog8.git
synced 2024-10-17 10:24:55 +00:00
ir: fix too greedy chunk removal
This commit is contained in:
parent
267b6f49b5
commit
d8e785aed0
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user