From d78bfcc35c05bb027d510197fc44938e791fe51b Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Tue, 5 Apr 2022 00:19:37 +0200 Subject: [PATCH] vm: more optimal code when array index is constant value --- .../prog8/codegen/virtual/ExpressionGen.kt | 21 ++++++++++++------- examples/test.p8 | 8 ++----- virtualmachine/src/prog8/vm/VirtualMachine.kt | 12 +++++------ 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt b/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt index 7066d5b44..4777e8ae8 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt @@ -138,15 +138,20 @@ internal class ExpressionGen(private val codeGen: CodeGen) { val vmDt = codeGen.vmType(arrayIx.type) val code = VmCodeChunk() val idxReg = codeGen.vmRegisters.nextFree() - // TODO: optimized code when the index is a constant value - code += translateExpression(arrayIx.index, idxReg) - if(eltSize>1) { - val factorReg = codeGen.vmRegisters.nextFree() - code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=factorReg, value=eltSize) - code += VmCodeInstruction(Opcode.MUL, VmDataType.BYTE, reg1=idxReg, reg2=idxReg, reg3=factorReg) - } val arrayLocation = codeGen.allocations.get(arrayIx.variable.targetName) - code += VmCodeInstruction(Opcode.LOADX, vmDt, reg1=resultRegister, reg2=idxReg, value = arrayLocation) + if(arrayIx.index is PtNumber) { + // optimized code when index is known - just calculate the memory address here + val memOffset = (arrayIx.index as PtNumber).number.toInt() * eltSize + code += VmCodeInstruction(Opcode.LOADM, vmDt, reg1=resultRegister, value=arrayLocation+memOffset) + } else { + code += translateExpression(arrayIx.index, idxReg) + if(eltSize>1) { + val factorReg = codeGen.vmRegisters.nextFree() + code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=factorReg, value=eltSize) + code += VmCodeInstruction(Opcode.MUL, VmDataType.BYTE, reg1=idxReg, reg2=idxReg, reg3=factorReg) + } + code += VmCodeInstruction(Opcode.LOADX, vmDt, reg1=resultRegister, reg2=idxReg, value = arrayLocation) + } return code } diff --git a/examples/test.p8 b/examples/test.p8 index 5ddbf8757..a94cc6395 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -7,13 +7,9 @@ main { sub start() { - ubyte counter + uword[] array = [1111,2222,3333,4444,5555] - repeat 256 { - txt.print_ub(counter) - txt.spc() - counter ++ - } + txt.print_uw(array[3]) txt.nl() ; a "pixelshader": diff --git a/virtualmachine/src/prog8/vm/VirtualMachine.kt b/virtualmachine/src/prog8/vm/VirtualMachine.kt index 8bd3548c0..fffd82141 100644 --- a/virtualmachine/src/prog8/vm/VirtualMachine.kt +++ b/virtualmachine/src/prog8/vm/VirtualMachine.kt @@ -588,7 +588,7 @@ class VirtualMachine(val memory: Memory, program: List) { if(right==0.toUByte()) 0xffu else left % right } - else -> TODO("operator byte $operator") + else -> throw IllegalArgumentException("operator byte $operator") } registers.setUB(reg1, result.toUByte()) } @@ -608,7 +608,7 @@ class VirtualMachine(val memory: Memory, program: List) { if(right==0.toUShort()) 0xffffu else left % right } - else -> TODO("operator word $operator") + else -> throw IllegalArgumentException("operator word $operator") } registers.setUW(reg1, result.toUShort()) } @@ -624,7 +624,7 @@ class VirtualMachine(val memory: Memory, program: List) { private fun InsEXT(i: Instruction) { when(i.type!!){ VmDataType.BYTE -> registers.setUW(i.reg1!!, registers.getUB(i.reg1).toUShort()) - VmDataType.WORD -> TODO("ext.w requires 32 bits registers") + VmDataType.WORD -> TODO("ext.w not yet supported, requires 32 bits registers") } pc++ } @@ -632,7 +632,7 @@ class VirtualMachine(val memory: Memory, program: List) { private fun InsEXTS(i: Instruction) { when(i.type!!){ VmDataType.BYTE -> registers.setSW(i.reg1!!, registers.getSB(i.reg1).toShort()) - VmDataType.WORD -> TODO("ext.w requires 32 bits registers") + VmDataType.WORD -> TODO("exts.w not yet supported, requires 32 bits registers") } pc++ } @@ -716,7 +716,7 @@ class VirtualMachine(val memory: Memory, program: List) { val newValue = value.toUByte()*256u + (value.toInt() ushr 8).toUInt() registers.setUW(i.reg1, newValue.toUShort()) } - VmDataType.WORD -> TODO("swap.w requires 32-bits registers") + VmDataType.WORD -> TODO("swap.w not yet supported, requires 32-bits registers") } pc++ } @@ -728,7 +728,7 @@ class VirtualMachine(val memory: Memory, program: List) { val lsb = registers.getUB(i.reg3!!) registers.setUW(i.reg1!!, ((msb.toInt() shl 8) or lsb.toInt()).toUShort()) } - VmDataType.WORD -> TODO("swap.w requires 32-bits registers") + VmDataType.WORD -> TODO("concat.w not yet supported, requires 32-bits registers") } pc++ }