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:
parent
9669e4d87d
commit
0bb662183c
@ -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) {
|
||||||
|
@ -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),
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user