improved codegen for testing for single bits: x & mask == mask

This commit is contained in:
Irmen de Jong 2024-12-09 03:58:56 +01:00
parent 26d0a174db
commit 535ec13072
3 changed files with 86 additions and 73 deletions

View File

@ -378,30 +378,44 @@ class ExpressionSimplifier(private val program: Program, private val errors: IEr
if (rightVal!=null && (expr.operator == "==" || expr.operator == "!=")) { if (rightVal!=null && (expr.operator == "==" || expr.operator == "!=")) {
val bitwise = expr.left as? BinaryExpression val bitwise = expr.left as? BinaryExpression
if(bitwise!=null && bitwise.operator=="&" && bitwise.inferType(program).isWords) { if (bitwise!=null && bitwise.operator=="&") {
val andNum = (bitwise.right as? NumericLiteral)?.number?.toInt()
if (andNum!=null) { if(rightVal.number in powersOfTwoFloat && bitwise.right.constValue(program) == rightVal) {
if ((andNum and 0x00ff) == 0) { if(expr.operator=="==") {
// (WORD & $xx00)==y -> (msb(WORD) & $xx)==y // x & const == const -> x & const != 0 (if const has only a single bit set!)
val msb = FunctionCallExpression(IdentifierReference(listOf("msb"), bitwise.left.position), mutableListOf(bitwise.left), bitwise.left.position) val notZero = BinaryExpression(bitwise, "!=", NumericLiteral(rightDt.base, 0.0, rightVal.position), expr.position)
val bytevalue = NumericLiteral(BaseDataType.UBYTE, (andNum shr 8).toDouble(), bitwise.right.position) return listOf(IAstModification.ReplaceNode(expr, notZero, parent))
val rightvalByte = NumericLiteral(BaseDataType.UBYTE, (rightVal.number.toInt() shr 8).toDouble(), rightVal.position) } else {
return listOf( // x & const != const -> x & const == 0 (if const has only a single bit set!)
IAstModification.ReplaceNode(bitwise.left, msb, bitwise), val equalsZero = BinaryExpression(bitwise, "==", NumericLiteral(rightDt.base, 0.0, rightVal.position), expr.position)
IAstModification.ReplaceNode(bitwise.right, bytevalue, bitwise), return listOf(IAstModification.ReplaceNode(expr, equalsZero, parent))
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) if (bitwise.inferType(program).isWords) {
val bytevalue = NumericLiteral(BaseDataType.UBYTE, andNum.toDouble(), bitwise.right.position) val andNum = (bitwise.right as? NumericLiteral)?.number?.toInt()
val rightvalByte = NumericLiteral(BaseDataType.UBYTE, (rightVal.number.toInt() and 255).toDouble(), rightVal.position) if (andNum!=null) {
return listOf( if ((andNum and 0x00ff) == 0) {
IAstModification.ReplaceNode(bitwise.left, lsb, bitwise), // (WORD & $xx00)==y -> (msb(WORD) & $xx)==y
IAstModification.ReplaceNode(bitwise.right, bytevalue, bitwise), val msb = FunctionCallExpression(IdentifierReference(listOf("msb"), bitwise.left.position), mutableListOf(bitwise.left), bitwise.left.position)
IAstModification.ReplaceNode(expr.right, rightvalByte, expr) 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)
)
}
} }
} }
} }

View File

@ -4,13 +4,11 @@ TODO
Halloween is stuck on a black screen 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 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 update zsmkit to newest version that includes the on_deck routines when stabilized

View File

@ -1,68 +1,69 @@
%import textio
%zeropage basicsafe %zeropage basicsafe
%option no_sysinit %option no_sysinit
main { main {
sub start() { 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 { ; this one must not be changed and stop after 3 iterations instead of 5!
} cx16.r0L = %11111110
while cx16.r0L &40 == 40 {
while cx16.r0L & 64 == 64 { cx16.r0L <<= 1
} txt.print_ubbin(cx16.r0L, true)
txt.nl()
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++
} }
txt.nl()
txt.nl()
cx16.r0L = %11111110
do { do {
cx16.r0L++ cx16.r0L <<= 1
} txt.print_ubbin(cx16.r0L, true)
until cx16.r0L & 1 == 0 txt.nl()
} until cx16.r0L &32 != 32
txt.nl()
cx16.r0L = %11111110
do { do {
cx16.r0L++ cx16.r0L <<= 1
} txt.print_ubbin(cx16.r0L, true)
until cx16.r0L & 1 == 1 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 { do {
cx16.r0L++ cx16.r0L <<= 1
} txt.print_ubbin(cx16.r0L, true)
until cx16.r0L & 64 == 0 txt.nl()
} until cx16.r0L &40 != 40
txt.nl()
do {
cx16.r0L++ ; while cx16.r0L & cx16.r1L == 0 {
} ; cx16.r0L++
until cx16.r0L & 64 == 64 ; }
;
; while cx16.r0L & cx16.r1L == cx16.r1L {
; cx16.r0L++
; }
/* /*
sys.set_irqd() sys.set_irqd()