From 99d63b13a86aff5c4ad160a4f15eeb503d5bcf53 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Thu, 27 Sep 2018 20:38:06 +0200 Subject: [PATCH] slightly simplified const grouping --- .../src/prog8/optimizing/ConstantFolding.kt | 71 ++++++++----------- compiler/src/prog8/stackvm/StackVm.kt | 6 +- 2 files changed, 34 insertions(+), 43 deletions(-) diff --git a/compiler/src/prog8/optimizing/ConstantFolding.kt b/compiler/src/prog8/optimizing/ConstantFolding.kt index 9ef5e09c5..62af95b84 100644 --- a/compiler/src/prog8/optimizing/ConstantFolding.kt +++ b/compiler/src/prog8/optimizing/ConstantFolding.kt @@ -172,13 +172,13 @@ class ConstantFolding(private val namespace: INameScope) : IAstProcessor { * Compile-time constant sub expressions will be evaluated on the spot. * For instance, "9 * (4 + 2)" will be optimized into the integer literal 54. * - * More complex: dealing with associative operators: - * if our operator is +,-,*,/ THEN: - * if one of our operands is a const, THEN: - * if the other operand is also a binary expression THEN: - * if its operator is in the same group as our operator (+ and -, * and /) THEN: - * if one of its operands is a const THEN: - * reorder the expression by lifting out the calculation on the 2 consts. (so that it can be const-folded later) + * More complex stuff: reordering to group constants: + * If one of our operands is a Constant, + * and the other operand is a Binary expression, + * and one of ITS operands is a Constant, + * and ITS other operand is NOT a Constant, + * ...it may be possible to rewrite the expression to group the two Constants together, + * to allow them to be const-folded away. */ override fun process(expr: BinaryExpression): IExpression { return try { @@ -186,31 +186,20 @@ class ConstantFolding(private val namespace: INameScope) : IAstProcessor { val leftconst = expr.left.constValue(namespace) val rightconst = expr.right.constValue(namespace) - // check associative operators and const operands - if(setOf("+", "-", "*", "/").contains(expr.operator)) { - val subExpr: BinaryExpression? = when { - leftconst!=null -> expr.right as? BinaryExpression - rightconst!=null -> expr.left as? BinaryExpression - else -> null - } - if(subExpr!=null) { - val sameGroupOperator = - when (expr.operator) { - "+", "-" -> subExpr.operator == "+" || subExpr.operator == "-" - "*", "/" -> subExpr.operator == "*" || subExpr.operator == "/" - else -> false - } - if (sameGroupOperator) { - val subleftconst = subExpr.left.constValue(namespace) - val subrightconst = subExpr.right.constValue(namespace) - if (subleftconst != null || subrightconst != null) { - // reorder! - return reorderAssociativeConst(expr, subExpr, leftconst!=null, rightconst!=null, subleftconst!=null, subrightconst!=null) - } - } - } + val subExpr: BinaryExpression? = when { + leftconst!=null -> expr.right as? BinaryExpression + rightconst!=null -> expr.left as? BinaryExpression + else -> null + } + if(subExpr!=null) { + val subleftconst = subExpr.left.constValue(namespace) + val subrightconst = subExpr.right.constValue(namespace) + if ((subleftconst != null && subrightconst == null) || (subleftconst==null && subrightconst!=null)) + // try reordering. + return groupTwoConstsTogether(expr, subExpr, + leftconst!=null, rightconst!=null, + subleftconst!=null, subrightconst!=null) } - // const fold when both operands are a const val evaluator = ConstExprEvaluator() @@ -227,16 +216,17 @@ class ConstantFolding(private val namespace: INameScope) : IAstProcessor { } } - private fun reorderAssociativeConst(expr: BinaryExpression, - subExpr: BinaryExpression, - leftIsConst: Boolean, - rightIsConst: Boolean, - subleftIsConst: Boolean, - subrightIsConst: Boolean): IExpression { + private fun groupTwoConstsTogether(expr: BinaryExpression, + subExpr: BinaryExpression, + leftIsConst: Boolean, + rightIsConst: Boolean, + subleftIsConst: Boolean, + subrightIsConst: Boolean): IExpression + { + // @todo this implements only a small set of possible reorderings for now if(expr.operator==subExpr.operator) { // both operators are the same. - // If + or *, we can simply swap the const of expr and Var in subexpr. if(expr.operator=="+" || expr.operator=="*") { if(leftIsConst) { @@ -280,10 +270,11 @@ class ConstantFolding(private val namespace: INameScope) : IAstProcessor { return expr } - // todo: other combinations of operators and constants + // todo: other cases where both operators are identical return expr } else { - return expr // TODO reorder when operators are not identical + // todo: other combinations of operators and constants (with different operator in subexpr) + return expr } } diff --git a/compiler/src/prog8/stackvm/StackVm.kt b/compiler/src/prog8/stackvm/StackVm.kt index 891ec0d02..73a44065b 100644 --- a/compiler/src/prog8/stackvm/StackVm.kt +++ b/compiler/src/prog8/stackvm/StackVm.kt @@ -117,10 +117,10 @@ enum class Opcode { CLC, // clear carry status flag NOTE: is mostly fake, carry flag is not affected by any numeric operations SEI, // set irq-disable status flag CLI, // clear irq-disable status flag - NOP, + NOP, // do nothing BREAKPOINT, // breakpoint TERMINATE, // end the program - LINE // record source file line number + LINE // track source file line number } enum class Syscall(val callNr: Short) { @@ -162,7 +162,7 @@ enum class Syscall(val callNr: Short) { FUNC_RNDF(91), // push a random float on the stack (between 0.0 and 1.0) // note: not all builtin functions of the Prog8 language are present as functions: - // some of them are already opcodes (such as MSB, LSB, LSL, LSR, ROL, ROR, ROL2, ROR2, and FLT)! + // some of them are straight opcodes (such as MSB, LSB, LSL, LSR, ROL, ROR, ROL2, ROR2, and FLT)! } class Memory {