mirror of
https://github.com/KarolS/millfork.git
synced 2024-09-10 11:54:30 +00:00
More various optimization fixes and improvements
This commit is contained in:
parent
dbe8e39e4a
commit
a985c4f753
@ -1320,44 +1320,52 @@ object AlwaysGoodOptimizations {
|
||||
HasOpcode(TAY) ~
|
||||
(LinearOrBranch & Not(ChangesY) & DoesntChangeMemoryAt(0, 1)).* ~
|
||||
(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",
|
||||
needsFlowInfo = FlowInfoRequirement.NoRequirement,
|
||||
needsFlowInfo = FlowInfoRequirement.BackwardFlow,
|
||||
|
||||
(HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1)) ~
|
||||
(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))
|
||||
},
|
||||
(HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1)) ~
|
||||
(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))
|
||||
},
|
||||
(HasOpcode(STA) & MatchAddrMode(0) & MatchParameter(1)) ~
|
||||
(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))
|
||||
},
|
||||
(HasOpcode(STA) & MatchAddrMode(0) & MatchParameter(1)) ~
|
||||
(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))
|
||||
},
|
||||
(HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(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
|
||||
},
|
||||
(HasOpcode(LDX) & MatchAddrMode(0) & MatchParameter(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
|
||||
},
|
||||
(HasOpcode(LDY) & MatchAddrMode(0) & MatchParameter(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
|
||||
},
|
||||
)
|
||||
@ -1787,7 +1795,7 @@ object AlwaysGoodOptimizations {
|
||||
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(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))),
|
||||
(HasOpcode(AND) & HasImmediate(1)) ~
|
||||
(Linear & Not(ChangesNAndZ) & Not(HasOpcode(CLC)) & Not(ChangesA)).* ~
|
||||
|
@ -175,7 +175,7 @@ object ZeropageRegisterOptimizations {
|
||||
|
||||
(Elidable & HasOpcode(LDY) & RefersTo("__reg", 0)) ~
|
||||
(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))).* ~
|
||||
(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)
|
||||
|
@ -1044,7 +1044,16 @@ object AlwaysGoodI80Optimizations {
|
||||
|
||||
val PointlessArithmetic = new RuleBasedAssemblyOptimization("Pointless arithmetic",
|
||||
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",
|
||||
@ -1175,7 +1184,6 @@ object AlwaysGoodI80Optimizations {
|
||||
},
|
||||
|
||||
(Elidable & HasOpcodeIn(Set(JP, JR)) & MatchJumpTarget(3) & IsUnconditional & MatchRegister(ZRegister.B, 1)) ~
|
||||
DebugMatching ~
|
||||
(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 & IsLabelMatching(3)) ~
|
||||
|
@ -10,7 +10,7 @@ import org.scalatest.{FunSuite, Matchers}
|
||||
class InliningSuite extends FunSuite with Matchers {
|
||||
|
||||
test("Should inline square") {
|
||||
EmuSizeOptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
"""
|
||||
| import zp_reg
|
||||
| byte output @$c000
|
||||
@ -24,7 +24,7 @@ class InliningSuite extends FunSuite with Matchers {
|
||||
}
|
||||
|
||||
test("Should inline <<") {
|
||||
EmuSizeOptimizedCrossPlatformRun(Cpu.Mos, Cpu.Z80)(
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
"""
|
||||
| byte output @$c000
|
||||
| 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))
|
||||
}
|
||||
}
|
||||
}
|
@ -18,6 +18,10 @@ object EmuOptimizedRun extends EmuRun(
|
||||
OptimizationPresets.Good ++ LaterOptimizations.Nmos ++
|
||||
ZeropageRegisterOptimizations.All ++
|
||||
OptimizationPresets.Good ++
|
||||
ZeropageRegisterOptimizations.All ++
|
||||
OptimizationPresets.Good ++
|
||||
ZeropageRegisterOptimizations.All ++
|
||||
OptimizationPresets.Good ++
|
||||
OptimizationPresets.Good)
|
||||
|
||||
object EmuSizeOptimizedRun extends EmuRun(
|
||||
@ -31,6 +35,10 @@ object EmuSizeOptimizedRun extends EmuRun(
|
||||
OptimizationPresets.Good ++ LaterOptimizations.Nmos ++
|
||||
ZeropageRegisterOptimizations.All ++
|
||||
OptimizationPresets.Good ++
|
||||
ZeropageRegisterOptimizations.All ++
|
||||
OptimizationPresets.Good ++
|
||||
ZeropageRegisterOptimizations.All ++
|
||||
OptimizationPresets.Good ++
|
||||
OptimizationPresets.Good) {
|
||||
override def optimizeForSize = true
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user