1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-06-12 06:29:34 +00:00

Better detection of memset loops (fixes #59)

This commit is contained in:
Karol Stasiak 2020-09-20 23:39:30 +02:00
parent fe094af912
commit a92f24b280
4 changed files with 14 additions and 11 deletions

View File

@ -231,8 +231,8 @@ abstract class AbstractStatementPreprocessor(protected val ctx: CompilationConte
!env.overlapsVariable(f.variable, source) &&
!env.overlapsVariable(f.variable, f.start) &&
!env.overlapsVariable(f.variable, f.end) &&
source.isPure &&
sourceType.size == 1 &&
ctx.isConstant(source) &&
sourceType.size <= 1 &&
targetType.size == 1 &&
sourceType.isAssignableTo(targetType)
) {
@ -738,9 +738,9 @@ object AbstractStatementPreprocessor {
val sourceType = AbstractExpressionCompiler.getExpressionType(ctx, source)
val targetType = AbstractExpressionCompiler.getExpressionType(ctx, target)
if (
source.isPure &&
index.isPure &&
sourceType.size == 1 &&
ctx.isConstant(source) &&
ctx.isConstant(index) &&
sourceType.size <= 1 &&
targetType.size == 1 &&
sourceType.isAssignableTo(targetType)&&
!env.isVolatile(VariableExpression(pointy)) &&

View File

@ -2,7 +2,7 @@ package millfork.compiler
import millfork.env.{Environment, Label, NormalFunction, NormalParamSignature}
import millfork.error.Logger
import millfork.node.NiceFunctionProperty
import millfork.node.{Expression, NiceFunctionProperty}
import millfork.{CompilationFlag, CompilationOptions, JobContext}
/**
@ -15,6 +15,9 @@ case class CompilationContext(env: Environment,
niceFunctionProperties: Set[(NiceFunctionProperty, String)],
breakLabels: Map[String, Label] = Map(),
continueLabels: Map[String, Label] = Map()){
def isConstant(v: Expression): Boolean = v.isPure || env.eval(v).isDefined
def withInlinedEnv(environment: Environment, newLabel: String): CompilationContext = {
val newEnv = new Environment(Some(env), newLabel, environment.cpuFamily, options)
newEnv.things ++= environment.things

View File

@ -1292,7 +1292,7 @@ object BuiltIns {
def compileByteMultiplication(ctx: CompilationContext, v: Expression, c: Int): List[AssemblyLine] = {
c match {
case 0 =>
if (v.isPure) return List(AssemblyLine.immediate(LDA, 0))
if (ctx.isConstant(v)) return List(AssemblyLine.immediate(LDA, 0))
else return MosExpressionCompiler.compileToA(ctx, v) ++ List(AssemblyLine.immediate(LDA, 0))
case 1 => return MosExpressionCompiler.compileToA(ctx, v)
case 2 | 4 | 8 | 16 | 32 =>

View File

@ -21,7 +21,7 @@ object Z80BulkMemoryOperations {
*/
def compileMemcpy(ctx: CompilationContext, target: IndexedExpression, source: IndexedExpression, f: ForStatement): List[ZLine] = {
val sourceOffset = removeVariableOnce(ctx, f.variable, source.index).getOrElse(return compileForStatement(ctx, f)._1)
if (!sourceOffset.isPure) return compileForStatement(ctx, f)._1
if (!ctx.isConstant(sourceOffset)) return compileForStatement(ctx, f)._1
val sourceIndexExpression = sourceOffset #+# f.start
val calculateSource = Z80ExpressionCompiler.calculateAddressToHL(ctx, IndexedExpression(source.name, sourceIndexExpression).pos(source.position), forWriting = false)
compileMemoryBulk(ctx, target, f,
@ -85,11 +85,11 @@ object Z80BulkMemoryOperations {
if (ctx.options.flag(CompilationFlag.EmitZ80Opcodes)) {
removeVariableOnce(ctx, f.variable, target.index) match {
case Some(targetOffset) if targetOffset.isPure =>
case Some(targetOffset) if ctx.isConstant(targetOffset) =>
return compileForZ80(targetOffset)
case _ =>
}
if (target.isPure && target.name == f.variable && !ctx.env.overlapsVariable(f.variable, target.index)) {
if (ctx.isConstant(target) && target.name == f.variable && !ctx.env.overlapsVariable(f.variable, target.index)) {
return compileForZ80(target.index)
}
}
@ -437,7 +437,7 @@ object Z80BulkMemoryOperations {
val pointy = ctx.env.getPointy(target.name)
if (pointy.elementType.alignedSize > 1) return Z80StatementCompiler.compileForStatement(ctx, f)._1
val targetOffset = removeVariableOnce(ctx, f.variable, target.index).getOrElse(return compileForStatement(ctx, f)._1)
if (!targetOffset.isPure) return compileForStatement(ctx, f)._1
if (!ctx.isConstant(targetOffset)) return compileForStatement(ctx, f)._1
val indexVariableSize = ctx.env.get[Variable](f.variable).typ.size
val wrapper = createForLoopPreconditioningIfStatement(ctx, f)
val decreasingDespiteSyntax = preferDecreasing && (f.direction == ForDirection.ParallelTo || f.direction == ForDirection.ParallelUntil)