optimized if-goto codegeneration

This commit is contained in:
Irmen de Jong 2021-12-27 20:46:10 +01:00
parent 97e84d0977
commit 1c7c4fc3b0
5 changed files with 52 additions and 44 deletions

View File

@ -1098,15 +1098,14 @@ class AsmGen(private val program: Program,
val booleanCondition = stmt.condition as BinaryExpression
if (stmt.elsepart.isEmpty()) {
// TODO specialize this
// if(stmt.truepart.statements.singleOrNull() is Jump) {
// translateCompareAndJumpIfTrue(booleanCondition, stmt.truepart.statements[0] as Jump)
// } else {
if(stmt.truepart.statements.singleOrNull() is Jump) {
translateCompareAndJumpIfTrue(booleanCondition, stmt.truepart.statements[0] as Jump)
} else {
val endLabel = makeLabel("if_end")
translateCompareAndJumpIfFalse(booleanCondition, endLabel)
translate(stmt.truepart)
out(endLabel)
// }
}
}
else {
// both true and else parts
@ -1613,16 +1612,29 @@ $label nop""")
}
private fun translateCompareAndJumpIfTrue(expr: BinaryExpression, jump: Jump) {
if(expr.operator !in ComparisonOperators)
throw AssemblyError("must be comparison expression")
// invert the comparison, so we can reuse the JumpIfFalse code generation routines
val invertedComparisonOperator = invertedComparisonOperator(expr.operator)
?: throw AssemblyError("can't invert comparison $expr")
val left = expr.left
val right = expr.right
val operator = expr.operator
val leftConstVal = left.constValue(program)
val rightConstVal = right.constValue(program)
val label = when {
jump.generatedLabel!=null -> jump.generatedLabel!!
jump.identifier!=null -> asmSymbolName(jump.identifier!!)
jump.address!=null -> jump.address!!.toHex()
else -> throw AssemblyError("weird jump")
}
if (rightConstVal!=null && rightConstVal.number == 0.0)
testZeroAndJump(left, operator, jump, null)
else
testNonzeroComparisonAndJump(left, operator, right, jump, null, leftConstVal, rightConstVal)
testZeroAndJump(left, invertedComparisonOperator, label)
else {
val leftConstVal = left.constValue(program)
testNonzeroComparisonAndJump(left, invertedComparisonOperator, right, label, leftConstVal, rightConstVal)
}
}
private fun translateCompareAndJumpIfFalse(expr: BinaryExpression, jumpIfFalseLabel: String) {
@ -1633,18 +1645,16 @@ $label nop""")
val rightConstVal = right.constValue(program)
if (rightConstVal!=null && rightConstVal.number == 0.0)
testZeroAndJump(left, operator, null, jumpIfFalseLabel)
testZeroAndJump(left, operator, jumpIfFalseLabel)
else
testNonzeroComparisonAndJump(left, operator, right, null, jumpIfFalseLabel, leftConstVal, rightConstVal)
testNonzeroComparisonAndJump(left, operator, right, jumpIfFalseLabel, leftConstVal, rightConstVal)
}
private fun testZeroAndJump(
left: Expression,
operator: String,
jumpIfTrue: Jump?,
jumpIfFalseLabel: String?
jumpIfFalseLabel: String
) {
require(jumpIfTrue!=null || jumpIfFalseLabel!=null)
when(val dt = left.inferType(program).getOr(DataType.UNDEFINED)) {
DataType.UBYTE, DataType.UWORD -> {
if(operator=="<") {
@ -1733,16 +1743,12 @@ $label nop""")
left: Expression,
operator: String,
right: Expression,
jumpIfTrue: Jump?,
jumpIfFalseLabel: String?,
jumpIfFalseLabel: String,
leftConstVal: NumericLiteralValue?,
rightConstVal: NumericLiteralValue?
) {
require(jumpIfTrue!=null || jumpIfFalseLabel!=null)
val dt = left.inferType(program).getOrElse { throw AssemblyError("unknown dt") }
jumpIfFalseLabel!! // TODO jump if true... or rewrite everything to use just jump-if-false
when (operator) {
"==" -> {
when (dt) {

View File

@ -724,25 +724,4 @@ class ExpressionSimplifier(private val program: Program) : AstWalker() {
private data class BinExprWithConstants(val expr: BinaryExpression, val leftVal: NumericLiteralValue?, val rightVal: NumericLiteralValue?)
}
fun invertCondition(cond: Expression): BinaryExpression? {
if(cond is BinaryExpression) {
val invertedOperator = invertedComparisonOperator(cond.operator)
if (invertedOperator != null)
return BinaryExpression(cond.left, invertedOperator, cond.right, cond.position)
}
return null
}
fun invertedComparisonOperator(operator: String) =
when (operator) {
"==" -> "!="
"!=" -> "=="
"<" -> ">="
">" -> "<="
"<=" -> ">"
">=" -> "<"
else -> null
}
}

View File

@ -9,7 +9,6 @@ import prog8.ast.statements.*
import prog8.ast.walk.AstWalker
import prog8.ast.walk.IAstModification
import prog8.compilerinterface.IErrorReporter
import prog8.optimizer.invertedComparisonOperator
internal class VariousCleanups(val program: Program, val errors: IErrorReporter): AstWalker() {

View File

@ -15,6 +15,17 @@ val AugmentAssignmentOperators = setOf("+", "-", "/", "*", "**", "&", "|", "^",
val LogicalOperators = setOf("and", "or", "xor", "not")
val BitwiseOperators = setOf("&", "|", "^")
fun invertedComparisonOperator(operator: String) =
when (operator) {
"==" -> "!="
"!=" -> "=="
"<" -> ">="
">" -> "<="
"<=" -> ">"
">=" -> "<"
else -> null
}
sealed class Expression: Node {
abstract override fun copy(): Expression
@ -938,3 +949,13 @@ class FunctionCall(override var target: IdentifierReference,
}
}
}
fun invertCondition(cond: Expression): BinaryExpression? {
if(cond is BinaryExpression) {
val invertedOperator = invertedComparisonOperator(cond.operator)
if (invertedOperator != null)
return BinaryExpression(cond.left, invertedOperator, cond.right, cond.position)
}
return null
}

View File

@ -3,7 +3,10 @@ TODO
For next compiler release (7.6)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
optimize ifs containing only a jump: reuse old code from AsmGen translateComparisonExpressionWithJumpIfFalse?
fix imageviewer pcx decoding, broken since if/goto changes...
also wormfood: worm freezes when you press fire...
also petaxian: gameplay doesn't work at all anymore
also textelite: after showing map, it just exits
Blocked by an official Commander-x16 v39 release