diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/cmd/compile/internal/gc/ssa.go | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index ac7f3eb22b..0706d95937 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -2767,10 +2767,14 @@ func (s *state) assign(left *Node, right *ssa.Value, deref bool, skip skipMask) s.addNamedValue(left, right) return } - // Left is not ssa-able. Compute its address. - if left.Op == ONAME && left.Class() != PEXTERN && skip == 0 { - s.vars[&memVar] = s.newValue1Apos(ssa.OpVarDef, types.TypeMem, left, s.mem(), !left.IsAutoTmp()) + + // If this assignment clobbers an entire local variable, then emit + // OpVarDef so liveness analysis knows the variable is redefined. + if base := clobberBase(left); base.Op == ONAME && base.Class() != PEXTERN && skip == 0 { + s.vars[&memVar] = s.newValue1Apos(ssa.OpVarDef, types.TypeMem, base, s.mem(), !base.IsAutoTmp()) } + + // Left is not ssa-able. Compute its address. addr := s.addr(left, false) if isReflectHeaderDataField(left) { // Package unsafe's documentation says storing pointers into @@ -6210,3 +6214,13 @@ func (n *Node) StorageClass() ssa.StorageClass { return 0 } } + +func clobberBase(n *Node) *Node { + if n.Op == ODOT && n.Left.Type.NumFields() == 1 { + return clobberBase(n.Left) + } + if n.Op == OINDEX && n.Left.Type.IsArray() && n.Left.Type.NumElem() == 1 { + return clobberBase(n.Left) + } + return n +} |
