From 9ca1c66f2b4d62012e34db89b4d8dd4a8ae98dcb Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Thu, 4 Jun 2020 01:43:37 +0200 Subject: [PATCH] added some optimizations for >= 0 and <0 comparisons for integers --- .../prog8/optimizer/ExpressionSimplifier.kt | 63 +++++++++++++- examples/test.p8 | 83 ++++++++++++++++++- 2 files changed, 141 insertions(+), 5 deletions(-) diff --git a/compiler/src/prog8/optimizer/ExpressionSimplifier.kt b/compiler/src/prog8/optimizer/ExpressionSimplifier.kt index 26739401a..6bef6f174 100644 --- a/compiler/src/prog8/optimizer/ExpressionSimplifier.kt +++ b/compiler/src/prog8/optimizer/ExpressionSimplifier.kt @@ -19,9 +19,6 @@ import kotlin.math.pow x + x + x -> ???? x*3 ??? words/bytes? x - x -> 0 - x < 0 (for word, byte as well?): just test the most significant bit for 1 - x >= 0 (for word, byte as well?): just test the most significant bit for 0 - (assignment) x += y + 1 -> x += y , x++ (add another x++ for +2) (assignment) x += y - 1 -> x += y , x-- (assignment) x -= y + 1 -> x -= y , x-- @@ -187,7 +184,65 @@ internal class ExpressionSimplifier(private val program: Program) : AstWalker() } } - // simplify when a term is constant and directly determines the outcome + if(expr.operator == ">=" && rightVal?.number == 0) { + if (leftDt == DataType.UBYTE || leftDt == DataType.UWORD) { + // unsigned >= 0 --> true + return listOf(IAstModification.ReplaceNode(expr, NumericLiteralValue.fromBoolean(true, expr.position), parent)) + } + when(leftDt) { + DataType.BYTE -> { + // signed >=0 --> signed ^ $80 + return listOf(IAstModification.ReplaceNode( + expr, + BinaryExpression(expr.left, "^", NumericLiteralValue.optimalInteger(0x80, expr.position), expr.position), + parent + )) + } + DataType.WORD -> { + // signedw >=0 --> msb(signedw) ^ $80 + return listOf(IAstModification.ReplaceNode( + expr, + BinaryExpression(FunctionCall(IdentifierReference(listOf("msb"), expr.position), + mutableListOf(expr.left), + expr.position + ), "^", NumericLiteralValue.optimalInteger(0x80, expr.position), expr.position), + parent + )) + } + else -> {} + } + } + + if(expr.operator == "<" && rightVal?.number == 0) { + if (leftDt == DataType.UBYTE || leftDt == DataType.UWORD) { + // unsigned < 0 --> false + return listOf(IAstModification.ReplaceNode(expr, NumericLiteralValue.fromBoolean(false, expr.position), parent)) + } + when(leftDt) { + DataType.BYTE -> { + // signed < 0 --> signed & $80 + return listOf(IAstModification.ReplaceNode( + expr, + BinaryExpression(expr.left, "&", NumericLiteralValue.optimalInteger(0x80, expr.position), expr.position), + parent + )) + } + DataType.WORD -> { + // signedw < 0 --> msb(signedw) & $80 + return listOf(IAstModification.ReplaceNode( + expr, + BinaryExpression(FunctionCall(IdentifierReference(listOf("msb"), expr.position), + mutableListOf(expr.left), + expr.position + ), "&", NumericLiteralValue.optimalInteger(0x80, expr.position), expr.position), + parent + )) + } + else -> {} + } + } + + // simplify when a term is constant and directly determines the outcome val constTrue = NumericLiteralValue.fromBoolean(true, expr.position) val constFalse = NumericLiteralValue.fromBoolean(false, expr.position) val newExpr: Expression? = when (expr.operator) { diff --git a/examples/test.p8 b/examples/test.p8 index 4bdde9e0c..e7e087b78 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -6,7 +6,88 @@ main { sub start() { - ;... + + ubyte ubb + byte bb + uword uww + word ww + + bb = -1 + ww = -1 + + if bb<0 + c64scr.print("1 ok\n") + else + c64scr.print("1 fail\n") + + if ww<0 + c64scr.print("2 ok\n") + else + c64scr.print("2 fail\n") + + bb = 0 + ww = 0 + + if bb>=0 + c64scr.print("4 ok\n") + else + c64scr.print("4 fail\n") + + if ww>=0 + c64scr.print("5 ok\n") + else + c64scr.print("5 fail\n") + + bb = 0 + ww = 0 + + if bb>=0 + c64scr.print("7 ok\n") + else + c64scr.print("7 fail\n") + + if ww>=0 + c64scr.print("8 ok\n") + else + c64scr.print("8 fail\n") + + ubb = 0 + uww = 0 + if ubb>=0 + c64scr.print("10 ok\n") + else + c64scr.print("10 fail\n") + if uww>=0 + c64scr.print("11 ok\n") + else + c64scr.print("11 fail\n") + if ubb<0 + c64scr.print("12 fail\n") + else + c64scr.print("12 ok\n") + if uww<0 + c64scr.print("13 fail\n") + else + c64scr.print("13 ok\n") + ubb = $ff + uww = $ffff + if ubb>=0 + c64scr.print("14 ok\n") + else + c64scr.print("14 fail\n") + if uww>=0 + c64scr.print("15 ok\n") + else + c64scr.print("15 fail\n") + if ubb<0 + c64scr.print("16 fail\n") + else + c64scr.print("16 ok\n") + if uww<0 + c64scr.print("17 fail\n") + else + c64scr.print("17 ok\n") + } }