mirror of
https://github.com/irmen/prog8.git
synced 2024-11-26 11:49:22 +00:00
ir: join code chunks
This commit is contained in:
parent
43e31765e5
commit
94f0f3e966
@ -5,6 +5,7 @@ import prog8.intermediate.*
|
||||
internal class IRPeepholeOptimizer(private val irprog: IRProgram) {
|
||||
fun optimize() {
|
||||
irprog.blocks.asSequence().flatMap { it.subroutines }.forEach { sub ->
|
||||
joinChunks(sub)
|
||||
sub.chunks.forEach { chunk ->
|
||||
// we don't optimize Inline Asm chunks here.
|
||||
if(chunk is IRCodeChunk) {
|
||||
@ -26,6 +27,40 @@ internal class IRPeepholeOptimizer(private val irprog: IRProgram) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun joinChunks(sub: IRSubroutine) {
|
||||
/*
|
||||
Subroutine contains a list of chunks.
|
||||
Some can be joined into one.
|
||||
TODO: this has to be changed later...
|
||||
*/
|
||||
|
||||
if(sub.chunks.isEmpty())
|
||||
return
|
||||
|
||||
fun mayJoin(previous: IRCodeChunkBase, chunk: IRCodeChunkBase): Boolean {
|
||||
if(previous is IRCodeChunk && chunk is IRCodeChunk) {
|
||||
if(chunk.lines.any{ it is IRCodeInlineBinary})
|
||||
return false
|
||||
return true
|
||||
|
||||
// TODO: only if all instructions are non-branching, allow it to join?
|
||||
// return !chunk.lines.filterIsInstance<IRInstruction>().any {it.opcode in OpcodesThatBranch }
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
val chunks = mutableListOf<IRCodeChunkBase>()
|
||||
chunks += sub.chunks[0]
|
||||
for(ix in 1 until sub.chunks.size) {
|
||||
if(mayJoin(chunks.last(), sub.chunks[ix]))
|
||||
chunks.last().lines += sub.chunks[ix].lines
|
||||
else
|
||||
chunks += sub.chunks[ix]
|
||||
}
|
||||
sub.chunks.clear()
|
||||
sub.chunks += chunks
|
||||
}
|
||||
|
||||
private fun cleanupPushPop(chunk: IRCodeChunk, indexedInstructions: List<IndexedValue<IRInstruction>>): Boolean {
|
||||
// push followed by pop to same target, or different target->replace with load
|
||||
var changed = false
|
||||
|
@ -18,10 +18,11 @@ Future Things and Ideas
|
||||
Compiler:
|
||||
|
||||
- create BSS section in output program and put StStaticVariables in there with bss=true. Don't forget to add init code to zero out everything that was put in bss. If array in bss->only zero ONCE! So requires self-modifying code
|
||||
- vm: Jumps go to a code block rather than a specific address(label) -> also helps future dead code elimination?
|
||||
- vm: the above means that every label introduces a new code block. This eliminates the use of actual labels altogether during execution/translation.
|
||||
- vm: add more optimizations in IRPeepholeOptimizer
|
||||
- vm: how to remove all unused subroutines? (the 6502 assembly codegen relies on 64tass solve this for us)
|
||||
- ir: Jumps go to a code block rather than a specific address(label) -> also helps future dead code elimination?
|
||||
- ir: the above means that every label introduces a new code block. This eliminates the use of actual labels altogether during execution/translation.
|
||||
- ir: joinChunks() in the IR optimizer should be changed accordingly
|
||||
- ir: add more optimizations in IRPeepholeOptimizer
|
||||
- ir: how to remove all unused subroutines? (the 6502 assembly codegen relies on 64tass solve this for us)
|
||||
- see if we can let for loops skip the loop if end<start, like other programming languages. Without adding a lot of code size/duplicating the loop condition.
|
||||
this is documented behavior to now loop around but it's too easy to forget about!
|
||||
Lot of work because of so many special cases in ForLoopsAsmgen.....
|
||||
|
@ -10,6 +10,9 @@ import kotlin.io.path.div
|
||||
class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
|
||||
private val outfile = outfileOverride ?: (irProgram.options.outputDir / ("${irProgram.name}.p8ir"))
|
||||
private val out = outfile.bufferedWriter()
|
||||
private var numChunks = 0
|
||||
private var numLines = 0
|
||||
|
||||
|
||||
fun write(): Path {
|
||||
println("Writing intermediate representation to $outfile")
|
||||
@ -28,6 +31,8 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
|
||||
writeBlocks()
|
||||
out.write("</PROGRAM>\n")
|
||||
out.close()
|
||||
|
||||
println("$numChunks code chunks and $numLines lines.")
|
||||
return outfile
|
||||
}
|
||||
|
||||
@ -43,13 +48,17 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
|
||||
it.parameters.forEach { param -> out.write("${getTypeString(param.dt)} ${param.name}\n") }
|
||||
out.write("</PARAMS>\n")
|
||||
it.chunks.forEach { chunk ->
|
||||
numChunks++
|
||||
if(chunk is IRInlineAsmChunk) {
|
||||
writeInlineAsm(chunk)
|
||||
} else {
|
||||
out.write("<C>\n")
|
||||
if (chunk.lines.isEmpty())
|
||||
throw InternalCompilerException("empty code chunk in ${it.name} ${it.position}")
|
||||
chunk.lines.forEach { line -> out.writeLine(line) }
|
||||
chunk.lines.forEach { line ->
|
||||
numLines++
|
||||
out.writeLine(line)
|
||||
}
|
||||
out.write("</C>\n")
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user