optimize code for logical expressions more if right operand is simple

This commit is contained in:
Irmen de Jong
2022-08-12 00:46:38 +02:00
parent 18790d867c
commit 44ee4b989f
3 changed files with 84 additions and 42 deletions

View File

@@ -360,43 +360,44 @@ internal class AssignmentAsmGen(private val program: Program,
if(expr.operator in setOf("&", "|", "^", "and", "or", "xor")) { if(expr.operator in setOf("&", "|", "^", "and", "or", "xor")) {
if(expr.left.inferType(program).isBytes && expr.right.inferType(program).isBytes && if(expr.left.inferType(program).isBytes && expr.right.inferType(program).isBytes &&
expr.left.isSimple && expr.right.isSimple) { expr.left.isSimple && expr.right.isSimple) {
// if(expr.right is NumericLiteral || expr.right is IdentifierReference) { if(expr.right is NumericLiteral || expr.right is IdentifierReference)
// TODO("optimized code for logical with right number/variable arg (byte)") assignLogicalWithSimpleRightOperandByte(assign.target, expr.left, expr.operator, expr.right)
// } else if(expr.left is NumericLiteral || expr.left is IdentifierReference) { else if(expr.left is NumericLiteral || expr.left is IdentifierReference)
// TODO("optimized code for logical with left number/variable arg (byte)") assignLogicalWithSimpleRightOperandByte(assign.target, expr.right, expr.operator, expr.left)
// } else {
assignExpressionToRegister(expr.left, RegisterOrPair.A, false) assignExpressionToRegister(expr.left, RegisterOrPair.A, false)
asmgen.saveRegisterStack(CpuRegister.A, false) asmgen.saveRegisterStack(CpuRegister.A, false)
assignExpressionToVariable(expr.right, "P8ZP_SCRATCH_B1", DataType.UBYTE, expr.definingSubroutine) assignExpressionToVariable(expr.right, "P8ZP_SCRATCH_B1", DataType.UBYTE, expr.definingSubroutine)
asmgen.restoreRegisterStack(CpuRegister.A, false) asmgen.restoreRegisterStack(CpuRegister.A, false)
when(expr.operator) { when (expr.operator) {
"&", "and" -> asmgen.out(" and P8ZP_SCRATCH_B1") "&", "and" -> asmgen.out(" and P8ZP_SCRATCH_B1")
"|", "or" -> asmgen.out(" ora P8ZP_SCRATCH_B1") "|", "or" -> asmgen.out(" ora P8ZP_SCRATCH_B1")
"^", "xor" -> asmgen.out(" eor P8ZP_SCRATCH_B1") "^", "xor" -> asmgen.out(" eor P8ZP_SCRATCH_B1")
else -> throw AssemblyError("invalid operator") else -> throw AssemblyError("invalid operator")
} }
assignRegisterByte(assign.target, CpuRegister.A) assignRegisterByte(assign.target, CpuRegister.A)
}
return true return true
} }
if(expr.left.inferType(program).isWords && expr.right.inferType(program).isWords && if(expr.left.inferType(program).isWords && expr.right.inferType(program).isWords &&
expr.left.isSimple && expr.right.isSimple) { expr.left.isSimple && expr.right.isSimple) {
// if(expr.right is NumericLiteral || expr.right is IdentifierReference) { if(expr.right is NumericLiteral || expr.right is IdentifierReference)
// TODO("optimized code for logical with right number/variable arg (word)") assignLogicalWithSimpleRightOperandWord(assign.target, expr.left, expr.operator, expr.right)
// } else if(expr.left is NumericLiteral || expr.left is IdentifierReference) { else if(expr.left is NumericLiteral || expr.left is IdentifierReference)
// TODO("optimized code for logical with left number/variable arg (word)") assignLogicalWithSimpleRightOperandWord(assign.target, expr.right, expr.operator, expr.left)
// } else {
assignExpressionToRegister(expr.left, RegisterOrPair.AY, false) assignExpressionToRegister(expr.left, RegisterOrPair.AY, false)
asmgen.saveRegisterStack(CpuRegister.A, false) asmgen.saveRegisterStack(CpuRegister.A, false)
asmgen.saveRegisterStack(CpuRegister.Y, false) asmgen.saveRegisterStack(CpuRegister.Y, false)
assignExpressionToVariable(expr.right, "P8ZP_SCRATCH_W1", DataType.UWORD, expr.definingSubroutine) assignExpressionToVariable(expr.right, "P8ZP_SCRATCH_W1", DataType.UWORD, expr.definingSubroutine)
when(expr.operator) { when (expr.operator) {
"&", "and" -> asmgen.out(" pla | and P8ZP_SCRATCH_W1+1 | tay | pla | and P8ZP_SCRATCH_W1") "&", "and" -> asmgen.out(" pla | and P8ZP_SCRATCH_W1+1 | tay | pla | and P8ZP_SCRATCH_W1")
"|", "or" -> asmgen.out(" pla | ora P8ZP_SCRATCH_W1+1 | tay | pla | ora P8ZP_SCRATCH_W1") "|", "or" -> asmgen.out(" pla | ora P8ZP_SCRATCH_W1+1 | tay | pla | ora P8ZP_SCRATCH_W1")
"^", "xor" -> asmgen.out(" pla | eor P8ZP_SCRATCH_W1+1 | tay | pla | eor P8ZP_SCRATCH_W1") "^", "xor" -> asmgen.out(" pla | eor P8ZP_SCRATCH_W1+1 | tay | pla | eor P8ZP_SCRATCH_W1")
else -> throw AssemblyError("invalid operator") else -> throw AssemblyError("invalid operator")
} }
assignRegisterpairWord(assign.target, RegisterOrPair.AY) assignRegisterpairWord(assign.target, RegisterOrPair.AY)
}
return true return true
} }
return false return false
@@ -596,6 +597,48 @@ internal class AssignmentAsmGen(private val program: Program,
return false return false
} }
private fun assignLogicalWithSimpleRightOperandByte(target: AsmAssignTarget, left: Expression, operator: String, right: Expression) {
assignExpressionToRegister(left, RegisterOrPair.A, false)
val operand = when(right) {
is NumericLiteral -> "#${right.number.toHex()}"
is IdentifierReference -> asmgen.asmSymbolName(right)
else -> throw AssemblyError("wrong right operand type")
}
when (operator) {
"&", "and" -> asmgen.out(" and $operand")
"|", "or" -> asmgen.out(" ora $operand")
"^", "xor" -> asmgen.out(" eor $operand")
else -> throw AssemblyError("invalid operator")
}
assignRegisterByte(target, CpuRegister.A)
}
private fun assignLogicalWithSimpleRightOperandWord(target: AsmAssignTarget, left: Expression, operator: String, right: Expression) {
assignExpressionToRegister(left, RegisterOrPair.AY, false)
when(right) {
is NumericLiteral -> {
val number = right.number.toHex()
when (operator) {
"&", "and" -> asmgen.out(" and #<$number | pha | tya | and #>$number | tay | pla")
"|", "or" -> asmgen.out(" ora #<$number | pha | tya | ora #>$number | tay | pla")
"^", "xor" -> asmgen.out(" eor #<$number | pha | tya | eor #>$number | tay | pla")
else -> throw AssemblyError("invalid operator")
}
}
is IdentifierReference -> {
val name = asmgen.asmSymbolName(right)
when (operator) {
"&", "and" -> asmgen.out(" and $name | pha | tya | and $name+1 | tay | pla")
"|", "or" -> asmgen.out(" ora $name | pha | tya | ora $name+1 | tay | pla")
"^", "xor" -> asmgen.out(" eor $name | pha | tya | eor $name+1 | tay | pla")
else -> throw AssemblyError("invalid operator")
}
}
else -> throw AssemblyError("wrong right operand type")
}
assignRegisterpairWord(target, RegisterOrPair.AY)
}
private fun attemptAssignToByteCompareZero(expr: BinaryExpression, assign: AsmAssignment): Boolean { private fun attemptAssignToByteCompareZero(expr: BinaryExpression, assign: AsmAssignment): Boolean {
when (expr.operator) { when (expr.operator) {
"==" -> { "==" -> {

View File

@@ -3,8 +3,8 @@ TODO
For next release For next release
^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^
- finish the logical expression optimizations set in TODO's in attemptAssignOptimizedBinexpr()
- try more benchmarks from https://gglabs.us/node/2293 - try more benchmarks from https://gglabs.us/node/2293
- check that all examples still function correctly
... ...

View File

@@ -4,16 +4,15 @@
main { main {
sub start() { sub start() {
uword crc = $ffff uword crc = $ffff
txt.print_uwhex(crc | (crc & $8000), true) if crc & $8000 ; msb(crc) & $80
; if crc & $8000 ; msb(crc) & $80 txt.print("yes")
; txt.print("yes") else
; else txt.print("fail!")
; txt.print("fail!")
; if crc & $1234
; if msb(crc) & $80 txt.print("yes")
; txt.print("yes") else
; else txt.print("fail!")
; txt.print("fail!")
} }
; sub start2() { ; sub start2() {