preparing optimizations for if statements

This commit is contained in:
Irmen de Jong 2021-04-12 03:34:58 +02:00
parent 0a03c46351
commit 319ac3a641
5 changed files with 43 additions and 2 deletions

View File

@ -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<IAstModification>()
// 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<VarDecl, Boolean, Assignment> {
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<IAstModification> {

View File

@ -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) {

View File

@ -931,6 +931,10 @@ internal class AsmGen(private val program: Program,
checkBooleanExpression(stmt.condition) // we require the condition to be of the form 'x <comparison> <value>'
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")

View File

@ -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 {

View File

@ -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 <left> <op> <right> {..} into:
if_eval_left = left