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:
parent
03c400a356
commit
7b480ea876
@ -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,
|
||||
|
@ -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)) ~
|
||||
|
@ -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))
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user