1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-12-25 21:29:25 +00:00

Added some more optimizations

This commit is contained in:
Karol Stasiak 2018-03-18 23:52:40 +01:00
parent 6fa82a5a58
commit 986252db5b
3 changed files with 118 additions and 1 deletions

View File

@ -16,6 +16,7 @@ object OptimizationPresets {
val AssOpt: List[AssemblyOptimization] = List[AssemblyOptimization]( val AssOpt: List[AssemblyOptimization] = List[AssemblyOptimization](
UnusedLabelRemoval, UnusedLabelRemoval,
AlwaysGoodOptimizations.NonetAddition, AlwaysGoodOptimizations.NonetAddition,
AlwaysGoodOptimizations.NonetBitOp,
AlwaysGoodOptimizations.PointlessSignCheck, AlwaysGoodOptimizations.PointlessSignCheck,
AlwaysGoodOptimizations.PoinlessLoadBeforeAnotherLoad, AlwaysGoodOptimizations.PoinlessLoadBeforeAnotherLoad,
AlwaysGoodOptimizations.PointlessLoadAfterLoadOrStore, AlwaysGoodOptimizations.PointlessLoadAfterLoadOrStore,
@ -154,6 +155,7 @@ object OptimizationPresets {
AlwaysGoodOptimizations.MathOperationOnTwoIdenticalMemoryOperands, AlwaysGoodOptimizations.MathOperationOnTwoIdenticalMemoryOperands,
AlwaysGoodOptimizations.ModificationOfJustWrittenValue, AlwaysGoodOptimizations.ModificationOfJustWrittenValue,
AlwaysGoodOptimizations.NonetAddition, AlwaysGoodOptimizations.NonetAddition,
AlwaysGoodOptimizations.NonetBitOp,
AlwaysGoodOptimizations.OperationsAroundShifting, AlwaysGoodOptimizations.OperationsAroundShifting,
AlwaysGoodOptimizations.PoinlessFlagChange, AlwaysGoodOptimizations.PoinlessFlagChange,
AlwaysGoodOptimizations.PointlessLoadAfterLoadOrStore, AlwaysGoodOptimizations.PointlessLoadAfterLoadOrStore,

View File

@ -601,6 +601,21 @@ object AlwaysGoodOptimizations {
val ConstantFlowAnalysis = new RuleBasedAssemblyOptimization("Constant flow analysis", val ConstantFlowAnalysis = new RuleBasedAssemblyOptimization("Constant flow analysis",
needsFlowInfo = FlowInfoRequirement.ForwardFlow, 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) => (MatchX(0) & HasAddrMode(AbsoluteX) & SupportsAbsolute & Elidable) ~~> { (code, ctx) =>
code.map(l => l.copy(addrMode = Absolute, parameter = l.parameter + ctx.get[Int](0))) code.map(l => l.copy(addrMode = Absolute, parameter = l.parameter + ctx.get[Int](0)))
}, },
@ -1532,7 +1547,79 @@ object AlwaysGoodOptimizations {
AssemblyLine.relative(BCC, label), AssemblyLine.relative(BCC, label),
code(8).copy(opcode = INC), code(8).copy(opcode = INC),
AssemblyLine.label(label)) 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 = { val CommonIndexSubexpressionElimination: RuleBasedAssemblyOptimization = {

View File

@ -72,4 +72,32 @@ class NonetSuite extends FunSuite with Matchers {
m.readWord(0xc006) should equal(0x180) 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)
}
}
} }