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

Byte comparison optimizations

This commit is contained in:
Karol Stasiak 2019-10-01 00:45:14 +02:00
parent ae1dd6326c
commit f7dd78e4c0
3 changed files with 87 additions and 3 deletions

View File

@ -446,6 +446,21 @@ object BuiltIns {
}
case _ =>
}
(maybeConstant, compType) match {
case (Some(NumericConstant(0, _)), ComparisonType.GreaterUnsigned) =>
return compileByteComparison(ctx, ComparisonType.NotEqual, lhs, rhs, branches)
case (Some(NumericConstant(0, _)), ComparisonType.LessOrEqualUnsigned) =>
return compileByteComparison(ctx, ComparisonType.Equal, lhs, rhs, branches)
case (Some(NumericConstant(1, _)), ComparisonType.LessUnsigned) =>
return compileByteComparison(ctx, ComparisonType.Equal, lhs, rhs #-# 1, branches)
case (Some(NumericConstant(1, _)), ComparisonType.GreaterOrEqualUnsigned) =>
return compileByteComparison(ctx, ComparisonType.NotEqual, lhs, rhs #-# 1, branches)
case (Some(NumericConstant(n, 1)), ComparisonType.GreaterUnsigned) if n >= 1 && n <= 254 =>
return compileByteComparison(ctx, ComparisonType.GreaterOrEqualUnsigned, lhs, rhs #+# 1, branches)
case (Some(NumericConstant(n, 1)), ComparisonType.LessOrEqualUnsigned) if n >= 1 && n <= 254 =>
return compileByteComparison(ctx, ComparisonType.LessUnsigned, lhs, rhs #+# 1, branches)
case _ =>
}
val cmpOp = if (ComparisonType.isSigned(compType)) SBC else CMP
var comparingAgainstZero = false
val secondParamCompiled0 = maybeConstant match {

View File

@ -21,19 +21,36 @@ object Z80Comparisons {
FunctionCallExpression("^", List(r, LiteralExpression(0x80, 1).pos(r.position))).pos(r.position),
branches)
}
(ctx.env.eval(r), compType) match {
case (Some(NumericConstant(0, _)), GreaterUnsigned) =>
return compile8BitComparison(ctx, ComparisonType.NotEqual, l, r, branches)
case (Some(NumericConstant(0, _)), LessOrEqualUnsigned) =>
return compile8BitComparison(ctx, ComparisonType.Equal, l, r, branches)
case (Some(NumericConstant(1, _)), ComparisonType.LessUnsigned) =>
return compile8BitComparison(ctx, ComparisonType.Equal, l, r #-# 1, branches)
case (Some(NumericConstant(1, _)), ComparisonType.GreaterOrEqualUnsigned) =>
return compile8BitComparison(ctx, ComparisonType.NotEqual, l, r #-# 1, branches)
case (Some(NumericConstant(n, 1)), ComparisonType.GreaterUnsigned) if n >= 1 && n <= 254 =>
return compile8BitComparison(ctx, ComparisonType.GreaterOrEqualUnsigned, l, r #+# 1, branches)
case (Some(NumericConstant(n, 1)), ComparisonType.LessOrEqualUnsigned) if n >= 1 && n <= 254 =>
return compile8BitComparison(ctx, ComparisonType.LessUnsigned, l, r #+# 1, branches)
case _ =>
}
compType match {
case GreaterUnsigned | LessOrEqualUnsigned | GreaterSigned | LessOrEqualSigned =>
return compile8BitComparison(ctx, ComparisonType.flip(compType), r, l, branches)
case _ => ()
}
val prepareAE = Z80ExpressionCompiler.compileToA(ctx, r) match {
var prepareAE = Z80ExpressionCompiler.compileToA(ctx, r) match {
case List(ZLine0(ZOpcode.LD, TwoRegisters(ZRegister.A, ZRegister.IMM_8), param)) =>
Z80ExpressionCompiler.compileToA(ctx, l) :+ ZLine.ldImm8(ZRegister.E, param)
case compiledR => compiledR ++
List(ZLine.ld8(ZRegister.E, ZRegister.A)) ++
Z80ExpressionCompiler.stashDEIfChanged(ctx, Z80ExpressionCompiler.compileToA(ctx, l))
}
val calculateFlags = if (ComparisonType.isSigned(compType) && ctx.options.flag(CompilationFlag.EmitZ80Opcodes)) {
var calculateFlags = if (ComparisonType.isSigned(compType) && ctx.options.flag(CompilationFlag.EmitZ80Opcodes)) {
val fixup = ctx.nextLabel("co")
List(
ZLine.register(ZOpcode.SUB, ZRegister.E),
@ -43,6 +60,17 @@ object Z80Comparisons {
} else if (ComparisonType.isSigned(compType) && !ctx.options.flag(CompilationFlag.EmitZ80Opcodes)) {
List(ZLine.register(ZOpcode.SUB, ZRegister.E))
} else List(ZLine.register(ZOpcode.CP, ZRegister.E))
(prepareAE.last, calculateFlags.head) match {
case (
ZLine0(ZOpcode.LD, TwoRegisters(ZRegister.E, ZRegister.IMM_8), c),
ZLine0(op, OneRegister(ZRegister.E), _)
) =>
prepareAE = prepareAE.init
calculateFlags = ZLine.imm8(op, c) :: calculateFlags.tail
case _ =>
}
if (branches == NoBranching) return prepareAE ++ calculateFlags
val (effectiveCompType, label) = branches match {
case BranchIfFalse(la) => ComparisonType.negate(compType) -> la

View File

@ -1,7 +1,7 @@
package millfork.test
import millfork.Cpu
import millfork.test.emu.{EmuBenchmarkRun, EmuCrossPlatformBenchmarkRun, EmuSuperOptimizedRun, EmuUltraBenchmarkRun}
import millfork.test.emu.{EmuBenchmarkRun, EmuCrossPlatformBenchmarkRun, EmuSuperOptimizedRun, EmuUltraBenchmarkRun, EmuUnoptimizedCrossPlatformRun}
import org.scalatest.{FunSuite, Matchers}
/**
@ -540,4 +540,45 @@ class ComparisonSuite extends FunSuite with Matchers {
|""".stripMargin
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Sixteen, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp)(code) {m => m.readByte(0xc000) should equal (code.count(_ == '↑'))}
}
test("Comparison optimization") {
val code =
"""
| noinline byte one() = 1
| noinline byte ten() = 10
| noinline byte ff() = $ff
| noinline byte zero() = 0
| byte output @$c000
| void main() {
| output = 0
| if zero() >= 0 { output += 1 } //
| if zero() <= 0 { output += 1 } //
| if one() > 0 { output += 1 } //
| if one() >= 0 { output += 1 } //
| if ten() > 0 { output += 1 } //
|
| if ten() <= $ff { output += 1 } //
| if ten() < $ff { output += 1 } //
| if ff() >= $ff { output += 1 } //
|
| if one() >= 1 { output += 1 } //
| if one() <= 1 { output += 1 } //
| if ten() >= 1 { output += 1 } //
| if ten() > 1 { output += 1 } //
| if zero() < 1 { output += 1 } //
| if zero() <= 1 { output += 1 } //
|
| if one() < 10 { output += 1 } //
| if one() <= 10 { output += 1 } //
| if ten() <= 10 { output += 1 } //
| if ten() >= 10 { output += 1 } //
| if ff() > 10 { output += 1 } //
| if ff() >= 10 { output += 1 } //
| }
|""".stripMargin
EmuUnoptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80)(code) { m =>
m.readByte(0xc000) should equal(code.count(_ == '↑'))
}
}
}