From 5c65af17d416008a6971ad41f42acc76a64d0c36 Mon Sep 17 00:00:00 2001 From: Karol Stasiak Date: Wed, 8 Aug 2018 13:45:26 +0200 Subject: [PATCH] Z80: More optimizations --- .../z80/opt/AlwaysGoodI80Optimizations.scala | 103 ++++++++++++++++++ .../z80/opt/LaterI80Optimizations.scala | 28 ++++- .../z80/opt/Z80OptimizationPresets.scala | 6 +- 3 files changed, 133 insertions(+), 4 deletions(-) diff --git a/src/main/scala/millfork/assembly/z80/opt/AlwaysGoodI80Optimizations.scala b/src/main/scala/millfork/assembly/z80/opt/AlwaysGoodI80Optimizations.scala index c878bb88..7cddd967 100644 --- a/src/main/scala/millfork/assembly/z80/opt/AlwaysGoodI80Optimizations.scala +++ b/src/main/scala/millfork/assembly/z80/opt/AlwaysGoodI80Optimizations.scala @@ -30,6 +30,9 @@ object AlwaysGoodI80Optimizations { def for6Registers(f: ZRegister.Value => AssemblyRuleSet) = MultipleAssemblyRules( List(ZRegister.B, ZRegister.C, ZRegister.D, ZRegister.E, ZRegister.H, ZRegister.L).map(f)) + def for6RegistersAndM(f: ZRegister.Value => AssemblyRuleSet) = MultipleAssemblyRules( + List(ZRegister.B, ZRegister.C, ZRegister.D, ZRegister.E, ZRegister.H, ZRegister.L, ZRegister.MEM_HL).map(f)) + val UsingKnownValueFromAnotherRegister = new RuleBasedAssemblyOptimization("Using known value from another register", needsFlowInfo = FlowInfoRequirement.ForwardFlow, for7Registers(register => @@ -557,6 +560,30 @@ object AlwaysGoodI80Optimizations { List(ZLine.ldImm16(BC, ctx.get[Constant](0).-(1).quickSimplify)) }, + for6RegistersAndM(reg => + (Elidable & Is8BitLoadTo(A) & Has8BitImmediate(1) ) ~ + (Elidable & HasOpcode(ADD) & opt.HasRegisterParam(reg) ) ~ + (Elidable & Is8BitLoad(reg, A) & DoesntMatterWhatItDoesWithFlags & DoesntMatterWhatItDoesWith(A)) ~~> { _ => + List(ZLine.register(INC, reg)) + } + ), + + for6RegistersAndM(reg => + (Elidable & Is8BitLoadTo(A) & Has8BitImmediate(2) ) ~ + (Elidable & HasOpcode(ADD) & opt.HasRegisterParam(reg) ) ~ + (Elidable & Is8BitLoad(reg, A) & DoesntMatterWhatItDoesWithFlags & DoesntMatterWhatItDoesWith(A)) ~~> { _ => + List(ZLine.register(INC, reg), ZLine.register(INC, reg)) + } + ), + + for6RegistersAndM(reg => + (Elidable & Is8BitLoadTo(A) & Has8BitImmediate(3) ) ~ + (Elidable & HasOpcode(ADD) & opt.HasRegisterParam(reg) ) ~ + (Elidable & Is8BitLoad(reg, A) & DoesntMatterWhatItDoesWithFlags & DoesntMatterWhatItDoesWith(A)) ~~> { _ => + List(ZLine.register(INC, reg), ZLine.register(INC, reg), ZLine.register(INC, reg)) + } + ), + ) val FreeHL = new RuleBasedAssemblyOptimization("Free HL", @@ -858,6 +885,82 @@ object AlwaysGoodI80Optimizations { (Elidable & HasOpcode(RLC) & HasRegisterParam(ZRegister.A) & DoesntMatterWhatItDoesWithFlagsExceptCarry) ~~> {_ => List(ZLine.implied(RLCA)) }, + (Elidable & HasOpcode(RRCA)) ~ + (Elidable & HasOpcode(RRCA)) ~ + (Elidable & HasOpcode(RRCA)) ~ + (Elidable & HasOpcode(RRCA)) ~ + (Elidable & HasOpcode(RRCA) & DoesntMatterWhatItDoesWithFlags) ~~> { _ => + List( + ZLine.implied(RLCA), + ZLine.implied(RLCA), + ZLine.implied(RLCA)) + }, + (Elidable & HasOpcode(RRCA)) ~ + (Elidable & HasOpcode(RRCA)) ~ + (Elidable & HasOpcode(RRCA)) ~ + (Elidable & HasOpcode(RRCA)) ~ + (Elidable & HasOpcode(RRCA)) ~ + (Elidable & HasOpcode(RRCA) & DoesntMatterWhatItDoesWithFlags) ~~> { _ => + List( + ZLine.implied(RLCA), + ZLine.implied(RLCA)) + }, + (Elidable & HasOpcode(RRCA)) ~ + (Elidable & HasOpcode(RRCA)) ~ + (Elidable & HasOpcode(RRCA)) ~ + (Elidable & HasOpcode(RRCA)) ~ + (Elidable & HasOpcode(RRCA)) ~ + (Elidable & HasOpcode(RRCA)) ~ + (Elidable & HasOpcode(RRCA) & DoesntMatterWhatItDoesWithFlags) ~~> { _ => + List(ZLine.implied(RLCA)) + }, + + (Elidable & HasOpcode(RLCA)) ~ + (Elidable & HasOpcode(RLCA)) ~ + (Elidable & HasOpcode(RLCA)) ~ + (Elidable & HasOpcode(RLCA)) ~ + (Elidable & HasOpcode(RLCA) & DoesntMatterWhatItDoesWithFlags) ~~> { _ => + List( + ZLine.implied(RRCA), + ZLine.implied(RRCA), + ZLine.implied(RRCA)) + }, + (Elidable & HasOpcode(RLCA)) ~ + (Elidable & HasOpcode(RLCA)) ~ + (Elidable & HasOpcode(RLCA)) ~ + (Elidable & HasOpcode(RLCA)) ~ + (Elidable & HasOpcode(RLCA)) ~ + (Elidable & HasOpcode(RLCA) & DoesntMatterWhatItDoesWithFlags) ~~> { _ => + List( + ZLine.implied(RRCA), + ZLine.implied(RRCA)) + }, + (Elidable & HasOpcode(RLCA)) ~ + (Elidable & HasOpcode(RLCA)) ~ + (Elidable & HasOpcode(RLCA)) ~ + (Elidable & HasOpcode(RLCA)) ~ + (Elidable & HasOpcode(RLCA)) ~ + (Elidable & HasOpcode(RLCA)) ~ + (Elidable & HasOpcode(RLCA) & DoesntMatterWhatItDoesWithFlags) ~~> { _ => + List(ZLine.implied(RRCA)) + }, + + (Elidable & HasOpcode(RLCA)) ~ + (Elidable & HasOpcode(RLCA)) ~ + (Elidable & HasOpcode(RLCA)) ~ + (Elidable & HasOpcode(RLCA)) ~ + (Elidable & HasOpcode(RLCA)) ~ + (Elidable & HasOpcode(RLCA)) ~ + (Elidable & HasOpcode(RLCA) & DoesntMatterWhatItDoesWithFlags) ~~> { _ => + List(ZLine.implied(RRCA)) + }, + + (Elidable & HasOpcode(RLCA)) ~ + (Elidable & HasOpcode(RRCA) & DoesntMatterWhatItDoesWithFlags) ~~> ( _ => Nil), + + (Elidable & HasOpcode(RRCA)) ~ + (Elidable & HasOpcode(RLCA) & DoesntMatterWhatItDoesWithFlags) ~~> ( _ => Nil), + ) val PointlessExdehl = new RuleBasedAssemblyOptimization("Pointless EX DE,HL", diff --git a/src/main/scala/millfork/assembly/z80/opt/LaterI80Optimizations.scala b/src/main/scala/millfork/assembly/z80/opt/LaterI80Optimizations.scala index 7059228a..25525747 100644 --- a/src/main/scala/millfork/assembly/z80/opt/LaterI80Optimizations.scala +++ b/src/main/scala/millfork/assembly/z80/opt/LaterI80Optimizations.scala @@ -25,7 +25,33 @@ object LaterI80Optimizations { }, ) + val FreeHL = new RuleBasedAssemblyOptimization("Free HL (later)", + needsFlowInfo = FlowInfoRequirement.BackwardFlow, + + (Elidable & Is8BitLoad(H, B)) ~ + (Elidable & Is8BitLoad(L, C)) ~ + (Elidable & Is8BitLoad(MEM_HL, A) & DoesntMatterWhatItDoesWith(B, C)) ~~> { _ => + List(ZLine.ld8(MEM_BC, A)) + }, + (Elidable & Is8BitLoad(H, B)) ~ + (Elidable & Is8BitLoad(L, C)) ~ + (Elidable & Is8BitLoad(A, MEM_HL) & DoesntMatterWhatItDoesWith(B, C)) ~~> { _ => + List(ZLine.ld8(A, MEM_BC)) + }, + (Elidable & Is8BitLoad(H, D)) ~ + (Elidable & Is8BitLoad(L, E)) ~ + (Elidable & Is8BitLoad(MEM_DE, A) & DoesntMatterWhatItDoesWith(D, E)) ~~> { _ => + List(ZLine.ld8(MEM_DE, A)) + }, + (Elidable & Is8BitLoad(H, D)) ~ + (Elidable & Is8BitLoad(L, E)) ~ + (Elidable & Is8BitLoad(A, MEM_HL) & DoesntMatterWhatItDoesWith(D, E)) ~~> { _ => + List(ZLine.ld8(A, MEM_DE)) + }, + ) + val All: List[AssemblyOptimization[ZLine]] = List( - VariousSmallOptimizations + VariousSmallOptimizations, + FreeHL ) } diff --git a/src/main/scala/millfork/assembly/z80/opt/Z80OptimizationPresets.scala b/src/main/scala/millfork/assembly/z80/opt/Z80OptimizationPresets.scala index ef07f81b..538ba07d 100644 --- a/src/main/scala/millfork/assembly/z80/opt/Z80OptimizationPresets.scala +++ b/src/main/scala/millfork/assembly/z80/opt/Z80OptimizationPresets.scala @@ -18,7 +18,7 @@ object Z80OptimizationPresets { EmptyMemoryStoreRemoval) ).flatten ++ List(WordVariableToRegisterOptimization, ByteVariableToRegisterOptimization, CompactStackFrame) ++ - LaterIntel8080Optimizations.All + LaterIntel8080Optimizations.All ++ LaterI80Optimizations.All ).flatten } @@ -32,7 +32,7 @@ object Z80OptimizationPresets { ) ).flatten ++ List(WordVariableToRegisterOptimization, ByteVariableToRegisterOptimization) ++ - LaterIntel8080Optimizations.All + LaterIntel8080Optimizations.All ++ LaterI80Optimizations.All ).flatten } @@ -45,7 +45,7 @@ object Z80OptimizationPresets { EmptyMemoryStoreRemoval) ).flatten ++ List(WordVariableToRegisterOptimization, ByteVariableToRegisterOptimization) ++ - LaterSharpOptimizations.All + LaterSharpOptimizations.All ++ LaterI80Optimizations.All ).flatten }