From 32a7cd31da9fd3c34c8873e02a9aa8b34de6248b Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Tue, 15 Sep 2020 00:31:44 +0200 Subject: [PATCH] more optimal codegen for if statements --- .../compiler/target/c64/codegen/AsmGen.kt | 43 ++++++++++++++----- docs/source/todo.rst | 4 +- examples/test.p8 | 32 +++++++------- 3 files changed, 50 insertions(+), 29 deletions(-) diff --git a/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt index f68e560bf..2ad774a2d 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/AsmGen.kt @@ -821,17 +821,38 @@ $save .byte 0 } private fun translate(stmt: IfStatement) { - // TODO don't generate needless jumps/labels when the if or else block is empty - expressionsAsmGen.translateExpression(stmt.condition) - translateTestStack(stmt.condition.inferType(program).typeOrElse(DataType.STRUCT)) - val elseLabel = makeLabel("if_else") - val endLabel = makeLabel("if_end") - out(" beq $elseLabel") - translate(stmt.truepart) - out(" jmp $endLabel") - out(elseLabel) - translate(stmt.elsepart) - out(endLabel) + when { + stmt.elsepart.containsNoCodeNorVars() -> { + // empty else + expressionsAsmGen.translateExpression(stmt.condition) + translateTestStack(stmt.condition.inferType(program).typeOrElse(DataType.STRUCT)) + val endLabel = makeLabel("if_end") + out(" beq $endLabel") + translate(stmt.truepart) + out(endLabel) + } + stmt.truepart.containsNoCodeNorVars() -> { + // empty true part + expressionsAsmGen.translateExpression(stmt.condition) + translateTestStack(stmt.condition.inferType(program).typeOrElse(DataType.STRUCT)) + val endLabel = makeLabel("if_end") + out(" bne $endLabel") + translate(stmt.elsepart) + out(endLabel) + } + else -> { + expressionsAsmGen.translateExpression(stmt.condition) + translateTestStack(stmt.condition.inferType(program).typeOrElse(DataType.STRUCT)) + val elseLabel = makeLabel("if_else") + val endLabel = makeLabel("if_end") + out(" beq $elseLabel") + translate(stmt.truepart) + out(" jmp $endLabel") + out(elseLabel) + translate(stmt.elsepart) + out(endLabel) + } + } } private fun translateTestStack(dataType: DataType) { diff --git a/docs/source/todo.rst b/docs/source/todo.rst index aadfe3a51..87242508c 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -2,15 +2,15 @@ TODO ==== +- get rid of all other TODO's in the code ;-) +- gfx examples are now a few hundred bytes larger than before. Why is that, can it be fixed? - compiler errors and warnings in standard format so the IDE shows them as clickable links; ./test.asm:2578:3: blablabla - further optimize assignment codegeneration - auto select correct library to import based on target, instead of having c64- and cx16- prefix variants -- get rid of all TODO's ;-) - implement @stack for asmsub parameters - make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as '_' - option to load the built-in library files from a directory instead of the embedded ones (for easier library development/debugging) - aliases for imported symbols for example perhaps '%alias print = c64scr.print' ? -- investigate support for 8bitguy's Commander X16 platform https://www.commanderx16.com and https://github.com/commanderx16/x16-docs - see if we can group some errors together for instance the (now single) errors about unidentified symbols diff --git a/examples/test.p8 b/examples/test.p8 index e1757a1bc..72fec038d 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -9,23 +9,23 @@ main { sub start() { - %asm {{ - sei - ldy #0 - sty $1 - lda #0 -- sta $f000,y - iny - bne - -- lda $f000,y - sta $0400,y - iny - bne - - }} + ubyte b + if b > 15 { + b = 99 + } else { + ; nothing + } - repeat 60000 { - ubyte a = sin (3) - a++ + if b > 15 { + ; nothing + } else { + b = 99 + } + + if b > 15 { + ; nothing + } else { + ; nothing } ;asmsub clear_screen (ubyte char @ A, ubyte color @ Y) clobbers(A) { ...}