optimize comparison against zero

This commit is contained in:
Irmen de Jong 2023-09-01 01:50:28 +02:00
parent cfea8b3745
commit 09a7a4bbe5
3 changed files with 43 additions and 147 deletions

View File

@ -416,7 +416,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
val translatedOk = when (expr.operator) {
in ComparisonOperators -> optimizedComparison(expr, assign)
in setOf("&", "|", "^", "and", "or", "xor") -> optimizedLogicalOrBitwiseExpr(expr, assign.target)
"==", "!=" -> optimizedEqualityExpr(expr, assign.target)
"+", "-" -> optimizedPlusMinExpr(expr, assign.target)
"<<", ">>" -> optimizedBitshiftExpr(expr, assign.target)
"*" -> optimizedMultiplyExpr(expr, assign.target)
@ -888,63 +887,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
return false
}
private fun optimizedEqualityExpr(expr: PtBinaryExpression, target: AsmAssignTarget): Boolean {
// expression datatype is BOOL (ubyte) but operands can be anything
if(expr.left.type in ByteDatatypes && expr.right.type in ByteDatatypes &&
expr.left.isSimple() && expr.right.isSimple()) {
assignExpressionToRegister(expr.left, RegisterOrPair.A, false)
asmgen.saveRegisterStack(CpuRegister.A, false)
assignExpressionToVariable(expr.right, "P8ZP_SCRATCH_B1", DataType.UBYTE)
asmgen.restoreRegisterStack(CpuRegister.A, false)
if(expr.operator=="==") {
asmgen.out("""
cmp P8ZP_SCRATCH_B1
bne +
lda #1
bne ++
+ lda #0
+""")
} else {
asmgen.out("""
cmp P8ZP_SCRATCH_B1
beq +
lda #1
bne ++
+ lda #0
+""")
}
assignRegisterByte(target, CpuRegister.A, false)
return true
} else if(expr.left.type in WordDatatypes && expr.right.type in WordDatatypes &&
expr.left.isSimple() && expr.right.isSimple()) {
asmgen.assignWordOperandsToAYAndVar(expr.left, expr.right, "P8ZP_SCRATCH_W1")
if(expr.operator=="==") {
asmgen.out("""
cmp P8ZP_SCRATCH_W1
bne +
cpy P8ZP_SCRATCH_W1+1
bne +
lda #1
bne ++
+ lda #0
+""")
} else {
asmgen.out("""
cmp P8ZP_SCRATCH_W1
bne +
cpy P8ZP_SCRATCH_W1+1
bne +
lda #0
beq ++
+ lda #1
+""")
}
assignRegisterByte(target, CpuRegister.A, false)
return true
}
return false
}
private fun optimizedLogicalOrBitwiseExpr(expr: PtBinaryExpression, target: AsmAssignTarget): Boolean {
if (expr.left.type in ByteDatatypes && expr.right.type in ByteDatatypes) {
if (expr.right.isSimple()) {
@ -1085,7 +1027,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
}
}
// checked OK:
private fun byteLess(expr: PtBinaryExpression, signed: Boolean) {
// note: this is the inverse of byteGreaterEqual
when(expr.right) {
@ -1232,78 +1173,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
}
}
private fun byteLessEqualsWRONG(expr: PtBinaryExpression, signed: Boolean) {
// note: this is the inverse of byteGreater
when(expr.right) {
is PtNumber -> {
// TODO verify if this is correct code on all corner cases
val number = (expr.right as PtNumber).number.toInt()
asmgen.assignExpressionToRegister(expr.left, RegisterOrPair.A, signed)
if(signed)
asmgen.out("""
sec
sbc #$number
bvc +
eor #$80
+ bmi +
lda #0
beq ++
+ lda #1
+""")
else
asmgen.out("""
cmp #$number
lda #0
rol a
eor #1""")
}
is PtIdentifier -> {
// TODO verify if this is correct code on all corner cases
val varname = (expr.right as PtIdentifier).name
asmgen.assignExpressionToRegister(expr.left, RegisterOrPair.A, signed)
if(signed)
asmgen.out("""
sec
sbc $varname
bvc +
eor #$80
+ bmi +
lda #0
beq ++
+ lda #1
+""")
else
asmgen.out("""
cmp $varname
lda #0
rol a
eor #1""")
}
else -> {
// TODO verify if this is correct code on all corner cases
// note: left and right operands get reversed here to reduce code size
asmgen.assignByteOperandsToAAndVar(expr.right, expr.left, "P8ZP_SCRATCH_B1")
if(signed)
asmgen.out("""
sec
sbc P8ZP_SCRATCH_B1
bvc +
eor #$80
+ bmi +
lda #1
bne ++
+ lda #0
+""")
else
asmgen.out("""
cmp P8ZP_SCRATCH_B1
lda #0
rol a""")
}
}
}
// checked OK:
private fun byteGreater(expr: PtBinaryExpression, signed: Boolean) {
// note: this is the inverse of byteLessEqual
when(expr.right) {
@ -1381,7 +1250,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
}
}
// checked OK:
private fun byteGreaterEquals(expr: PtBinaryExpression, signed: Boolean) {
// note: this is the inverse of byteLess
when(expr.right) {
@ -1649,10 +1517,8 @@ internal class AssignmentAsmGen(private val program: PtProgram,
assignExpressionToRegister(expr.left, RegisterOrPair.A, dt==DataType.BYTE)
asmgen.out("""
beq +
lda #0
beq ++
+ lda #1
+""")
lda #1
+ eor #1""")
assignRegisterByte(assign.target, CpuRegister.A, false)
return true
}
@ -1662,10 +1528,8 @@ internal class AssignmentAsmGen(private val program: PtProgram,
sty P8ZP_SCRATCH_B1
ora P8ZP_SCRATCH_B1
beq +
lda #0
beq ++
+ lda #1
+""")
lda #1
+ eor #1""")
assignRegisterByte(assign.target, CpuRegister.A, false)
return true
}

View File

@ -1,6 +1,6 @@
TODO
====
- optimize assembly output for if word1 & word2 ... (no need for stack pushes)
- optimize assembly output for ( word1 & word2 ==0) ... (no need for stack pushes)
- prefix prog8 subroutines with p8s_ instead of p8_ to not let them clash with variables in the asm?

View File

@ -1,13 +1,45 @@
%import textio
%import math
%zeropage basicsafe
main {
sub start() {
thing()
}
sub thing() {
ubyte start=22
txt.print_ub(start)
txt.print_uw(&main.start)
uword w1
uword w2
ubyte b1
ubyte b2
b1 = 255
b2 = 1
txt.print_ub(b1&b2!=0) ; true
txt.spc()
txt.print_ub(b1&b2==0) ; false
txt.nl()
b1 = 255
b2 = 0
txt.print_ub(b1&b2!=0) ; false
txt.spc()
txt.print_ub(b1&b2==0) ; true
txt.nl()
w1 = $ff0f
w2 = $0101
txt.print_ub(w1&w2!=0) ; true
txt.spc()
txt.print_ub(w1&w2==0) ; false
txt.nl()
w1 = $ff0f
w2 = $00f0
txt.print_ub(w1&w2!=0) ; false
txt.spc()
txt.print_ub(w1&w2==0) ; true
txt.nl()
; if w1 & w2
; cx16.r0++
}
}