1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-07-05 09:28:54 +00:00

Optimization improvements:

– reloading from zeropage is faster than stashing the result into another register
– more jumping optimizations
This commit is contained in:
Karol Stasiak 2018-06-18 18:52:34 +02:00
parent daf8461c07
commit 7510b44412
2 changed files with 78 additions and 2 deletions

View File

@ -140,6 +140,7 @@ object OptimizationPresets {
val Good: List[AssemblyOptimization[AssemblyLine]] = List[AssemblyOptimization[AssemblyLine]](
UnusedLabelRemoval,
AlwaysGoodOptimizations.Adc0Optimization,
AlwaysGoodOptimizations.AlwaysTakenJumpRemoval,
AlwaysGoodOptimizations.BitPackingUnpacking,
AlwaysGoodOptimizations.BranchInPlaceRemoval,
AlwaysGoodOptimizations.CarryFlagConversion,
@ -158,6 +159,7 @@ object OptimizationPresets {
AlwaysGoodOptimizations.IncrementingIndexRegistersAfterTransfer,
AlwaysGoodOptimizations.IndexComparisonOptimization,
AlwaysGoodOptimizations.IndexSequenceOptimization,
AlwaysGoodOptimizations.InefficientStashingToRegister,
AlwaysGoodOptimizations.LoopInvariantRegister,
LoopUnrolling.LoopUnrolling,
AlwaysGoodOptimizations.MathOperationOnTwoIdenticalMemoryOperands,

View File

@ -337,6 +337,25 @@ object AlwaysGoodOptimizations {
},
)
val InefficientStashingToRegister = new RuleBasedAssemblyOptimization("Inefficient stashing to register",
needsFlowInfo = FlowInfoRequirement.BackwardFlow,
(Elidable & HasOpcodeIn(Set(LDA, STA)) & IsZeroPage & MatchAddrMode(0) & MatchParameter(1)) ~
(Elidable & HasOpcode(TAX) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~
(Linear & Not(ConcernsX) & DoesntChangeMemoryAt(0, 1)).* ~
(Elidable & HasOpcode(TXA) & DoesntMatterWhatItDoesWith(State.X)) ~~> (code => code.head :: (code.drop(2) :+ code.head.copy(opcode = LDA))),
(Elidable & HasOpcodeIn(Set(LDA, STA)) & IsZeroPage & MatchAddrMode(0) & MatchParameter(1)) ~
(Elidable & HasOpcode(TAY) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~
(Linear & Not(ConcernsY) & DoesntChangeMemoryAt(0, 1)).* ~
(Elidable & HasOpcode(TYA) & DoesntMatterWhatItDoesWith(State.Y)) ~~> (code => code.head :: (code.drop(2) :+ code.head.copy(opcode = LDA))),
(Elidable & HasOpcodeIn(Set(LDA, STA)) & IsZeroPage & MatchAddrMode(0) & MatchParameter(1)) ~
(Elidable & HasOpcode(TAZ) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~
(Linear & Not(ConcernsIZ) & DoesntChangeMemoryAt(0, 1)).* ~
(Elidable & HasOpcode(TZA) & DoesntMatterWhatItDoesWith(State.IZ)) ~~> (code => code.head :: (code.drop(2) :+ code.head.copy(opcode = LDA))),
)
private def operationPairBuilder(op1: Opcode.Value, op2: Opcode.Value, middle: AssemblyLinePattern, discardToRemove: Option[Opcode.Value]) = {
(HasOpcode(op1) & Elidable) ~
(Linear & middle).*.capture(1) ~
@ -517,10 +536,34 @@ object AlwaysGoodOptimizations {
val BranchInPlaceRemoval = new RuleBasedAssemblyOptimization("Branch in place",
needsFlowInfo = FlowInfoRequirement.NoRequirement,
(AllDirectJumps & MatchParameter(0) & Elidable) ~
(AllDirectJumps & HasAddrModeIn(Set(Absolute, Relative, LongAbsolute, LongRelative)) & MatchParameter(0) & Elidable) ~
HasOpcodeIn(NoopDiscardsFlags).* ~
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (c => c.last :: Nil),
(AllDirectJumps & MatchParameter(0) & Elidable) ~
(AllDirectJumps & HasAddrModeIn(Set(Absolute, Relative, LongAbsolute, LongRelative)) & MatchParameter(0) & Elidable) ~
(HasOpcode(LABEL) & Not(MatchParameter(0))).* ~
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (_.tail),
(HasOpcode(BEQ) & MatchParameter(0) & Elidable) ~ HasOpcode(BNE) ~
(HasOpcode(LABEL) & Not(MatchParameter(0))).* ~
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (_.tail),
(HasOpcode(BNE) & MatchParameter(0) & Elidable) ~ HasOpcode(BEQ) ~
(HasOpcode(LABEL) & Not(MatchParameter(0))).* ~
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (_.tail),
(HasOpcode(BCC) & MatchParameter(0) & Elidable) ~ HasOpcode(BCS) ~
(HasOpcode(LABEL) & Not(MatchParameter(0))).* ~
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (_.tail),
(HasOpcode(BCS) & MatchParameter(0) & Elidable) ~ HasOpcode(BCC) ~
(HasOpcode(LABEL) & Not(MatchParameter(0))).* ~
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (_.tail),
(HasOpcode(BMI) & MatchParameter(0) & Elidable) ~ HasOpcode(BPL) ~
(HasOpcode(LABEL) & Not(MatchParameter(0))).* ~
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (_.tail),
(HasOpcode(BPL) & MatchParameter(0) & Elidable) ~ HasOpcode(BMI) ~
(HasOpcode(LABEL) & Not(MatchParameter(0))).* ~
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (_.tail),
(HasOpcode(BVS) & MatchParameter(0) & Elidable) ~ HasOpcode(BVC) ~
(HasOpcode(LABEL) & Not(MatchParameter(0))).* ~
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (_.tail),
(HasOpcode(BVC) & MatchParameter(0) & Elidable) ~ HasOpcode(BVS) ~
(HasOpcode(LABEL) & Not(MatchParameter(0))).* ~
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (_.tail),
)
@ -542,6 +585,9 @@ object AlwaysGoodOptimizations {
(Elidable & HasOpcode(JMP) & HasAddrMode(Absolute) & MatchParameter(0)) ~
(Elidable & LinearOrBranch).* ~
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (_ => Nil),
(Elidable & HasOpcode(BRA) & MatchParameter(0)) ~
(Elidable & LinearOrBranch).* ~
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (_ => Nil),
(Elidable & HasOpcode(JMP) & HasAddrMode(Absolute) & MatchParameter(0)) ~
(Not(HasOpcode(LABEL)) & Not(MatchParameter(0))).* ~
(HasOpcode(LABEL) & MatchParameter(0)) ~
@ -555,6 +601,34 @@ object AlwaysGoodOptimizations {
(Elidable & HasOpcode(RTS)) ~~> ((code, ctx) => ctx.get[List[AssemblyLine]](1)),
)
val AlwaysTakenJumpRemoval = new RuleBasedAssemblyOptimization("Always taken jump removal",
needsFlowInfo = FlowInfoRequirement.ForwardFlow,
(Elidable & HasOpcode(BEQ) & HasSet(State.Z) & MatchParameter(0)) ~
(Elidable & LinearOrBranch).* ~
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (_ => Nil),
(Elidable & HasOpcode(BNE) & HasClear(State.Z) & MatchParameter(0)) ~
(Elidable & LinearOrBranch).* ~
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (_ => Nil),
(Elidable & HasOpcode(BCC) & HasClear(State.C) & MatchParameter(0)) ~
(Elidable & LinearOrBranch).* ~
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (_ => Nil),
(Elidable & HasOpcode(BCS) & HasSet(State.C) & MatchParameter(0)) ~
(Elidable & LinearOrBranch).* ~
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (_ => Nil),
(Elidable & HasOpcode(BMI) & HasSet(State.N) & MatchParameter(0)) ~
(Elidable & LinearOrBranch).* ~
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (_ => Nil),
(Elidable & HasOpcode(BPL) & HasClear(State.N) & MatchParameter(0)) ~
(Elidable & LinearOrBranch).* ~
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (_ => Nil),
(Elidable & HasOpcode(BVC) & HasClear(State.V) & MatchParameter(0)) ~
(Elidable & LinearOrBranch).* ~
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (_ => Nil),
(Elidable & HasOpcode(BVS) & HasSet(State.V) & MatchParameter(0)) ~
(Elidable & LinearOrBranch).* ~
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (_ => Nil),
)
val TailCallOptimization = new RuleBasedAssemblyOptimization("Tail call optimization",
needsFlowInfo = FlowInfoRequirement.NoRequirement,
(Elidable & HasOpcode(JSR)) ~ HasOpcodeIn(NoopDiscardsFlags).* ~ (Elidable & HasOpcode(RTS)) ~~> (c => c.head.copy(opcode = JMP) :: Nil),