diff --git a/codeOptimizers/src/prog8/optimizer/ExpressionSimplifier.kt b/codeOptimizers/src/prog8/optimizer/ExpressionSimplifier.kt index fe4efc190..bb1c01eba 100644 --- a/codeOptimizers/src/prog8/optimizer/ExpressionSimplifier.kt +++ b/codeOptimizers/src/prog8/optimizer/ExpressionSimplifier.kt @@ -378,30 +378,44 @@ class ExpressionSimplifier(private val program: Program, private val errors: IEr if (rightVal!=null && (expr.operator == "==" || expr.operator == "!=")) { val bitwise = expr.left as? BinaryExpression - if(bitwise!=null && bitwise.operator=="&" && bitwise.inferType(program).isWords) { - val andNum = (bitwise.right as? NumericLiteral)?.number?.toInt() - if (andNum!=null) { - if ((andNum and 0x00ff) == 0) { - // (WORD & $xx00)==y -> (msb(WORD) & $xx)==y - val msb = FunctionCallExpression(IdentifierReference(listOf("msb"), bitwise.left.position), mutableListOf(bitwise.left), bitwise.left.position) - val bytevalue = NumericLiteral(BaseDataType.UBYTE, (andNum shr 8).toDouble(), bitwise.right.position) - val rightvalByte = NumericLiteral(BaseDataType.UBYTE, (rightVal.number.toInt() shr 8).toDouble(), rightVal.position) - return listOf( - IAstModification.ReplaceNode(bitwise.left, msb, bitwise), - IAstModification.ReplaceNode(bitwise.right, bytevalue, bitwise), - IAstModification.ReplaceNode(expr.right, rightvalByte, expr) - ) + if (bitwise!=null && bitwise.operator=="&") { + + if(rightVal.number in powersOfTwoFloat && bitwise.right.constValue(program) == rightVal) { + if(expr.operator=="==") { + // x & const == const -> x & const != 0 (if const has only a single bit set!) + val notZero = BinaryExpression(bitwise, "!=", NumericLiteral(rightDt.base, 0.0, rightVal.position), expr.position) + return listOf(IAstModification.ReplaceNode(expr, notZero, parent)) + } else { + // x & const != const -> x & const == 0 (if const has only a single bit set!) + val equalsZero = BinaryExpression(bitwise, "==", NumericLiteral(rightDt.base, 0.0, rightVal.position), expr.position) + return listOf(IAstModification.ReplaceNode(expr, equalsZero, parent)) } - else if((andNum and 0xff00) == 0) { - // (WORD & $00xx)==y -> (lsb(WORD) & $xx)==y - val lsb = FunctionCallExpression(IdentifierReference(listOf("lsb"), bitwise.left.position), mutableListOf(bitwise.left), bitwise.left.position) - val bytevalue = NumericLiteral(BaseDataType.UBYTE, andNum.toDouble(), bitwise.right.position) - val rightvalByte = NumericLiteral(BaseDataType.UBYTE, (rightVal.number.toInt() and 255).toDouble(), rightVal.position) - return listOf( - IAstModification.ReplaceNode(bitwise.left, lsb, bitwise), - IAstModification.ReplaceNode(bitwise.right, bytevalue, bitwise), - IAstModification.ReplaceNode(expr.right, rightvalByte, expr) - ) + } + + if (bitwise.inferType(program).isWords) { + val andNum = (bitwise.right as? NumericLiteral)?.number?.toInt() + if (andNum!=null) { + if ((andNum and 0x00ff) == 0) { + // (WORD & $xx00)==y -> (msb(WORD) & $xx)==y + val msb = FunctionCallExpression(IdentifierReference(listOf("msb"), bitwise.left.position), mutableListOf(bitwise.left), bitwise.left.position) + val bytevalue = NumericLiteral(BaseDataType.UBYTE, (andNum shr 8).toDouble(), bitwise.right.position) + val rightvalByte = NumericLiteral(BaseDataType.UBYTE, (rightVal.number.toInt() shr 8).toDouble(), rightVal.position) + return listOf( + IAstModification.ReplaceNode(bitwise.left, msb, bitwise), + IAstModification.ReplaceNode(bitwise.right, bytevalue, bitwise), + IAstModification.ReplaceNode(expr.right, rightvalByte, expr) + ) + } else if((andNum and 0xff00) == 0) { + // (WORD & $00xx)==y -> (lsb(WORD) & $xx)==y + val lsb = FunctionCallExpression(IdentifierReference(listOf("lsb"), bitwise.left.position), mutableListOf(bitwise.left), bitwise.left.position) + val bytevalue = NumericLiteral(BaseDataType.UBYTE, andNum.toDouble(), bitwise.right.position) + val rightvalByte = NumericLiteral(BaseDataType.UBYTE, (rightVal.number.toInt() and 255).toDouble(), rightVal.position) + return listOf( + IAstModification.ReplaceNode(bitwise.left, lsb, bitwise), + IAstModification.ReplaceNode(bitwise.right, bytevalue, bitwise), + IAstModification.ReplaceNode(expr.right, rightvalByte, expr) + ) + } } } } diff --git a/docs/source/todo.rst b/docs/source/todo.rst index bfc8fa256..29eb70191 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -4,13 +4,11 @@ TODO Halloween is stuck on a black screen -Optimize bitwise operations on word values where only the msb or lsb is touched: (already done for simple expressions!) +Optimize 6502 bitwise operations on word values where only the msb or lsb is touched: (already done for simple augmented expressions!) cx16.r0 = (cx16.r0 & $a000) | $0055 cx16.r0 = (cx16.r0 | $a000) ^ $0055 cx16.r0 = (cx16.r0 ^ $a000) & $0055 -Optimize (x & y) == y expressions especially in loop conditions - update zsmkit to newest version that includes the on_deck routines when stabilized diff --git a/examples/test.p8 b/examples/test.p8 index 858091579..dec36ba29 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,68 +1,69 @@ +%import textio %zeropage basicsafe %option no_sysinit main { sub start() { - while cx16.r0L & 1 == 0 { + cx16.r0L = %11111110 + while cx16.r0L &32 == 32 { + cx16.r0L <<= 1 + txt.print_ubbin(cx16.r0L, true) + txt.nl() } + txt.nl() - while cx16.r0L & 1 == 1 { + cx16.r0L = %11111110 + while cx16.r0L &32 != 0 { + cx16.r0L <<= 1 + txt.print_ubbin(cx16.r0L, true) + txt.nl() } + txt.nl() - while cx16.r0L & 64 == 0 { - } - - while cx16.r0L & 64 == 64 { - } - - do { } - until cx16.r0L & 1 == 0 - - do { } - until cx16.r0L & 1 == 1 - - do { } - until cx16.r0L & 64 == 0 - - do { } - until cx16.r0L & 64 == 64 - - while cx16.r0L & 1 == 0 { - cx16.r0L++ - } - - while cx16.r0L & 1 == 1 { - cx16.r0L++ - } - - while cx16.r0L & 64 == 0 { - cx16.r0L++ - } - - while cx16.r0L & 64 == 64 { - cx16.r0L++ + ; this one must not be changed and stop after 3 iterations instead of 5! + cx16.r0L = %11111110 + while cx16.r0L &40 == 40 { + cx16.r0L <<= 1 + txt.print_ubbin(cx16.r0L, true) + txt.nl() } + txt.nl() + txt.nl() + cx16.r0L = %11111110 do { - cx16.r0L++ - } - until cx16.r0L & 1 == 0 + cx16.r0L <<= 1 + txt.print_ubbin(cx16.r0L, true) + txt.nl() + } until cx16.r0L &32 != 32 + txt.nl() + cx16.r0L = %11111110 do { - cx16.r0L++ - } - until cx16.r0L & 1 == 1 + cx16.r0L <<= 1 + txt.print_ubbin(cx16.r0L, true) + txt.nl() + } until cx16.r0L &32 == 0 + txt.nl() + ; this one must not be changed and stop after 3 iterations instead of 5! + cx16.r0L = %11111110 do { - cx16.r0L++ - } - until cx16.r0L & 64 == 0 + cx16.r0L <<= 1 + txt.print_ubbin(cx16.r0L, true) + txt.nl() + } until cx16.r0L &40 != 40 + txt.nl() - do { - cx16.r0L++ - } - until cx16.r0L & 64 == 64 + +; while cx16.r0L & cx16.r1L == 0 { +; cx16.r0L++ +; } +; +; while cx16.r0L & cx16.r1L == cx16.r1L { +; cx16.r0L++ +; } /* sys.set_irqd()