Skip to content

Commit

Permalink
cmd/compile: issue VarDef only for pointer-ful types
Browse files Browse the repository at this point in the history
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 <[email protected]>
Reviewed-by: Joedian Reid <[email protected]>
Run-TryBot: Keith Randall <[email protected]>
  • Loading branch information
randall77 committed Aug 22, 2022
1 parent a726c9f commit a74e5f5
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 10 deletions.
5 changes: 5 additions & 0 deletions src/cmd/compile/internal/ssa/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package ssa

import (
"cmd/compile/internal/ir"
"cmd/internal/obj/s390x"
"math"
"math/bits"
Expand Down Expand Up @@ -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())
}

}

Expand Down
4 changes: 2 additions & 2 deletions src/cmd/compile/internal/ssa/cse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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",
Expand Down
1 change: 1 addition & 0 deletions src/cmd/compile/internal/ssa/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
28 changes: 20 additions & 8 deletions src/cmd/compile/internal/ssagen/ssa.go
Original file line number Diff line number Diff line change
Expand Up @@ -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])
}
}
Expand Down Expand Up @@ -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())
Expand Down Expand Up @@ -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))
}

Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
}
Expand Down

0 comments on commit a74e5f5

Please sign in to comment.