1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-11-03 18:04:46 +00:00

More various optimization fixes and improvements

This commit is contained in:
Karol Stasiak 2018-12-14 00:10:30 +01:00
parent dbe8e39e4a
commit a985c4f753
5 changed files with 53 additions and 14 deletions

View File

@ -1320,44 +1320,52 @@ object AlwaysGoodOptimizations {
HasOpcode(TAY) ~ HasOpcode(TAY) ~
(LinearOrBranch & Not(ChangesY) & DoesntChangeMemoryAt(0, 1)).* ~ (LinearOrBranch & Not(ChangesY) & DoesntChangeMemoryAt(0, 1)).* ~
(Elidable & HasOpcode(LDY) & HasAddrModeIn(ZeroPage, Absolute) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> (_.init), (Elidable & HasOpcode(LDY) & HasAddrModeIn(ZeroPage, Absolute) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> (_.init),
(HasOpcodeIn(LDA, STA) & MatchAddrMode(0) & MatchParameter(1)) ~
(Linear & Not(ChangesA) & Not(HasOpcode(DISCARD_AF)) & DoesntChangeIndexingInAddrMode(0) & DoesNotConcernMemoryAt(0, 1)).* ~
(Elidable & HasOpcode(LDX) & MatchAddrMode(0) & MatchParameter(1)) ~~> (code => code.init :+ AssemblyLine.implied(TAX)),
(HasOpcodeIn(LDA, STA) & MatchAddrMode(0) & MatchParameter(1)) ~
(Linear & Not(ChangesA) & Not(HasOpcode(DISCARD_AF)) & DoesntChangeIndexingInAddrMode(0) & DoesNotConcernMemoryAt(0, 1)).* ~
(Elidable & HasOpcode(LDY) & MatchAddrMode(0) & MatchParameter(1)) ~~> (code => code.init :+ AssemblyLine.implied(TAY)),
) )
val RearrangableLoadFromTheSameLocation = new RuleBasedAssemblyOptimization("Rearrangable load from the same location", val RearrangableLoadFromTheSameLocation = new RuleBasedAssemblyOptimization("Rearrangable load from the same location",
needsFlowInfo = FlowInfoRequirement.NoRequirement, needsFlowInfo = FlowInfoRequirement.BackwardFlow,
(HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1)) ~ (HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1)) ~
(HasOpcode(STA) & Not(ReadsX)) ~ (HasOpcode(STA) & Not(ReadsX)) ~
(Elidable & HasOpcode(LDX) & MatchAddrMode(0) & MatchParameter(1)) ~~> {code => (Elidable & HasOpcode(LDX) & MatchAddrMode(0) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> { code =>
List(code.head, AssemblyLine.implied(TAX), code(1)) List(code.head, AssemblyLine.implied(TAX), code(1))
}, },
(HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1)) ~ (HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1)) ~
(HasOpcode(STA) & Not(ReadsY)) ~ (HasOpcode(STA) & Not(ReadsY)) ~
(Elidable & HasOpcode(LDY) & MatchAddrMode(0) & MatchParameter(1)) ~~> {code => (Elidable & HasOpcode(LDY) & MatchAddrMode(0) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> {code =>
List(code.head, AssemblyLine.implied(TAY), code(1)) List(code.head, AssemblyLine.implied(TAY), code(1))
}, },
(HasOpcode(STA) & MatchAddrMode(0) & MatchParameter(1)) ~ (HasOpcode(STA) & MatchAddrMode(0) & MatchParameter(1)) ~
(HasOpcode(LDA) & Not(ReadsX)) ~ (HasOpcode(LDA) & Not(ReadsX)) ~
(Elidable & HasOpcode(LDX) & MatchAddrMode(0) & MatchParameter(1)) ~~> {code => (Elidable & HasOpcode(LDX) & MatchAddrMode(0) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> {code =>
List(code.head, AssemblyLine.implied(TAX), code(1)) List(code.head, AssemblyLine.implied(TAX), code(1))
}, },
(HasOpcode(STA) & MatchAddrMode(0) & MatchParameter(1)) ~ (HasOpcode(STA) & MatchAddrMode(0) & MatchParameter(1)) ~
(HasOpcode(LDA) & Not(ReadsY)) ~ (HasOpcode(LDA) & Not(ReadsY)) ~
(Elidable & HasOpcode(LDY) & MatchAddrMode(0) & MatchParameter(1)) ~~> {code => (Elidable & HasOpcode(LDY) & MatchAddrMode(0) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> {code =>
List(code.head, AssemblyLine.implied(TAY), code(1)) List(code.head, AssemblyLine.implied(TAY), code(1))
}, },
(HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1)) ~ (HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1)) ~
(Linear & Not(ChangesA) & Not(ChangesNAndZ) & DoesntChangeMemoryAt(0, 1)).* ~ (Linear & Not(ChangesA) & Not(ChangesNAndZ) & DoesntChangeMemoryAt(0, 1)).* ~
(Elidable & HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1)) ~~> {code => (Elidable & HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> {code =>
code.init code.init
}, },
(HasOpcode(LDX) & MatchAddrMode(0) & MatchParameter(1)) ~ (HasOpcode(LDX) & MatchAddrMode(0) & MatchParameter(1)) ~
(Linear & Not(ChangesX) & Not(ChangesNAndZ) & DoesntChangeMemoryAt(0, 1)).* ~ (Linear & Not(ChangesX) & Not(ChangesNAndZ) & DoesntChangeMemoryAt(0, 1)).* ~
(Elidable & HasOpcode(LDX) & MatchAddrMode(0) & MatchParameter(1)) ~~> {code => (Elidable & HasOpcode(LDX) & MatchAddrMode(0) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> {code =>
code.init code.init
}, },
(HasOpcode(LDY) & MatchAddrMode(0) & MatchParameter(1)) ~ (HasOpcode(LDY) & MatchAddrMode(0) & MatchParameter(1)) ~
(Linear & Not(ChangesY) & Not(ChangesNAndZ) & DoesntChangeMemoryAt(0, 1)).* ~ (Linear & Not(ChangesY) & Not(ChangesNAndZ) & DoesntChangeMemoryAt(0, 1)).* ~
(Elidable & HasOpcode(LDY) & MatchAddrMode(0) & MatchParameter(1)) ~~> {code => (Elidable & HasOpcode(LDY) & MatchAddrMode(0) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> {code =>
code.init code.init
}, },
) )
@ -1787,7 +1795,7 @@ object AlwaysGoodOptimizations {
List(code.head, AssemblyLine.implied(ROL)) List(code.head, AssemblyLine.implied(ROL))
}, },
(Elidable & HasOpcode(ADC) & HasImmediate(0) & HasClear(State.C) & DoesntMatterWhatItDoesWith(State.V, State.C, State.N, State.Z)) ~~> (_ => Nil), (Elidable & HasOpcode(ADC) & HasImmediate(0) & HasClear(State.C) & DoesntMatterWhatItDoesWith(State.V, State.C, State.N, State.Z)) ~~> (_ => Nil),
(Elidable & HasOpcode(ROL) & HasClear(State.C)) ~~> (code => code.map(_.copy(opcode = ASL))), (Elidable & HasOpcode(ROL) & HasClear(State.C)) ~ DebugMatching ~~> (code => code.map(_.copy(opcode = ASL))),
(Elidable & HasOpcode(ROR) & HasClear(State.C)) ~~> (code => code.map(_.copy(opcode = LSR))), (Elidable & HasOpcode(ROR) & HasClear(State.C)) ~~> (code => code.map(_.copy(opcode = LSR))),
(HasOpcode(AND) & HasImmediate(1)) ~ (HasOpcode(AND) & HasImmediate(1)) ~
(Linear & Not(ChangesNAndZ) & Not(HasOpcode(CLC)) & Not(ChangesA)).* ~ (Linear & Not(ChangesNAndZ) & Not(HasOpcode(CLC)) & Not(ChangesA)).* ~

View File

@ -175,7 +175,7 @@ object ZeropageRegisterOptimizations {
(Elidable & HasOpcode(LDY) & RefersTo("__reg", 0)) ~ (Elidable & HasOpcode(LDY) & RefersTo("__reg", 0)) ~
(Linear & Not(ConcernsY) & Not(RefersToOrUses("__reg", 0))).*.capture(2) ~ (Linear & Not(ConcernsY) & Not(RefersToOrUses("__reg", 0))).*.capture(2) ~
(Elidable & (HasA(0) & HasOpcode(STA) | HasOpcode(STZ)) & RefersTo("__reg", 0) & DoesntMatterWhatItDoesWith(State.A)) ~ (Elidable & (HasA(0) & HasOpcode(STA) | HasZ(0) & HasOpcode(STZ)) & RefersTo("__reg", 0) & DoesntMatterWhatItDoesWith(State.A)) ~
((Linear & Not(ConcernsY) & Not(RefersToOrUses("__reg", 0))).* ~ ((Linear & Not(ConcernsY) & Not(RefersToOrUses("__reg", 0))).* ~
(Elidable & RefersToOrUses("__reg", 0) & HasAddrMode(IndexedY) & DoesntMatterWhatItDoesWithReg(0) & DoesntMatterWhatItDoesWith(State.Y))).capture(3) ~~> ((code, ctx) => (Elidable & RefersToOrUses("__reg", 0) & HasAddrMode(IndexedY) & DoesntMatterWhatItDoesWithReg(0) & DoesntMatterWhatItDoesWith(State.Y))).capture(3) ~~> ((code, ctx) =>
ctx.get[List[AssemblyLine]](2) ++ List(AssemblyLine.immediate(LDY, 0)) ++ ctx.get[List[AssemblyLine]](3) ctx.get[List[AssemblyLine]](2) ++ List(AssemblyLine.immediate(LDY, 0)) ++ ctx.get[List[AssemblyLine]](3)

View File

@ -1044,7 +1044,16 @@ object AlwaysGoodI80Optimizations {
val PointlessArithmetic = new RuleBasedAssemblyOptimization("Pointless arithmetic", val PointlessArithmetic = new RuleBasedAssemblyOptimization("Pointless arithmetic",
needsFlowInfo = FlowInfoRequirement.BackwardFlow, needsFlowInfo = FlowInfoRequirement.BackwardFlow,
(Elidable & HasOpcodeIn(Set(ADD, ADC, SUB, SBC, OR, AND, XOR, CP)) & DoesntMatterWhatItDoesWithFlags & DoesntMatterWhatItDoesWith(ZRegister.A)) ~~> (_ => Nil) (Elidable & HasOpcodeIn(Set(ADD, ADC, SUB, SBC, OR, AND, XOR, CP)) & DoesntMatterWhatItDoesWithFlags & DoesntMatterWhatItDoesWith(ZRegister.A)) ~~> (_ => Nil),
for7Registers(register =>
(Elidable & HasOpcodeIn(Set(INC, DEC))
& HasRegisterParam(register) & DoesntMatterWhatItDoesWithFlagsExceptCarry & DoesntMatterWhatItDoesWith(register)) ~~> (_ => Nil)
),
for7Registers(register =>
(Elidable & HasOpcodeIn(Set(SLA, RRC, RR, RL, RLC, SLL, SRL, SRA))
& HasRegisterParam(register) & DoesntMatterWhatItDoesWithFlags & DoesntMatterWhatItDoesWith(register)) ~~> (_ => Nil)
),
(Elidable & HasOpcode(DAA) & DoesntMatterWhatItDoesWithFlags & DoesntMatterWhatItDoesWith(ZRegister.A)) ~~> (_ => Nil),
) )
val ConstantMultiplication = new RuleBasedAssemblyOptimization("Constant multiplication", val ConstantMultiplication = new RuleBasedAssemblyOptimization("Constant multiplication",
@ -1175,7 +1184,6 @@ object AlwaysGoodI80Optimizations {
}, },
(Elidable & HasOpcodeIn(Set(JP, JR)) & MatchJumpTarget(3) & IsUnconditional & MatchRegister(ZRegister.B, 1)) ~ (Elidable & HasOpcodeIn(Set(JP, JR)) & MatchJumpTarget(3) & IsUnconditional & MatchRegister(ZRegister.B, 1)) ~
DebugMatching ~
(Elidable & IsLabelMatching(2)) ~ (Elidable & IsLabelMatching(2)) ~
(Elidable & HasOpcodeIn(Set(ADD, SLA, SRL, SLL, RLC, RLCA, RRC, RRCA, RR, RL, RLA, RRA)) & Not(HasRegisterParam(ZRegister.B))).*.capture(5) ~ (Elidable & HasOpcodeIn(Set(ADD, SLA, SRL, SLL, RLC, RLCA, RRC, RRCA, RR, RL, RLA, RRA)) & Not(HasRegisterParam(ZRegister.B))).*.capture(5) ~
(Elidable & IsLabelMatching(3)) ~ (Elidable & IsLabelMatching(3)) ~

View File

@ -10,7 +10,7 @@ import org.scalatest.{FunSuite, Matchers}
class InliningSuite extends FunSuite with Matchers { class InliningSuite extends FunSuite with Matchers {
test("Should inline square") { test("Should inline square") {
EmuSizeOptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80)( EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
""" """
| import zp_reg | import zp_reg
| byte output @$c000 | byte output @$c000
@ -24,7 +24,7 @@ class InliningSuite extends FunSuite with Matchers {
} }
test("Should inline <<") { test("Should inline <<") {
EmuSizeOptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80)( EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
""" """
| byte output @$c000 | byte output @$c000
| word output2 @$c006 | word output2 @$c006
@ -44,4 +44,19 @@ class InliningSuite extends FunSuite with Matchers {
} }
} }
test("Should inline this weird thing") {
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
"""
| byte output @$c000
| inline word square(word x) {
| return x << x.lo
| }
| void main() {
| output = hi(square(6))
| }
""".stripMargin) { m =>
m.readByte(0xc000) should equal(6.<<(6).>>(8))
}
}
} }

View File

@ -18,6 +18,10 @@ object EmuOptimizedRun extends EmuRun(
OptimizationPresets.Good ++ LaterOptimizations.Nmos ++ OptimizationPresets.Good ++ LaterOptimizations.Nmos ++
ZeropageRegisterOptimizations.All ++ ZeropageRegisterOptimizations.All ++
OptimizationPresets.Good ++ OptimizationPresets.Good ++
ZeropageRegisterOptimizations.All ++
OptimizationPresets.Good ++
ZeropageRegisterOptimizations.All ++
OptimizationPresets.Good ++
OptimizationPresets.Good) OptimizationPresets.Good)
object EmuSizeOptimizedRun extends EmuRun( object EmuSizeOptimizedRun extends EmuRun(
@ -31,6 +35,10 @@ object EmuSizeOptimizedRun extends EmuRun(
OptimizationPresets.Good ++ LaterOptimizations.Nmos ++ OptimizationPresets.Good ++ LaterOptimizations.Nmos ++
ZeropageRegisterOptimizations.All ++ ZeropageRegisterOptimizations.All ++
OptimizationPresets.Good ++ OptimizationPresets.Good ++
ZeropageRegisterOptimizations.All ++
OptimizationPresets.Good ++
ZeropageRegisterOptimizations.All ++
OptimizationPresets.Good ++
OptimizationPresets.Good) { OptimizationPresets.Good) {
override def optimizeForSize = true override def optimizeForSize = true
} }