optimization added: bitwise operations with a negative constant number -> replace the number by its positive 2 complement

This commit is contained in:
Irmen de Jong 2021-11-18 02:51:42 +01:00
parent 8f379e2262
commit 4f5d36a84d
4 changed files with 70 additions and 45 deletions

View File

@ -232,58 +232,62 @@ class ExpressionSimplifier(private val program: Program) : AstWalker() {
val constFalse = NumericLiteralValue.fromBoolean(false, expr.position) val constFalse = NumericLiteralValue.fromBoolean(false, expr.position)
val newExpr: Expression? = when (expr.operator) { val newExpr: Expression? = when (expr.operator) {
"or" -> { "or" -> {
if ((leftVal != null && leftVal.asBooleanValue) || (rightVal != null && rightVal.asBooleanValue)) when {
constTrue leftVal != null && leftVal.asBooleanValue || rightVal != null && rightVal.asBooleanValue -> constTrue
else if (leftVal != null && !leftVal.asBooleanValue) leftVal != null && !leftVal.asBooleanValue -> expr.right
expr.right rightVal != null && !rightVal.asBooleanValue -> expr.left
else if (rightVal != null && !rightVal.asBooleanValue) else -> null
expr.left }
else
null
} }
"and" -> { "and" -> {
if ((leftVal != null && !leftVal.asBooleanValue) || (rightVal != null && !rightVal.asBooleanValue)) when {
constFalse leftVal != null && !leftVal.asBooleanValue || rightVal != null && !rightVal.asBooleanValue -> constFalse
else if (leftVal != null && leftVal.asBooleanValue) leftVal != null && leftVal.asBooleanValue -> expr.right
expr.right rightVal != null && rightVal.asBooleanValue -> expr.left
else if (rightVal != null && rightVal.asBooleanValue) else -> null
expr.left }
else
null
} }
"xor" -> { "xor" -> {
if (leftVal != null && !leftVal.asBooleanValue) when {
expr.right leftVal != null && !leftVal.asBooleanValue -> expr.right
else if (rightVal != null && !rightVal.asBooleanValue) rightVal != null && !rightVal.asBooleanValue -> expr.left
expr.left leftVal != null && leftVal.asBooleanValue -> PrefixExpression("not", expr.right, expr.right.position)
else if (leftVal != null && leftVal.asBooleanValue) rightVal != null && rightVal.asBooleanValue -> PrefixExpression("not", expr.left, expr.left.position)
PrefixExpression("not", expr.right, expr.right.position) else -> null
else if (rightVal != null && rightVal.asBooleanValue)
PrefixExpression("not", expr.left, expr.left.position)
else
null
} }
"|", "^" -> { }
if (leftVal != null && !leftVal.asBooleanValue) "|" -> {
expr.right when {
else if (rightVal != null && !rightVal.asBooleanValue) leftVal?.number==0.0 -> expr.right
expr.left rightVal?.number==0.0 -> expr.left
else { rightIDt.isBytes && rightVal?.number==255.0 -> NumericLiteralValue(DataType.UBYTE, 255.0, rightVal.position)
if(rightIDt.isBytes && (rightVal?.number==-1.0 || rightVal?.number==255.0)) rightIDt.isWords && rightVal?.number==65535.0 -> NumericLiteralValue(DataType.UWORD, 65535.0, rightVal.position)
PrefixExpression("~", expr.left, expr.left.position) leftIDt.isBytes && leftVal?.number==255.0 -> NumericLiteralValue(DataType.UBYTE, 255.0, leftVal.position)
else if(rightIDt.isWords && (rightVal?.number==-1.0 || rightVal?.number==65535.0)) leftIDt.isWords && leftVal?.number==65535.0 -> NumericLiteralValue(DataType.UWORD, 65535.0, leftVal.position)
PrefixExpression("~", expr.left, expr.left.position) else -> null
else }
null }
"^" -> {
when {
leftVal?.number==0.0 -> expr.right
rightVal?.number==0.0 -> expr.left
rightIDt.isBytes && rightVal?.number==255.0 -> PrefixExpression("~", expr.left, expr.left.position)
rightIDt.isWords && rightVal?.number==65535.0 -> PrefixExpression("~", expr.left, expr.left.position)
leftIDt.isBytes && leftVal?.number==255.0 -> PrefixExpression("~", expr.right, expr.right.position)
leftIDt.isWords && leftVal?.number==65535.0 -> PrefixExpression("~", expr.right, expr.right.position)
else -> null
} }
} }
"&" -> { "&" -> {
if (leftVal != null && !leftVal.asBooleanValue) when {
constFalse leftVal?.number==0.0 -> constFalse
else if (rightVal != null && !rightVal.asBooleanValue) rightVal?.number==0.0 -> constFalse
constFalse rightIDt.isBytes && rightVal?.number==255.0 -> expr.left
else rightIDt.isWords && rightVal?.number==65535.0 -> expr.left
null leftIDt.isBytes && leftVal?.number==255.0 -> expr.right
leftIDt.isWords && leftVal?.number==65535.0 -> expr.right
else -> null
}
} }
"*" -> optimizeMultiplication(expr, leftVal, rightVal) "*" -> optimizeMultiplication(expr, leftVal, rightVal)
"/" -> optimizeDivision(expr, leftVal, rightVal) "/" -> optimizeDivision(expr, leftVal, rightVal)

View File

@ -46,6 +46,27 @@ class TypecastsAdder(val program: Program, val errors: IErrorReporter) : AstWalk
val leftDt = expr.left.inferType(program) val leftDt = expr.left.inferType(program)
val rightDt = expr.right.inferType(program) val rightDt = expr.right.inferType(program)
if(leftDt.isKnown && rightDt.isKnown && leftDt!=rightDt) { if(leftDt.isKnown && rightDt.isKnown && leftDt!=rightDt) {
// convert a negative operand for bitwise operator to the 2's complement positive number instead
if(expr.operator in bitwiseOperators && leftDt.isInteger && rightDt.isInteger) {
val leftCv = expr.left.constValue(program)
if(leftCv!=null && leftCv.number<0) {
val value = if(rightDt.isBytes) 256+leftCv.number else 65536+leftCv.number
return listOf(IAstModification.ReplaceNode(
expr.left,
NumericLiteralValue(rightDt.getOr(DataType.UNDEFINED), value, expr.left.position),
expr))
}
val rightCv = expr.right.constValue(program)
if(rightCv!=null && rightCv.number<0) {
val value = if(leftDt.isBytes) 256+rightCv.number else 65536+rightCv.number
return listOf(IAstModification.ReplaceNode(
expr.right,
NumericLiteralValue(leftDt.getOr(DataType.UNDEFINED), value, expr.right.position),
expr))
}
}
// determine common datatype and add typecast as required to make left and right equal types // determine common datatype and add typecast as required to make left and right equal types
val (commonDt, toFix) = BinaryExpression.commonDatatype(leftDt.getOr(DataType.UNDEFINED), rightDt.getOr(DataType.UNDEFINED), expr.left, expr.operator, expr.right) val (commonDt, toFix) = BinaryExpression.commonDatatype(leftDt.getOr(DataType.UNDEFINED), rightDt.getOr(DataType.UNDEFINED), expr.left, expr.operator, expr.right)
if(toFix!=null) { if(toFix!=null) {

View File

@ -14,6 +14,7 @@ val associativeOperators = setOf("+", "*", "&", "|", "^", "or", "and", "xor", "=
val comparisonOperators = setOf("==", "!=", "<", ">", "<=", ">=") val comparisonOperators = setOf("==", "!=", "<", ">", "<=", ">=")
val augmentAssignmentOperators = setOf("+", "-", "/", "*", "**", "&", "|", "^", "<<", ">>", "%", "and", "or", "xor") val augmentAssignmentOperators = setOf("+", "-", "/", "*", "**", "&", "|", "^", "<<", ">>", "%", "and", "or", "xor")
val logicalOperators = setOf("and", "or", "xor", "not") val logicalOperators = setOf("and", "or", "xor", "not")
val bitwiseOperators = setOf("&", "|", "^")
sealed class Expression: Node { sealed class Expression: Node {

View File

@ -7,7 +7,6 @@ BUG: fix "assignment isAugmented correctness" test
optimize TODO in "Add assignment to initialize with zero" in StatementReorderer optimize TODO in "Add assignment to initialize with zero" in StatementReorderer
optimize TODO in after(assignment) in VariousCleanups optimize TODO in after(assignment) in VariousCleanups
optimize: bitwise operations with a negative constant number -> replace the number by its positive 2 complement
optimize: add some more constant folders mentioned in test.p8 optimize: add some more constant folders mentioned in test.p8
optimize: there is an optimizations in AsmOptimizer that can only be done correctly optimize: there is an optimizations in AsmOptimizer that can only be done correctly
if it knows about regular ram vs io space ram distinction. if it knows about regular ram vs io space ram distinction.