From 00d190c3d868719b94267e6e0c793e59008b3961 Mon Sep 17 00:00:00 2001 From: Karol Stasiak Date: Thu, 18 Apr 2019 16:24:57 +0200 Subject: [PATCH] 8080: Optimization improvements --- .../z80/opt/AlwaysGoodI80Optimizations.scala | 36 +++++++++++++++++++ .../z80/opt/LaterI80Optimizations.scala | 12 +++++++ 2 files changed, 48 insertions(+) diff --git a/src/main/scala/millfork/assembly/z80/opt/AlwaysGoodI80Optimizations.scala b/src/main/scala/millfork/assembly/z80/opt/AlwaysGoodI80Optimizations.scala index 89ada0b6..c68fda37 100644 --- a/src/main/scala/millfork/assembly/z80/opt/AlwaysGoodI80Optimizations.scala +++ b/src/main/scala/millfork/assembly/z80/opt/AlwaysGoodI80Optimizations.scala @@ -398,6 +398,12 @@ object AlwaysGoodI80Optimizations { ZLine.ld8(ZRegister.C, ZRegister.E) :: code.tail.init }, + //26 + (Elidable & HasOpcode(PUSH) & HasRegisterParam(ZRegister.AF)) ~ + (Linear & Not(HasOpcodeIn(Set(POP, PUSH))) & Not(ReadsStackPointer) & Not(Changes(A))).* ~ + (Elidable & HasOpcode(POP) & HasRegisterParam(ZRegister.AF) & DoesntMatterWhatItDoesWithFlags) ~~> { code => + code.tail.init + }, ) val PointlessStackStashingFromFlow = new RuleBasedAssemblyOptimization("Pointless stack stashing from flow", @@ -1420,11 +1426,41 @@ object AlwaysGoodI80Optimizations { (Elidable & HasOpcodeIn(Set(OR, AND)) & HasRegisterParam(ZRegister.A)) ~~> (_.init), ) + val LoopInvariant = new RuleBasedAssemblyOptimization("Loop invariant", + needsFlowInfo = FlowInfoRequirement.JustLabels, + + for5LargeRegisters(reg => + ((HasOpcode(LABEL) & MatchParameterOrNothing(0) & IsNotALabelUsedManyTimes) ~ + (Linear & Not(Concerns(reg))).*).capture(1) ~ + (Elidable & HasOpcode(LD_16) & HasRegisters(TwoRegisters(reg, IMM_16))).capture(2) ~ + ((Linear & Not(Changes(reg))).* ~ + (HasOpcodeIn(Set(JP, JR, DJNZ)) & MatchParameterOrNothing(0))).capture(3) ~~> { (code, ctx) => + ctx.get[List[ZLine]](2) ++ + ctx.get[List[ZLine]](1) ++ + ctx.get[List[ZLine]](3) + } + ), + + for7Registers (reg => + ((HasOpcode(LABEL) & MatchParameterOrNothing(0) & IsNotALabelUsedManyTimes) ~ + (Linear & Not(Concerns(reg))).*).capture(1) ~ + (Elidable & HasOpcode(LD) & HasRegisters(TwoRegisters(reg, IMM_8))).capture(2) ~ + ((Linear & Not(Changes(reg))).* ~ + (HasOpcodeIn(Set(JP, JR, DJNZ)) & MatchParameterOrNothing(0))).capture(3) ~~> { (code, ctx) => + ctx.get[List[ZLine]](2) ++ + ctx.get[List[ZLine]](1) ++ + ctx.get[List[ZLine]](3) + } + ), + ) + + val All: List[AssemblyOptimization[ZLine]] = List[AssemblyOptimization[ZLine]]( BranchInPlaceRemoval, ConstantMultiplication, ConstantInlinedShifting, FreeHL, + LoopInvariant, PointlessArithmetic, PointlessFlagChange, PointlessLoad, diff --git a/src/main/scala/millfork/assembly/z80/opt/LaterI80Optimizations.scala b/src/main/scala/millfork/assembly/z80/opt/LaterI80Optimizations.scala index ce91025d..120129fe 100644 --- a/src/main/scala/millfork/assembly/z80/opt/LaterI80Optimizations.scala +++ b/src/main/scala/millfork/assembly/z80/opt/LaterI80Optimizations.scala @@ -74,6 +74,18 @@ object LaterI80Optimizations { val h = ctx.get[Constant](1) List(ZLine.ldImm16(DE, h.asl(8).+(l).quickSimplify).pos(code.map(_.source))) }, + + (Elidable & HasOpcode(LD_16) & HasRegisters(TwoRegisters(HL, IMM_16))) ~ + (Elidable & Is8BitLoad(E, L)) ~ + (Elidable & Is8BitLoad(D, H) & DoesntMatterWhatItDoesWith(HL)) ~~> { code => + List(code.head.copy(registers = TwoRegisters(DE, IMM_16))) + }, + + (Elidable & HasOpcode(LD_16) & HasRegisters(TwoRegisters(HL, IMM_16))) ~ + (Elidable & Is8BitLoad(C, L)) ~ + (Elidable & Is8BitLoad(B, H) & DoesntMatterWhatItDoesWith(HL)) ~~> { code => + List(code.head.copy(registers = TwoRegisters(BC, IMM_16))) + }, ) val FreeHL = new RuleBasedAssemblyOptimization("Free HL (later)",