1
0
mirror of https://github.com/KarolS/millfork.git synced 2025-04-10 16:39:59 +00:00

Even more optimizations

This commit is contained in:
Karol Stasiak 2018-02-26 01:07:23 +01:00
parent 03c400a356
commit 7b480ea876
4 changed files with 70 additions and 0 deletions

View File

@ -45,6 +45,7 @@ object OptimizationPresets {
AlwaysGoodOptimizations.FlagFlowAnalysis,
AlwaysGoodOptimizations.ConstantFlowAnalysis,
AlwaysGoodOptimizations.PointlessMath,
AlwaysGoodOptimizations.PointlessOperationFromFlow,
VariableToRegisterOptimization,
ChangeIndexRegisterOptimizationPreferringX2Y,
VariableToRegisterOptimization,
@ -59,6 +60,7 @@ object OptimizationPresets {
LaterOptimizations.DoubleLoadToTheSameRegister,
LaterOptimizations.DoubleLoadToTwoRegistersWhenOneWillBeTrashed,
EmptyMemoryStoreRemoval,
AlwaysGoodOptimizations.PointlessOperationFromFlow,
AlwaysGoodOptimizations.PoinlessLoadBeforeAnotherLoad,
AlwaysGoodOptimizations.IdempotentDuplicateRemoval,
AlwaysGoodOptimizations.ConstantIndexPropagation,
@ -83,6 +85,7 @@ object OptimizationPresets {
AlwaysGoodOptimizations.PoinlessStoreBeforeStore,
LaterOptimizations.PointlessLoadAfterStore,
AlwaysGoodOptimizations.PoinlessLoadBeforeAnotherLoad,
AlwaysGoodOptimizations.RearrangableLoadFromTheSameLocation,
LaterOptimizations.LoadingAfterShifting,
EmptyMemoryStoreRemoval,
@ -150,6 +153,7 @@ object OptimizationPresets {
AlwaysGoodOptimizations.PointlessMath,
AlwaysGoodOptimizations.PointlessMathFromFlow,
AlwaysGoodOptimizations.PointlessOperationAfterLoad,
AlwaysGoodOptimizations.PointlessOperationFromFlow,
AlwaysGoodOptimizations.PointlessOperationPairRemoval,
AlwaysGoodOptimizations.PointlessOperationPairRemoval2,
AlwaysGoodOptimizations.PointlessRegisterTransfers,
@ -159,6 +163,7 @@ object OptimizationPresets {
AlwaysGoodOptimizations.PointlessStackStashing,
AlwaysGoodOptimizations.PointlessStashingToIndexOverShortSafeBranch,
AlwaysGoodOptimizations.PoinlessStoreBeforeStore,
AlwaysGoodOptimizations.RearrangableLoadFromTheSameLocation,
AlwaysGoodOptimizations.RearrangeMath,
AlwaysGoodOptimizations.RemoveNops,
AlwaysGoodOptimizations.ReverseFlowAnalysis,

View File

@ -111,6 +111,9 @@ object AlwaysGoodOptimizations {
HasOpcode(ANC) & HasAddrMode(Immediate) & DoesntMatterWhatItDoesWith(State.C)) ~~> { (code, ctx) =>
AssemblyLine.immediate(LDA, CompoundConstant(MathOperator.And, NumericConstant(ctx.get[Int](0), 1), ctx.get[Constant](1)).quickSimplify) :: Nil
},
(Elidable & HasA(0) & HasOpcodeIn(Set(ORA, EOR))) ~~> (code => code.map(_.copy(opcode = LDA))),
(Elidable & HasA(0) & HasOpcode(AND)) ~~> (code => List(AssemblyLine.immediate(LDA, 0))),
(Elidable & HasX(0) & HasOpcode(XAA)) ~~> (code => List(AssemblyLine.immediate(LDA, 0))),
)
val MathOperationOnTwoIdenticalMemoryOperands = new RuleBasedAssemblyOptimization("Math operation on two identical memory operands",
@ -694,6 +697,31 @@ object AlwaysGoodOptimizations {
(Elidable & HasOpcode(LDY) & MatchAddrMode(0) & MatchParameter(1)) ~~> (_.init),
)
val RearrangableLoadFromTheSameLocation = new RuleBasedAssemblyOptimization("Rearrangable load from the same location",
needsFlowInfo = FlowInfoRequirement.NoRequirement,
(HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1)) ~
(HasOpcode(STA) & Not(ReadsX)) ~
(Elidable & HasOpcode(LDX) & MatchAddrMode(0) & MatchParameter(1)) ~~> {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 =>
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 =>
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 =>
List(code.head, AssemblyLine.implied(TAY), code(1))
},
)
val PointlessOperationAfterLoad = new RuleBasedAssemblyOptimization("Pointless operation after load",
needsFlowInfo = FlowInfoRequirement.NoRequirement,
(ChangesA & ChangesNAndZ) ~ (Elidable & HasOpcode(EOR) & HasImmediate(0)) ~~> (_.init),
@ -701,6 +729,22 @@ object AlwaysGoodOptimizations {
(ChangesA & ChangesNAndZ) ~ (Elidable & HasOpcode(AND) & HasImmediate(0xff)) ~~> (_.init)
)
val PointlessOperationFromFlow = new RuleBasedAssemblyOptimization("Pointless operation from flow",
needsFlowInfo = FlowInfoRequirement.BackwardFlow,
(Elidable & HasOpcodeIn(Set(LDA, TXA, TYA, AND, EOR, ORA, XAA)) & DoesntMatterWhatItDoesWith(State.A, State.N, State.Z)) ~~> (_ => Nil),
(Elidable & HasOpcodeIn(Set(LDX, TSX, TAX, SBX, INX, DEX)) & DoesntMatterWhatItDoesWith(State.X, State.N, State.Z)) ~~> (_ => Nil),
(Elidable & HasOpcodeIn(Set(LDY, TAY, INY, DEY)) & DoesntMatterWhatItDoesWith(State.Y, State.N, State.Z)) ~~> (_ => Nil),
(Elidable & HasOpcodeIn(Set(LAX, LXA)) & DoesntMatterWhatItDoesWith(State.A, State.X, State.N, State.Z)) ~~> (_ => Nil),
(Elidable & HasOpcodeIn(Set(ANC, ALR)) & DoesntMatterWhatItDoesWith(State.A, State.N, State.Z, State.C)) ~~> (_ => Nil),
(Elidable & HasOpcodeIn(Set(ADC, SBC, ARR)) & DoesntMatterWhatItDoesWith(State.A, State.N, State.Z, State.C, State.V)) ~~> (_ => Nil),
(Elidable & HasOpcodeIn(Set(CMP, CPY, CPX, BIT)) & DoesntMatterWhatItDoesWith(State.N, State.Z, State.C, State.V)) ~~> (_ => Nil),
(Elidable & HasOpcodeIn(Set(ROL, ROR, ASL, LSR)) & HasAddrMode(Implied) & DoesntMatterWhatItDoesWith(State.A, State.N, State.Z, State.C)) ~~> (_ => Nil),
(Elidable & HasOpcodeIn(Set(INC, DEC)) & HasAddrMode(Implied) & DoesntMatterWhatItDoesWith(State.A, State.N, State.Z)) ~~> (_ => Nil),
(Elidable & HasOpcodeIn(Set(CLC, SEC)) & DoesntMatterWhatItDoesWith(State.C)) ~~> (_ => Nil),
(Elidable & HasOpcodeIn(Set(CLD, SED)) & DoesntMatterWhatItDoesWith(State.D)) ~~> (_ => Nil),
(Elidable & HasOpcodeIn(Set(CLV)) & DoesntMatterWhatItDoesWith(State.V)) ~~> (_ => Nil),
)
val SimplifiableBitOpsSequence = new RuleBasedAssemblyOptimization("Simplifiable sequence of bit operations",
needsFlowInfo = FlowInfoRequirement.NoRequirement,
(Elidable & HasOpcode(EOR) & MatchImmediate(0)) ~

View File

@ -142,6 +142,12 @@ object UndocumentedOptimizations {
code.head,
AssemblyLine.immediate(SBX, ctx.get[Constant](0)),
)),
(HasOpcodeIn(Set(LDA, TYA)) & MatchAddrMode(0) & MatchParameter(1)) ~
(Elidable & HasOpcode(AND)) ~
(Elidable & HasOpcode(TAX)) ~
(Elidable & HasOpcodeIn(Set(LDA, TYA)) & MatchAddrMode(0) & MatchParameter(1) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> {code =>
List(code.head, code(1).copy(opcode = LDX), AssemblyLine.immediate(SBX, 0))
}
)

View File

@ -207,4 +207,19 @@ class IllegalSuite extends FunSuite with Matchers {
m.readByte(0xc001) should equal(3)
m.readByte(0xc002) should equal(5)
}
test("SBX test 2") {
val m = EmuUndocumentedRun("""
| word output @$c000
| byte i
| void main () {
| i = 5
| output = o()
| }
| word o () {
| return i&3:i
| }
""".stripMargin)
m.readWord(0xc000) should equal(0x105)
}
}