optimize for loop over 1-valued range

This commit is contained in:
Irmen de Jong 2018-09-25 20:40:41 +02:00
parent 53cd50ad48
commit a2c165839d
4 changed files with 20 additions and 2 deletions

View File

@ -333,6 +333,10 @@ class AnonymousStatementList(override var parent: Node,
var statements: List<IStatement>,
override val position: Position) : IStatement {
init {
linkParents(parent)
}
override fun linkParents(parent: Node) {
this.parent = parent
statements.forEach { it.linkParents(this) }

View File

@ -438,7 +438,7 @@ class AstChecker(private val namespace: INameScope, private val compilerOptions:
when {
from.asIntegerValue!=null && to.asIntegerValue!=null -> {
if(from.asIntegerValue == to.asIntegerValue)
err("range is just a single value - don't use a loop here, use an assignment") // TODO optimize this away automatically in the statement optimizer
printWarning("range is just a single value, don't use a loop here", range.position)
else if(from.asIntegerValue < to.asIntegerValue && step<=0)
err("ascending range requires step > 0")
else if(from.asIntegerValue > to.asIntegerValue && step>=0)

View File

@ -54,7 +54,6 @@ import prog8.ast.INameScope
todo expression optimization: remove redundant builtin function calls
todo expression optimization: reduce expression nesting / flattening of parenthesis
todo expression optimization: simplify logical expression when a term makes it always true or false (1 or 0)
todo expression optimization: optimize some simple multiplications into shifts (A*8 -> A<<3, A/4 -> A>>2)
todo optimize addition with self into shift 1 (A+=A -> A<<=1)

View File

@ -75,6 +75,21 @@ class StatementOptimizer(private val globalNamespace: INameScope) : IAstProcesso
return ifStatement
}
override fun process(forLoop: ForLoop): IStatement {
super.process(forLoop)
val range = forLoop.iterable as? RangeExpr
if(range!=null) {
if(range.size()==1) {
// for loop over a (constant) range of just a single value-- optimize the loop away
// loopvar/reg = range value , follow by block
val assignment = Assignment(AssignTarget(forLoop.loopRegister, forLoop.loopVar, forLoop.position), null, range.from, forLoop.position)
forLoop.body.add(0, assignment)
return AnonymousStatementList(forLoop.parent, forLoop.body, forLoop.position)
}
}
return forLoop
}
override fun process(whileLoop: WhileLoop): IStatement {
super.process(whileLoop)
val constvalue = whileLoop.condition.constValue(globalNamespace)