63 lines
1.7 KiB
Go
63 lines
1.7 KiB
Go
package optimizer
|
|
|
|
import "fmt"
|
|
|
|
// debugDiff produces annotated output showing original vs optimized code.
|
|
// Lines that were removed are shown with "[removed]" annotation.
|
|
func debugDiff(original, optimized []asmLine) []asmLine {
|
|
origCount := countCodeLines(original)
|
|
optCount := countCodeLines(optimized)
|
|
saved := origCount - optCount
|
|
|
|
header := fmt.Sprintf("; --- peephole: %d asm lines → %d (%d saved) ---", origCount, optCount, saved)
|
|
var result []asmLine
|
|
result = append(result, asmLine{text: header, isComment: true})
|
|
|
|
// Walk both arrays in sync. When optimized doesn't have a line
|
|
// that original has, it was removed.
|
|
oi := 0 // index into original (pre-stripped)
|
|
opi := 0 // index into optimized
|
|
|
|
for oi < len(original) {
|
|
origLine := original[oi]
|
|
|
|
if opi < len(optimized) && linesMatch(origLine, optimized[opi]) {
|
|
result = append(result, optimized[opi])
|
|
oi++
|
|
opi++
|
|
} else if !origLine.isCode {
|
|
// Non-code line that doesn't match anything — pass through
|
|
result = append(result, origLine)
|
|
oi++
|
|
} else {
|
|
// Code line in original but not in optimized → removed
|
|
result = append(result, asmLine{
|
|
text: fmt.Sprintf("; [removed] %s", origLine.text),
|
|
isComment: true,
|
|
})
|
|
oi++
|
|
}
|
|
}
|
|
|
|
// Append any remaining optimized lines (shouldn't happen in practice)
|
|
for ; opi < len(optimized); opi++ {
|
|
result = append(result, optimized[opi])
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// linesMatch returns true if two asmLines represent the same instruction.
|
|
func linesMatch(a, b asmLine) bool {
|
|
return a.isCode == b.isCode && a.isLabel == b.isLabel && a.isComment == b.isComment && a.text == b.text
|
|
}
|
|
|
|
func countCodeLines(lines []asmLine) int {
|
|
n := 0
|
|
for _, l := range lines {
|
|
if l.isCode {
|
|
n++
|
|
}
|
|
}
|
|
return n
|
|
}
|