vm/ir: for loop is now correctly skipped if loopvar>endvar

this is different still in the 6502 codegen, where it wraps around $00!
This commit is contained in:
Irmen de Jong 2022-12-27 18:12:41 +01:00
parent 81bd5c784e
commit 7ee777f405
4 changed files with 29 additions and 21 deletions

View File

@ -542,12 +542,19 @@ class IRCodeGen(
result += expressionEval.translateExpression(iterable.to, endvalueReg, -1)
result += expressionEval.translateExpression(iterable.from, indexReg, -1)
val labelAfterFor = createLabelName()
val greaterOpcode = if(loopvarDt in SignedDatatypes) Opcode.BGTS else Opcode.BGT
addInstr(result, IRInstruction(greaterOpcode, loopvarDtIr, indexReg, endvalueReg, labelSymbol=labelAfterFor), null)
addInstr(result, IRInstruction(Opcode.STOREM, loopvarDtIr, reg1=indexReg, labelSymbol=loopvarSymbol), null)
result += labelFirstChunk(translateNode(forLoop.statements), loopLabel)
result += addConstMem(loopvarDtIr, null, loopvarSymbol, step)
addInstr(result, IRInstruction(Opcode.LOADM, loopvarDtIr, reg1 = indexReg, labelSymbol = loopvarSymbol), null)
val branchOpcode = if(loopvarDt in SignedDatatypes) Opcode.BLES else Opcode.BLE
addInstr(result, IRInstruction(branchOpcode, loopvarDtIr, reg1=indexReg, reg2=endvalueReg, labelSymbol=loopLabel), null)
result += IRCodeChunk(labelAfterFor, null)
return result
}

View File

@ -1 +1 @@
8.8.1
8.9-dev

View File

@ -3,6 +3,7 @@ TODO
For next release
^^^^^^^^^^^^^^^^
- remove redundant branch opcodes in IR: BLT(S), BLE(S). Replace by swapped BGT(S), BGE(S).
- make sure bool value is always 0 or 1 (all casts should convert), then:
- rewrite bool=bool^1 into bool=not bool
- should solve: bool bb = not bb -> larger code than bool bb ^= 1
@ -33,10 +34,10 @@ Compiler:
- ir peephole opt: reuse registers in chunks (but keep result registers in mind that pass values out!)
- ir: add more optimizations in IRPeepholeOptimizer
- vm: somehow be able to load a label address as value? (VmProgramLoader)
- 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.....
How is it for the vm target? -> just 2 special cases in CodeGen.
- 6502 codegen: see if we can let for loops skip the loop if startvar>endvar, without adding a lot of code size/duplicating the loop condition.
It is documented behavior to now loop 'around' $00 but it's too easy to forget about!
Lot of work because of so many special cases in ForLoopsAsmgen..... (vm codegen already behaves like this)
- ir: can we determine for the loop variable in forloops if it could be kept in a (virtual) register instead of a real variable? Need to be able to check if the variable is used by another statement beside just the for loop.
- createAssemblyAndAssemble(): make it possible to actually get rid of the VarDecl nodes by fixing the rest of the code mentioned there.
but probably better to rewrite the 6502 codegen on top of the new Ast.
- generate WASM to eventually run prog8 on a browser canvas?

View File

@ -76,20 +76,20 @@ bz reg1, address - branch to location if reg1 is zero
bnz reg1, address - branch to location if reg1 is not zero
beq reg1, reg2, address - jump to location in program given by location, if reg1 == reg2
bne reg1, reg2, address - jump to location in program given by location, if reg1 != reg2
blt reg1, reg2, address - jump to location in program given by location, if reg1 < reg2 (unsigned)
blts reg1, reg2, address - jump to location in program given by location, if reg1 < reg2 (signed)
ble reg1, reg2, address - jump to location in program given by location, if reg1 <= reg2 (unsigned)
bles reg1, reg2, address - jump to location in program given by location, if reg1 <= reg2 (signed)
blt reg1, reg2, address - jump to location in program given by location, if reg1 < reg2 (unsigned) TODO REMOVE
blts reg1, reg2, address - jump to location in program given by location, if reg1 < reg2 (signed) TODO REMOVE
ble reg1, reg2, address - jump to location in program given by location, if reg1 <= reg2 (unsigned) TODO REMOVE
bles reg1, reg2, address - jump to location in program given by location, if reg1 <= reg2 (signed) TODO REMOVE
bgt reg1, reg2, address - jump to location in program given by location, if reg1 > reg2 (unsigned)
bgts reg1, reg2, address - jump to location in program given by location, if reg1 > reg2 (signed)
bge reg1, reg2, address - jump to location in program given by location, if reg1 >= reg2 (unsigned)
bges reg1, reg2, address - jump to location in program given by location, if reg1 >= reg2 (signed)
seq reg1, reg2 - set reg=1 if reg1 == reg2, otherwise set reg1=0
sne reg1, reg2 - set reg=1 if reg1 != reg2, otherwise set reg1=0
slt reg1, reg2 - set reg=1 if reg1 < reg2 (unsigned), otherwise set reg1=0
slts reg1, reg2 - set reg=1 if reg1 < reg2 (signed), otherwise set reg1=0
sle reg1, reg2 - set reg=1 if reg1 <= reg2 (unsigned), otherwise set reg1=0
sles reg1, reg2 - set reg=1 if reg1 <= reg2 (signed), otherwise set reg1=0
slt reg1, reg2 - set reg=1 if reg1 < reg2 (unsigned), otherwise set reg1=0 TODO REMOVE
slts reg1, reg2 - set reg=1 if reg1 < reg2 (signed), otherwise set reg1=0 TODO REMOVE
sle reg1, reg2 - set reg=1 if reg1 <= reg2 (unsigned), otherwise set reg1=0 TODO REMOVE
sles reg1, reg2 - set reg=1 if reg1 <= reg2 (signed), otherwise set reg1=0 TODO REMOVE
sgt reg1, reg2 - set reg=1 if reg1 > reg2 (unsigned), otherwise set reg1=0
sgts reg1, reg2 - set reg=1 if reg1 > reg2 (signed), otherwise set reg1=0
sge reg1, reg2 - set reg=1 if reg1 >= reg2 (unsigned), otherwise set reg1=0
@ -244,22 +244,22 @@ enum class Opcode {
BNZ,
BEQ,
BNE,
BLT,
BLTS,
BLT, // TODO REMOVE
BLTS, // TODO REMOVE
BGT,
BGTS,
BLE,
BLES,
BLE, // TODO REMOVE
BLES, // TODO REMOVE
BGE,
BGES,
SEQ,
SNE,
SLT,
SLTS,
SLT, // TODO REMOVE ?
SLTS, // TODO REMOVE ?
SGT,
SGTS,
SLE,
SLES,
SLE, // TODO REMOVE ?
SLES, // TODO REMOVE ?
SGE,
SGES,