mirror of
https://github.com/golang/go
synced 2024-11-17 09:14:46 -07:00
cmd/compile: issue VarDef only for pointer-ful types
Use OpVarDef only when the variable being defined has pointers in it. VarDef markers are only used for liveness analysis, and that only runs on pointer-ful variables. Fixes #53810 Change-Id: I09b0ef7ed31e72528916fe79325f80bbe69ff9b4 Reviewed-on: https://go-review.googlesource.com/c/go/+/419320 Reviewed-by: David Chase <drchase@google.com> Reviewed-by: Joedian Reid <joedian@golang.org> Run-TryBot: Keith Randall <khr@golang.org>
This commit is contained in:
parent
a726c9f662
commit
a74e5f584e
@ -5,6 +5,7 @@
|
||||
package ssa
|
||||
|
||||
import (
|
||||
"cmd/compile/internal/ir"
|
||||
"cmd/internal/obj/s390x"
|
||||
"math"
|
||||
"math/bits"
|
||||
@ -312,6 +313,10 @@ func checkFunc(f *Func) {
|
||||
if !v.Args[1].Type.IsInteger() {
|
||||
f.Fatalf("bad arg 1 type to %s: want integer, have %s", v.Op, v.Args[1].LongString())
|
||||
}
|
||||
case OpVarDef:
|
||||
if !v.Aux.(*ir.Name).Type().HasPointers() {
|
||||
f.Fatalf("vardef must have pointer type %s", v.Aux.(*ir.Name).Type().String())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ func TestCSEAuxPartitionBug(t *testing.T) {
|
||||
arg1Aux := &tstAux{"arg1-aux"}
|
||||
arg2Aux := &tstAux{"arg2-aux"}
|
||||
arg3Aux := &tstAux{"arg3-aux"}
|
||||
a := c.Frontend().Auto(src.NoXPos, c.config.Types.Int8)
|
||||
a := c.Frontend().Auto(src.NoXPos, c.config.Types.Int8.PtrTo())
|
||||
|
||||
// construct lots of values with args that have aux values and place
|
||||
// them in an order that triggers the bug
|
||||
@ -93,7 +93,7 @@ func TestCSEAuxPartitionBug(t *testing.T) {
|
||||
// TestZCSE tests the zero arg cse.
|
||||
func TestZCSE(t *testing.T) {
|
||||
c := testConfig(t)
|
||||
a := c.Frontend().Auto(src.NoXPos, c.config.Types.Int8)
|
||||
a := c.Frontend().Auto(src.NoXPos, c.config.Types.Int8.PtrTo())
|
||||
|
||||
fun := c.Fun("entry",
|
||||
Bloc("entry",
|
||||
|
@ -72,6 +72,7 @@ func (TestFrontend) StringData(s string) *obj.LSym {
|
||||
}
|
||||
func (TestFrontend) Auto(pos src.XPos, t *types.Type) *ir.Name {
|
||||
n := ir.NewNameAt(pos, &types.Sym{Name: "aFakeAuto"})
|
||||
n.SetType(t)
|
||||
n.Class = ir.PAUTO
|
||||
return n
|
||||
}
|
||||
|
@ -630,7 +630,9 @@ func (s *state) zeroResults() {
|
||||
if typ := n.Type(); TypeOK(typ) {
|
||||
s.assign(n, s.zeroVal(typ), false, 0)
|
||||
} else {
|
||||
s.vars[memVar] = s.newValue1A(ssa.OpVarDef, types.TypeMem, n, s.mem())
|
||||
if typ.HasPointers() {
|
||||
s.vars[memVar] = s.newValue1A(ssa.OpVarDef, types.TypeMem, n, s.mem())
|
||||
}
|
||||
s.zero(n.Type(), s.decladdrs[n])
|
||||
}
|
||||
}
|
||||
@ -1978,14 +1980,16 @@ func (s *state) exit() *ssa.Block {
|
||||
for i, f := range resultFields {
|
||||
n := f.Nname.(*ir.Name)
|
||||
if s.canSSA(n) { // result is in some SSA variable
|
||||
if !n.IsOutputParamInRegisters() {
|
||||
if !n.IsOutputParamInRegisters() && n.Type().HasPointers() {
|
||||
// We are about to store to the result slot.
|
||||
s.vars[memVar] = s.newValue1A(ssa.OpVarDef, types.TypeMem, n, s.mem())
|
||||
}
|
||||
results[i] = s.variable(n, n.Type())
|
||||
} else if !n.OnStack() { // result is actually heap allocated
|
||||
// We are about to copy the in-heap result to the result slot.
|
||||
s.vars[memVar] = s.newValue1A(ssa.OpVarDef, types.TypeMem, n, s.mem())
|
||||
if n.Type().HasPointers() {
|
||||
s.vars[memVar] = s.newValue1A(ssa.OpVarDef, types.TypeMem, n, s.mem())
|
||||
}
|
||||
ha := s.expr(n.Heapaddr)
|
||||
s.instrumentFields(n.Type(), ha, instrumentRead)
|
||||
results[i] = s.newValue2(ssa.OpDereference, n.Type(), ha, s.mem())
|
||||
@ -3607,7 +3611,7 @@ func (s *state) assign(left ir.Node, right *ssa.Value, deref bool, skip skipMask
|
||||
|
||||
// If this assignment clobbers an entire local variable, then emit
|
||||
// OpVarDef so liveness analysis knows the variable is redefined.
|
||||
if base, ok := clobberBase(left).(*ir.Name); ok && base.OnStack() && skip == 0 {
|
||||
if base, ok := clobberBase(left).(*ir.Name); ok && base.OnStack() && skip == 0 && t.HasPointers() {
|
||||
s.vars[memVar] = s.newValue1Apos(ssa.OpVarDef, types.TypeMem, base, s.mem(), !ir.IsAutoTmp(base))
|
||||
}
|
||||
|
||||
@ -4843,14 +4847,18 @@ func (s *state) openDeferSave(t *types.Type, val *ssa.Value) *ssa.Value {
|
||||
// Force the tmp storing this defer function to be declared in the entry
|
||||
// block, so that it will be live for the defer exit code (which will
|
||||
// actually access it only if the associated defer call has been activated).
|
||||
s.defvars[s.f.Entry.ID][memVar] = s.f.Entry.NewValue1A(src.NoXPos, ssa.OpVarDef, types.TypeMem, temp, s.defvars[s.f.Entry.ID][memVar])
|
||||
if t.HasPointers() {
|
||||
s.defvars[s.f.Entry.ID][memVar] = s.f.Entry.NewValue1A(src.NoXPos, ssa.OpVarDef, types.TypeMem, temp, s.defvars[s.f.Entry.ID][memVar])
|
||||
}
|
||||
s.defvars[s.f.Entry.ID][memVar] = s.f.Entry.NewValue1A(src.NoXPos, ssa.OpVarLive, types.TypeMem, temp, s.defvars[s.f.Entry.ID][memVar])
|
||||
addrTemp = s.f.Entry.NewValue2A(src.NoXPos, ssa.OpLocalAddr, types.NewPtr(temp.Type()), temp, s.sp, s.defvars[s.f.Entry.ID][memVar])
|
||||
} else {
|
||||
// Special case if we're still in the entry block. We can't use
|
||||
// the above code, since s.defvars[s.f.Entry.ID] isn't defined
|
||||
// until we end the entry block with s.endBlock().
|
||||
s.vars[memVar] = s.newValue1Apos(ssa.OpVarDef, types.TypeMem, temp, s.mem(), false)
|
||||
if t.HasPointers() {
|
||||
s.vars[memVar] = s.newValue1Apos(ssa.OpVarDef, types.TypeMem, temp, s.mem(), false)
|
||||
}
|
||||
s.vars[memVar] = s.newValue1Apos(ssa.OpVarLive, types.TypeMem, temp, s.mem(), false)
|
||||
addrTemp = s.newValue2Apos(ssa.OpLocalAddr, types.NewPtr(temp.Type()), temp, s.sp, s.mem(), false)
|
||||
}
|
||||
@ -5032,7 +5040,9 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val
|
||||
t := deferstruct()
|
||||
d := typecheck.TempAt(n.Pos(), s.curfn, t)
|
||||
|
||||
s.vars[memVar] = s.newValue1A(ssa.OpVarDef, types.TypeMem, d, s.mem())
|
||||
if t.HasPointers() {
|
||||
s.vars[memVar] = s.newValue1A(ssa.OpVarDef, types.TypeMem, d, s.mem())
|
||||
}
|
||||
addr := s.addr(d)
|
||||
|
||||
// Must match deferstruct() below and src/runtime/runtime2.go:_defer.
|
||||
@ -6428,7 +6438,9 @@ func (s *state) dottype1(pos src.XPos, src, dst *types.Type, iface, source, targ
|
||||
// temp allocates a temp of type t at position pos
|
||||
func (s *state) temp(pos src.XPos, t *types.Type) (*ir.Name, *ssa.Value) {
|
||||
tmp := typecheck.TempAt(pos, s.curfn, t)
|
||||
s.vars[memVar] = s.newValue1A(ssa.OpVarDef, types.TypeMem, tmp, s.mem())
|
||||
if t.HasPointers() {
|
||||
s.vars[memVar] = s.newValue1A(ssa.OpVarDef, types.TypeMem, tmp, s.mem())
|
||||
}
|
||||
addr := s.addr(tmp)
|
||||
return tmp, addr
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user