From: Keith Randall Date: Sun, 24 Jul 2022 20:24:21 +0000 (-0700) Subject: cmd/compile: issue VarDef only for pointer-ful types X-Git-Tag: go1.20rc1~1479 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=a74e5f584e96cc89a8f6a1bb1a8cd9fc6ed6e72d;p=gostls13.git 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 Reviewed-by: Joedian Reid Run-TryBot: Keith Randall --- diff --git a/src/cmd/compile/internal/ssa/check.go b/src/cmd/compile/internal/ssa/check.go index df677e674a..f34b907419 100644 --- a/src/cmd/compile/internal/ssa/check.go +++ b/src/cmd/compile/internal/ssa/check.go @@ -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()) + } } diff --git a/src/cmd/compile/internal/ssa/cse_test.go b/src/cmd/compile/internal/ssa/cse_test.go index 8052016f3a..813ebe43a1 100644 --- a/src/cmd/compile/internal/ssa/cse_test.go +++ b/src/cmd/compile/internal/ssa/cse_test.go @@ -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", diff --git a/src/cmd/compile/internal/ssa/export_test.go b/src/cmd/compile/internal/ssa/export_test.go index 87d1b41419..f98437b629 100644 --- a/src/cmd/compile/internal/ssa/export_test.go +++ b/src/cmd/compile/internal/ssa/export_test.go @@ -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 } diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index c72cfa5144..1fa905bcc9 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -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 }