mirror of
https://github.com/KarolS/millfork.git
synced 2024-08-30 19:29:42 +00:00
Initialize constant registers outside loops
This commit is contained in:
parent
addfde48ec
commit
1909fd7154
@ -72,6 +72,7 @@ object OptimizationPresets {
|
|||||||
AlwaysGoodOptimizations.PointlessRegisterTransfersBeforeReturn,
|
AlwaysGoodOptimizations.PointlessRegisterTransfersBeforeReturn,
|
||||||
AlwaysGoodOptimizations.PointlessRegisterTransfersBeforeStore,
|
AlwaysGoodOptimizations.PointlessRegisterTransfersBeforeStore,
|
||||||
AlwaysGoodOptimizations.PointlessStashingToIndexOverShortSafeBranch,
|
AlwaysGoodOptimizations.PointlessStashingToIndexOverShortSafeBranch,
|
||||||
|
AlwaysGoodOptimizations.LoopInvariantRegister,
|
||||||
AlwaysGoodOptimizations.PointlessStackStashing,
|
AlwaysGoodOptimizations.PointlessStackStashing,
|
||||||
AlwaysGoodOptimizations.RearrangeMath,
|
AlwaysGoodOptimizations.RearrangeMath,
|
||||||
EmptyMemoryStoreRemoval,
|
EmptyMemoryStoreRemoval,
|
||||||
@ -146,6 +147,7 @@ object OptimizationPresets {
|
|||||||
AlwaysGoodOptimizations.IncrementingIndexRegistersAfterTransfer,
|
AlwaysGoodOptimizations.IncrementingIndexRegistersAfterTransfer,
|
||||||
AlwaysGoodOptimizations.IndexComparisonOptimization,
|
AlwaysGoodOptimizations.IndexComparisonOptimization,
|
||||||
AlwaysGoodOptimizations.IndexSequenceOptimization,
|
AlwaysGoodOptimizations.IndexSequenceOptimization,
|
||||||
|
AlwaysGoodOptimizations.LoopInvariantRegister,
|
||||||
LoopUnrolling.LoopUnrolling,
|
LoopUnrolling.LoopUnrolling,
|
||||||
AlwaysGoodOptimizations.MathOperationOnTwoIdenticalMemoryOperands,
|
AlwaysGoodOptimizations.MathOperationOnTwoIdenticalMemoryOperands,
|
||||||
AlwaysGoodOptimizations.ModificationOfJustWrittenValue,
|
AlwaysGoodOptimizations.ModificationOfJustWrittenValue,
|
||||||
|
@ -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",
|
val UnusedLabelRemoval = new RuleBasedAssemblyOptimization("Unused label removal",
|
||||||
needsFlowInfo = FlowInfoRequirement.JustLabels,
|
needsFlowInfo = FlowInfoRequirement.JustLabels,
|
||||||
|
@ -198,8 +198,8 @@ object HelperCheckers {
|
|||||||
def memoryAccessDoesntOverlap(l1: AssemblyLine, l2: AssemblyLine): Boolean = {
|
def memoryAccessDoesntOverlap(l1: AssemblyLine, l2: AssemblyLine): Boolean = {
|
||||||
val a1 = l1.addrMode
|
val a1 = l1.addrMode
|
||||||
val a2 = l2.addrMode
|
val a2 = l2.addrMode
|
||||||
if (badAddrModes(a1) || badAddrModes(a2)) return false
|
|
||||||
if (goodAddrModes(a1) || goodAddrModes(a2)) return true
|
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
|
if ((a1 == IndexedSY) != (a2 == IndexedSY)) return true // bold assertion, but usually true
|
||||||
val p1 = l1.parameter
|
val p1 = l1.parameter
|
||||||
val p2 = l2.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 {
|
case object ReadsX extends TrivialAssemblyLinePattern {
|
||||||
val XAddrModes = Set(AddrMode.AbsoluteX, AddrMode.IndexedX, AddrMode.ZeroPageX, AddrMode.AbsoluteIndexedX)
|
val XAddrModes = Set(AddrMode.AbsoluteX, AddrMode.IndexedX, AddrMode.ZeroPageX, AddrMode.AbsoluteIndexedX)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user