From f40620aa250e992683b168945351f86eb682fc65 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sat, 6 Nov 2021 23:25:32 +0100 Subject: [PATCH] "not x" as a condition (if, while, until) is optimized into "x==0", this avoids calculating the value --- .../compiler/BeforeAsmGenerationAstChanger.kt | 24 +++++++++ compiler/src/prog8/compiler/Compiler.kt | 3 +- docs/source/todo.rst | 2 +- examples/test.p8 | 51 ++++++++++++------- 4 files changed, 61 insertions(+), 19 deletions(-) diff --git a/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt b/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt index 2009ad3bf..606bf92bc 100644 --- a/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt +++ b/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt @@ -185,7 +185,15 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, private val o return noModifications } + @Suppress("DuplicatedCode") override fun after(ifStatement: IfStatement, parent: Node): Iterable { + val prefixExpr = ifStatement.condition as? PrefixExpression + if(prefixExpr!=null && prefixExpr.operator=="not") { + // if not x -> if x==0 + val booleanExpr = BinaryExpression(prefixExpr.expression, "==", NumericLiteralValue.optimalInteger(0, ifStatement.condition.position), ifStatement.condition.position) + return listOf(IAstModification.ReplaceNode(ifStatement.condition, booleanExpr, ifStatement)) + } + val binExpr = ifStatement.condition as? BinaryExpression if(binExpr==null || binExpr.operator !in comparisonOperators) { // if x -> if x!=0, if x+5 -> if x+5 != 0 @@ -201,7 +209,15 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, private val o return noModifications } + @Suppress("DuplicatedCode") override fun after(untilLoop: UntilLoop, parent: Node): Iterable { + val prefixExpr = untilLoop.condition as? PrefixExpression + if(prefixExpr!=null && prefixExpr.operator=="not") { + // until not x -> until x==0 + val booleanExpr = BinaryExpression(prefixExpr.expression, "==", NumericLiteralValue.optimalInteger(0, untilLoop.condition.position), untilLoop.condition.position) + return listOf(IAstModification.ReplaceNode(untilLoop.condition, booleanExpr, untilLoop)) + } + val binExpr = untilLoop.condition as? BinaryExpression if(binExpr==null || binExpr.operator !in comparisonOperators) { // until x -> until x!=0, until x+5 -> until x+5 != 0 @@ -211,7 +227,15 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, private val o return noModifications } + @Suppress("DuplicatedCode") override fun after(whileLoop: WhileLoop, parent: Node): Iterable { + val prefixExpr = whileLoop.condition as? PrefixExpression + if(prefixExpr!=null && prefixExpr.operator=="not") { + // while not x -> while x==0 + val booleanExpr = BinaryExpression(prefixExpr.expression, "==", NumericLiteralValue.optimalInteger(0, whileLoop.condition.position), whileLoop.condition.position) + return listOf(IAstModification.ReplaceNode(whileLoop.condition, booleanExpr, whileLoop)) + } + val binExpr = whileLoop.condition as? BinaryExpression if(binExpr==null || binExpr.operator !in comparisonOperators) { // while x -> while x!=0, while x+5 -> while x+5 != 0 diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index ce80637fb..453f7bda5 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -324,7 +324,8 @@ private fun writeAssembly(program: Program, program.processAstBeforeAsmGeneration(compilerOptions, errors) errors.report() - // printAst(program) +// println("*********** AST RIGHT BEFORE ASM GENERATION *************") +// printAst(program) compilerOptions.compTarget.machine.initializeZeropage(compilerOptions) val assembly = asmGeneratorFor(compilerOptions.compTarget, diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 626938f06..968ba36fb 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,7 +3,7 @@ TODO For next compiler release (7.2) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- optimize "if not x" / "while not x" to not actually calculate the whole "not x" value first --> transform in to "x==0" in these conditional statements? +... Blocked by Commander-x16 v39 release diff --git a/examples/test.p8 b/examples/test.p8 index 1271eb37e..93e6e7ab6 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,30 +1,47 @@ %import textio -%import floats +; %import floats %zeropage basicsafe main { sub start() { - uword xx= $2000 - ubyte yy=$30 - ubyte zz=9 - sys.memset(xx+200, yy*2, ~yy) + word xx=0 - if yy & %10000 { - yy++ + if not xx { + txt.print("xx is zero\n") } - @($c030) = 10 - @(~xx) *= 2 - txt.print_ub(@($c030)) + while not xx { + xx ++ + } - float f1 = 1111.11 - float f2 = 2222.22 - float[] fa = [2222.22, 3333.33] + do { + xx-- + } until not xx - swap(f1, fa[1]) - floats.print_f(f1) - txt.nl() - floats.print_f(fa[1]) + if not xx { + txt.print("xx is zero\n") + } + +; ubyte yy=$30 +; ubyte zz=9 +; sys.memset(xx+200, yy*2, ~yy) +; +; if yy & %10000 { +; yy++ +; } +; +; @($c030) = 10 +; @(~xx) *= 2 +; txt.print_ub(@($c030)) +; +; float f1 = 1111.11 +; float f2 = 2222.22 +; float[] fa = [2222.22, 3333.33] +; +; swap(f1, fa[1]) +; floats.print_f(f1) +; txt.nl() +; floats.print_f(fa[1]) } }