mirror of
https://github.com/KarolS/millfork.git
synced 2024-10-25 05:24:11 +00:00
Tracing index register changes during superoptimization
This commit is contained in:
parent
57e11c8741
commit
f8f1af287f
@ -33,14 +33,21 @@ class ChangeIndexRegisterOptimization(preferX2Y: Boolean) extends AssemblyOptimi
|
|||||||
override def name = "Changing index registers"
|
override def name = "Changing index registers"
|
||||||
|
|
||||||
override def optimize(f: NormalFunction, code: List[AssemblyLine], options: CompilationOptions): List[AssemblyLine] = {
|
override def optimize(f: NormalFunction, code: List[AssemblyLine], options: CompilationOptions): List[AssemblyLine] = {
|
||||||
val usesIndex = code.exists(l =>
|
val usesX = code.exists(l =>
|
||||||
OpcodeClasses.ReadsXAlways(l.opcode) ||
|
OpcodeClasses.ReadsXAlways(l.opcode) ||
|
||||||
OpcodeClasses.ReadsYAlways(l.opcode) ||
|
OpcodeClasses.ReadsYAlways(l.opcode) ||
|
||||||
OpcodeClasses.ChangesX(l.opcode) ||
|
OpcodeClasses.ChangesX(l.opcode) ||
|
||||||
OpcodeClasses.ChangesY(l.opcode) ||
|
OpcodeClasses.ChangesY(l.opcode) ||
|
||||||
Set(AbsoluteX, AbsoluteY, ZeroPageY, ZeroPageX, IndexedX, IndexedY)(l.addrMode)
|
Set(AbsoluteX, AbsoluteY, ZeroPageY, ZeroPageX, IndexedX, IndexedY)(l.addrMode)
|
||||||
)
|
)
|
||||||
if (!usesIndex) {
|
val usesY = code.exists(l =>
|
||||||
|
OpcodeClasses.ReadsXAlways(l.opcode) ||
|
||||||
|
OpcodeClasses.ReadsYAlways(l.opcode) ||
|
||||||
|
OpcodeClasses.ChangesX(l.opcode) ||
|
||||||
|
OpcodeClasses.ChangesY(l.opcode) ||
|
||||||
|
Set(AbsoluteX, AbsoluteY, ZeroPageY, ZeroPageX, IndexedX, IndexedY)(l.addrMode)
|
||||||
|
)
|
||||||
|
if (!usesX && !usesY) {
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
val canX2Y = f.returnType.size <= 1 && canOptimize(code, X2Y, None)
|
val canX2Y = f.returnType.size <= 1 && canOptimize(code, X2Y, None)
|
||||||
@ -48,18 +55,44 @@ class ChangeIndexRegisterOptimization(preferX2Y: Boolean) extends AssemblyOptimi
|
|||||||
(canX2Y, canY2X) match {
|
(canX2Y, canY2X) match {
|
||||||
case (false, false) => code
|
case (false, false) => code
|
||||||
case (true, false) =>
|
case (true, false) =>
|
||||||
|
if (!usesX) code else {
|
||||||
ErrorReporting.debug("Changing index register from X to Y")
|
ErrorReporting.debug("Changing index register from X to Y")
|
||||||
switchX2Y(code)
|
val changed = switchX2Y(code)
|
||||||
|
traceDiff(code, changed)
|
||||||
|
changed
|
||||||
|
}
|
||||||
case (false, true) =>
|
case (false, true) =>
|
||||||
ErrorReporting.debug("Changing index register from X to Y")
|
if (!usesY) code else {
|
||||||
switchY2X(code)
|
ErrorReporting.debug("Changing index register from Y to X")
|
||||||
|
val changed = switchY2X(code)
|
||||||
|
traceDiff(code, changed)
|
||||||
|
changed
|
||||||
|
}
|
||||||
case (true, true) =>
|
case (true, true) =>
|
||||||
if (preferX2Y) {
|
if (preferX2Y) {
|
||||||
|
if (!usesX) code else {
|
||||||
ErrorReporting.debug("Changing index register from X to Y (arbitrarily)")
|
ErrorReporting.debug("Changing index register from X to Y (arbitrarily)")
|
||||||
switchX2Y(code)
|
val changed = switchX2Y(code)
|
||||||
|
traceDiff(code, changed)
|
||||||
|
changed
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if (!usesY) code else {
|
||||||
ErrorReporting.debug("Changing index register from Y to X (arbitrarily)")
|
ErrorReporting.debug("Changing index register from Y to X (arbitrarily)")
|
||||||
switchY2X(code)
|
val changed = switchY2X(code)
|
||||||
|
traceDiff(code, changed)
|
||||||
|
changed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private def traceDiff(original: List[AssemblyLine], changed: List[AssemblyLine]): Unit = {
|
||||||
|
if (ErrorReporting.traceEnabled) {
|
||||||
|
original.zip(changed).foreach{
|
||||||
|
case (o, n) =>
|
||||||
|
if (o.addrMode == n.addrMode && o.opcode == n.opcode) ErrorReporting.trace(n.toString)
|
||||||
|
else ErrorReporting.trace(f"$o%-30s → $n%s")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -68,10 +101,11 @@ class ChangeIndexRegisterOptimization(preferX2Y: Boolean) extends AssemblyOptimi
|
|||||||
private def canOptimize(code: List[AssemblyLine], dir: IndexDirection, loaded: Option[IndexReg]): Boolean = code match {
|
private def canOptimize(code: List[AssemblyLine], dir: IndexDirection, loaded: Option[IndexReg]): Boolean = code match {
|
||||||
case AssemblyLine(_, AbsoluteY, _, _) :: xs if loaded != Some(Y) => false
|
case AssemblyLine(_, AbsoluteY, _, _) :: xs if loaded != Some(Y) => false
|
||||||
case AssemblyLine(_, ZeroPageY, _, _) :: xs if loaded != Some(Y) => false
|
case AssemblyLine(_, ZeroPageY, _, _) :: xs if loaded != Some(Y) => false
|
||||||
case AssemblyLine(_, IndexedX, _, _) :: xs if dir == X2Y || loaded != Some(Y) => false
|
case AssemblyLine(_, IndexedY, _, _) :: xs if dir == Y2X || loaded != Some(Y) => false
|
||||||
case AssemblyLine(_, AbsoluteX, _, _) :: xs if loaded != Some(X) => false
|
case AssemblyLine(_, AbsoluteX, _, _) :: xs if loaded != Some(X) => false
|
||||||
case AssemblyLine(_, ZeroPageX, _, _) :: xs if loaded != Some(X) => false
|
case AssemblyLine(_, ZeroPageX, _, _) :: xs if loaded != Some(X) => false
|
||||||
case AssemblyLine(_, IndexedY, _, _) :: xs if dir == Y2X || loaded != Some(Y) => false
|
case AssemblyLine(_, IndexedX, _, _) :: xs if dir == X2Y || loaded != Some(X) => false
|
||||||
|
case AssemblyLine(_, AbsoluteIndexedX, _, _) :: xs if dir == X2Y => false
|
||||||
|
|
||||||
// using a wrong index register for one instruction is fine
|
// using a wrong index register for one instruction is fine
|
||||||
case AssemblyLine(LDY | TAY, _, _, _) :: AssemblyLine(_, IndexedY, _, _) :: xs if dir == Y2X =>
|
case AssemblyLine(LDY | TAY, _, _, _) :: AssemblyLine(_, IndexedY, _, _) :: xs if dir == Y2X =>
|
||||||
|
@ -23,6 +23,8 @@ object ErrorReporting {
|
|||||||
flushOutput()
|
flushOutput()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def traceEnabled: Boolean = verbosity >= 2
|
||||||
|
|
||||||
def trace(msg: String, position: Option[Position] = None): Unit = {
|
def trace(msg: String, position: Option[Position] = None): Unit = {
|
||||||
if (verbosity < 2) return
|
if (verbosity < 2) return
|
||||||
println("TRACE: " + f(position) + msg)
|
println("TRACE: " + f(position) + msg)
|
||||||
|
Loading…
Reference in New Issue
Block a user