cmd/compile: fix write barrier coalescing

We can't coalesce a non-WB store with a subsequent Move, as the
result of the store might be the source of the move.

There's a simple codegen test. Not sure how we might do a real test,
as all the repro's I've come up with are very expensive and unreliable.

Fixes #71228

Change-Id: If18bf181a266b9b90964e2591cd2e61a7168371c
Reviewed-on: https://go-review.googlesource.com/c/go/+/642197
Reviewed-by: Keith Randall <khr@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
Keith Randall 2025-01-10 17:33:26 -08:00
parent 19e923182e
commit 44a6f817ea
2 changed files with 40 additions and 0 deletions

View file

@ -252,6 +252,7 @@ func writebarrier(f *Func) {
var start, end int
var nonPtrStores int
values := b.Values
hasMove := false
FindSeq:
for i := len(values) - 1; i >= 0; i-- {
w := values[i]
@ -263,6 +264,9 @@ func writebarrier(f *Func) {
end = i + 1
}
nonPtrStores = 0
if w.Op == OpMoveWB {
hasMove = true
}
case OpVarDef, OpVarLive:
continue
case OpStore:
@ -273,6 +277,17 @@ func writebarrier(f *Func) {
if nonPtrStores > 2 {
break FindSeq
}
if hasMove {
// We need to ensure that this store happens
// before we issue a wbMove, as the wbMove might
// use the result of this store as its source.
// Even though this store is not write-barrier
// eligible, it might nevertheless be the store
// of a pointer to the stack, which is then the
// source of the move.
// See issue 71228.
break FindSeq
}
default:
if last == nil {
continue