From 319ac3a64105defed1f824f3ad7e12c6901ec1b8 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Mon, 12 Apr 2021 03:34:58 +0200 Subject: [PATCH] preparing optimizations for if statements --- .../compiler/BeforeAsmGenerationAstChanger.kt | 31 +++++++++++++++++++ .../compiler/astprocessing/AstExtensions.kt | 4 ++- .../compiler/target/cpu6502/codegen/AsmGen.kt | 4 +++ .../prog8/ast/expressions/AstExpressions.kt | 2 +- docs/source/todo.rst | 4 +++ 5 files changed, 43 insertions(+), 2 deletions(-) diff --git a/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt b/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt index 88fe2f48c..b594813b8 100644 --- a/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt +++ b/compiler/src/prog8/compiler/BeforeAsmGenerationAstChanger.kt @@ -1,6 +1,7 @@ package prog8.compiler import prog8.ast.IFunctionCall +import prog8.ast.INameScope import prog8.ast.Node import prog8.ast.Program import prog8.ast.base.* @@ -183,7 +184,37 @@ internal class BeforeAsmGenerationAstChanger(val program: Program, val errors: I val booleanExpr = BinaryExpression(ifStatement.condition, "!=", NumericLiteralValue.optimalInteger(0, ifStatement.condition.position), ifStatement.condition.position) return listOf(IAstModification.ReplaceNode(ifStatement.condition, booleanExpr, ifStatement)) } + return noModifications + // TODO split the conditional expression into separate variables if the operand(s) is not simple. +// val modifications = mutableListOf() +// if(!binExpr.left.isSimple) { +// val sub = binExpr.definingSubroutine()!! +// val (variable, isNew, assignment) = addIfOperandVar(sub, "left", binExpr.left) +// if(isNew) +// modifications.add(IAstModification.InsertFirst(variable, sub)) +// modifications.add(IAstModification.InsertBefore(ifStatement, assignment, parent as INameScope)) +// modifications.add(IAstModification.ReplaceNode(binExpr.left, IdentifierReference(listOf(variable.name), binExpr.position), binExpr)) +// } +// if(!binExpr.right.isSimple) { +// val sub = binExpr.definingSubroutine()!! +// val (variable, isNew, assignment) = addIfOperandVar(sub, "right", binExpr.right) +// if(isNew) +// modifications.add(IAstModification.InsertFirst(variable, sub)) +// modifications.add(IAstModification.InsertBefore(ifStatement, assignment, parent as INameScope)) +// modifications.add(IAstModification.ReplaceNode(binExpr.right, IdentifierReference(listOf(variable.name), binExpr.position), binExpr)) +// } +// return modifications + } + + private fun addIfOperandVar(sub: Subroutine, side: String, operand: Expression): Triple { + val dt = operand.inferType(program).typeOrElse(DataType.STRUCT) + val varname = "prog8_ifvar_${side}_${dt.name.toLowerCase()}" + // TODO check occurrence in sub + val vardecl = VarDecl(VarDeclType.VAR, dt, ZeropageWish.DONTCARE, null, varname, null, null, false, true, operand.position) + val tgt = AssignTarget(IdentifierReference(listOf(varname), operand.position), null, null, operand.position) + val assign = Assignment(tgt, operand, operand.position) + return Triple(vardecl, true, assign) } override fun after(untilLoop: UntilLoop, parent: Node): Iterable { diff --git a/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt b/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt index 04326b272..624e409e1 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstExtensions.kt @@ -17,7 +17,9 @@ internal fun Program.checkValid(compilerOptions: CompilationOptions, errors: IEr internal fun Program.processAstBeforeAsmGeneration(errors: IErrorReporter, compTarget: ICompilationTarget) { val fixer = BeforeAsmGenerationAstChanger(this, errors, compTarget) fixer.visit(this) - fixer.applyModifications() + while(errors.noErrors() && fixer.applyModifications()>0) { + fixer.visit(this) + } } internal fun Program.reorderStatements(errors: IErrorReporter) { diff --git a/compiler/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt b/compiler/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt index 64994b5c7..b991c3c85 100644 --- a/compiler/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt @@ -931,6 +931,10 @@ internal class AsmGen(private val program: Program, checkBooleanExpression(stmt.condition) // we require the condition to be of the form 'x ' val booleanCondition = stmt.condition as BinaryExpression + // TODO check this: +// if(!booleanCondition.left.isSimple || !booleanCondition.right.isSimple) +// throw AssemblyError("both operands for if comparison expression should have been simplified") + if (stmt.elsepart.containsNoCodeNorVars()) { // empty else val endLabel = makeLabel("if_end") diff --git a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt index 9f38edd60..82fa11d1b 100644 --- a/compilerAst/src/prog8/ast/expressions/AstExpressions.kt +++ b/compilerAst/src/prog8/ast/expressions/AstExpressions.kt @@ -247,7 +247,7 @@ class ArrayIndexedExpression(var arrayvar: IdentifierReference, indexer.linkParents(this) } - override val isSimple = false + override val isSimple = indexer.indexExpr is NumericLiteralValue || indexer.indexExpr is IdentifierReference override fun replaceChildNode(node: Node, replacement: Node) { when { diff --git a/docs/source/todo.rst b/docs/source/todo.rst index bcc46287d..823238bc5 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,6 +1,10 @@ ==== TODO ==== + +- fix: cube3d is suddenly way bigger than it was a few changes ago + + - make sure that in if statements, the left and right operand of the comparison is never a complex expression anymore (only number, variable, addressof or memread) by rewriting if {..} into: if_eval_left = left