Skip to content

Commit bf833ea

Browse files
committed
cmd/compile: ensure that ssa.Func constant cache is consistent
It was not necessarily consistent before, we were just lucky. Change-Id: I3a92dc724e0af7b4d810a6a0b7b1d58844eb8f87 Reviewed-on: https://go-review.googlesource.com/c/go/+/251440 Run-TryBot: David Chase <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Cherry Zhang <[email protected]>
1 parent 721819e commit bf833ea

File tree

3 files changed

+56
-13
lines changed

3 files changed

+56
-13
lines changed

src/cmd/compile/internal/ssa/func.go

Lines changed: 46 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,49 @@ func (f *Func) LogStat(key string, args ...interface{}) {
257257
f.Warnl(f.Entry.Pos, "\t%s\t%s%s\t%s", n, key, value, f.Name)
258258
}
259259

260+
// unCacheLine removes v from f's constant cache "line" for aux,
261+
// resets v.InCache when it is found (and removed),
262+
// and returns whether v was found in that line.
263+
func (f *Func) unCacheLine(v *Value, aux int64) bool {
264+
vv := f.constants[aux]
265+
for i, cv := range vv {
266+
if v == cv {
267+
vv[i] = vv[len(vv)-1]
268+
vv[len(vv)-1] = nil
269+
f.constants[aux] = vv[0 : len(vv)-1]
270+
v.InCache = false
271+
return true
272+
}
273+
}
274+
return false
275+
}
276+
277+
// unCache removes v from f's constant cache.
278+
func (f *Func) unCache(v *Value) {
279+
if v.InCache {
280+
aux := v.AuxInt
281+
if f.unCacheLine(v, aux) {
282+
return
283+
}
284+
if aux == 0 {
285+
switch v.Op {
286+
case OpConstNil:
287+
aux = constNilMagic
288+
case OpConstSlice:
289+
aux = constSliceMagic
290+
case OpConstString:
291+
aux = constEmptyStringMagic
292+
case OpConstInterface:
293+
aux = constInterfaceMagic
294+
}
295+
if aux != 0 && f.unCacheLine(v, aux) {
296+
return
297+
}
298+
}
299+
f.Fatalf("unCached value %s not found in cache, auxInt=0x%x, adjusted aux=0x%x", v.LongString(), v.AuxInt, aux)
300+
}
301+
}
302+
260303
// freeValue frees a value. It must no longer be referenced or have any args.
261304
func (f *Func) freeValue(v *Value) {
262305
if v.Block == nil {
@@ -270,19 +313,8 @@ func (f *Func) freeValue(v *Value) {
270313
}
271314
// Clear everything but ID (which we reuse).
272315
id := v.ID
273-
274-
// Values with zero arguments and OpOffPtr values might be cached, so remove them there.
275-
nArgs := opcodeTable[v.Op].argLen
276-
if nArgs == 0 || v.Op == OpOffPtr {
277-
vv := f.constants[v.AuxInt]
278-
for i, cv := range vv {
279-
if v == cv {
280-
vv[i] = vv[len(vv)-1]
281-
vv[len(vv)-1] = nil
282-
f.constants[v.AuxInt] = vv[0 : len(vv)-1]
283-
break
284-
}
285-
}
316+
if v.InCache {
317+
f.unCache(v)
286318
}
287319
*v = Value{}
288320
v.ID = id
@@ -548,6 +580,7 @@ func (f *Func) constVal(op Op, t *types.Type, c int64, setAuxInt bool) *Value {
548580
v = f.Entry.NewValue0(src.NoXPos, op, t)
549581
}
550582
f.constants[c] = append(vv, v)
583+
v.InCache = true
551584
return v
552585
}
553586

src/cmd/compile/internal/ssa/softfloat.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ func softfloat(f *Func) {
1818
for _, b := range f.Blocks {
1919
for _, v := range b.Values {
2020
if v.Type.IsFloat() {
21+
f.unCache(v)
2122
switch v.Op {
2223
case OpPhi, OpLoad, OpArg:
2324
if v.Type.Size() == 4 {

src/cmd/compile/internal/ssa/value.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ type Value struct {
5454
// nor a slot on Go stack, and the generation of this value is delayed to its use time.
5555
OnWasmStack bool
5656

57+
// Is this value in the per-function constant cache? If so, remove from cache before changing it or recycling it.
58+
InCache bool
59+
5760
// Storage for the first three args
5861
argstorage [3]*Value
5962
}
@@ -332,6 +335,9 @@ func (v *Value) resetArgs() {
332335
// of cmd/compile by almost 10%, and slows it down.
333336
//go:noinline
334337
func (v *Value) reset(op Op) {
338+
if v.InCache {
339+
v.Block.Func.unCache(v)
340+
}
335341
v.Op = op
336342
v.resetArgs()
337343
v.AuxInt = 0
@@ -342,6 +348,9 @@ func (v *Value) reset(op Op) {
342348
// It modifies v to be (Copy a).
343349
//go:noinline
344350
func (v *Value) copyOf(a *Value) {
351+
if v.InCache {
352+
v.Block.Func.unCache(v)
353+
}
345354
v.Op = OpCopy
346355
v.resetArgs()
347356
v.AddArg(a)

0 commit comments

Comments
 (0)