mirror of
https://github.com/irmen/prog8.git
synced 2025-08-15 14:27:37 +00:00
optimize code for logical expressions more if right operand is simple
This commit is contained in:
@@ -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) {
|
||||||
"==" -> {
|
"==" -> {
|
||||||
|
@@ -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
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
|
@@ -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() {
|
||||||
|
Reference in New Issue
Block a user