diff --git a/src/main/scala/millfork/assembly/z80/opt/AlwaysGoodZ80Optimizations.scala b/src/main/scala/millfork/assembly/z80/opt/AlwaysGoodZ80Optimizations.scala index 2c60fc0c..01012919 100644 --- a/src/main/scala/millfork/assembly/z80/opt/AlwaysGoodZ80Optimizations.scala +++ b/src/main/scala/millfork/assembly/z80/opt/AlwaysGoodZ80Optimizations.scala @@ -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, ) } diff --git a/src/main/scala/millfork/assembly/z80/opt/CoarseFlowAnalyzer.scala b/src/main/scala/millfork/assembly/z80/opt/CoarseFlowAnalyzer.scala index f3840394..a13410e3 100644 --- a/src/main/scala/millfork/assembly/z80/opt/CoarseFlowAnalyzer.scala +++ b/src/main/scala/millfork/assembly/z80/opt/CoarseFlowAnalyzer.scala @@ -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)(_ ~ _) diff --git a/src/main/scala/millfork/assembly/z80/opt/FlowAnalyzer.scala b/src/main/scala/millfork/assembly/z80/opt/FlowAnalyzer.scala index d7a984e2..37867452 100644 --- a/src/main/scala/millfork/assembly/z80/opt/FlowAnalyzer.scala +++ b/src/main/scala/millfork/assembly/z80/opt/FlowAnalyzer.scala @@ -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)) } diff --git a/src/main/scala/millfork/assembly/z80/opt/RuleBasedAssemblyOptimization.scala b/src/main/scala/millfork/assembly/z80/opt/RuleBasedAssemblyOptimization.scala index 7e482577..3f06122a 100644 --- a/src/main/scala/millfork/assembly/z80/opt/RuleBasedAssemblyOptimization.scala +++ b/src/main/scala/millfork/assembly/z80/opt/RuleBasedAssemblyOptimization.scala @@ -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 })