From c12bf991b31b98b07f2873774689ee848c0b36fb Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sun, 12 Mar 2023 22:16:20 +0100 Subject: [PATCH] reintegrate into existing IR optimizer --- .../prog8/codegen/intermediate/IRCodeGen.kt | 7 -- .../intermediate/IRPeepholeOptimizer.kt | 36 ++++++++--- .../src/prog8/iroptimizer/IROptimizer.kt | 64 ------------------- 3 files changed, 28 insertions(+), 79 deletions(-) delete mode 100644 codeGenIntermediate/src/prog8/iroptimizer/IROptimizer.kt diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt index e445e39f2..549f4a543 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/IRCodeGen.kt @@ -7,7 +7,6 @@ import prog8.code.SymbolTable import prog8.code.ast.* import prog8.code.core.* import prog8.intermediate.* -import prog8.iroptimizer.IROptimizer import kotlin.io.path.readBytes import kotlin.math.pow @@ -67,12 +66,6 @@ class IRCodeGen( irProg.linkChunks() // re-link } - if(options.optimize) { - // TODO integrate into peephole optimizer above - val opt = IROptimizer(irProg) - opt.optimize() - } - irProg.validate() return irProg } diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/IRPeepholeOptimizer.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/IRPeepholeOptimizer.kt index 3ed86967f..1bb9fa767 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/IRPeepholeOptimizer.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/IRPeepholeOptimizer.kt @@ -119,8 +119,8 @@ internal class IRPeepholeOptimizer(private val irprog: IRProgram) { indexedInstructions.reversed().forEach { (idx, ins) -> if(ins.opcode== Opcode.PUSH) { if(idx < chunk.instructions.size-1) { - val insAfter = chunk.instructions[idx+1] as? IRInstruction - if(insAfter!=null && insAfter.opcode == Opcode.POP) { + val insAfter = chunk.instructions[idx+1] + if(insAfter.opcode == Opcode.POP) { if(ins.reg1==insAfter.reg1) { chunk.instructions.removeAt(idx) chunk.instructions.removeAt(idx) @@ -143,16 +143,16 @@ internal class IRPeepholeOptimizer(private val irprog: IRProgram) { indexedInstructions.reversed().forEach { (idx, ins) -> if(ins.opcode== Opcode.SEC || ins.opcode== Opcode.CLC) { if(idx < chunk.instructions.size-1) { - val insAfter = chunk.instructions[idx+1] as? IRInstruction - if(insAfter?.opcode == ins.opcode) { + val insAfter = chunk.instructions[idx+1] + if(insAfter.opcode == ins.opcode) { chunk.instructions.removeAt(idx) changed = true } - else if(ins.opcode== Opcode.SEC && insAfter?.opcode== Opcode.CLC) { + else if(ins.opcode== Opcode.SEC && insAfter.opcode== Opcode.CLC) { chunk.instructions.removeAt(idx) changed = true } - else if(ins.opcode== Opcode.CLC && insAfter?.opcode== Opcode.SEC) { + else if(ins.opcode== Opcode.CLC && insAfter.opcode== Opcode.SEC) { chunk.instructions.removeAt(idx) changed = true } @@ -174,10 +174,30 @@ internal class IRPeepholeOptimizer(private val irprog: IRProgram) { changed = true } } + // remove useless RETURN if(idx>0 && (ins.opcode == Opcode.RETURN || ins.opcode==Opcode.RETURNREG)) { - val previous = chunk.instructions[idx-1] as? IRInstruction - if(previous?.opcode in OpcodesThatJump) { + val previous = chunk.instructions[idx-1] + if(previous.opcode in OpcodesThatJump) { + chunk.instructions.removeAt(idx) + changed = true + } + } + + // replace subsequent opcodes that jump by just the first + if(idx>0 && (ins.opcode in OpcodesThatJump)) { + val previous = chunk.instructions[idx-1] + if(previous.opcode in OpcodesThatJump) { + chunk.instructions.removeAt(idx) + changed = true + } + } + + // replace call + return --> jump + if(idx>0 && ins.opcode==Opcode.RETURN) { + val previous = chunk.instructions[idx-1] + if(previous.opcode==Opcode.CALL || previous.opcode==Opcode.CALLRVAL) { + chunk.instructions[idx-1] = IRInstruction(Opcode.JUMP, value=previous.value, labelSymbol = previous.labelSymbol, branchTarget = previous.branchTarget) chunk.instructions.removeAt(idx) changed = true } diff --git a/codeGenIntermediate/src/prog8/iroptimizer/IROptimizer.kt b/codeGenIntermediate/src/prog8/iroptimizer/IROptimizer.kt deleted file mode 100644 index 6b2d85a01..000000000 --- a/codeGenIntermediate/src/prog8/iroptimizer/IROptimizer.kt +++ /dev/null @@ -1,64 +0,0 @@ -package prog8.iroptimizer - -import prog8.intermediate.* - -// TODO integrate into peephole optimizer - -internal class IROptimizer(val program: IRProgram) { - fun optimize() { - program.blocks.forEach { block -> - block.children.forEach { elt -> - process(elt) - } - } - } - - private fun process(elt: IIRBlockElement) { - when(elt) { - is IRCodeChunkBase -> { - optimizeInstructions(elt) - // TODO renumber registers that are only used within the code chunk - // val used = elt.usedRegisters() - } - is IRAsmSubroutine -> { - if(elt.asmChunk.isIR) { - optimizeInstructions(elt.asmChunk) - } - // TODO renumber registers that are only used within the code chunk - // val used = elt.usedRegisters() - } - is IRSubroutine -> { - elt.chunks.forEach { process(it) } - } - } - } - - private fun optimizeInstructions(elt: IRCodeChunkBase) { - elt.instructions.withIndex().windowed(2).forEach {(first, second) -> - val i1 = first.value - val i2 = second.value - // replace call + return --> jump - if((i1.opcode==Opcode.CALL || i1.opcode==Opcode.CALLRVAL) && i2.opcode==Opcode.RETURN) { - elt.instructions[first.index] = IRInstruction(Opcode.JUMP, value=i1.value, labelSymbol = i1.labelSymbol, branchTarget = i1.branchTarget) - elt.instructions[second.index] = IRInstruction(Opcode.NOP) - if(second.index==elt.instructions.size-1) { - // it was the last instruction, so the link to the next chunk needs to be cleared - elt.next = null - } - } - - // replace subsequent opcodes that jump by just the first - if(i1.opcode in OpcodesThatJump && i2.opcode in OpcodesThatJump) { - elt.instructions[second.index] = IRInstruction(Opcode.NOP) - } - } - - // remove nops - elt.instructions.withIndex() - .filter { it.value.opcode==Opcode.NOP } - .reversed() - .forEach { - elt.instructions.removeAt(it.index) - } - } -} \ No newline at end of file