From a9b45630d791895a91efd5ae07a71e4f629edd70 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sun, 9 Jan 2022 13:10:01 +0100 Subject: [PATCH] optimized code for variable comparisons to zero --- .../codegen/target/cpu6502/codegen/AsmGen.kt | 66 ++++++++++++++++++- docs/source/todo.rst | 6 +- examples/test.p8 | 59 +++++++++++------ 3 files changed, 109 insertions(+), 22 deletions(-) diff --git a/codeGeneration/src/prog8/codegen/target/cpu6502/codegen/AsmGen.kt b/codeGeneration/src/prog8/codegen/target/cpu6502/codegen/AsmGen.kt index 128694998..a342b1b91 100644 --- a/codeGeneration/src/prog8/codegen/target/cpu6502/codegen/AsmGen.kt +++ b/codeGeneration/src/prog8/codegen/target/cpu6502/codegen/AsmGen.kt @@ -1840,7 +1840,11 @@ $label nop""") operator: String, jumpIfFalseLabel: String ) { - when(val dt = left.inferType(program).getOr(DataType.UNDEFINED)) { + val dt = left.inferType(program).getOr(DataType.UNDEFINED) + if(dt in IntegerDatatypes && left is IdentifierReference) + return testVariableZeroAndJump(left, dt, operator, jumpIfFalseLabel) + + when(dt) { DataType.UBYTE, DataType.UWORD -> { if(operator=="<") { out(" jmp $jumpIfFalseLabel") @@ -1924,6 +1928,66 @@ $label nop""") } } + private fun testVariableZeroAndJump(variable: IdentifierReference, dt: DataType, operator: String, jumpIfFalseLabel: String) { + // optimized code if the expression is just an identifier (variable) + val varname = asmVariableName(variable) + when(dt) { + DataType.UBYTE -> when(operator) { + "==" -> out(" lda $varname | bne $jumpIfFalseLabel") + "!=" -> out(" lda $varname | beq $jumpIfFalseLabel") + ">" -> out(" lda $varname | beq $jumpIfFalseLabel") + "<" -> out(" bra $jumpIfFalseLabel") + ">=" -> {} + "<=" -> out(" lda $varname | bne $jumpIfFalseLabel") + else -> throw AssemblyError("invalid operator") + } + DataType.BYTE -> when(operator) { + "==" -> out(" lda $varname | bne $jumpIfFalseLabel") + "!=" -> out(" lda $varname | beq $jumpIfFalseLabel") + ">" -> out(" lda $varname | beq $jumpIfFalseLabel | bmi $jumpIfFalseLabel") + "<" -> out(" lda $varname | bpl $jumpIfFalseLabel") + ">=" -> out(" lda $varname | bmi $jumpIfFalseLabel") + "<=" -> out(""" + lda $varname + beq + + bpl $jumpIfFalseLabel + + """) + else -> throw AssemblyError("invalid operator") + } + DataType.UWORD -> when(operator) { + "==" -> out(" lda $varname | ora $varname+1 | bne $jumpIfFalseLabel") + "!=" -> out(" lda $varname | ora $varname+1 | beq $jumpIfFalseLabel") + ">" -> out(" lda $varname | ora $varname+1 | beq $jumpIfFalseLabel") + "<" -> out(" bra $jumpIfFalseLabel") + ">=" -> {} + "<=" -> out(" lda $varname | ora $varname+1 | bne $jumpIfFalseLabel") + else -> throw AssemblyError("invalid operator") + } + DataType.WORD -> when (operator) { + "==" -> out(" lda $varname | bne $jumpIfFalseLabel | lda $varname+1 | bne $jumpIfFalseLabel") + "!=" -> out(" lda $varname | ora $varname+1 | beq $jumpIfFalseLabel") + ">" -> out(""" + lda $varname+1 + bmi $jumpIfFalseLabel + bne + + lda $varname + beq $jumpIfFalseLabel + + """) + "<" -> out(" lda $varname+1 | bpl $jumpIfFalseLabel") + ">=" -> out(" lda $varname+1 | bmi $jumpIfFalseLabel") + "<=" -> out(""" + lda $varname+1 + bmi + + bne $jumpIfFalseLabel + lda $varname + bne $jumpIfFalseLabel + + """) + else -> throw AssemblyError("invalid comparison operator $operator") + } + else -> throw AssemblyError("invalid dt") + } + } + private fun testNonzeroComparisonAndJump( left: Expression, operator: String, diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 410912fde..5b9d5a0af 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,11 +3,13 @@ TODO For next compiler release (7.7) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- optimize (u)word comparison against 0 to use MSB only if possible +- perhaps also optimize testNonzeroComparisonAndJump() ? - copying floats around: do it with a subroutine rather than 5 lda/sta pairs . is slower but floats are very slow already anyway and this should take a lot less program size. + -> assignVariableFloat() + assignConstantFloat() +- don't remove dead variable assignment if it contains a function call - optimize codegen of pipe operator to avoid needless assigns to temp var - +- why is this using stack evaluation: bb = ww>0 (if ww>0 is not using stack!) Need help with ^^^^^^^^^^^^^^ diff --git a/examples/test.p8 b/examples/test.p8 index e60c9f116..a29aa0a5b 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -9,28 +9,49 @@ main { word ww = 0 float fl = 0 - if fl< 0 { - txt.print("wrong fl\n") + ubyte @shared ub + + if ww==0 { + ub++ } - fl=-1.111 - if 0>fl or fl==2 { - txt.print("good fl\n") + if ww!=0 { + ub++ + } + if ww>0 { + ub++ + } + if ww<0 { + ub++ + } + if ww<=0 { + ub++ + } + if ww>=0 { + ub++ } - if ww< 0 { - txt.print("wrong ww\n") - } - if bb<0 { - txt.print("wrong bb\n") - } - bb = -1 - ww = -1111 - if 0>ww or ww==2 { - txt.print("good ww\n") - } - if 0>bb or bb==2 { - txt.print("good bb\n") - } +; if fl< 0 { +; txt.print("wrong fl\n") +; } +; fl=-1.111 +; if 0>fl or fl==2 { +; txt.print("good fl\n") +; } +; +; if ww< 0 { +; txt.print("wrong ww\n") +; } +; if bb<0 { +; txt.print("wrong bb\n") +; } +; bb = -1 +; ww = -1111 +; if 0>ww or ww==2 { +; txt.print("good ww\n") +; } +; if 0>bb or bb==2 { +; txt.print("good bb\n") +; } ; float @shared f1 ; ; f1 = 1.234 |> addfloat1 |> addfloat2 |> addfloat3 ; TODO fix that the value is actually returned