]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: when compiling with -N, avoid entry block
authorKeith Randall <khr@golang.org>
Mon, 3 May 2021 15:55:57 +0000 (08:55 -0700)
committerKeith Randall <khr@golang.org>
Tue, 4 May 2021 14:38:36 +0000 (14:38 +0000)
Lots of constant SSA values we put in the entry block so that
CSE can easily combine them. With -N, however, we don't run CSE, so
putting values in the entry block only serves to extend their lifetime
for no benefit.

Fixes #45897. The number of live SSA values per block goes from >5K to 22.
Memory use goes from ~3GB to ~400MB.

Change-Id: I620b423611790a900e0d4cd270eac5dbdddf2a2b
Reviewed-on: https://go-review.googlesource.com/c/go/+/316369
Trust: Keith Randall <khr@golang.org>
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
src/cmd/compile/internal/ssagen/ssa.go

index 85ebf62e98012ac6e837684f6bcd392758503d2a..c65e738188f5105db83d2139b1d57f32a2dd05ed 100644 (file)
@@ -1161,39 +1161,51 @@ func (s *state) newValue4I(op ssa.Op, t *types.Type, aux int64, arg0, arg1, arg2
        return s.curBlock.NewValue4I(s.peekPos(), op, t, aux, arg0, arg1, arg2, arg3)
 }
 
+func (s *state) entryBlock() *ssa.Block {
+       b := s.f.Entry
+       if base.Flag.N > 0 && s.curBlock != nil {
+               // If optimizations are off, allocate in current block instead. Since with -N
+               // we're not doing the CSE or tighten passes, putting lots of stuff in the
+               // entry block leads to O(n^2) entries in the live value map during regalloc.
+               // See issue 45897.
+               b = s.curBlock
+       }
+       return b
+}
+
 // entryNewValue0 adds a new value with no arguments to the entry block.
 func (s *state) entryNewValue0(op ssa.Op, t *types.Type) *ssa.Value {
-       return s.f.Entry.NewValue0(src.NoXPos, op, t)
+       return s.entryBlock().NewValue0(src.NoXPos, op, t)
 }
 
 // entryNewValue0A adds a new value with no arguments and an aux value to the entry block.
 func (s *state) entryNewValue0A(op ssa.Op, t *types.Type, aux ssa.Aux) *ssa.Value {
-       return s.f.Entry.NewValue0A(src.NoXPos, op, t, aux)
+       return s.entryBlock().NewValue0A(src.NoXPos, op, t, aux)
 }
 
 // entryNewValue1 adds a new value with one argument to the entry block.
 func (s *state) entryNewValue1(op ssa.Op, t *types.Type, arg *ssa.Value) *ssa.Value {
-       return s.f.Entry.NewValue1(src.NoXPos, op, t, arg)
+       return s.entryBlock().NewValue1(src.NoXPos, op, t, arg)
 }
 
 // entryNewValue1 adds a new value with one argument and an auxint value to the entry block.
 func (s *state) entryNewValue1I(op ssa.Op, t *types.Type, auxint int64, arg *ssa.Value) *ssa.Value {
-       return s.f.Entry.NewValue1I(src.NoXPos, op, t, auxint, arg)
+       return s.entryBlock().NewValue1I(src.NoXPos, op, t, auxint, arg)
 }
 
 // entryNewValue1A adds a new value with one argument and an aux value to the entry block.
 func (s *state) entryNewValue1A(op ssa.Op, t *types.Type, aux ssa.Aux, arg *ssa.Value) *ssa.Value {
-       return s.f.Entry.NewValue1A(src.NoXPos, op, t, aux, arg)
+       return s.entryBlock().NewValue1A(src.NoXPos, op, t, aux, arg)
 }
 
 // entryNewValue2 adds a new value with two arguments to the entry block.
 func (s *state) entryNewValue2(op ssa.Op, t *types.Type, arg0, arg1 *ssa.Value) *ssa.Value {
-       return s.f.Entry.NewValue2(src.NoXPos, op, t, arg0, arg1)
+       return s.entryBlock().NewValue2(src.NoXPos, op, t, arg0, arg1)
 }
 
 // entryNewValue2A adds a new value with two arguments and an aux value to the entry block.
 func (s *state) entryNewValue2A(op ssa.Op, t *types.Type, aux ssa.Aux, arg0, arg1 *ssa.Value) *ssa.Value {
-       return s.f.Entry.NewValue2A(src.NoXPos, op, t, aux, arg0, arg1)
+       return s.entryBlock().NewValue2A(src.NoXPos, op, t, aux, arg0, arg1)
 }
 
 // const* routines add a new const value to the entry block.
@@ -4766,9 +4778,9 @@ func (s *state) openDeferSave(n ir.Node, t *types.Type, val *ssa.Value) *ssa.Val
                // 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.entryNewValue1A(ssa.OpVarDef, types.TypeMem, argTemp, s.defvars[s.f.Entry.ID][memVar])
-               s.defvars[s.f.Entry.ID][memVar] = s.entryNewValue1A(ssa.OpVarLive, types.TypeMem, argTemp, s.defvars[s.f.Entry.ID][memVar])
-               addrArgTemp = s.entryNewValue2A(ssa.OpLocalAddr, types.NewPtr(argTemp.Type()), argTemp, s.sp, s.defvars[s.f.Entry.ID][memVar])
+               s.defvars[s.f.Entry.ID][memVar] = s.f.Entry.NewValue1A(src.NoXPos, ssa.OpVarDef, types.TypeMem, argTemp, s.defvars[s.f.Entry.ID][memVar])
+               s.defvars[s.f.Entry.ID][memVar] = s.f.Entry.NewValue1A(src.NoXPos, ssa.OpVarLive, types.TypeMem, argTemp, s.defvars[s.f.Entry.ID][memVar])
+               addrArgTemp = s.f.Entry.NewValue2A(src.NoXPos, ssa.OpLocalAddr, types.NewPtr(argTemp.Type()), argTemp, 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