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

Optimization fixes and improvements for Z80

This commit is contained in:
Karol Stasiak 2018-07-02 14:58:45 +02:00
parent ed067d3a67
commit 619bf8116a
4 changed files with 40 additions and 6 deletions

View File

@ -1,7 +1,7 @@
package millfork.assembly.z80.opt
import millfork.assembly.AssemblyOptimization
import millfork.assembly.z80.{TwoRegisters, ZLine, ZOpcode}
import millfork.assembly.z80.{OneRegister, TwoRegisters, ZLine, ZOpcode}
import millfork.assembly.z80.ZOpcode._
import millfork.env.{Constant, NumericConstant}
import millfork.node.ZRegister
@ -69,6 +69,18 @@ object AlwaysGoodZ80Optimizations {
(Linear & Not(Changes(register))).* ~
(Elidable & Is16BitLoad(register, ZRegister.IMM_16) & MatchImmediate(0)) ~~> (_.init)
),
(Elidable & Is8BitLoadTo(ZRegister.MEM_HL)) ~
(Linear & Not(ConcernsMemory) & Not(Changes(ZRegister.HL))).* ~
Is8BitLoadTo(ZRegister.MEM_HL) ~~> (_.tail),
(Elidable & Is8BitLoadTo(ZRegister.MEM_DE)) ~
(Linear & Not(ConcernsMemory) & Not(Changes(ZRegister.DE))).* ~
Is8BitLoadTo(ZRegister.MEM_DE) ~~> (_.tail),
(Elidable & Is8BitLoadTo(ZRegister.MEM_BC)) ~
(Linear & Not(ConcernsMemory) & Not(Changes(ZRegister.BC))).* ~
Is8BitLoadTo(ZRegister.MEM_BC) ~~> (_.tail),
)
private def simplifiable16BitAddWithSplitTarget(targetH: ZRegister.Value, targetL: ZRegister.Value, target: ZRegister.Value, source: ZRegister.Value) = MultipleAssemblyRules(List(
@ -147,6 +159,23 @@ object AlwaysGoodZ80Optimizations {
code.head.copy(opcode = LD, registers = TwoRegisters(ZRegister.A, ZRegister.MEM_ABS_8)),
code(1).copy(registers = TwoRegisters(code(1).registers.asInstanceOf[TwoRegisters].target, ZRegister.A)),
)),
(Elidable & Is16BitLoad(ZRegister.HL, ZRegister.IMM_16)) ~
(Elidable & Is8BitLoad(ZRegister.D, ZRegister.H)) ~
(Elidable & Is8BitLoad(ZRegister.E, ZRegister.L) & DoesntMatterWhatItDoesWith(ZRegister.HL)) ~~> (code =>
List(
code.head.copy(registers = TwoRegisters(ZRegister.DE, ZRegister.IMM_16))
)),
(Elidable & Is16BitLoad(ZRegister.HL, ZRegister.IMM_16)) ~
(Elidable & Is8BitLoad(ZRegister.B, ZRegister.H)) ~
(Elidable & Is8BitLoad(ZRegister.C, ZRegister.L) & DoesntMatterWhatItDoesWith(ZRegister.HL)) ~~> (code =>
List(
code.head.copy(registers = TwoRegisters(ZRegister.BC, ZRegister.IMM_16))
)),
)
val UnusedLabelRemoval = new RuleBasedAssemblyOptimization("Unused label removal",
needsFlowInfo = FlowInfoRequirement.JustLabels,
(Elidable & HasOpcode(LABEL) & HasCallerCount(0)) ~~> (_ => Nil)
)
val All: List[AssemblyOptimization[ZLine]] = List[AssemblyOptimization[ZLine]](
@ -155,6 +184,7 @@ object AlwaysGoodZ80Optimizations {
PointlessLoad,
ReloadingKnownValueFromMemory,
SimplifiableMaths,
UnusedLabelRemoval,
)
}

View File

@ -1,6 +1,5 @@
package millfork.assembly.z80.opt
import millfork.assembly.mos.{AssemblyLine, OpcodeClasses}
import millfork.assembly.opt.{AnyStatus, SingleStatus}
import millfork.assembly.z80.{OneRegister, TwoRegisters, ZLine, ZOpcodeClasses}
import millfork.env.{Label, MemoryAddressConstant, NormalFunction, NumericConstant}
@ -35,6 +34,7 @@ object CoarseFlowAnalyzer {
case ZLine(LABEL, _, MemoryAddressConstant(Label(l)), _) =>
val L = l
currentStatus = codeArray.indices.flatMap(j => codeArray(j) match {
case ZLine(DJNZ, _, MemoryAddressConstant(Label(L)), _) => Some(flagArray(j).copy(b = AnyStatus))
case ZLine(_, _, MemoryAddressConstant(Label(L)), _) => Some(flagArray(j))
case _ => None
}).fold(currentStatus)(_ ~ _)

View File

@ -1,8 +1,7 @@
package millfork.assembly.z80.opt
import millfork.CompilationOptions
import millfork.assembly.mos.{AssemblyLine, Opcode, State}
import millfork.assembly.z80.ZLine
import millfork.assembly.z80.{ZLine, ZOpcode}
import millfork.env.{Label, MemoryAddressConstant, NormalFunction}
/**
@ -44,7 +43,7 @@ object FlowAnalyzer {
val labelMap: (() => Option[Map[String, Int]]) = () => req match {
case FlowInfoRequirement.NoRequirement => None
case _ => Some(code.flatMap {
case ZLine(op, _, MemoryAddressConstant(Label(l)), _) if op != Opcode.LABEL => Some(l)
case ZLine(op, _, MemoryAddressConstant(Label(l)), _) if op != ZOpcode.LABEL => Some(l)
case _ => None
}.groupBy(identity).mapValues(_.size))
}

View File

@ -456,6 +456,11 @@ case class MatchParameter(i: Int) extends AssemblyLinePattern {
}
}
case class MatchOpcode(i: Int) extends AssemblyLinePattern {
override def matchLineTo(ctx: AssemblyMatchingContext, flowInfo: FlowInfo, line: ZLine): Boolean =
ctx.addObject(i, line.opcode)
}
case class HasRegister(register: ZRegister.Value, value: Int) extends AssemblyLinePattern {
override def validate(needsFlowInfo: FlowInfoRequirement.Value): Unit =
FlowInfoRequirement.assertForward(needsFlowInfo)
@ -615,7 +620,7 @@ case class Is16BitLoad(target:ZRegister.Value, source: ZRegister.Value) extends
case class IsRegular8BitLoadFrom(source: ZRegister.Value) extends TrivialAssemblyLinePattern {
override def apply(line: ZLine): Boolean =
line.opcode == ZOpcode.LD && line.registers.asInstanceOf[TwoRegisters].source == source && (line.registers.asInstanceOf[TwoRegisters].target match {
case ZRegister.I | ZRegister.MEM_ABS_8 | ZRegister.R => false
case ZRegister.I | ZRegister.MEM_ABS_8 | ZRegister.R | ZRegister.MEM_DE | ZRegister.MEM_BC => false
case _ => true
})