1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-07-05 09:28:54 +00:00

6502: Various optimization fixes and improvements

This commit is contained in:
Karol Stasiak 2018-07-24 16:17:27 +02:00
parent e280aca08b
commit 80efa95ba7

View File

@ -23,7 +23,9 @@ object AlwaysGoodOptimizations {
def getNextLabel(prefix: String) = f".$prefix%s__${counter.getAndIncrement()}%05d"
val PointlessMath = new RuleBasedAssemblyOptimization("Pointless math",
private def jvmFix(r: => RuleBasedAssemblyOptimization): RuleBasedAssemblyOptimization = r
val PointlessMath = jvmFix(new RuleBasedAssemblyOptimization("Pointless math",
needsFlowInfo = FlowInfoRequirement.BackwardFlow,
(HasOpcode(CLC) & Elidable) ~
(HasOpcode(ADC) & Elidable & MatchParameter(0)) ~
@ -39,7 +41,7 @@ object AlwaysGoodOptimizations {
AssemblyLine.implied(CLC),
AssemblyLine.immediate(ADC, (ctx.get[Constant](0) + ctx.get[Constant](1)).quickSimplify),
)),
)
))
val PointlessAccumulatorShifting = new RuleBasedAssemblyOptimization("Pointless accumulator shifting",
needsFlowInfo = FlowInfoRequirement.BackwardFlow,
@ -333,7 +335,7 @@ object AlwaysGoodOptimizations {
},
)
val PointlessStashingForLaterLoad = new RuleBasedAssemblyOptimization("Pointless stashing for later load",
val PointlessStashingForLaterLoad = jvmFix(new RuleBasedAssemblyOptimization("Pointless stashing for later load",
needsFlowInfo = FlowInfoRequirement.BackwardFlow,
(Elidable & HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1)) ~
(Elidable & HasOpcode(STA) & MatchAddrMode(10) & MatchParameter(11) & DoesntMatterWhatItDoesWith(State.A, State.Z, State.N)) ~
@ -382,7 +384,7 @@ object AlwaysGoodOptimizations {
(Elidable & HasOpcode(TZA)) ~~> { code =>
code.tail.init ++ List(code.head.copy(opcode = LDA), AssemblyLine.implied(TAZ))
},
)
))
val PointlessLoadBeforeReturn = new RuleBasedAssemblyOptimization("Pointless load before return",
needsFlowInfo = FlowInfoRequirement.NoRequirement,
@ -441,8 +443,8 @@ object AlwaysGoodOptimizations {
operationPairBuilder(PHZ, PLZ, Not(ChangesIZ) & Not(ConcernsStack), Some(DISCARD_YF)),
operationPairBuilder(INX, DEX, Not(ConcernsX) & Not(ReadsNOrZ), None),
operationPairBuilder(DEX, INX, Not(ConcernsX) & Not(ReadsNOrZ), None),
operationPairBuilder(INY, DEY, Not(ConcernsX) & Not(ReadsNOrZ), None),
operationPairBuilder(DEY, INY, Not(ConcernsX) & Not(ReadsNOrZ), None),
operationPairBuilder(INY, DEY, Not(ConcernsY) & Not(ReadsNOrZ), None),
operationPairBuilder(DEY, INY, Not(ConcernsY) & Not(ReadsNOrZ), None),
)
@ -510,8 +512,8 @@ object AlwaysGoodOptimizations {
operationPairBuilder3(PHB, Anything, PLB, Not(HasOpcodeIn(ChangesDataBankRegister)), None),
operationPairBuilder3(INX, DoesntMatterWhatItDoesWith(State.N, State.Z), DEX, Not(ConcernsX) & Not(ReadsNOrZ), None),
operationPairBuilder3(DEX, DoesntMatterWhatItDoesWith(State.N, State.Z), INX, Not(ConcernsX) & Not(ReadsNOrZ), None),
operationPairBuilder3(INY, DoesntMatterWhatItDoesWith(State.N, State.Z), DEY, Not(ConcernsX) & Not(ReadsNOrZ), None),
operationPairBuilder3(DEY, DoesntMatterWhatItDoesWith(State.N, State.Z), INY, Not(ConcernsX) & Not(ReadsNOrZ), None),
operationPairBuilder3(INY, DoesntMatterWhatItDoesWith(State.N, State.Z), DEY, Not(ConcernsY) & Not(ReadsNOrZ), None),
operationPairBuilder3(DEY, DoesntMatterWhatItDoesWith(State.N, State.Z), INY, Not(ConcernsY) & Not(ReadsNOrZ), None),
operationPairBuilder4(
LDA, DoesntMatterWhatItDoesWith(State.N, State.Z),
Not(ConcernsA),
@ -589,24 +591,48 @@ object AlwaysGoodOptimizations {
needsFlowInfo = FlowInfoRequirement.BothFlows,
(Elidable & HasOpcode(CLC) & HasClear(State.D)) ~
(Elidable & HasOpcode(ADC) & HasImmediate(1)) ~
(Elidable & HasOpcode(TAY) & DoesntMatterWhatItDoesWith(State.A, State.C)) ~~> { code =>
(Elidable & HasOpcode(TAY) & DoesntMatterWhatItDoesWith(State.A, State.C, State.V)) ~~> { code =>
List(AssemblyLine.implied(TAY), AssemblyLine.implied(INY))
},
(Elidable & HasOpcode(SEC) & HasClear(State.D)) ~
(Elidable & HasOpcode(SBC) & HasImmediate(1)) ~
(Elidable & HasOpcode(TAY) & DoesntMatterWhatItDoesWith(State.A, State.C)) ~~> { code =>
(Elidable & HasOpcode(TAY) & DoesntMatterWhatItDoesWith(State.A, State.C, State.V)) ~~> { code =>
List(AssemblyLine.implied(TAY), AssemblyLine.implied(DEY))
},
(Elidable & HasOpcode(CLC) & HasClear(State.D)) ~
(Elidable & HasOpcode(ADC) & HasImmediate(1)) ~
(Elidable & HasOpcode(TAX) & DoesntMatterWhatItDoesWith(State.A, State.C)) ~~> { code =>
(Elidable & HasOpcode(TAX) & DoesntMatterWhatItDoesWith(State.A, State.C, State.V)) ~~> { code =>
List(AssemblyLine.implied(TAX), AssemblyLine.implied(INX))
},
(Elidable & HasOpcode(SEC) & HasClear(State.D)) ~
(Elidable & HasOpcode(SBC) & HasImmediate(1)) ~
(Elidable & HasOpcode(TAX) & DoesntMatterWhatItDoesWith(State.A, State.C)) ~~> { code =>
(Elidable & HasOpcode(TAX) & DoesntMatterWhatItDoesWith(State.A, State.C, State.V)) ~~> { code =>
List(AssemblyLine.implied(TAX), AssemblyLine.implied(DEX))
},
(Elidable & HasOpcode(TXA)) ~
(Elidable & HasOpcode(CLC) & HasClear(State.D)) ~
(Elidable & HasOpcode(ADC) & HasImmediate(1)) ~
(Elidable & HasOpcode(TAX) & DoesntMatterWhatItDoesWith(State.C, State.V)) ~~> { code =>
List(AssemblyLine.implied(INX), AssemblyLine.implied(TXA))
},
(Elidable & HasOpcode(TXA)) ~
(Elidable & HasOpcode(CLC) & HasClear(State.D)) ~
(Elidable & HasOpcode(ADC) & HasImmediate(2)) ~
(Elidable & HasOpcode(TAX) & DoesntMatterWhatItDoesWith(State.C, State.V)) ~~> { code =>
List(AssemblyLine.implied(INX), AssemblyLine.implied(INX), AssemblyLine.implied(TXA))
},
(Elidable & HasOpcode(TYA)) ~
(Elidable & HasOpcode(CLC) & HasClear(State.D)) ~
(Elidable & HasOpcode(ADC) & HasImmediate(1)) ~
(Elidable & HasOpcode(TAY) & DoesntMatterWhatItDoesWith(State.C, State.V)) ~~> { code =>
List(AssemblyLine.implied(INY), AssemblyLine.implied(TYA))
},
(Elidable & HasOpcode(TYA)) ~
(Elidable & HasOpcode(CLC) & HasClear(State.D)) ~
(Elidable & HasOpcode(ADC) & HasImmediate(2)) ~
(Elidable & HasOpcode(TAY) & DoesntMatterWhatItDoesWith(State.C, State.V)) ~~> { code =>
List(AssemblyLine.implied(INY), AssemblyLine.implied(INY), AssemblyLine.implied(TYA))
},
)
val BranchInPlaceRemoval = new RuleBasedAssemblyOptimization("Branch in place",
@ -792,7 +818,7 @@ object AlwaysGoodOptimizations {
}
}
val ModificationOfJustWrittenValue = new RuleBasedAssemblyOptimization("Modification of just written value",
val ModificationOfJustWrittenValue = jvmFix(new RuleBasedAssemblyOptimization("Modification of just written value",
needsFlowInfo = FlowInfoRequirement.BothFlows,
modificationOfJustWrittenValue(STA, Absolute, MatchA(5), INC, Anything, atLeastTwo = false, Seq(), (c, i) => List(
AssemblyLine.immediate(LDA, (c.get[Int](5) + i) & 0xff)
@ -870,7 +896,7 @@ object AlwaysGoodOptimizations {
(Elidable & HasOpcode(DEC) & Not(HasAddrMode(Implied)) & MatchAddrMode(3) & MatchParameter(0) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~
(Linear & DoesNotConcernMemoryAt(3, 0) & DoesntChangeIndexingInAddrMode(3)).* ~
(Elidable & HasOpcode(INC) & Not(HasAddrMode(Implied)) & MatchAddrMode(3) & MatchParameter(0) & DoesntMatterWhatItDoesWith(State.N, State.Z)) ~~> (_.init.tail),
)
))
val ConstantFlowAnalysis = new RuleBasedAssemblyOptimization("Constant flow analysis",
needsFlowInfo = FlowInfoRequirement.ForwardFlow,
@ -903,8 +929,8 @@ object AlwaysGoodOptimizations {
},
)
val LoadingOfJustWrittenValue = new RuleBasedAssemblyOptimization("Loading of just written value",
needsFlowInfo = FlowInfoRequirement.ForwardFlow,
val LoadingOfJustWrittenValue = jvmFix(new RuleBasedAssemblyOptimization("Loading of just written value",
needsFlowInfo = FlowInfoRequirement.BothFlows,
(HasOpcode(STA) & XContainsStackPointer & HasAddrMode(AbsoluteX) & MatchAddrMode(0) & MatchParameter(1) & MatchA(2) & HasParameterWhere(_ match {
case NumericConstant(addr, _) => addr >= 0x100 && addr <= 0x1ff
@ -944,7 +970,34 @@ object AlwaysGoodOptimizations {
code.init :+ code.last.copy(addrMode = AddrMode.Immediate, parameter = NumericConstant(ctx.get[Int](2), 1))
},
)
(HasOpcode(PHA)) ~
(Linear & Not(ChangesA) & Not(ChangesStack) & Not(ChangesMemory)).* ~
(Elidable & XContainsStackPointer & HasOpcode(LDA) & DoesntMatterWhatItDoesWith(State.N, State.Z) & HasAddrMode(AbsoluteX) & HasParameterWhere(p => p.quickSimplify match {
case NumericConstant(n, _) => n == 0x101
case _ => false
})) ~~> (_.init),
(HasOpcode(PHA)) ~
(Linear & Not(ChangesA) & Not(ChangesStack) & Not(ChangesMemory)).* ~
(Elidable & HasOpcode(LDA) & HasAddrMode(Stack) & DoesntMatterWhatItDoesWith(State.N, State.Z) & HasParameterWhere(p => p.quickSimplify match {
case NumericConstant(n, _) => n == 1
case _ => false
})) ~~> (_.init),
(HasOpcode(PHA)) ~
(Linear & Not(ChangesA) & Not(ChangesStack) & Not(ChangesMemory)).* ~
(Elidable & XContainsStackPointer & HasOpcode(LDA) & HasAddrMode(AbsoluteX) & HasParameterWhere(p => p.quickSimplify match {
case NumericConstant(n, _) => n == 0x101
case _ => false
})) ~~> (code => code.init :+ AssemblyLine.immediate(ORA, 0)),
(HasOpcode(PHA)) ~
(Linear & Not(ChangesA) & Not(ChangesStack) & Not(ChangesMemory)).* ~
(Elidable & HasOpcode(LDA) & HasAddrMode(Stack) & HasParameterWhere(p => p.quickSimplify match {
case NumericConstant(n, _) => n == 1
case _ => false
})) ~~> (code => code.init :+ AssemblyLine.immediate(ORA, 0))
))
val PointlessStackStore = new RuleBasedAssemblyOptimization("Pointless stack store",
needsFlowInfo = FlowInfoRequirement.BothFlows,