mirror of
https://github.com/KarolS/millfork.git
synced 2024-12-25 06:29:17 +00:00
Added some more optimizations
This commit is contained in:
parent
6fa82a5a58
commit
986252db5b
@ -16,6 +16,7 @@ object OptimizationPresets {
|
||||
val AssOpt: List[AssemblyOptimization] = List[AssemblyOptimization](
|
||||
UnusedLabelRemoval,
|
||||
AlwaysGoodOptimizations.NonetAddition,
|
||||
AlwaysGoodOptimizations.NonetBitOp,
|
||||
AlwaysGoodOptimizations.PointlessSignCheck,
|
||||
AlwaysGoodOptimizations.PoinlessLoadBeforeAnotherLoad,
|
||||
AlwaysGoodOptimizations.PointlessLoadAfterLoadOrStore,
|
||||
@ -154,6 +155,7 @@ object OptimizationPresets {
|
||||
AlwaysGoodOptimizations.MathOperationOnTwoIdenticalMemoryOperands,
|
||||
AlwaysGoodOptimizations.ModificationOfJustWrittenValue,
|
||||
AlwaysGoodOptimizations.NonetAddition,
|
||||
AlwaysGoodOptimizations.NonetBitOp,
|
||||
AlwaysGoodOptimizations.OperationsAroundShifting,
|
||||
AlwaysGoodOptimizations.PoinlessFlagChange,
|
||||
AlwaysGoodOptimizations.PointlessLoadAfterLoadOrStore,
|
||||
|
@ -601,6 +601,21 @@ object AlwaysGoodOptimizations {
|
||||
|
||||
val ConstantFlowAnalysis = new RuleBasedAssemblyOptimization("Constant flow analysis",
|
||||
needsFlowInfo = FlowInfoRequirement.ForwardFlow,
|
||||
(MatchX(0) & HasAddrMode(AbsoluteX) & SupportsAbsolute & Elidable & HasParameterWhere({
|
||||
case MemoryAddressConstant(th) => th.name == "identity$"
|
||||
case _ => false
|
||||
})) ~~> { (code, ctx) =>
|
||||
code.map(l => l.copy(addrMode = Immediate, parameter = NumericConstant(ctx.get[Int](0), 1)))
|
||||
},
|
||||
(MatchY(0) & HasAddrMode(AbsoluteY) & SupportsAbsolute & Elidable & HasParameterWhere({
|
||||
case MemoryAddressConstant(th) => th.name == "identity$"
|
||||
case _ => false
|
||||
})) ~~> { (code, ctx) =>
|
||||
code.map(l => l.copy(addrMode = Immediate, parameter = NumericConstant(ctx.get[Int](0), 1)))
|
||||
},
|
||||
(MatchY(0) & HasAddrMode(AbsoluteY) & SupportsAbsolute & Elidable) ~~> { (code, ctx) =>
|
||||
code.map(l => l.copy(addrMode = Absolute, parameter = l.parameter + ctx.get[Int](0)))
|
||||
},
|
||||
(MatchX(0) & HasAddrMode(AbsoluteX) & SupportsAbsolute & Elidable) ~~> { (code, ctx) =>
|
||||
code.map(l => l.copy(addrMode = Absolute, parameter = l.parameter + ctx.get[Int](0)))
|
||||
},
|
||||
@ -1532,7 +1547,79 @@ object AlwaysGoodOptimizations {
|
||||
AssemblyLine.relative(BCC, label),
|
||||
code(8).copy(opcode = INC),
|
||||
AssemblyLine.label(label))
|
||||
}
|
||||
},
|
||||
(Elidable & HasOpcode(LDX) & HasImmediate(0) & HasClear(State.D)) ~
|
||||
(Elidable & HasOpcode(BCC) & MatchParameter(14)) ~
|
||||
(Elidable & HasOpcode(INX)) ~
|
||||
(Elidable & HasOpcode(LABEL) & MatchParameter(14) & HasCallerCount(1)) ~
|
||||
(Elidable & HasOpcode(CLC)) ~
|
||||
(Elidable & HasOpcode(ADC) & MatchAddrMode(0) & MatchParameter(1) & Not(ConcernsX)) ~
|
||||
(Elidable & HasOpcode(STA) & MatchAddrMode(0) & MatchParameter(1) & Not(ConcernsX)) ~
|
||||
(Elidable & HasOpcode(TXA)) ~
|
||||
(Elidable & HasOpcode(ADC) & MatchAddrMode(2) & MatchParameter(3) & Not(ConcernsX) & DoesNotConcernMemoryAt(0, 1)) ~
|
||||
(Elidable & HasOpcode(STA) & MatchAddrMode(2) & MatchParameter(3) & Not(ConcernsX) & DoesntMatterWhatItDoesWith(State.C, State.N, State.V, State.Z)) ~~> { (code, ctx) =>
|
||||
val label = getNextLabel("in")
|
||||
List(
|
||||
code(1), // BCC
|
||||
code(8).copy(opcode = INC),
|
||||
code(3), //LABEL
|
||||
code(4), //CLC
|
||||
code(5), //ADC
|
||||
code(6), //STA
|
||||
AssemblyLine.relative(BCC, label),
|
||||
code(8).copy(opcode = INC),
|
||||
AssemblyLine.label(label))
|
||||
},
|
||||
(Elidable & HasOpcode(LDX) & HasAddrMode(Immediate) & HasClear(State.D)) ~
|
||||
(Elidable & HasOpcode(BCC) & MatchParameter(14)) ~
|
||||
(Elidable & HasOpcode(INX)) ~
|
||||
(Elidable & HasOpcode(LABEL) & MatchParameter(14) & HasCallerCount(1)) ~
|
||||
(Elidable & HasOpcode(STA) & MatchAddrMode(0) & MatchParameter(1) & Not(ConcernsX)) ~
|
||||
(Elidable & HasOpcode(STX) & MatchAddrMode(2) & MatchParameter(3) & DoesNotConcernMemoryAt(0, 1) & Not(HasAddrMode(ZeroPageY)) &
|
||||
DoesntMatterWhatItDoesWith(State.X, State.A, State.C, State.V)) ~~> { (code, ctx) =>
|
||||
val label = getNextLabel("in")
|
||||
List(
|
||||
code(4), // STA
|
||||
code.head.copy(opcode = LDA), // LDX
|
||||
AssemblyLine.immediate(ADC, 0),
|
||||
code(5).copy(opcode = STA)) //STX
|
||||
},
|
||||
(Elidable & HasOpcode(TAX) & HasClear(State.D)) ~
|
||||
(Elidable & HasOpcode(BCC) & MatchParameter(14)) ~
|
||||
(Elidable & HasOpcode(INX)) ~
|
||||
(Elidable & HasOpcode(LABEL) & MatchParameter(14) & HasCallerCount(1)) ~
|
||||
(Elidable & HasOpcode(STA) & MatchAddrMode(0) & MatchParameter(1) & Not(ConcernsX)) ~
|
||||
(Elidable & HasOpcode(STX) & MatchAddrMode(2) & MatchParameter(3) & DoesNotConcernMemoryAt(0, 1) & Not(HasAddrMode(ZeroPageY)) &
|
||||
DoesntMatterWhatItDoesWith(State.X, State.A, State.C, State.V)) ~~> { (code, ctx) =>
|
||||
val label = getNextLabel("in")
|
||||
List(
|
||||
code(4), // STA
|
||||
AssemblyLine.immediate(ADC, 0),
|
||||
code(5).copy(opcode = STA)) //STX
|
||||
},
|
||||
)
|
||||
|
||||
val NonetBitOp = new RuleBasedAssemblyOptimization("Nonet bit operation",
|
||||
needsFlowInfo = FlowInfoRequirement.BothFlows,
|
||||
(Elidable & HasOpcode(LDX) & HasImmediate(0)) ~
|
||||
(Elidable & HasOpcode(BCC) & MatchParameter(14)) ~
|
||||
(Elidable & HasOpcode(INX)) ~
|
||||
(Elidable & HasOpcode(LABEL) & MatchParameter(14) & HasCallerCount(1)) ~
|
||||
(Elidable & HasOpcodeIn(Set(ORA, EOR)) & MatchAddrMode(0) & MatchParameter(1) & Not(ConcernsX)) ~
|
||||
(Elidable & HasOpcode(STA) & MatchAddrMode(0) & MatchParameter(1) & Not(ConcernsX)) ~
|
||||
(Elidable & HasOpcode(TXA)) ~
|
||||
(Elidable & HasOpcodeIn(Set(ORA, EOR)) & MatchAddrMode(2) & MatchParameter(3) & Not(ConcernsX) & DoesNotConcernMemoryAt(0, 1)) ~
|
||||
(Elidable & HasOpcode(STA) & MatchAddrMode(2) & MatchParameter(3) & Not(ConcernsX) & DoesntMatterWhatItDoesWith(State.C, State.N, State.V, State.Z)) ~~>{ (code, ctx) =>
|
||||
val label = getNextLabel("in")
|
||||
List(
|
||||
code(4), //EOR/ORA
|
||||
code(5), //STA
|
||||
code(1), // BCC
|
||||
AssemblyLine.immediate(LDA, 1),
|
||||
code(7), //EOR/ORA
|
||||
code(8), //STA
|
||||
code(3)) // LABEL
|
||||
}
|
||||
)
|
||||
|
||||
val CommonIndexSubexpressionElimination: RuleBasedAssemblyOptimization = {
|
||||
|
@ -72,4 +72,32 @@ class NonetSuite extends FunSuite with Matchers {
|
||||
m.readWord(0xc006) should equal(0x180)
|
||||
}
|
||||
}
|
||||
|
||||
test("Nonet OR/EXOR") {
|
||||
EmuBenchmarkRun(
|
||||
"""
|
||||
| word output0 @$c000
|
||||
| word output1 @$c002
|
||||
| word output2 @$c004
|
||||
| word output3 @$c006
|
||||
| void main () {
|
||||
| byte a
|
||||
| output0 = 0
|
||||
| output1 = 0
|
||||
| output2 = $8100
|
||||
| output3 = $8100
|
||||
| a = three()
|
||||
| output0 |= nonet(a << 1)
|
||||
| output1 ^= nonet(a << 2)
|
||||
| output2 |= nonet(a << 6)
|
||||
| output3 ^= nonet(a << 7)
|
||||
| }
|
||||
| noinline byte three() { return 3 }
|
||||
""".stripMargin) { m =>
|
||||
m.readWord(0xc000) should equal(0x06)
|
||||
m.readWord(0xc002) should equal(0x0C)
|
||||
m.readWord(0xc004) should equal(0x81C0)
|
||||
m.readWord(0xc006) should equal(0x8080)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user