From 9410b8f9e3dfe4abe42e52f35aece3c3510112b1 Mon Sep 17 00:00:00 2001 From: Karol Stasiak Date: Wed, 31 Jan 2018 22:27:11 +0100 Subject: [PATCH] Interrupt handler optimization --- .../scala/millfork/OptimizationPresets.scala | 2 + .../opt/AlwaysGoodOptimizations.scala | 41 +++++++++++++++++++ .../assembly/opt/ReverseFlowAnalyzer.scala | 4 +- .../test/AssemblyOptimizationSuite.scala | 12 +++++- 4 files changed, 57 insertions(+), 2 deletions(-) diff --git a/src/main/scala/millfork/OptimizationPresets.scala b/src/main/scala/millfork/OptimizationPresets.scala index 467004f0..892168ce 100644 --- a/src/main/scala/millfork/OptimizationPresets.scala +++ b/src/main/scala/millfork/OptimizationPresets.scala @@ -32,6 +32,7 @@ object OptimizationPresets { VariableToRegisterOptimization, AlwaysGoodOptimizations.PoinlessLoadBeforeAnotherLoad, AlwaysGoodOptimizations.PointlessOperationPairRemoval, + AlwaysGoodOptimizations.PointlessOperationPairRemoval2, AlwaysGoodOptimizations.PoinlessLoadBeforeAnotherLoad, LaterOptimizations.PointlessLoadAfterStore, AlwaysGoodOptimizations.PointlessOperationAfterLoad, @@ -146,6 +147,7 @@ object OptimizationPresets { AlwaysGoodOptimizations.PointlessMathFromFlow, AlwaysGoodOptimizations.PointlessOperationAfterLoad, AlwaysGoodOptimizations.PointlessOperationPairRemoval, + AlwaysGoodOptimizations.PointlessOperationPairRemoval2, AlwaysGoodOptimizations.PointlessRegisterTransfers, AlwaysGoodOptimizations.PointlessRegisterTransfersBeforeCompare, AlwaysGoodOptimizations.PointlessRegisterTransfersBeforeReturn, diff --git a/src/main/scala/millfork/assembly/opt/AlwaysGoodOptimizations.scala b/src/main/scala/millfork/assembly/opt/AlwaysGoodOptimizations.scala index 9c35a1d7..5a23cbf8 100644 --- a/src/main/scala/millfork/assembly/opt/AlwaysGoodOptimizations.scala +++ b/src/main/scala/millfork/assembly/opt/AlwaysGoodOptimizations.scala @@ -194,6 +194,47 @@ object AlwaysGoodOptimizations { operationPairBuilder(DEY, INY, Not(ConcernsX) & Not(ReadsNOrZ)), ) + + private def operationPairBuilder2(op1: Opcode.Value, op1extra: AssemblyLinePattern, middle: AssemblyLinePattern,op2: Opcode.Value, op2extra: AssemblyLinePattern) = { + (HasOpcode(op1) & Elidable & op1extra) ~ + (Linear & middle).*.capture(1) ~ + (HasOpcode(op2) & Elidable & op2extra) ~~> { (_, ctx) => + ctx.get[List[AssemblyLine]](1) + } + } + + val PointlessOperationPairRemoval2 = new RuleBasedAssemblyOptimization("Pointless operation pair 2", + needsFlowInfo = FlowInfoRequirement.BackwardFlow, + operationPairBuilder2( + PHA, Anything, + Not(ConcernsStack), + PLA, DoesntMatterWhatItDoesWith(State.A, State.N, State.Z)), + operationPairBuilder2( + PHX, Anything, + Not(ConcernsStack), + PLX, DoesntMatterWhatItDoesWith(State.X, State.N, State.Z)), + operationPairBuilder2( + PHY, Anything, + Not(ConcernsStack), + PLY, DoesntMatterWhatItDoesWith(State.Y, State.N, State.Z)), + operationPairBuilder2( + INX, DoesntMatterWhatItDoesWith(State.X, State.N, State.Z), + Anything, + DEX, DoesntMatterWhatItDoesWith(State.X, State.N, State.Z)), + operationPairBuilder2( + DEX, DoesntMatterWhatItDoesWith(State.X, State.N, State.Z), + Anything, + INX, DoesntMatterWhatItDoesWith(State.X, State.N, State.Z)), + operationPairBuilder2( + INY, DoesntMatterWhatItDoesWith(State.Y, State.N, State.Z), + Anything, + DEY, DoesntMatterWhatItDoesWith(State.Y, State.N, State.Z)), + operationPairBuilder2( + DEY, DoesntMatterWhatItDoesWith(State.Y, State.N, State.Z), + Anything, + INY, DoesntMatterWhatItDoesWith(State.Y, State.N, State.Z)), + ) + val PointlessStackStashing = new RuleBasedAssemblyOptimization("Pointless stack stashing", needsFlowInfo = FlowInfoRequirement.NoRequirement, (Elidable & HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1)) ~ diff --git a/src/main/scala/millfork/assembly/opt/ReverseFlowAnalyzer.scala b/src/main/scala/millfork/assembly/opt/ReverseFlowAnalyzer.scala index 280be179..4fb95d86 100644 --- a/src/main/scala/millfork/assembly/opt/ReverseFlowAnalyzer.scala +++ b/src/main/scala/millfork/assembly/opt/ReverseFlowAnalyzer.scala @@ -145,8 +145,10 @@ object ReverseFlowAnalyzer { currentImportance = currentImportance.copy(n = Important) case AssemblyLine(SED | CLD, _, _, _) => currentImportance = currentImportance.copy(d = Unimportant) - case AssemblyLine(RTS | RTI, _, _, _) => + case AssemblyLine(RTS, _, _, _) => currentImportance = finalImportance + case AssemblyLine(RTI, _, _, _) => + currentImportance = new CpuImportance(a = Unimportant, x = Unimportant, y = Unimportant, z = Unimportant, n = Unimportant, c = Unimportant, v = Unimportant, d = Unimportant) case AssemblyLine(DISCARD_XF, _, _, _) => currentImportance = currentImportance.copy(x = Unimportant, n = Unimportant, z = Unimportant, c = Unimportant, v = Unimportant) case AssemblyLine(DISCARD_YF, _, _, _) => diff --git a/src/test/scala/millfork/test/AssemblyOptimizationSuite.scala b/src/test/scala/millfork/test/AssemblyOptimizationSuite.scala index 916a4776..393a528a 100644 --- a/src/test/scala/millfork/test/AssemblyOptimizationSuite.scala +++ b/src/test/scala/millfork/test/AssemblyOptimizationSuite.scala @@ -2,7 +2,7 @@ package millfork.test import millfork.{Cpu, OptimizationPresets} import millfork.assembly.opt.{AlwaysGoodOptimizations, LaterOptimizations, VariableToRegisterOptimization} -import millfork.test.emu.{EmuBenchmarkRun, EmuUltraBenchmarkRun, EmuRun} +import millfork.test.emu.{EmuBenchmarkRun, EmuRun, EmuSuperOptimizedRun, EmuUltraBenchmarkRun} import org.scalatest.{FunSuite, Matchers} /** @@ -292,4 +292,14 @@ class AssemblyOptimizationSuite extends FunSuite with Matchers { m.readWord(0xc00c) should equal(0x201) } } + + test("Empty interrupt"){ + EmuSuperOptimizedRun( + """ + | void main () { + | } + | interrupt void i (){} + | + """.stripMargin) + } }