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:
parent
dbe8e39e4a
commit
a985c4f753
@ -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)).* ~
|
||||||
|
@ -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)
|
||||||
|
@ -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)) ~
|
||||||
|
@ -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))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -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
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user