64 lines
1.6 KiB
Go
64 lines
1.6 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 {
|
|
// Count [removed] annotations from the walk, then derive optCount from
|
|
// origCount - removedCount. This avoids mismatches when later pipeline
|
|
// steps (e.g. removeUnusedFunctions) remove code that the optimizer saw.
|
|
origCount := countCodeLines(original)
|
|
|
|
var body []asmLine
|
|
oi := 0
|
|
opi := 0
|
|
removedCount := 0
|
|
|
|
for oi < len(original) {
|
|
origLine := original[oi]
|
|
|
|
if opi < len(optimized) && linesMatch(origLine, optimized[opi]) {
|
|
body = append(body, optimized[opi])
|
|
oi++
|
|
opi++
|
|
} else if !origLine.isCode {
|
|
body = append(body, origLine)
|
|
oi++
|
|
} else {
|
|
body = append(body, asmLine{
|
|
text: fmt.Sprintf("; [removed] %s", origLine.text),
|
|
isComment: true,
|
|
})
|
|
removedCount++
|
|
oi++
|
|
}
|
|
}
|
|
|
|
for ; opi < len(optimized); opi++ {
|
|
body = append(body, optimized[opi])
|
|
}
|
|
|
|
optCount := origCount - removedCount
|
|
header := fmt.Sprintf("; --- peephole: %d asm lines → %d (%d saved) ---",
|
|
origCount, optCount, removedCount)
|
|
|
|
result := []asmLine{{text: header, isComment: true}}
|
|
result = append(result, body...)
|
|
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
|
|
}
|