mirror of https://github.com/golang/go.git
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 <drchase@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
parent
721819e7ba
commit
bf833ead62
|
|
@ -257,6 +257,49 @@ func (f *Func) LogStat(key string, args ...interface{}) {
|
|||
f.Warnl(f.Entry.Pos, "\t%s\t%s%s\t%s", n, key, value, f.Name)
|
||||
}
|
||||
|
||||
// unCacheLine removes v from f's constant cache "line" for aux,
|
||||
// resets v.InCache when it is found (and removed),
|
||||
// and returns whether v was found in that line.
|
||||
func (f *Func) unCacheLine(v *Value, aux int64) bool {
|
||||
vv := f.constants[aux]
|
||||
for i, cv := range vv {
|
||||
if v == cv {
|
||||
vv[i] = vv[len(vv)-1]
|
||||
vv[len(vv)-1] = nil
|
||||
f.constants[aux] = vv[0 : len(vv)-1]
|
||||
v.InCache = false
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// unCache removes v from f's constant cache.
|
||||
func (f *Func) unCache(v *Value) {
|
||||
if v.InCache {
|
||||
aux := v.AuxInt
|
||||
if f.unCacheLine(v, aux) {
|
||||
return
|
||||
}
|
||||
if aux == 0 {
|
||||
switch v.Op {
|
||||
case OpConstNil:
|
||||
aux = constNilMagic
|
||||
case OpConstSlice:
|
||||
aux = constSliceMagic
|
||||
case OpConstString:
|
||||
aux = constEmptyStringMagic
|
||||
case OpConstInterface:
|
||||
aux = constInterfaceMagic
|
||||
}
|
||||
if aux != 0 && f.unCacheLine(v, aux) {
|
||||
return
|
||||
}
|
||||
}
|
||||
f.Fatalf("unCached value %s not found in cache, auxInt=0x%x, adjusted aux=0x%x", v.LongString(), v.AuxInt, aux)
|
||||
}
|
||||
}
|
||||
|
||||
// freeValue frees a value. It must no longer be referenced or have any args.
|
||||
func (f *Func) freeValue(v *Value) {
|
||||
if v.Block == nil {
|
||||
|
|
@ -270,19 +313,8 @@ func (f *Func) freeValue(v *Value) {
|
|||
}
|
||||
// Clear everything but ID (which we reuse).
|
||||
id := v.ID
|
||||
|
||||
// Values with zero arguments and OpOffPtr values might be cached, so remove them there.
|
||||
nArgs := opcodeTable[v.Op].argLen
|
||||
if nArgs == 0 || v.Op == OpOffPtr {
|
||||
vv := f.constants[v.AuxInt]
|
||||
for i, cv := range vv {
|
||||
if v == cv {
|
||||
vv[i] = vv[len(vv)-1]
|
||||
vv[len(vv)-1] = nil
|
||||
f.constants[v.AuxInt] = vv[0 : len(vv)-1]
|
||||
break
|
||||
}
|
||||
}
|
||||
if v.InCache {
|
||||
f.unCache(v)
|
||||
}
|
||||
*v = Value{}
|
||||
v.ID = id
|
||||
|
|
@ -548,6 +580,7 @@ func (f *Func) constVal(op Op, t *types.Type, c int64, setAuxInt bool) *Value {
|
|||
v = f.Entry.NewValue0(src.NoXPos, op, t)
|
||||
}
|
||||
f.constants[c] = append(vv, v)
|
||||
v.InCache = true
|
||||
return v
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ func softfloat(f *Func) {
|
|||
for _, b := range f.Blocks {
|
||||
for _, v := range b.Values {
|
||||
if v.Type.IsFloat() {
|
||||
f.unCache(v)
|
||||
switch v.Op {
|
||||
case OpPhi, OpLoad, OpArg:
|
||||
if v.Type.Size() == 4 {
|
||||
|
|
|
|||
|
|
@ -54,6 +54,9 @@ type Value struct {
|
|||
// nor a slot on Go stack, and the generation of this value is delayed to its use time.
|
||||
OnWasmStack bool
|
||||
|
||||
// Is this value in the per-function constant cache? If so, remove from cache before changing it or recycling it.
|
||||
InCache bool
|
||||
|
||||
// Storage for the first three args
|
||||
argstorage [3]*Value
|
||||
}
|
||||
|
|
@ -332,6 +335,9 @@ func (v *Value) resetArgs() {
|
|||
// of cmd/compile by almost 10%, and slows it down.
|
||||
//go:noinline
|
||||
func (v *Value) reset(op Op) {
|
||||
if v.InCache {
|
||||
v.Block.Func.unCache(v)
|
||||
}
|
||||
v.Op = op
|
||||
v.resetArgs()
|
||||
v.AuxInt = 0
|
||||
|
|
@ -342,6 +348,9 @@ func (v *Value) reset(op Op) {
|
|||
// It modifies v to be (Copy a).
|
||||
//go:noinline
|
||||
func (v *Value) copyOf(a *Value) {
|
||||
if v.InCache {
|
||||
v.Block.Func.unCache(v)
|
||||
}
|
||||
v.Op = OpCopy
|
||||
v.resetArgs()
|
||||
v.AddArg(a)
|
||||
|
|
|
|||
Loading…
Reference in New Issue