mirror of
https://github.com/KarolS/millfork.git
synced 2025-01-11 12:29:46 +00:00
Important bugfixes; removing empty stores to larger variables
This commit is contained in:
parent
3dc526bcb7
commit
f8bd496b6b
@ -50,14 +50,14 @@ object OpcodeClasses {
|
||||
PHX, PHY, PLX, PLY, TAS, LAS
|
||||
)
|
||||
val ChangesMemoryAlways = Set(
|
||||
STA, STY, STZ,
|
||||
STX, DEC, INC,
|
||||
STA, STY, STZ, STX,
|
||||
TRB, TSB,
|
||||
SAX, DCP, ISC,
|
||||
SLO, RLA, SRE, RRA,
|
||||
AHX, SHY, SHX, TAS, LAS
|
||||
)
|
||||
val ChangesMemoryIfNotImplied = Set(
|
||||
ASL, ROL, LSR, ROR
|
||||
DEC, INC, ASL, ROL, LSR, ROR
|
||||
)
|
||||
val ReadsMemoryIfNotImpliedOrImmediate = Set(
|
||||
LDY, CPX, CPY,
|
||||
@ -305,7 +305,7 @@ case class AssemblyLine(opcode: Opcode.Value, addrMode: AddrMode.Value, var para
|
||||
|
||||
def sizeInBytes: Int = addrMode match {
|
||||
case Implied => 1
|
||||
case Relative | ZeroPageX | ZeroPage | ZeroPageY | IndexedX | IndexedY | Immediate => 2
|
||||
case Relative | ZeroPageX | ZeroPage | ZeroPageY | ZeroPageIndirect | IndexedX | IndexedY | Immediate => 2
|
||||
case AbsoluteIndexedX | AbsoluteX | Absolute | AbsoluteY | Indirect => 3
|
||||
case DoesNotExist => 0
|
||||
}
|
||||
|
@ -195,16 +195,16 @@ object CoarseFlowAnalyzer {
|
||||
currentStatus = initialStatus
|
||||
|
||||
case AssemblyLine(LDX, Immediate, NumericConstant(nn, _), _) =>
|
||||
val n = nn.toInt
|
||||
val n = nn.toInt & 0xff
|
||||
currentStatus = currentStatus.nz(n).copy(x = SingleStatus(n))
|
||||
case AssemblyLine(LDY, Immediate, NumericConstant(nn, _), _) =>
|
||||
val n = nn.toInt
|
||||
val n = nn.toInt & 0xff
|
||||
currentStatus = currentStatus.nz(n).copy(y = SingleStatus(n))
|
||||
case AssemblyLine(LDA, Immediate, NumericConstant(nn, _), _) =>
|
||||
val n = nn.toInt
|
||||
val n = nn.toInt & 0xff
|
||||
currentStatus = currentStatus.nz(n).copy(a = SingleStatus(n))
|
||||
case AssemblyLine(LAX, Immediate, NumericConstant(nn, _), _) =>
|
||||
val n = nn.toInt
|
||||
val n = nn.toInt & 0xff
|
||||
currentStatus = currentStatus.nz(n).copy(a = SingleStatus(n), x = SingleStatus(n))
|
||||
|
||||
case AssemblyLine(ADC, Immediate, NumericConstant(nn, _), _) =>
|
||||
@ -232,17 +232,17 @@ object CoarseFlowAnalyzer {
|
||||
a = currentStatus.a.map(i => (i & n & 0xff) >> 1))
|
||||
|
||||
case AssemblyLine(INX, Implied, _, _) =>
|
||||
currentStatus = currentStatus.copy(n = currentStatus.x.n(_ + 1), z = currentStatus.x.z(_ + 1), x = currentStatus.x.map(_ + 1))
|
||||
currentStatus = currentStatus.copy(n = currentStatus.x.n(_ + 1), z = currentStatus.x.z(_ + 1), x = currentStatus.x.map(v => (v + 1) & 0xff))
|
||||
case AssemblyLine(DEX, Implied, _, _) =>
|
||||
currentStatus = currentStatus.copy(n = currentStatus.x.n(_ - 1), z = currentStatus.x.z(_ - 1), x = currentStatus.x.map(_ - 1))
|
||||
currentStatus = currentStatus.copy(n = currentStatus.x.n(_ - 1), z = currentStatus.x.z(_ - 1), x = currentStatus.x.map(v => (v - 1) & 0xff))
|
||||
case AssemblyLine(INY, Implied, _, _) =>
|
||||
currentStatus = currentStatus.copy(n = currentStatus.y.n(_ + 1), z = currentStatus.y.z(_ + 1), y = currentStatus.y.map(_ + 1))
|
||||
currentStatus = currentStatus.copy(n = currentStatus.y.n(_ + 1), z = currentStatus.y.z(_ + 1), y = currentStatus.y.map(v => (v + 1) & 0xff))
|
||||
case AssemblyLine(DEY, Implied, _, _) =>
|
||||
currentStatus = currentStatus.copy(n = currentStatus.y.n(_ - 1), z = currentStatus.y.z(_ - 1), y = currentStatus.y.map(_ - 1))
|
||||
currentStatus = currentStatus.copy(n = currentStatus.y.n(_ - 1), z = currentStatus.y.z(_ - 1), y = currentStatus.y.map(v => (v - 1) & 0xff))
|
||||
case AssemblyLine(INC, Implied, _, _) =>
|
||||
currentStatus = currentStatus.copy(n = currentStatus.a.n(_ + 1), z = currentStatus.a.z(_ + 1), a = currentStatus.a.map(_ + 1))
|
||||
currentStatus = currentStatus.copy(n = currentStatus.a.n(_ + 1), z = currentStatus.a.z(_ + 1), a = currentStatus.a.map(v => (v + 1) & 0xff))
|
||||
case AssemblyLine(DEC, Implied, _, _) =>
|
||||
currentStatus = currentStatus.copy(n = currentStatus.a.n(_ - 1), z = currentStatus.a.z(_ - 1), a = currentStatus.a.map(_ - 1))
|
||||
currentStatus = currentStatus.copy(n = currentStatus.a.n(_ - 1), z = currentStatus.a.z(_ - 1), a = currentStatus.a.map(v => (v - 1) & 0xff))
|
||||
case AssemblyLine(TAX, _, _, _) =>
|
||||
currentStatus = currentStatus.copy(x = currentStatus.a, n = currentStatus.a.n(), z = currentStatus.a.z())
|
||||
case AssemblyLine(TXA, _, _, _) =>
|
||||
@ -253,7 +253,7 @@ object CoarseFlowAnalyzer {
|
||||
currentStatus = currentStatus.copy(a = currentStatus.y, n = currentStatus.y.n(), z = currentStatus.y.z())
|
||||
|
||||
case AssemblyLine(ASL, Implied, _, _) =>
|
||||
currentStatus = currentStatus.copy(a = currentStatus.a.map(_ << 1), n = currentStatus.a.n(_ << 1), z = currentStatus.a.z(_ << 1),c = currentStatus.a.map(a => a.&(0xff).!=(0)))
|
||||
currentStatus = currentStatus.copy(a = currentStatus.a.map(v => (v << 1) & 0xff), n = currentStatus.a.n(_ << 1), z = currentStatus.a.z(_ << 1),c = currentStatus.a.map(a => a.&(0xff).!=(0)))
|
||||
case AssemblyLine(LSR, Implied, _, _) =>
|
||||
currentStatus = currentStatus.copy(a = currentStatus.a.map(a => a.>>(1).&(0x7f)), n = currentStatus.a.n(a => a.>>(1).&(0x7f)), z = currentStatus.a.z(a => a.>>(1).&(0x7f)),c = currentStatus.a.map(a => a.&(1).!=(0)))
|
||||
|
||||
|
@ -4,6 +4,7 @@ import millfork.CompilationOptions
|
||||
import millfork.assembly.AssemblyLine
|
||||
import millfork.env._
|
||||
import millfork.assembly.Opcode._
|
||||
import millfork.assembly.AddrMode._
|
||||
import millfork.error.ErrorReporting
|
||||
|
||||
import scala.collection.{immutable, mutable}
|
||||
@ -14,7 +15,7 @@ import scala.collection.{immutable, mutable}
|
||||
object EmptyMemoryStoreRemoval extends AssemblyOptimization {
|
||||
override def name = "Removing pointless stores to automatic variables"
|
||||
|
||||
private val storeOpcodes = Set(STA, STX, STY, STZ, SAX)
|
||||
private val storeAddrModes = Set(Absolute, ZeroPage, AbsoluteX, AbsoluteY, ZeroPageX, ZeroPageY)
|
||||
|
||||
override def optimize(f: NormalFunction, code: List[AssemblyLine], options: CompilationOptions): List[AssemblyLine] = {
|
||||
val paramVariables = f.params match {
|
||||
@ -26,11 +27,13 @@ object EmptyMemoryStoreRemoval extends AssemblyOptimization {
|
||||
}
|
||||
val stillUsedVariables = code.flatMap {
|
||||
case AssemblyLine(_, _, MemoryAddressConstant(th), _) => Some(th.name)
|
||||
case AssemblyLine(_, _, CompoundConstant(MathOperator.Plus, MemoryAddressConstant(th), NumericConstant(_, _)), _) => Some(th.name)
|
||||
case _ => None
|
||||
}.toSet
|
||||
val localVariables = f.environment.getAllLocalVariables.filter {
|
||||
case MemoryVariable(name, typ, VariableAllocationMethod.Auto) =>
|
||||
typ.size == 1 && !paramVariables(name) && stillUsedVariables(name)
|
||||
val allLocalVariables = f.environment.getAllLocalVariables
|
||||
val localVariables = allLocalVariables.filter {
|
||||
case MemoryVariable(name, typ, VariableAllocationMethod.Auto | VariableAllocationMethod.Zeropage) =>
|
||||
typ.size > 0 && !paramVariables(name) && stillUsedVariables(name)
|
||||
case _ => false
|
||||
}
|
||||
|
||||
@ -46,17 +49,43 @@ object EmptyMemoryStoreRemoval extends AssemblyOptimization {
|
||||
val lifetime = VariableLifetime.apply(v.name, code)
|
||||
val lastaccess = lifetime.last
|
||||
if (lastaccess >= 0) {
|
||||
if (code(lastaccess).opcode match {
|
||||
case STA | STX | STY | SAX =>
|
||||
val lastVariableAccess = code(lastaccess)
|
||||
if (lastVariableAccess.elidable && storeAddrModes(lastVariableAccess.addrMode) && (lastVariableAccess.opcode match {
|
||||
case STA | STX | STY | SAX | STZ | SHX | SHY | AHX =>
|
||||
true
|
||||
case TSB | TRB =>
|
||||
if (importances eq null) importances = ReverseFlowAnalyzer.analyze(f, code)
|
||||
importances(lastaccess).z != Important
|
||||
case INC | DEC =>
|
||||
if (importances eq null) {
|
||||
importances = ReverseFlowAnalyzer.analyze(f, code)
|
||||
}
|
||||
importances(lastaccess).z != Important && importances(lastaccess).n != Important
|
||||
if (importances eq null) importances = ReverseFlowAnalyzer.analyze(f, code)
|
||||
importances(lastaccess).z != Important &&
|
||||
importances(lastaccess).n != Important
|
||||
case ASL | LSR | ROL | ROR | DCP =>
|
||||
if (importances eq null) importances = ReverseFlowAnalyzer.analyze(f, code)
|
||||
importances(lastaccess).z != Important &&
|
||||
importances(lastaccess).n != Important &&
|
||||
importances(lastaccess).c != Important
|
||||
case ISC =>
|
||||
if (importances eq null) importances = ReverseFlowAnalyzer.analyze(f, code)
|
||||
importances(lastaccess).z != Important &&
|
||||
importances(lastaccess).n != Important &&
|
||||
importances(lastaccess).a != Important
|
||||
case DCP | SLO | SRE | RLA =>
|
||||
if (importances eq null) importances = ReverseFlowAnalyzer.analyze(f, code)
|
||||
importances(lastaccess).z != Important &&
|
||||
importances(lastaccess).n != Important &&
|
||||
importances(lastaccess).c != Important &&
|
||||
importances(lastaccess).a != Important
|
||||
case RRA =>
|
||||
if (importances eq null) importances = ReverseFlowAnalyzer.analyze(f, code)
|
||||
importances(lastaccess).z != Important &&
|
||||
importances(lastaccess).n != Important &&
|
||||
importances(lastaccess).c != Important &&
|
||||
importances(lastaccess).a != Important &&
|
||||
importances(lastaccess).v != Important
|
||||
case _ => // last variable access is important, or we're in a loop, do not remove
|
||||
false
|
||||
}) {
|
||||
})) {
|
||||
badVariables += v.name
|
||||
toRemove += lastaccess
|
||||
}
|
||||
|
@ -9,11 +9,11 @@ import millfork.error.ErrorReporting
|
||||
*/
|
||||
object VariableLifetime {
|
||||
|
||||
// TODO: This only works for 1-byte non-stack variables.
|
||||
// Should be fixed to also work with larger variables.
|
||||
// This only works for non-stack variables.
|
||||
def apply(variableName: String, code: List[AssemblyLine]): Range = {
|
||||
val flags = code.map(_.parameter match {
|
||||
case MemoryAddressConstant(MemoryVariable(n, _, _)) if n == variableName => true
|
||||
case CompoundConstant(MathOperator.Plus, MemoryAddressConstant(MemoryVariable(n, _, _)), NumericConstant(_, 1)) if n == variableName => true
|
||||
case _ => false
|
||||
})
|
||||
if (flags.forall(!_)) return Range(0, 0)
|
||||
|
@ -708,6 +708,7 @@ object Assembler {
|
||||
cm(TRB, ZeroPage, 0x14)
|
||||
cm(TRB, Absolute, 0x1C)
|
||||
|
||||
cm(BRA, Relative, 0x80)
|
||||
cm(BIT, ZeroPageX, 0x34)
|
||||
cm(BIT, AbsoluteX, 0x3C)
|
||||
cm(INC, Implied, 0x1A)
|
||||
|
Loading…
x
Reference in New Issue
Block a user