shortcutting part one

This commit is contained in:
Irmen de Jong
2023-12-30 02:18:56 +01:00
parent 8f18b5b8a7
commit 1c55a6c6dc
7 changed files with 152 additions and 70 deletions

View File

@@ -1041,39 +1041,60 @@ internal class AssignmentAsmGen(private val program: PtProgram,
private fun optimizedLogicalAndOrExpr(expr: PtBinaryExpression, target: AsmAssignTarget): Boolean {
if (expr.left.type in ByteDatatypes && expr.right.type in ByteDatatypes) {
if (expr.right.isSimple()) {
if (expr.right is PtNumber || expr.right is PtIdentifier) {
assignLogicalAndOrWithSimpleRightOperandByte(target, expr.left, expr.operator, expr.right)
return true
}
else if (expr.left is PtNumber || expr.left is PtIdentifier) {
assignLogicalAndOrWithSimpleRightOperandByte(target, expr.right, expr.operator, expr.left)
return true
}
if (expr.right is PtNumber || expr.right is PtIdentifier) {
assignLogicalAndOrWithSimpleRightOperandByte(target, expr.left, expr.operator, expr.right)
return true
}
else if (expr.left is PtNumber || expr.left is PtIdentifier) {
assignLogicalAndOrWithSimpleRightOperandByte(target, expr.right, expr.operator, expr.left)
return true
}
assignExpressionToRegister(expr.left, RegisterOrPair.A, false)
asmgen.saveRegisterStack(CpuRegister.A, false)
assignExpressionToVariable(expr.right, "P8ZP_SCRATCH_B1", DataType.UBYTE)
asmgen.restoreRegisterStack(CpuRegister.A, false)
when (expr.operator) {
"and" -> TODO("logical and (with optional shortcircuit) ${expr.position}")
"or" -> TODO("logical or (with optional shortcircuit) ${expr.position}")
else -> throw AssemblyError("invalid logical operator")
if(asmgen.options.shortCircuit && (!expr.left.isSimple() && !expr.right.isSimple())) {
// shortcircuit evaluation into A
val shortcutLabel = asmgen.makeLabel("shortcut")
when (expr.operator) {
"and" -> {
// short-circuit LEFT and RIGHT --> if LEFT then RIGHT else LEFT (== if !LEFT then LEFT else RIGHT)
println("SHORTCUT AND ${expr.position}") // TODO weg
assignExpressionToRegister(expr.left, RegisterOrPair.A, false)
asmgen.out(" beq $shortcutLabel")
assignExpressionToRegister(expr.right, RegisterOrPair.A, false)
asmgen.out(shortcutLabel)
}
"or" -> {
// short-circuit LEFT or RIGHT --> if LEFT then LEFT else RIGHT
println("SHORTCUT OR ${expr.position}") // TODO weg
assignExpressionToRegister(expr.left, RegisterOrPair.A, false)
asmgen.out(" bne $shortcutLabel")
assignExpressionToRegister(expr.right, RegisterOrPair.A, false)
asmgen.out(shortcutLabel)
}
else -> throw AssemblyError("invalid logical operator")
}
} else {
// normal evaluation into A
assignExpressionToRegister(expr.left, RegisterOrPair.A, false)
asmgen.saveRegisterStack(CpuRegister.A, false)
assignExpressionToVariable(expr.right, "P8ZP_SCRATCH_B1", DataType.UBYTE)
asmgen.restoreRegisterStack(CpuRegister.A, false)
when (expr.operator) {
"and" -> asmgen.out(" and P8ZP_SCRATCH_B1")
"or" -> asmgen.out(" ora P8ZP_SCRATCH_B1")
else -> throw AssemblyError("invalid logical operator")
}
}
assignRegisterByte(target, CpuRegister.A, false, true)
return true
}
else if (expr.left.type in WordDatatypes && expr.right.type in WordDatatypes) {
if (expr.right.isSimple()) {
if (expr.right is PtNumber || expr.right is PtIdentifier) {
assignLogicalAndOrWithSimpleRightOperandWord(target, expr.left, expr.operator, expr.right)
return true
}
else if (expr.left is PtNumber || expr.left is PtIdentifier) {
assignLogicalAndOrWithSimpleRightOperandWord(target, expr.right, expr.operator, expr.left)
return true
}
if (expr.right is PtNumber || expr.right is PtIdentifier) {
assignLogicalAndOrWithSimpleRightOperandWord(target, expr.left, expr.operator, expr.right)
return true
}
else if (expr.left is PtNumber || expr.left is PtIdentifier) {
assignLogicalAndOrWithSimpleRightOperandWord(target, expr.right, expr.operator, expr.left)
return true
}
asmgen.assignWordOperandsToAYAndVar(expr.left, expr.right, "P8ZP_SCRATCH_W1")
when (expr.operator) {
@@ -1775,11 +1796,15 @@ internal class AssignmentAsmGen(private val program: PtProgram,
}
private fun assignLogicalAndOrWithSimpleRightOperandByte(target: AsmAssignTarget, left: PtExpression, operator: String, right: PtExpression) {
// normal evaluation, not worth to shortcircuit the simple right operand
assignExpressionToVariable(left, "P8ZP_SCRATCH_B1", DataType.UBYTE)
assignExpressionToRegister(right, RegisterOrPair.A, false)
when (operator) {
"and" -> TODO("logical and (with optional shortcircuit) ${left.position}")
"or" -> TODO("logical or (with optional shortcircuit) ${left.position}")
"and" -> asmgen.out(" and P8ZP_SCRATCH_B1")
"or" -> asmgen.out(" ora P8ZP_SCRATCH_B1")
else -> throw AssemblyError("invalid logical operator")
}
assignRegisterByte(target, CpuRegister.A, false, true)
}
private fun assignBitwiseWithSimpleRightOperandWord(target: AsmAssignTarget, left: PtExpression, operator: String, right: PtExpression) {

View File

@@ -37,8 +37,10 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
"*=" -> inplaceModification(assign.target, "*", assign.source)
"/=" -> inplaceModification(assign.target, "/", assign.source)
"|=" -> inplaceModification(assign.target, "|", assign.source)
"or=" -> inplaceModification(assign.target, "or", assign.source)
"&=" -> inplaceModification(assign.target, "&", assign.source)
"^=" -> inplaceModification(assign.target, "^", assign.source)
"and=" -> inplaceModification(assign.target, "and", assign.source)
"^=", "xor=" -> inplaceModification(assign.target, "^", assign.source)
"<<=" -> inplaceModification(assign.target, "<<", assign.source)
">>=" -> inplaceModification(assign.target, ">>", assign.source)
"%=" -> inplaceModification(assign.target, "%", assign.source)
@@ -791,12 +793,42 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
}
private fun inplacemodificationByteVariableWithValue(name: String, dt: DataType, operator: String, value: PtExpression) {
if(asmgen.options.shortCircuit) {
val shortcutLabel = asmgen.makeLabel("shortcut")
when (operator) {
"and" -> {
// short-circuit LEFT and RIGHT --> if LEFT then RIGHT else LEFT (== if !LEFT then LEFT else RIGHT)
println("SHORTCUT AND ${value.position}") // TODO weg
asmgen.out(" lda $name | beq $shortcutLabel")
asmgen.assignExpressionToRegister(value, RegisterOrPair.A, dt in SignedDatatypes)
asmgen.out("""
and $name
sta $name
$shortcutLabel:""")
return
}
"or" -> {
// short-circuit LEFT or RIGHT --> if LEFT then LEFT else RIGHT
println("SHORTCUT OR ${value.position}") // TODO weg
asmgen.out(" lda $name | bne $shortcutLabel")
asmgen.assignExpressionToRegister(value, RegisterOrPair.A, dt in SignedDatatypes)
asmgen.out("""
ora $name
sta $name
$shortcutLabel:""")
return
}
}
}
// normal evaluation
asmgen.assignExpressionToRegister(value, RegisterOrPair.A, dt in SignedDatatypes)
inplacemodificationRegisterAwithVariableWithSwappedOperands(operator, name, dt in SignedDatatypes)
asmgen.out(" sta $name")
}
private fun inplacemodificationByteVariableWithVariable(name: String, dt: DataType, operator: String, otherName: String) {
// note: no logical and/or shortcut here, not worth it due to simple right operand
asmgen.out(" lda $name")
inplacemodificationRegisterAwithVariable(operator, otherName, dt in SignedDatatypes)
asmgen.out(" sta $name")
@@ -852,6 +884,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
}
"&" -> asmgen.out(" and $variable")
"|" -> asmgen.out(" ora $variable")
"and", "or" -> throw AssemblyError("logical and/or should have been handled earlier because of shortcircuit handling")
"^" -> asmgen.out(" eor $variable")
"==" -> {
asmgen.out("""
@@ -1130,6 +1163,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
private fun inplacemodificationByteVariableWithLiteralval(name: String, dt: DataType, operator: String, value: Int) {
// note: this contains special optimized cases because we know the exact value. Don't replace this with another routine.
// note: no logical and/or shortcut here, not worth it due to simple right operand
when (operator) {
"+" -> asmgen.out(" lda $name | clc | adc #$value | sta $name")
"-" -> asmgen.out(" lda $name | sec | sbc #$value | sta $name")
@@ -1192,9 +1226,9 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
}
}
}
"&" -> immediateAndInplace(name, value)
"|" -> immediateOrInplace(name, value)
"^" -> asmgen.out(" lda $name | eor #$value | sta $name")
"&", "and" -> immediateAndInplace(name, value)
"|", "or" -> immediateOrInplace(name, value)
"^", "xor" -> asmgen.out(" lda $name | eor #$value | sta $name")
"==" -> {
asmgen.out("""
lda $name