56 lines
1.2 KiB
Go
56 lines
1.2 KiB
Go
package optimizer
|
|
|
|
// passLoadElimination removes redundant memory-to-register loads.
|
|
// Pattern: lda X; ... (X not modified) ...; lda X → remove second
|
|
// Applies to A, X, Y registers identically.
|
|
func passLoadElimination(lines []asmLine) []asmLine {
|
|
rs := newRegState()
|
|
var result []asmLine
|
|
|
|
for _, line := range lines {
|
|
if !line.isCode {
|
|
if line.optMarker {
|
|
continue
|
|
}
|
|
if line.isLabel {
|
|
rs.reset()
|
|
}
|
|
result = append(result, line)
|
|
continue
|
|
}
|
|
|
|
if isChainBreaker(line.opcode) {
|
|
rs.reset()
|
|
result = append(result, line)
|
|
continue
|
|
}
|
|
|
|
// Check for redundant memory load
|
|
if line.opcode == "lda" && !isImmediate(line.operand) {
|
|
if rs.a.src == line.operand {
|
|
continue // redundant, remove
|
|
}
|
|
rs.a.src = line.operand
|
|
} else if line.opcode == "ldx" && !isImmediate(line.operand) {
|
|
if rs.x.src == line.operand {
|
|
continue
|
|
}
|
|
rs.x.src = line.operand
|
|
} else if line.opcode == "ldy" && !isImmediate(line.operand) {
|
|
if rs.y.src == line.operand {
|
|
continue
|
|
}
|
|
rs.y.src = line.operand
|
|
} else {
|
|
updateRegState(line, rs)
|
|
}
|
|
|
|
result = append(result, line)
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
func isImmediate(operand string) bool {
|
|
return len(operand) > 0 && operand[0] == '#'
|
|
}
|