1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-07-18 02:28:57 +00:00

Initialize constant registers outside loops

This commit is contained in:
Karol Stasiak 2018-03-06 00:22:39 +01:00
parent addfde48ec
commit 1909fd7154
3 changed files with 45 additions and 1 deletions

View File

@ -72,6 +72,7 @@ object OptimizationPresets {
AlwaysGoodOptimizations.PointlessRegisterTransfersBeforeReturn,
AlwaysGoodOptimizations.PointlessRegisterTransfersBeforeStore,
AlwaysGoodOptimizations.PointlessStashingToIndexOverShortSafeBranch,
AlwaysGoodOptimizations.LoopInvariantRegister,
AlwaysGoodOptimizations.PointlessStackStashing,
AlwaysGoodOptimizations.RearrangeMath,
EmptyMemoryStoreRemoval,
@ -146,6 +147,7 @@ object OptimizationPresets {
AlwaysGoodOptimizations.IncrementingIndexRegistersAfterTransfer,
AlwaysGoodOptimizations.IndexComparisonOptimization,
AlwaysGoodOptimizations.IndexSequenceOptimization,
AlwaysGoodOptimizations.LoopInvariantRegister,
LoopUnrolling.LoopUnrolling,
AlwaysGoodOptimizations.MathOperationOnTwoIdenticalMemoryOperands,
AlwaysGoodOptimizations.ModificationOfJustWrittenValue,

View File

@ -1096,6 +1096,35 @@ object AlwaysGoodOptimizations {
}
)
val LoopInvariantRegister = new RuleBasedAssemblyOptimization("Loop invariant register",
needsFlowInfo = FlowInfoRequirement.JustLabels,
(HasOpcode(LABEL) & MatchParameter(2) & HasCallerCount(1)) ~
(Elidable & HasOpcode(LDA) & MatchAddrMode(0) & MatchParameter(1) & IsNonvolatile) ~
(Linear & Not(ChangesA) & DoesntChangeMemoryAt(0, 1)).* ~
(ShortConditionalBranching & MatchParameter(2)) ~~> { code =>
code(1) :: code(0) :: code.drop(2)
},
(HasOpcode(LABEL) & MatchParameter(2) & HasCallerCount(1)) ~
(Elidable & HasOpcode(LDX) & MatchAddrMode(0) & MatchParameter(1) & IsNonvolatile) ~
(Linear & Not(ChangesX) & DoesntChangeMemoryAt(0, 1)).* ~
(ShortConditionalBranching & MatchParameter(2)) ~~> { code =>
code(1) :: code(0) :: code.drop(2)
},
(HasOpcode(LABEL) & MatchParameter(2) & HasCallerCount(1)) ~
(Elidable & HasOpcode(LDY) & MatchAddrMode(0) & MatchParameter(1) & IsNonvolatile) ~
(Linear & Not(ChangesY) & DoesntChangeMemoryAt(0, 1)).* ~
(ShortConditionalBranching & MatchParameter(2)) ~~> { code =>
code(1) :: code(0) :: code.drop(2)
},
(HasOpcode(LABEL) & MatchParameter(2) & HasCallerCount(1)) ~
(Elidable & HasOpcode(LDZ) & MatchAddrMode(0) & MatchParameter(1)) ~
(Linear & Not(ChangesIZ) & DoesntChangeMemoryAt(0, 1)).* ~
(ShortConditionalBranching & MatchParameter(2)) ~~> { code =>
code(1) :: code(0) :: code.drop(2)
},
)
val UnusedLabelRemoval = new RuleBasedAssemblyOptimization("Unused label removal",
needsFlowInfo = FlowInfoRequirement.JustLabels,

View File

@ -198,8 +198,8 @@ object HelperCheckers {
def memoryAccessDoesntOverlap(l1: AssemblyLine, l2: AssemblyLine): Boolean = {
val a1 = l1.addrMode
val a2 = l2.addrMode
if (badAddrModes(a1) || badAddrModes(a2)) return false
if (goodAddrModes(a1) || goodAddrModes(a2)) return true
if (badAddrModes(a1) || badAddrModes(a2)) return false
if ((a1 == IndexedSY) != (a2 == IndexedSY)) return true // bold assertion, but usually true
val p1 = l1.parameter
val p2 = l2.parameter
@ -658,6 +658,19 @@ case object ReadsMemory extends TrivialAssemblyLinePattern {
}
}
case object IsNonvolatile extends TrivialAssemblyLinePattern {
// TODO: this is a big hack
override def apply(line: AssemblyLine): Boolean =
line.addrMode match {
case AddrMode.Implied | AddrMode.Immediate => true
case _ => line.parameter match {
case MemoryAddressConstant(_) => true
case CompoundConstant(_, MemoryAddressConstant(_), _) => true
case _ => false
}
}
}
case object ReadsX extends TrivialAssemblyLinePattern {
val XAddrModes = Set(AddrMode.AbsoluteX, AddrMode.IndexedX, AddrMode.ZeroPageX, AddrMode.AbsoluteIndexedX)