1
0
mirror of https://github.com/golang/go synced 2024-09-29 15:14:28 -06: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:
Keith Randall 2022-07-24 13:24:21 -07:00
parent a726c9f662
commit a74e5f584e
4 changed files with 28 additions and 10 deletions

View File

@ -5,6 +5,7 @@
package ssa package ssa
import ( import (
"cmd/compile/internal/ir"
"cmd/internal/obj/s390x" "cmd/internal/obj/s390x"
"math" "math"
"math/bits" "math/bits"
@ -312,6 +313,10 @@ func checkFunc(f *Func) {
if !v.Args[1].Type.IsInteger() { if !v.Args[1].Type.IsInteger() {
f.Fatalf("bad arg 1 type to %s: want integer, have %s", v.Op, v.Args[1].LongString()) 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())
}
} }

View File

@ -22,7 +22,7 @@ func TestCSEAuxPartitionBug(t *testing.T) {
arg1Aux := &tstAux{"arg1-aux"} arg1Aux := &tstAux{"arg1-aux"}
arg2Aux := &tstAux{"arg2-aux"} arg2Aux := &tstAux{"arg2-aux"}
arg3Aux := &tstAux{"arg3-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 // construct lots of values with args that have aux values and place
// them in an order that triggers the bug // them in an order that triggers the bug
@ -93,7 +93,7 @@ func TestCSEAuxPartitionBug(t *testing.T) {
// TestZCSE tests the zero arg cse. // TestZCSE tests the zero arg cse.
func TestZCSE(t *testing.T) { func TestZCSE(t *testing.T) {
c := testConfig(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", fun := c.Fun("entry",
Bloc("entry", Bloc("entry",

View File

@ -72,6 +72,7 @@ func (TestFrontend) StringData(s string) *obj.LSym {
} }
func (TestFrontend) Auto(pos src.XPos, t *types.Type) *ir.Name { func (TestFrontend) Auto(pos src.XPos, t *types.Type) *ir.Name {
n := ir.NewNameAt(pos, &types.Sym{Name: "aFakeAuto"}) n := ir.NewNameAt(pos, &types.Sym{Name: "aFakeAuto"})
n.SetType(t)
n.Class = ir.PAUTO n.Class = ir.PAUTO
return n return n
} }

View File

@ -630,7 +630,9 @@ func (s *state) zeroResults() {
if typ := n.Type(); TypeOK(typ) { if typ := n.Type(); TypeOK(typ) {
s.assign(n, s.zeroVal(typ), false, 0) s.assign(n, s.zeroVal(typ), false, 0)
} else { } 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]) s.zero(n.Type(), s.decladdrs[n])
} }
} }
@ -1978,14 +1980,16 @@ func (s *state) exit() *ssa.Block {
for i, f := range resultFields { for i, f := range resultFields {
n := f.Nname.(*ir.Name) n := f.Nname.(*ir.Name)
if s.canSSA(n) { // result is in some SSA variable 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. // We are about to store to the result slot.
s.vars[memVar] = s.newValue1A(ssa.OpVarDef, types.TypeMem, n, s.mem()) s.vars[memVar] = s.newValue1A(ssa.OpVarDef, types.TypeMem, n, s.mem())
} }
results[i] = s.variable(n, n.Type()) results[i] = s.variable(n, n.Type())
} else if !n.OnStack() { // result is actually heap allocated } else if !n.OnStack() { // result is actually heap allocated
// We are about to copy the in-heap result to the result slot. // 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) ha := s.expr(n.Heapaddr)
s.instrumentFields(n.Type(), ha, instrumentRead) s.instrumentFields(n.Type(), ha, instrumentRead)
results[i] = s.newValue2(ssa.OpDereference, n.Type(), ha, s.mem()) 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 // If this assignment clobbers an entire local variable, then emit
// OpVarDef so liveness analysis knows the variable is redefined. // 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)) 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 // 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 // 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). // 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]) 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]) addrTemp = s.f.Entry.NewValue2A(src.NoXPos, ssa.OpLocalAddr, types.NewPtr(temp.Type()), temp, s.sp, s.defvars[s.f.Entry.ID][memVar])
} else { } else {
// Special case if we're still in the entry block. We can't use // 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 // the above code, since s.defvars[s.f.Entry.ID] isn't defined
// until we end the entry block with s.endBlock(). // 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) 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) 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() t := deferstruct()
d := typecheck.TempAt(n.Pos(), s.curfn, t) 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) addr := s.addr(d)
// Must match deferstruct() below and src/runtime/runtime2.go:_defer. // 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 // temp allocates a temp of type t at position pos
func (s *state) temp(pos src.XPos, t *types.Type) (*ir.Name, *ssa.Value) { func (s *state) temp(pos src.XPos, t *types.Type) (*ir.Name, *ssa.Value) {
tmp := typecheck.TempAt(pos, s.curfn, t) 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) addr := s.addr(tmp)
return tmp, addr return tmp, addr
} }