1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-11-18 22:07:07 +00:00

Faster comparisons to 0 and $FFFF

This commit is contained in:
Karol Stasiak 2018-12-26 02:05:41 +01:00
parent 9669e4d87d
commit 0bb662183c
3 changed files with 93 additions and 12 deletions

View File

@ -631,8 +631,27 @@ object BuiltIns {
} }
val lType = MosExpressionCompiler.getExpressionType(ctx, lhs) val lType = MosExpressionCompiler.getExpressionType(ctx, lhs)
val rType = MosExpressionCompiler.getExpressionType(ctx, rhs) val rType = MosExpressionCompiler.getExpressionType(ctx, rhs)
val compactEqualityComparison = if (ctx.options.flag(CompilationFlag.OptimizeForSpeed)) { def isConstant(h: List[AssemblyLine], l: List[AssemblyLine], value: Int): Boolean = {
(h,l) match {
case (
List(AssemblyLine0(CMP, Immediate, NumericConstant(vh, _))),
List(AssemblyLine0(CMP, Immediate, NumericConstant(vl, _)))
) if vh.&(0xff).<<(8) + vl.&(0xff) == value => true
case _ => false
}
}
val compactEqualityComparison =
if (isConstant(rh, rl, 0)) {
Some(cmpTo(LDA, ll) ++ cmpTo(ORA, lh))
} else if (isConstant(lh, ll, 0)) {
Some(cmpTo(LDA, rl) ++ cmpTo(ORA, rh))
} else if (ctx.options.flag(CompilationFlag.OptimizeForSpeed)) {
None None
} else if (isConstant(rh, rl, 0xffff)) {
Some(cmpTo(LDA, ll) ++ cmpTo(AND, lh) ++ List(AssemblyLine.immediate(CMP, 0xff)))
} else if (isConstant(lh, ll, 0xffff)) {
Some(cmpTo(LDA, rl) ++ cmpTo(AND, rh) ++ List(AssemblyLine.immediate(CMP, 0xff)))
} else if (lType.size == 1 && !lType.isSigned) { } else if (lType.size == 1 && !lType.isSigned) {
Some(cmpTo(LDA, ll) ++ cmpTo(EOR, rl) ++ cmpTo(ORA, rh)) Some(cmpTo(LDA, ll) ++ cmpTo(EOR, rl) ++ cmpTo(ORA, rh))
} else if (rType.size == 1 && !rType.isSigned) { } else if (rType.size == 1 && !rType.isSigned) {

View File

@ -123,8 +123,34 @@ object Z80Comparisons {
return compile16BitComparison(ctx, ComparisonType.flip(compType), r, l, branches) return compile16BitComparison(ctx, ComparisonType.flip(compType), r, l, branches)
case _ => () case _ => ()
} }
import ZRegister._
import ZOpcode._
val calculateLeft = Z80ExpressionCompiler.compileToHL(ctx, l) val calculateLeft = Z80ExpressionCompiler.compileToHL(ctx, l)
val calculateRight = Z80ExpressionCompiler.compileToHL(ctx, r) val calculateRight = Z80ExpressionCompiler.compileToHL(ctx, r)
val fastEqualityComparison: Option[List[ZLine]] = (calculateLeft, calculateRight) match {
case (List(ZLine0(LD_16, TwoRegisters(HL, IMM_16), NumericConstant(0, _))), _) =>
Some(calculateRight ++ List(ZLine.ld8(A, H), ZLine.register(OR, L)))
case (List(ZLine0(LD_16, TwoRegisters(HL, IMM_16), NumericConstant(0xffff, _))), _) =>
Some(calculateRight ++ List(ZLine.ld8(A, H), ZLine.register(AND, L), ZLine.imm8(CP, 0xff)))
case (_, List(ZLine0(LD_16, TwoRegisters(HL, IMM_16), NumericConstant(0, _)))) =>
Some(calculateLeft ++ List(ZLine.ld8(A, H), ZLine.register(OR, L)))
case (_, List(ZLine0(LD_16, TwoRegisters(HL, IMM_16), NumericConstant(0xffff, _)))) =>
Some(calculateLeft ++ List(ZLine.ld8(A, H), ZLine.register(AND, L), ZLine.imm8(CP, 0xff)))
case _ =>
None
}
fastEqualityComparison match {
case Some(code) =>
(compType, branches) match {
case (ComparisonType.Equal, BranchIfTrue(lbl)) => return code :+ ZLine.jumpR(ctx, lbl, IfFlagSet(ZFlag.Z))
case (ComparisonType.Equal, BranchIfFalse(lbl)) => return code :+ ZLine.jumpR(ctx, lbl, IfFlagClear(ZFlag.Z))
case (ComparisonType.NotEqual, BranchIfTrue(lbl)) => return code :+ ZLine.jumpR(ctx, lbl, IfFlagClear(ZFlag.Z))
case (ComparisonType.NotEqual, BranchIfFalse(lbl)) => return code :+ ZLine.jumpR(ctx, lbl, IfFlagSet(ZFlag.Z))
case _ =>
}
case _ =>
}
val (calculated, useBC) = if (calculateLeft.exists(Z80ExpressionCompiler.changesBC)) { val (calculated, useBC) = if (calculateLeft.exists(Z80ExpressionCompiler.changesBC)) {
if (calculateLeft.exists(Z80ExpressionCompiler.changesDE)) { if (calculateLeft.exists(Z80ExpressionCompiler.changesDE)) {
calculateRight ++ List(ZLine.register(ZOpcode.PUSH, ZRegister.HL)) ++ Z80ExpressionCompiler.fixTsx(ctx, calculateLeft) ++ List(ZLine.register(ZOpcode.POP, ZRegister.BC)) -> false calculateRight ++ List(ZLine.register(ZOpcode.PUSH, ZRegister.HL)) ++ Z80ExpressionCompiler.fixTsx(ctx, calculateLeft) ++ List(ZLine.register(ZOpcode.POP, ZRegister.BC)) -> false
@ -152,8 +178,6 @@ object Z80Comparisons {
} }
calculateFlags :+ jump calculateFlags :+ jump
} else if (compType == Equal || compType == NotEqual) { } else if (compType == Equal || compType == NotEqual) {
import ZRegister._
import ZOpcode._
val calculateFlags = calculated ++ List( val calculateFlags = calculated ++ List(
ZLine.ld8(A, L), ZLine.ld8(A, L),
ZLine.register(XOR, if (useBC) C else E), ZLine.register(XOR, if (useBC) C else E),
@ -169,8 +193,6 @@ object Z80Comparisons {
} }
calculateFlags :+ jump calculateFlags :+ jump
} else { } else {
import ZRegister._
import ZOpcode._
val calculateFlags = calculated ++ List( val calculateFlags = calculated ++ List(
ZLine.ld8(A, L), ZLine.ld8(A, L),
ZLine.register(SUB, if (useBC) C else E), ZLine.register(SUB, if (useBC) C else E),

View File

@ -420,4 +420,44 @@ class ComparisonSuite extends FunSuite with Matchers {
m.readByte(0xc002) should equal(0) m.readByte(0xc002) should equal(0)
} }
} }
test("Compare to $ffff") {
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
"""
| byte output @$c000
| void main() {
| stuff($ffff)
| barrier()
| }
| noinline void stuff (word x) {
| if x == $ffff {
| output = 11
| }
| }
| noinline void barrier() {}
""".stripMargin
) { m =>
m.readByte(0xc000) should equal(11)
}
}
test("Compare to 0") {
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
"""
| byte output @$c000
| void main() {
| stuff(0)
| barrier()
| }
| noinline void stuff (word x) {
| if x == 0 {
| output = 11
| }
| }
| noinline void barrier() {}
""".stripMargin
) { m =>
m.readByte(0xc000) should equal(11)
}
}
} }