mirror of
https://github.com/KarolS/millfork.git
synced 2025-01-11 12:29:46 +00:00
Optimization improvements:
– reloading from zeropage is faster than stashing the result into another register – more jumping optimizations
This commit is contained in:
parent
daf8461c07
commit
7510b44412
@ -140,6 +140,7 @@ object OptimizationPresets {
|
|||||||
val Good: List[AssemblyOptimization[AssemblyLine]] = List[AssemblyOptimization[AssemblyLine]](
|
val Good: List[AssemblyOptimization[AssemblyLine]] = List[AssemblyOptimization[AssemblyLine]](
|
||||||
UnusedLabelRemoval,
|
UnusedLabelRemoval,
|
||||||
AlwaysGoodOptimizations.Adc0Optimization,
|
AlwaysGoodOptimizations.Adc0Optimization,
|
||||||
|
AlwaysGoodOptimizations.AlwaysTakenJumpRemoval,
|
||||||
AlwaysGoodOptimizations.BitPackingUnpacking,
|
AlwaysGoodOptimizations.BitPackingUnpacking,
|
||||||
AlwaysGoodOptimizations.BranchInPlaceRemoval,
|
AlwaysGoodOptimizations.BranchInPlaceRemoval,
|
||||||
AlwaysGoodOptimizations.CarryFlagConversion,
|
AlwaysGoodOptimizations.CarryFlagConversion,
|
||||||
@ -158,6 +159,7 @@ object OptimizationPresets {
|
|||||||
AlwaysGoodOptimizations.IncrementingIndexRegistersAfterTransfer,
|
AlwaysGoodOptimizations.IncrementingIndexRegistersAfterTransfer,
|
||||||
AlwaysGoodOptimizations.IndexComparisonOptimization,
|
AlwaysGoodOptimizations.IndexComparisonOptimization,
|
||||||
AlwaysGoodOptimizations.IndexSequenceOptimization,
|
AlwaysGoodOptimizations.IndexSequenceOptimization,
|
||||||
|
AlwaysGoodOptimizations.InefficientStashingToRegister,
|
||||||
AlwaysGoodOptimizations.LoopInvariantRegister,
|
AlwaysGoodOptimizations.LoopInvariantRegister,
|
||||||
LoopUnrolling.LoopUnrolling,
|
LoopUnrolling.LoopUnrolling,
|
||||||
AlwaysGoodOptimizations.MathOperationOnTwoIdenticalMemoryOperands,
|
AlwaysGoodOptimizations.MathOperationOnTwoIdenticalMemoryOperands,
|
||||||
|
@ -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]) = {
|
private def operationPairBuilder(op1: Opcode.Value, op2: Opcode.Value, middle: AssemblyLinePattern, discardToRemove: Option[Opcode.Value]) = {
|
||||||
(HasOpcode(op1) & Elidable) ~
|
(HasOpcode(op1) & Elidable) ~
|
||||||
(Linear & middle).*.capture(1) ~
|
(Linear & middle).*.capture(1) ~
|
||||||
@ -517,10 +536,34 @@ object AlwaysGoodOptimizations {
|
|||||||
|
|
||||||
val BranchInPlaceRemoval = new RuleBasedAssemblyOptimization("Branch in place",
|
val BranchInPlaceRemoval = new RuleBasedAssemblyOptimization("Branch in place",
|
||||||
needsFlowInfo = FlowInfoRequirement.NoRequirement,
|
needsFlowInfo = FlowInfoRequirement.NoRequirement,
|
||||||
(AllDirectJumps & MatchParameter(0) & Elidable) ~
|
(AllDirectJumps & HasAddrModeIn(Set(Absolute, Relative, LongAbsolute, LongRelative)) & MatchParameter(0) & Elidable) ~
|
||||||
HasOpcodeIn(NoopDiscardsFlags).* ~
|
HasOpcodeIn(NoopDiscardsFlags).* ~
|
||||||
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (c => c.last :: Nil),
|
(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) & Not(MatchParameter(0))).* ~
|
||||||
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (_.tail),
|
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (_.tail),
|
||||||
)
|
)
|
||||||
@ -542,6 +585,9 @@ object AlwaysGoodOptimizations {
|
|||||||
(Elidable & HasOpcode(JMP) & HasAddrMode(Absolute) & MatchParameter(0)) ~
|
(Elidable & HasOpcode(JMP) & HasAddrMode(Absolute) & MatchParameter(0)) ~
|
||||||
(Elidable & LinearOrBranch).* ~
|
(Elidable & LinearOrBranch).* ~
|
||||||
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (_ => Nil),
|
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (_ => Nil),
|
||||||
|
(Elidable & HasOpcode(BRA) & MatchParameter(0)) ~
|
||||||
|
(Elidable & LinearOrBranch).* ~
|
||||||
|
(HasOpcode(LABEL) & MatchParameter(0)) ~~> (_ => Nil),
|
||||||
(Elidable & HasOpcode(JMP) & HasAddrMode(Absolute) & MatchParameter(0)) ~
|
(Elidable & HasOpcode(JMP) & HasAddrMode(Absolute) & MatchParameter(0)) ~
|
||||||
(Not(HasOpcode(LABEL)) & Not(MatchParameter(0))).* ~
|
(Not(HasOpcode(LABEL)) & Not(MatchParameter(0))).* ~
|
||||||
(HasOpcode(LABEL) & MatchParameter(0)) ~
|
(HasOpcode(LABEL) & MatchParameter(0)) ~
|
||||||
@ -555,6 +601,34 @@ object AlwaysGoodOptimizations {
|
|||||||
(Elidable & HasOpcode(RTS)) ~~> ((code, ctx) => ctx.get[List[AssemblyLine]](1)),
|
(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",
|
val TailCallOptimization = new RuleBasedAssemblyOptimization("Tail call optimization",
|
||||||
needsFlowInfo = FlowInfoRequirement.NoRequirement,
|
needsFlowInfo = FlowInfoRequirement.NoRequirement,
|
||||||
(Elidable & HasOpcode(JSR)) ~ HasOpcodeIn(NoopDiscardsFlags).* ~ (Elidable & HasOpcode(RTS)) ~~> (c => c.head.copy(opcode = JMP) :: Nil),
|
(Elidable & HasOpcode(JSR)) ~ HasOpcodeIn(NoopDiscardsFlags).* ~ (Elidable & HasOpcode(RTS)) ~~> (c => c.head.copy(opcode = JMP) :: Nil),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user