mirror of
https://github.com/KarolS/millfork.git
synced 2024-09-10 11:54:30 +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](
|
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,
|
||||||
|
@ -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 = {
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user