add optimization: replace simple for loops by repeat loop

This commit is contained in:
Irmen de Jong 2023-03-15 21:11:37 +01:00
parent af1b07ad44
commit 1152191f48
4 changed files with 32 additions and 5 deletions

View File

@ -166,6 +166,16 @@ class StatementOptimizer(private val program: Program,
}
}
val iterationCount = forLoop.constIterationCount(program)
if(iterationCount!=null) {
val loopName = forLoop.loopVar.nameInSource
if(!forLoop.iterable.referencesIdentifier(loopName) && !forLoop.body.referencesIdentifier(loopName)) {
errors.warn("for loop can be replaced with repeat loop, possibly also remove the loop variable", forLoop.position)
val repeat = RepeatLoop(NumericLiteral.optimalNumeric(iterationCount, forLoop.position), forLoop.body, forLoop.position)
return listOf(IAstModification.ReplaceNode(forLoop, repeat, parent))
}
}
return noModifications
}

View File

@ -125,8 +125,8 @@ class UnusedCodeRemover(private val program: Program,
if(usages.size==1) {
val singleUse = usages[0].parent
if(singleUse is AssignTarget) {
val assignment = singleUse.parent as Assignment
if(assignment.origin==AssignmentOrigin.VARINIT) {
val assignment = singleUse.parent as? Assignment
if(assignment!=null && assignment.origin==AssignmentOrigin.VARINIT) {
if(assignment.value.isSimple) {
// remove the vardecl
if(!decl.definingModule.isLibrary)

View File

@ -863,6 +863,26 @@ class ForLoop(var loopVar: IdentifierReference,
body.referencesIdentifier(nameInSource)
fun loopVarDt(program: Program) = loopVar.inferType(program)
fun constIterationCount(program: Program): Int? {
return when (val iter = iterable) {
is IdentifierReference -> {
val target = iter.targetVarDecl(program)!!
if (target.isArray)
target.arraysize!!.constIndex()
else if (target.value is StringLiteral)
(target.value as StringLiteral).value.length
else if (target.value is ArrayLiteral)
(target.value as ArrayLiteral).value.size
else null
}
is ArrayLiteral -> iter.value.size
is RangeExpression -> iter.size()
is StringLiteral -> iter.value.length
else -> null
}
}
}
class WhileLoop(var condition: Expression,

View File

@ -3,9 +3,6 @@ TODO
For next minor release
^^^^^^^^^^^^^^^^^^^^^^
- when a loopvariable of a forloop is *only* referenced in the for loop as loopvariable, and the number of iterations is known, replace the loop by a repeatloop (and remove the vardecl)
but we have no efficient way right now to see if the body references a variable. (what about ReferencesIdentifier?)
...