From 2ee2de62cdd68f11f8fe49be610173681c2ff898 Mon Sep 17 00:00:00 2001 From: Karol Stasiak Date: Fri, 24 Jul 2020 22:25:21 +0200 Subject: [PATCH] =?UTF-8?q?Don't=20optimize=20accesses=20to=20arrays=20of?= =?UTF-8?q?=20size=200=20and=201=20=E2=80=93=20assume=20that=20overruns=20?= =?UTF-8?q?are=20deliberate.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AbstractStatementPreprocessor.scala | 18 +++++++++++------- .../m6809/M6809ExpressionCompiler.scala | 3 ++- .../compiler/mos/MosExpressionCompiler.scala | 5 ++++- .../compiler/z80/Z80ExpressionCompiler.scala | 4 ++-- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/main/scala/millfork/compiler/AbstractStatementPreprocessor.scala b/src/main/scala/millfork/compiler/AbstractStatementPreprocessor.scala index 95343860..002d6d2f 100644 --- a/src/main/scala/millfork/compiler/AbstractStatementPreprocessor.scala +++ b/src/main/scala/millfork/compiler/AbstractStatementPreprocessor.scala @@ -437,18 +437,20 @@ abstract class AbstractStatementPreprocessor(protected val ctx: CompilationConte val shrunkElementSize = targetType.alignedSize >> shifts val shrunkArraySize = arraySizeInBytes.fold(9999)(_.>>(shifts)) val scaledIndex = arraySizeInBytes match { - case Some(n) if n <= 256 => targetType.alignedSize match { + // "n > targetType.alignedSize" means + // "don't do optimizations on arrays size 0 or 1" + case Some(n) if n > targetType.alignedSize && n <= 256 => targetType.alignedSize match { case 1 => "byte" <| index case 2 => "<<" <| ("byte" <| index, LiteralExpression(1, 1)) case 4 => "<<" <| ("byte" <| index, LiteralExpression(2, 1)) case 8 => "<<" <| ("byte" <| index, LiteralExpression(3, 1)) case _ => "*" <| ("byte" <| index, LiteralExpression(targetType.alignedSize, 1)) } - case Some(n) if n <= 512 && targetType.alignedSize == 2 => + case Some(n) if n > targetType.alignedSize && n <= 512 && targetType.alignedSize == 2 => "nonet" <| ("<<" <| ("byte" <| index, LiteralExpression(1, 1))) - case Some(n) if n <= 512 && targetType.alignedSize == 2 => + case Some(n) if n > targetType.alignedSize && n <= 512 && targetType.alignedSize == 2 => "nonet" <| ("<<" <| ("byte" <| index, LiteralExpression(1, 1))) - case Some(_) if shrunkArraySize <= 256 => + case Some(n) if n > targetType.alignedSize && shrunkArraySize <= 256 => "<<" <| ("word" <| ("*" <| ("byte" <| index, LiteralExpression(shrunkElementSize, 1))), LiteralExpression(shifts, 1)) case _ => targetType.alignedSize match { case 1 => "word" <| index @@ -668,16 +670,18 @@ abstract class AbstractStatementPreprocessor(protected val ctx: CompilationConte val shrunkElementSize = targetType.alignedSize >> shifts val shrunkArraySize = arraySizeInBytes.fold(9999)(_.>>(shifts)) val scaledIndex = arraySizeInBytes match { - case Some(n) if n <= 256 => targetType.alignedSize match { + // "n > targetType.alignedSize" means + // "don't do optimizations on arrays size 0 or 1" + case Some(n) if n > targetType.alignedSize && n <= 256 => targetType.alignedSize match { case 1 => "byte" <| index case 2 => "<<" <| ("byte" <| index, LiteralExpression(1, 1)) case 4 => "<<" <| ("byte" <| index, LiteralExpression(2, 1)) case 8 => "<<" <| ("byte" <| index, LiteralExpression(3, 1)) case _ => "*" <| ("byte" <| index, LiteralExpression(targetType.alignedSize, 1)) } - case Some(n) if n <= 512 && targetType.alignedSize == 2 => + case Some(n) if n > targetType.alignedSize && n <= 512 && targetType.alignedSize == 2 => "nonet" <| ("<<" <| ("byte" <| index, LiteralExpression(1, 1))) - case Some(_) if shrunkArraySize <= 256 => + case Some(n) if n > targetType.alignedSize && shrunkArraySize <= 256 => "<<" <| ("word" <| ("*" <| ("byte" <| index, LiteralExpression(shrunkElementSize, 1))), LiteralExpression(shifts, 1)) case _ => targetType.alignedSize match { case 1 => "word" <| index diff --git a/src/main/scala/millfork/compiler/m6809/M6809ExpressionCompiler.scala b/src/main/scala/millfork/compiler/m6809/M6809ExpressionCompiler.scala index 919061b1..0f4fe48e 100644 --- a/src/main/scala/millfork/compiler/m6809/M6809ExpressionCompiler.scala +++ b/src/main/scala/millfork/compiler/m6809/M6809ExpressionCompiler.scala @@ -829,7 +829,8 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] { ctx.env.getPointy(aname) match { case p: VariablePointy => compileToD(ctx, index #*# p.elementType.alignedSize) ++ List(MLine.absolute(ADDD, p.addr), MLine.tfr(M6809Register.D, M6809Register.X)) case p: ConstantPointy => - if (p.sizeInBytes.exists(_ < 255)) { + // don't optimize arrays of size 0 or 1 + if (p.sizeInBytes.exists(_ < 255) && p.elementCount.forall(_ > 1)) { compileToB(ctx, index #*# p.elementType.alignedSize) ++ List(MLine.immediate(LDX, p.value), MLine.inherent(ABX)) } else { compileToX(ctx, index #*# p.elementType.alignedSize) :+ MLine.indexedX(LEAX, p.value) diff --git a/src/main/scala/millfork/compiler/mos/MosExpressionCompiler.scala b/src/main/scala/millfork/compiler/mos/MosExpressionCompiler.scala index be193048..f994b338 100644 --- a/src/main/scala/millfork/compiler/mos/MosExpressionCompiler.scala +++ b/src/main/scala/millfork/compiler/mos/MosExpressionCompiler.scala @@ -2381,7 +2381,10 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] { case _: VariablePointy => return Nil case p: ConstantPointy => p.sizeInBytes match { case None => return Nil - case Some(s) => s + case Some(s) => + // don't do checks on arrays size 0 or 1 + if (p.elementCount.exists(_ < 2)) return Nil + s } } ctx.env.eval(index) match { diff --git a/src/main/scala/millfork/compiler/z80/Z80ExpressionCompiler.scala b/src/main/scala/millfork/compiler/z80/Z80ExpressionCompiler.scala index 0eabed54..c8246772 100644 --- a/src/main/scala/millfork/compiler/z80/Z80ExpressionCompiler.scala +++ b/src/main/scala/millfork/compiler/z80/Z80ExpressionCompiler.scala @@ -1404,7 +1404,7 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] { 0 } pointy match { - case ConstantPointy(baseAddr, _, sizeInBytes, _, _, _, alignment, readOnly) => + case ConstantPointy(baseAddr, _, sizeInBytes, elementCount, _, _, alignment, readOnly) => if (forWriting && readOnly) { ctx.log.error("Writing to a constant array", i.position) } @@ -1412,7 +1412,7 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] { case (None, offset) => List(ZLine.ldImm16(ZRegister.HL, (baseAddr + extraOffset + offset * elementSize).quickSimplify)) case (Some(index), offset) => val constantPart = (baseAddr + extraOffset + offset * elementSize).quickSimplify - if (getExpressionType(ctx, i.index).size == 1 && sizeInBytes.exists(_ < 256) && alignment == WithinPageAlignment) { + if (getExpressionType(ctx, i.index).size == 1 && sizeInBytes.exists(_ < 256) && elementCount.forall(_ > 1) && alignment == WithinPageAlignment) { compileToA(ctx, i.index) ++ List.fill(logElemSize)(ZLine.register(ADD, ZRegister.A)) ++ List( ZLine.imm8(ADD, constantPart.loByte), ZLine.ld8(ZRegister.L, ZRegister.A),