cmd/compile: when CSEing two values, prefer the statement marked one

Fixes #75249

Change-Id: Ifd61bf5341f23ce2c9735e607e00d987489caacf
Reviewed-on: https://go-review.googlesource.com/c/go/+/701295
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Alexander Musman <alexander.musman@gmail.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
Keith Randall 2025-09-05 10:19:17 -07:00 committed by Keith Randall
parent 00824f5ff5
commit b1f3e38e41
2 changed files with 139 additions and 23 deletions

View file

@ -0,0 +1,105 @@
// Copyright 2025 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package dwarfgen
import (
"debug/dwarf"
"internal/platform"
"internal/testenv"
"io"
"runtime"
"testing"
)
func TestIssue75249(t *testing.T) {
testenv.MustHaveGoRun(t)
t.Parallel()
if !platform.ExecutableHasDWARF(runtime.GOOS, runtime.GOARCH) {
t.Skipf("skipping on %s/%s: no DWARF symbol table in executables", runtime.GOOS, runtime.GOARCH)
}
code := `
package main
type Data struct {
Field1 int
Field2 *int
Field3 int
Field4 *int
Field5 int
Field6 *int
Field7 int
Field8 *int
}
//go:noinline
func InitializeData(d *Data) {
d.Field1++ // line 16
d.Field2 = d.Field4
d.Field3++
d.Field4 = d.Field6
d.Field5++
d.Field6 = d.Field8
d.Field7++
d.Field8 = d.Field2 // line 23
}
func main() {
var data Data
InitializeData(&data)
}
`
_, f := gobuild(t, t.TempDir(), true, []testline{{line: code}})
defer f.Close()
dwarfData, err := f.DWARF()
if err != nil {
t.Fatal(err)
}
dwarfReader := dwarfData.Reader()
for {
entry, err := dwarfReader.Next()
if err != nil {
t.Fatal(err)
}
if entry == nil {
break
}
if entry.Tag != dwarf.TagCompileUnit {
continue
}
name := entry.AttrField(dwarf.AttrName)
if name == nil || name.Class != dwarf.ClassString || name.Val != "main" {
continue
}
lr, err := dwarfData.LineReader(entry)
if err != nil {
t.Fatal(err)
}
stmts := map[int]bool{}
for {
var le dwarf.LineEntry
err := lr.Next(&le)
if err == io.EOF {
break
}
if err != nil {
t.Fatal(err)
}
if !le.IsStmt {
continue
}
stmts[le.Line] = true
}
for i := 16; i <= 23; i++ {
if !stmts[i] {
t.Errorf("missing statement at line %d", i)
}
}
}
}

View file

@ -181,9 +181,10 @@ func cse(f *Func) {
for _, e := range partition {
slices.SortFunc(e, func(v, w *Value) int {
c := cmp.Compare(sdom.domorder(v.Block), sdom.domorder(w.Block))
if v.Op != OpLocalAddr || c != 0 {
if c != 0 {
return c
}
if v.Op == OpLocalAddr {
// compare the memory args for OpLocalAddrs in the same block
vm := v.Args[1]
wm := w.Args[1]
@ -209,6 +210,16 @@ func cse(f *Func) {
f.Fatalf("unable to determine the order of %s", wm.LongString())
}
return cmp.Compare(vs, ws)
}
vStmt := v.Pos.IsStmt() == src.PosIsStmt
wStmt := w.Pos.IsStmt() == src.PosIsStmt
if vStmt != wStmt {
if vStmt {
return -1
}
return +1
}
return 0
})
for i := 0; i < len(e)-1; i++ {