mirror of
https://github.com/KarolS/millfork.git
synced 2025-01-12 03:30:09 +00:00
Add empty parameter store removal optimization
This commit is contained in:
parent
ab57090790
commit
28e11873dc
@ -46,6 +46,7 @@ object OptimizationPresets {
|
||||
AlwaysGoodOptimizations.PointlessOperationAfterLoad,
|
||||
AlwaysGoodOptimizations.IdempotentDuplicateRemoval,
|
||||
LoopUnrolling.LoopUnrolling,
|
||||
AlwaysGoodOptimizations.ConstantPointer,
|
||||
AlwaysGoodOptimizations.ConstantIndexPropagation,
|
||||
AlwaysGoodOptimizations.PointlessLoadBeforeReturn,
|
||||
AlwaysGoodOptimizations.PoinlessFlagChange,
|
||||
@ -67,9 +68,11 @@ object OptimizationPresets {
|
||||
LaterOptimizations.DoubleLoadToTheSameRegister,
|
||||
LaterOptimizations.DoubleLoadToTwoRegistersWhenOneWillBeTrashed,
|
||||
EmptyMemoryStoreRemoval,
|
||||
EmptyParameterStoreRemoval,
|
||||
AlwaysGoodOptimizations.PointlessOperationFromFlow,
|
||||
AlwaysGoodOptimizations.PoinlessLoadBeforeAnotherLoad,
|
||||
AlwaysGoodOptimizations.IdempotentDuplicateRemoval,
|
||||
AlwaysGoodOptimizations.ConstantPointer,
|
||||
AlwaysGoodOptimizations.ConstantIndexPropagation,
|
||||
AlwaysGoodOptimizations.ConstantFlowAnalysis,
|
||||
AlwaysGoodOptimizations.PointlessRegisterTransfers,
|
||||
@ -86,6 +89,7 @@ object OptimizationPresets {
|
||||
AlwaysGoodOptimizations.RearrangeMath,
|
||||
AlwaysGoodOptimizations.LoadingOfJustWrittenValue,
|
||||
EmptyMemoryStoreRemoval,
|
||||
EmptyParameterStoreRemoval,
|
||||
AlwaysGoodOptimizations.PointlessLoadBeforeReturn,
|
||||
LaterOptimizations.PointessLoadingForShifting,
|
||||
AlwaysGoodOptimizations.SimplifiableBitOpsSequence,
|
||||
@ -95,6 +99,7 @@ object OptimizationPresets {
|
||||
|
||||
LaterOptimizations.LoadingAfterShifting,
|
||||
EmptyMemoryStoreRemoval,
|
||||
EmptyParameterStoreRemoval,
|
||||
AlwaysGoodOptimizations.PoinlessStoreBeforeStore,
|
||||
LaterOptimizations.PointlessLoadAfterStore,
|
||||
AlwaysGoodOptimizations.PoinlessLoadBeforeAnotherLoad,
|
||||
@ -105,6 +110,7 @@ object OptimizationPresets {
|
||||
|
||||
LaterOptimizations.LoadingAfterShifting,
|
||||
EmptyMemoryStoreRemoval,
|
||||
EmptyParameterStoreRemoval,
|
||||
AlwaysGoodOptimizations.PoinlessStoreBeforeStore,
|
||||
LaterOptimizations.PointlessLoadAfterStore,
|
||||
AlwaysGoodOptimizations.PoinlessLoadBeforeAnotherLoad,
|
||||
@ -112,7 +118,9 @@ object OptimizationPresets {
|
||||
LaterOptimizations.LoadingAfterShifting,
|
||||
AlwaysGoodOptimizations.PointlessAccumulatorShifting,
|
||||
EmptyMemoryStoreRemoval,
|
||||
EmptyParameterStoreRemoval,
|
||||
AlwaysGoodOptimizations.PoinlessStoreBeforeStore,
|
||||
AlwaysGoodOptimizations.ConstantPointer,
|
||||
LaterOptimizations.PointlessLoadAfterStore,
|
||||
AlwaysGoodOptimizations.PoinlessLoadBeforeAnotherLoad,
|
||||
AlwaysGoodOptimizations.TailCallOptimization,
|
||||
@ -135,6 +143,7 @@ object OptimizationPresets {
|
||||
AlwaysGoodOptimizations.PointlessStackStore,
|
||||
AlwaysGoodOptimizations.OptimizeZeroComparisons,
|
||||
AlwaysGoodOptimizations.SimplifiableCondition,
|
||||
AlwaysGoodOptimizations.ConstantPointer,
|
||||
AlwaysGoodOptimizations.IncrementingIndexRegistersAfterTransfer,
|
||||
AlwaysGoodOptimizations.MathOperationOnTwoIdenticalMemoryOperands,
|
||||
LaterOptimizations.UseZeropageAddressingMode,
|
||||
@ -167,6 +176,7 @@ object OptimizationPresets {
|
||||
AlwaysGoodOptimizations.ConstantIndexPropagation,
|
||||
AlwaysGoodOptimizations.DoubleJumpSimplification,
|
||||
EmptyMemoryStoreRemoval,
|
||||
EmptyParameterStoreRemoval,
|
||||
AlwaysGoodOptimizations.FlagFlowAnalysis,
|
||||
AlwaysGoodOptimizations.IdempotentDuplicateRemoval,
|
||||
AlwaysGoodOptimizations.ImpossibleBranchRemoval,
|
||||
|
@ -0,0 +1,80 @@
|
||||
package millfork.assembly.mos.opt
|
||||
|
||||
import millfork.assembly.mos.AddrMode._
|
||||
import millfork.assembly.mos.AssemblyLine
|
||||
import millfork.assembly.mos.Opcode._
|
||||
import millfork.assembly.{AssemblyOptimization, OptimizationContext}
|
||||
import millfork.env._
|
||||
import millfork.error.ErrorReporting
|
||||
|
||||
/**
|
||||
* @author Karol Stasiak
|
||||
*/
|
||||
object EmptyParameterStoreRemoval extends AssemblyOptimization[AssemblyLine] {
|
||||
override def name = "Removing pointless stores to foreign variables"
|
||||
|
||||
private val storeInstructions = Set(STA, STX, STY, SAX, STZ, STA_W, STX_W, STY_W, STZ_W)
|
||||
private val storeAddrModes = Set(Absolute, ZeroPage, AbsoluteX, AbsoluteY, ZeroPageX, ZeroPageY)
|
||||
|
||||
override def optimize(f: NormalFunction, code: List[AssemblyLine], optimizationContext: OptimizationContext): List[AssemblyLine] = {
|
||||
val usedFunctions = code.flatMap {
|
||||
case AssemblyLine(JSR | BSR | JMP, _, MemoryAddressConstant(th), _) => Some(th.name)
|
||||
case AssemblyLine(JSR | BSR | JMP, _, NumericConstant(addr, _), _) => Some("$" + addr.toHexString)
|
||||
case _ => None
|
||||
}.toSet
|
||||
val foreignVariables = f.environment.root.things.values.flatMap {
|
||||
case other: NormalFunction =>
|
||||
val address = other.address match {
|
||||
case Some(NumericConstant(addr, _)) => "$" + addr.toHexString
|
||||
case _ => ""
|
||||
}
|
||||
if (other.name == f.name || usedFunctions(other.name) || usedFunctions(address)) {
|
||||
Nil
|
||||
} else {
|
||||
val params = other.params match {
|
||||
case NormalParamSignature(ps) => ps.map(_.name)
|
||||
case _ => Nil
|
||||
}
|
||||
val locals = other.environment.things.values.flatMap{
|
||||
case th: MemoryVariable if th.alloc == VariableAllocationMethod.Auto => Some(th.name)
|
||||
case th: MemoryVariable if th.alloc == VariableAllocationMethod.Zeropage => Some(th.name) // TODO: ???
|
||||
case _ => None
|
||||
}
|
||||
params ++ locals
|
||||
}
|
||||
case _ => Nil
|
||||
}.toSet
|
||||
val stillReadOrStoredVariables = code.flatMap {
|
||||
case AssemblyLine(_, _, MemoryAddressConstant(th), _) => Some(th.name)
|
||||
case AssemblyLine(_, _, CompoundConstant(_, MemoryAddressConstant(th), _), _) => Some(th.name)
|
||||
case AssemblyLine(_, Immediate, SubbyteConstant(MemoryAddressConstant(th), _), _) => Some(th.name)
|
||||
case _ => None
|
||||
}.toSet
|
||||
val stillReadVariables = code.flatMap {
|
||||
case AssemblyLine(op, am, MemoryAddressConstant(th), true)
|
||||
if storeInstructions(op) && storeAddrModes(am) => Nil
|
||||
case AssemblyLine(op, am, CompoundConstant(MathOperator.Plus, MemoryAddressConstant(th), NumericConstant(_, _)), true)
|
||||
if storeInstructions(op) && storeAddrModes(am) => Nil
|
||||
case AssemblyLine(_, _, MemoryAddressConstant(th), _) => Some(th.name)
|
||||
case AssemblyLine(_, _, CompoundConstant(_, MemoryAddressConstant(th), _), _) => Some(th.name)
|
||||
case AssemblyLine(_, Immediate, SubbyteConstant(MemoryAddressConstant(th), _), _) => Some(th.name)
|
||||
case _ => None
|
||||
}.toSet
|
||||
|
||||
val unusedForeignVariables = (foreignVariables & stillReadOrStoredVariables) -- stillReadVariables
|
||||
if (unusedForeignVariables.isEmpty) {
|
||||
return code
|
||||
}
|
||||
|
||||
ErrorReporting.debug(s"Removing pointless store(s) to foreign variables ${unusedForeignVariables.mkString(", ")}")
|
||||
code.filterNot {
|
||||
case AssemblyLine(op, am, MemoryAddressConstant(th), _)
|
||||
if storeInstructions(op) && storeAddrModes(am) =>
|
||||
unusedForeignVariables(th.name)
|
||||
case AssemblyLine(op, am, CompoundConstant(MathOperator.Plus, MemoryAddressConstant(th), NumericConstant(_, _)), true)
|
||||
if storeInstructions(op) && storeAddrModes(am) =>
|
||||
unusedForeignVariables(th.name)
|
||||
case _ => false
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user