diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/IRPeepholeOptimizer.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/IRPeepholeOptimizer.kt index 3bd1ecae6..4c4a70d31 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/IRPeepholeOptimizer.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/IRPeepholeOptimizer.kt @@ -55,6 +55,8 @@ class IRPeepholeOptimizer(private val irprog: IRProgram) { || cleanupPushPop(chunk1, indexedInstructions) || simplifyConstantReturns(chunk1, indexedInstructions) || removeNeedlessLoads(chunk1, indexedInstructions) + || useArrayIndexingInsteadOfAdds(chunk1, indexedInstructions) + || removeNops(chunk1, indexedInstructions) // last time, in case one of the optimizers replaced something with a nop } while (changed) } } @@ -553,4 +555,40 @@ jump p8_label_gen_2 } return changed } + + private fun useArrayIndexingInsteadOfAdds(chunk: IRCodeChunk, indexedInstructions: List>): Boolean { + var changed = false + indexedInstructions.reversed().forEach { (idx, ins) -> + if (ins.opcode == Opcode.ADD && ins.immediate!=null && idx>0) { + val load = indexedInstructions[idx-1].value + if((load.opcode==Opcode.LOAD) && load.labelSymbol!=null) { + val lastInstruction = indexedInstructions[idx+1].value + if(lastInstruction.opcode==Opcode.LOADI) { + val targetRegister = lastInstruction.reg1!! + if(ins.reg1==lastInstruction.reg2!! && load.reg1==lastInstruction.reg2!!) { + val loadm = IRInstruction(Opcode.LOADM, lastInstruction.type, reg1=targetRegister, labelSymbol = load.labelSymbol, symbolOffset = ins.immediate) + chunk.instructions[idx-1] = loadm + chunk.instructions.removeAt(idx+1) + chunk.instructions.removeAt(idx) + changed = true + } + } else if(lastInstruction.opcode==Opcode.STOREI) { + val targetRegister = lastInstruction.reg1!! + if(ins.reg1==lastInstruction.reg2!! && load.reg1==lastInstruction.reg2!!) { + val valueLoad = indexedInstructions[idx-2].value + if(valueLoad.opcode==Opcode.LOAD && valueLoad.reg1==targetRegister) { + val storem = IRInstruction(Opcode.STOREM, lastInstruction.type, reg1=valueLoad.reg1, labelSymbol = load.labelSymbol, symbolOffset = ins.immediate) + chunk.instructions[idx-1] = storem + chunk.instructions.removeAt(idx+1) + chunk.instructions.removeAt(idx) + changed = true + } + } + } + } + } + } + + return changed + } } \ No newline at end of file diff --git a/docs/source/_static/symboldumps/skeletons-c128.txt b/docs/source/_static/symboldumps/skeletons-c128.txt index ac37b0564..34ebce024 100644 --- a/docs/source/_static/symboldumps/skeletons-c128.txt +++ b/docs/source/_static/symboldumps/skeletons-c128.txt @@ -1,6 +1,5 @@ Prog8 compiler v12.0.1 by Irmen de Jong (irmen@razorvine.net) -Prerelease version from git commit cfa4355a in branch master This software is licensed under the GNU GPL 3.0, see https://www.gnu.org/licenses/gpl.html Compiling program import-all-c128.p8 diff --git a/docs/source/_static/symboldumps/skeletons-c64.txt b/docs/source/_static/symboldumps/skeletons-c64.txt index 513816679..8ddb12693 100644 --- a/docs/source/_static/symboldumps/skeletons-c64.txt +++ b/docs/source/_static/symboldumps/skeletons-c64.txt @@ -1,6 +1,5 @@ Prog8 compiler v12.0.1 by Irmen de Jong (irmen@razorvine.net) -Prerelease version from git commit cfa4355a in branch master This software is licensed under the GNU GPL 3.0, see https://www.gnu.org/licenses/gpl.html Compiling program import-all-c64.p8 diff --git a/docs/source/_static/symboldumps/skeletons-cx16.txt b/docs/source/_static/symboldumps/skeletons-cx16.txt index a6894afa8..1cabf847a 100644 --- a/docs/source/_static/symboldumps/skeletons-cx16.txt +++ b/docs/source/_static/symboldumps/skeletons-cx16.txt @@ -1,6 +1,5 @@ Prog8 compiler v12.0.1 by Irmen de Jong (irmen@razorvine.net) -Prerelease version from git commit cfa4355a in branch master This software is licensed under the GNU GPL 3.0, see https://www.gnu.org/licenses/gpl.html Compiling program import-all-cx16.p8 diff --git a/docs/source/_static/symboldumps/skeletons-pet32.txt b/docs/source/_static/symboldumps/skeletons-pet32.txt index 48fb8ad94..e14c3b45b 100644 --- a/docs/source/_static/symboldumps/skeletons-pet32.txt +++ b/docs/source/_static/symboldumps/skeletons-pet32.txt @@ -1,6 +1,5 @@ Prog8 compiler v12.0.1 by Irmen de Jong (irmen@razorvine.net) -Prerelease version from git commit cfa4355a in branch master This software is licensed under the GNU GPL 3.0, see https://www.gnu.org/licenses/gpl.html Compiling program import-all-pet32.p8 diff --git a/docs/source/_static/symboldumps/skeletons-virtual.txt b/docs/source/_static/symboldumps/skeletons-virtual.txt index 5afd9fbd8..32b540fbe 100644 --- a/docs/source/_static/symboldumps/skeletons-virtual.txt +++ b/docs/source/_static/symboldumps/skeletons-virtual.txt @@ -1,6 +1,5 @@ Prog8 compiler v12.0.1 by Irmen de Jong (irmen@razorvine.net) -Prerelease version from git commit cfa4355a in branch master This software is licensed under the GNU GPL 3.0, see https://www.gnu.org/licenses/gpl.html Compiling program import-all-virtual.p8 diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 40e94bcf2..6cac21a8a 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -61,9 +61,8 @@ Future Things and Ideas IR/VM ----- -- optimize away the use of ADD to offset from a label. It's possible to do that with a label-offset in the instruction itself: loadm.b r7,main.start.array2+255 (it works for 255 but after that it starts using ADD!) -- get rid of LOADX/STOREX/STOREZX, LOADINDEXED/STOREINDEXED just use add + loadi / storei? - extend the index range from 0-255 to 0-32767 in the LOADX, STOREX, STOREZX, LOADINDEXED, STOREINDEXED etc instructions (not compatible with 8 bit 6502, but the 68000 can use that) +- get rid of LOADX/STOREX/STOREZX, LOADINDEXED/STOREINDEXED just use add + loadi / storei? - if float<0 / if word<0 uses sgn or load, but still use a bgt etc instruction after that with a #0 operand even though the sgn and load instructions sets the status bits already, so just use bstneg etc - add and sub instructions should modify the status flags so an explicit compare to zero can be avoided for example: if cx16.r0sL + cx16.r1sL <= 0 now compiles into: addr.b r10,r11 / bgts.b r10,#0,label - getting it in shape for code generation: the IR file should be able to encode every detail about a prog8 program (the VM doesn't have to actually be able to run all of it though!) diff --git a/examples/test.p8 b/examples/test.p8 index df0b1269f..0f2ede821 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -26,8 +26,6 @@ main { %ir {{ loadm.b r1007,main.start.array2+255 storem.b r1007,$ff02 -loadm.b r1007,main.start.array2+256 -storem.b r1007,$ff04 load.w r1009,main.start.array2 add.w r1009,#$0100 loadi.b r1008,r1009 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 8bdaf60c7..f8e1ee312 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2e1113280..bad7c2462 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.0-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/intermediate/src/prog8/intermediate/IRProgram.kt b/intermediate/src/prog8/intermediate/IRProgram.kt index 029b78bce..9018d7609 100644 --- a/intermediate/src/prog8/intermediate/IRProgram.kt +++ b/intermediate/src/prog8/intermediate/IRProgram.kt @@ -306,7 +306,7 @@ class IRProgram(val name: String, fun convert(asmChunk: IRInlineAsmChunk): IRCodeChunks { val chunks = mutableListOf() var chunk = IRCodeChunk(asmChunk.label, null) - asmChunk.assembly.lineSequence().forEach { + asmChunk.assembly.lineSequence().filter{it.isNotBlank()}.forEach { val parsed = parseIRCodeLine(it.trim()) parsed.fold( ifLeft = { instruction -> chunk += instruction },