1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-12-24 15:29:23 +00:00

Optimization improvements

This commit is contained in:
Karol Stasiak 2018-02-27 12:02:15 +01:00
parent f9835ebf7e
commit 3d056a7eee
2 changed files with 70 additions and 0 deletions

View File

@ -33,6 +33,22 @@ object LaterOptimizations {
TwoDifferentLoadsWhoseFlagsWillNotBeChecked(LDA, Not(ChangesA), LDY, TAY),
TwoDifferentLoadsWhoseFlagsWillNotBeChecked(LDX, Not(ChangesX), LDA, TXA),
TwoDifferentLoadsWhoseFlagsWillNotBeChecked(LDY, Not(ChangesY), LDA, TYA),
(HasOpcodeIn(Set(LDA, STA)) & MatchAddrMode(0) & MatchParameter(1)) ~
(Linear & Not(ChangesA) & Not(HasOpcode(LDX)) & DoesntChangeIndexingInAddrMode(0) & DoesntChangeMemoryAt(0, 1)).* ~
(Elidable & HasOpcode(LDX) & MatchAddrMode(0) & MatchParameter(1)) ~~> (code => code.init :+ AssemblyLine.implied(TAX)),
(HasOpcodeIn(Set(LDA, STA)) & MatchAddrMode(0) & MatchParameter(1)) ~
(Linear & Not(ChangesA) & Not(HasOpcode(LDY)) & DoesntChangeIndexingInAddrMode(0) & DoesntChangeMemoryAt(0, 1)).* ~
(Elidable & HasOpcode(LDY) & MatchAddrMode(0) & MatchParameter(1)) ~~> (code => code.init :+ AssemblyLine.implied(TAY)),
(HasOpcodeIn(Set(LDX, STX)) & MatchAddrMode(0) & MatchParameter(1)) ~
(Linear & Not(ChangesX) & Not(HasOpcode(LDA)) & DoesntChangeIndexingInAddrMode(0) & DoesntChangeMemoryAt(0, 1)).* ~
(Elidable & HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1)) ~~> (code => code.init :+ AssemblyLine.implied(TXA)),
(HasOpcodeIn(Set(LDY, STY)) & MatchAddrMode(0) & MatchParameter(1)) ~
(Linear & Not(ChangesY) & Not(HasOpcode(LDA)) & DoesntChangeIndexingInAddrMode(0) & DoesntChangeMemoryAt(0, 1)).* ~
(Elidable & HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1)) ~~> (code => code.init :+ AssemblyLine.implied(TYA)),
)
private def a2x(line: AssemblyLine) = line.opcode match {

View File

@ -53,6 +53,8 @@ object VariableToRegisterOptimization extends AssemblyOptimization {
AHX, SHY, SHX, LAS, TAS,
TRB, TSB)
private val opcodesCommutative = Set(AND, ORA, EOR, ADC)
private val LdxAddrModes = Set(ZeroPage, Absolute, Immediate, AbsoluteY, ZeroPageY)
private val LdyAddrModes = Set(ZeroPage, Absolute, Immediate, AbsoluteX, ZeroPageX)
@ -288,6 +290,20 @@ object VariableToRegisterOptimization extends AssemblyOptimization {
// if a register is populated with something else than a variable, then no variable cannot be assigned to that register
None
case (AssemblyLine(LDA, _, _, elidable),_) :: (AssemblyLine(op, Absolute | ZeroPage, MemoryAddressConstant(th), elidable2),_) :: xs
if opcodesCommutative(op) =>
if (th.name == vx || th.name == vy) {
if (elidable && elidable2) canBeInlined(xCandidate, yCandidate, xs).map(_ + 2)
else None
} else canBeInlined(xCandidate, yCandidate, xs)
case (AssemblyLine(LDA, _, _, elidable),_) :: (AssemblyLine(CLC, _, _, _),_) :: (AssemblyLine(op, Absolute | ZeroPage, MemoryAddressConstant(th), elidable2),_) :: xs
if opcodesCommutative(op) =>
if (th.name == vx || th.name == vy) {
if (elidable && elidable2) canBeInlined(xCandidate, yCandidate, xs).map(_ + 2)
else None
} else canBeInlined(xCandidate, yCandidate, xs)
case (AssemblyLine(LDA, Absolute | ZeroPage, MemoryAddressConstant(th), elidable), _) :: (AssemblyLine(TAX, _, _, elidable2), _) :: xs
if xCandidate.isDefined =>
// a variable cannot be inlined if there is TAX not after LDA of that variable
@ -416,6 +432,20 @@ object VariableToRegisterOptimization extends AssemblyOptimization {
None
}
case (AssemblyLine(LDA, _, _, elidable),_) :: (AssemblyLine(op, Absolute | ZeroPage, MemoryAddressConstant(th), elidable2),_) :: xs
if opcodesCommutative(op) =>
if (th.name == candidate) {
if (elidable && elidable2) canBeInlinedToAccumulator(options, start = false, synced = true, candidate, xs).map(_ + 3)
else None
} else canBeInlinedToAccumulator(options, start = false, synced = synced, candidate, xs)
case (AssemblyLine(LDA, _, _, elidable),_) :: (AssemblyLine(CLC, _, _, _),_) :: (AssemblyLine(op, Absolute | ZeroPage, MemoryAddressConstant(th), elidable2),_) :: xs
if opcodesCommutative(op) =>
if (th.name == candidate) {
if (elidable && elidable2) canBeInlinedToAccumulator(options, start = false, synced = true, candidate, xs).map(_ + 3)
else None
} else canBeInlinedToAccumulator(options, start = false, synced = synced, candidate, xs)
case (AssemblyLine(LDA, Absolute | ZeroPage, MemoryAddressConstant(th), true), imp) :: xs
if th.name == candidate =>
// removing LDA saves 3 cycles
@ -505,6 +535,30 @@ object VariableToRegisterOptimization extends AssemblyOptimization {
if th.name == vx =>
AssemblyLine.implied(TXA) :: inlineVars(xCandidate, yCandidate, aCandidate, xs)
case (l@AssemblyLine(LDA, _, _, _), _) :: (AssemblyLine(op, Absolute | ZeroPage, MemoryAddressConstant(th), _), _) :: xs
if opcodesCommutative(op) && th.name == va =>
l.copy(opcode = op) :: inlineVars(xCandidate, yCandidate, aCandidate, xs)
case (l@AssemblyLine(LDA, _, _, _), _) :: (clc@AssemblyLine(CLC, _, _, _), _) :: (AssemblyLine(op, Absolute | ZeroPage, MemoryAddressConstant(th), _), _) :: xs
if opcodesCommutative(op) && th.name == va =>
l.copy(opcode = op) :: clc :: inlineVars(xCandidate, yCandidate, aCandidate, xs)
case (l@AssemblyLine(LDA, _, _, _), _) :: (AssemblyLine(op, Absolute | ZeroPage, MemoryAddressConstant(th), _), _) :: xs
if opcodesCommutative(op) && th.name == vx =>
AssemblyLine.implied(TXA) :: l.copy(opcode = op) :: inlineVars(xCandidate, yCandidate, aCandidate, xs)
case (l@AssemblyLine(LDA, _, _, _), _) :: (clc@AssemblyLine(CLC, _, _, _), _) :: (AssemblyLine(op, Absolute | ZeroPage, MemoryAddressConstant(th), _), _) :: xs
if opcodesCommutative(op) && th.name == vx =>
AssemblyLine.implied(TXA) :: l.copy(opcode = op) :: clc :: inlineVars(xCandidate, yCandidate, aCandidate, xs)
case (l@AssemblyLine(LDA, _, _, _), _) :: (AssemblyLine(op, Absolute | ZeroPage, MemoryAddressConstant(th), _), _) :: xs
if opcodesCommutative(op) && th.name == vy =>
AssemblyLine.implied(TYA) :: l.copy(opcode = op) :: inlineVars(xCandidate, yCandidate, aCandidate, xs)
case (l@AssemblyLine(LDA, _, _, _), _) :: (clc@AssemblyLine(CLC, _, _, _), _) :: (AssemblyLine(op, Absolute | ZeroPage, MemoryAddressConstant(th), _), _) :: xs
if opcodesCommutative(op) && th.name == vy =>
AssemblyLine.implied(TYA) :: l.copy(opcode = op) :: clc :: inlineVars(xCandidate, yCandidate, aCandidate, xs)
case (AssemblyLine(LDA | STA, Absolute | ZeroPage, MemoryAddressConstant(th), _), imp) :: xs
if th.name == va =>
if (imp.z == Unimportant && imp.n == Unimportant) {