From b8251b2e2613138230dd9a0ad651588b176489e5 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Fri, 11 Jan 2019 22:15:05 +0100 Subject: [PATCH] simplify expressions --- .../src/prog8/compiler/target/c64/AsmGen.kt | 10 +-- .../prog8/optimizing/SimplifyExpressions.kt | 88 +++++++++++++++++-- .../prog8/optimizing/StatementOptimizer.kt | 29 +++--- examples/test.p8 | 22 +++-- 4 files changed, 119 insertions(+), 30 deletions(-) diff --git a/compiler/src/prog8/compiler/target/c64/AsmGen.kt b/compiler/src/prog8/compiler/target/c64/AsmGen.kt index 803613098..d1caa0fcb 100644 --- a/compiler/src/prog8/compiler/target/c64/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/AsmGen.kt @@ -3188,10 +3188,10 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, """ }, - // more efficient versions of x+1 and x-1 to avoid pushing the 1 on the stack @todo what about 1+x? reorder? what about x+ (-1) and x-(-1)? is that rewritten already? + // more efficient versions of x+1 and x-1 to avoid pushing the 1 on the stack @todo what about 1+x? reorder? AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.ADD_B), listOf(Opcode.PUSH_BYTE, Opcode.ADD_UB)) { segment -> val amount = segment[0].arg!!.integerValue() - if(amount in 1..8) { + if(amount in 1..2) { " inc ${(ESTACK_LO + 1).toHex()},x | ".repeat(amount) } else @@ -3199,7 +3199,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, }, AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.ADD_UW), listOf(Opcode.PUSH_WORD, Opcode.ADD_W)) { segment -> val amount = segment[0].arg!!.integerValue() - if(amount in 1..8) { + if(amount in 1..2) { " inc ${(ESTACK_LO + 1).toHex()},x | bne + | inc ${(ESTACK_HI + 1).toHex()},x |+ | ".repeat(amount) } else @@ -3207,7 +3207,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, }, AsmPattern(listOf(Opcode.PUSH_BYTE, Opcode.SUB_B), listOf(Opcode.PUSH_BYTE, Opcode.SUB_UB)) { segment -> val amount = segment[0].arg!!.integerValue() - if(amount in 1..8) { + if(amount in 1..2) { " dec ${(ESTACK_LO + 1).toHex()},x | ".repeat(amount) } else @@ -3215,7 +3215,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, }, AsmPattern(listOf(Opcode.PUSH_WORD, Opcode.SUB_UW), listOf(Opcode.PUSH_WORD, Opcode.SUB_W)) { segment -> val amount = segment[0].arg!!.integerValue() - if(amount in 1..8) { + if(amount in 1..2) { " lda ${(ESTACK_LO + 1).toHex()},x | bne + | dec ${(ESTACK_HI + 1).toHex()},x |+ | dec ${(ESTACK_LO + 1).toHex()},x | ".repeat(amount) } else diff --git a/compiler/src/prog8/optimizing/SimplifyExpressions.kt b/compiler/src/prog8/optimizing/SimplifyExpressions.kt index f9a9fdba5..a42468d48 100644 --- a/compiler/src/prog8/optimizing/SimplifyExpressions.kt +++ b/compiler/src/prog8/optimizing/SimplifyExpressions.kt @@ -8,11 +8,10 @@ import kotlin.math.log2 /* todo simplify expression terms: - X*Y - X -> X*(Y-1) - X*Y - Y -> Y*(X-1) - -X + A -> A - X - X+ (-A) -> X - A - X- (-A) -> X + A + X*Y - X -> X*(Y-1) ??? + Y*X - X -> X*(Y-1) ??? + + value X --> X value <<<<< should be done already todo expression optimization: common (sub) expression elimination (turn common expressions into single subroutine call + introduce variable to hold it) @@ -28,6 +27,15 @@ class SimplifyExpressions(private val namespace: INameScope, private val heap: H return super.process(assignment) } + override fun process(expr: PrefixExpression): IExpression { + if(expr.operator == "+") { + // +X --> X + optimizationsDone++ + return expr.expression.process(this) + } + return super.process(expr) + } + override fun process(expr: BinaryExpression): IExpression { super.process(expr) val leftVal = expr.left.constValue(namespace, heap) @@ -45,6 +53,74 @@ class SimplifyExpressions(private val namespace: INameScope, private val heap: H } } + // Value X --> X Value + if(leftVal!=null && expr.operator in associativeOperators && rightVal==null) { + val tmp = expr.left + expr.left = expr.right + expr.right = tmp + optimizationsDone++ + return expr + } + + // X + (-A) --> X - A + if(expr.operator=="+" && (expr.right as? PrefixExpression)?.operator=="-") { + expr.operator = "-" + expr.right = (expr.right as PrefixExpression).expression + optimizationsDone++ + return expr + } + + // (-A) + X --> X - A + if(expr.operator=="+" && (expr.left as? PrefixExpression)?.operator=="-") { + expr.operator = "-" + val newRight = (expr.left as PrefixExpression).expression + expr.left = expr.right + expr.right = newRight + optimizationsDone++ + return expr + } + + // X + (-value) --> X - value + if(expr.operator=="+" && rightVal!=null) { + val rv = rightVal.asNumericValue?.toDouble() + if(rv!=null && rv<0.0) { + expr.operator = "-" + expr.right = LiteralValue.fromNumber(-rv, rightVal.type, rightVal.position) + optimizationsDone++ + return expr + } + } + + // (-value) + X --> X - value + if(expr.operator=="+" && leftVal!=null) { + val lv = leftVal.asNumericValue?.toDouble() + if(lv!=null && lv<0.0) { + expr.operator = "-" + expr.right = LiteralValue.fromNumber(-lv, leftVal.type, leftVal.position) + optimizationsDone++ + return expr + } + } + + // X - (-A) --> X + A + if(expr.operator=="-" && (expr.right as? PrefixExpression)?.operator=="-") { + expr.operator = "+" + expr.right = (expr.right as PrefixExpression).expression + optimizationsDone++ + return expr + } + + // X - (-value) --> X + value + if(expr.operator=="-" && rightVal!=null) { + val rv = rightVal.asNumericValue?.toDouble() + if(rv!=null && rv<0.0) { + expr.operator = "+" + expr.right = LiteralValue.fromNumber(-rv, rightVal.type, rightVal.position) + optimizationsDone++ + return expr + } + } + // simplify when a term is constant and determines the outcome when(expr.operator) { "or" -> { @@ -204,6 +280,8 @@ class SimplifyExpressions(private val namespace: INameScope, private val heap: H } } + + // todo: get rid of this? private data class ReorderedAssociativeBinaryExpr(val expr: BinaryExpression, val leftVal: LiteralValue?, val rightVal: LiteralValue?) private fun reorderAssociative(expr: BinaryExpression, leftVal: LiteralValue?): ReorderedAssociativeBinaryExpr { diff --git a/compiler/src/prog8/optimizing/StatementOptimizer.kt b/compiler/src/prog8/optimizing/StatementOptimizer.kt index 4a2462cfb..f2e6250d1 100644 --- a/compiler/src/prog8/optimizing/StatementOptimizer.kt +++ b/compiler/src/prog8/optimizing/StatementOptimizer.kt @@ -183,32 +183,37 @@ class StatementOptimizer(private val namespace: INameScope, private val heap: He // remove assignments that have no effect X=X , X+=0, X-=0, X*=1, X/=1, X//=1, A |= 0, A ^= 0, A<<=0, etc etc // A = A B + val vardeclDt = (target.identifier?.targetStatement(namespace) as? VarDecl)?.type when (bexpr.operator) { "+" -> { if (cv == 0.0) { optimizationsDone++ return NopStatement(assignment.position) - } else if (cv in 1.0..8.0 && targetDt in IntegerDatatypes && floor(cv) == cv) { - // replace by several INCs - val decs = AnonymousScope(mutableListOf(), assignment.position) - repeat(cv.toInt()) { - decs.statements.add(PostIncrDecr(target, "++", assignment.position)) + } else if (targetDt in IntegerDatatypes && floor(cv) == cv) { + if((vardeclDt == VarDeclType.MEMORY && cv in 1.0..3.0) || (vardeclDt!=VarDeclType.MEMORY && cv in 1.0..8.0)) { + // replace by several INCs (a bit less when dealing with memory targets) + val decs = AnonymousScope(mutableListOf(), assignment.position) + repeat(cv.toInt()) { + decs.statements.add(PostIncrDecr(target, "++", assignment.position)) + } + return decs } - return decs } } "-" -> { if (cv == 0.0) { optimizationsDone++ return NopStatement(assignment.position) - } else if (cv in 1.0..8.0 && targetDt in IntegerDatatypes && floor(cv) == cv) { - // replace by several DECs - val decs = AnonymousScope(mutableListOf(), assignment.position) - repeat(cv.toInt()) { - decs.statements.add(PostIncrDecr(target, "--", assignment.position)) + } else if (targetDt in IntegerDatatypes && floor(cv) == cv) { + if((vardeclDt == VarDeclType.MEMORY && cv in 1.0..3.0) || (vardeclDt!=VarDeclType.MEMORY && cv in 1.0..8.0)) { + // replace by several DECs (a bit less when dealing with memory targets) + val decs = AnonymousScope(mutableListOf(), assignment.position) + repeat(cv.toInt()) { + decs.statements.add(PostIncrDecr(target, "--", assignment.position)) + } + return decs } - return decs } } "*" -> if (cv == 1.0) { diff --git a/examples/test.p8 b/examples/test.p8 index 26d8cfe44..ec9b58f97 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -16,14 +16,20 @@ float f1 = 1.1 float f2 = 2.2 - i %= 1 - i %= 2 - ub2 = i % 1 - ub2 = i % 2 + b2 = j + (-1) + b2 = (-1) + j + b2 = j - (-1) + b2 = (-1) -j ; should not be reordered + b2 = j+1 + b2 = 1+j + b2 = 1-j ; should not be reordered - uw %= 1 - uw %= 2 - uw2 = uw % 1 - uw2 = uw % 2 + j = j + (-1) + j = (-1) + j + j = j - (-1) + j = (-1) -j ; should not be reordered + j = j+1 + j = 1+j + j = 1-j ; should not be reordered } }