]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: optimize Move with all-zero ro sym src to Zero
authorJosh Bleecher Snyder <josharian@gmail.com>
Thu, 23 Apr 2020 20:28:14 +0000 (13:28 -0700)
committerJosh Bleecher Snyder <josharian@gmail.com>
Fri, 24 Apr 2020 23:58:10 +0000 (23:58 +0000)
We set up static symbols during walk that
we later make copies of to initialize local variables.
It is difficult to ascertain at that time exactly
when copying a symbol is profitable vs locally
initializing an autotmp.

During SSA, we are much better placed to optimize.
This change recognizes when we are copying from a
global readonly all-zero symbol and replaces it with
direct zeroing.

This often allows the all-zero symbol to be
deadcode eliminated at link time.
This is not ideal--it makes for large object files,
and longer link times--but it is the cleanest fix I could find.

This makes the final binary for the program in #38554
shrink from >500mb to ~2.2mb.

It also shrinks the standard binaries:

file      before    after     Δ       %
addr2line 4412496   4404304   -8192   -0.186%
buildid   2893816   2889720   -4096   -0.142%
cgo       4841048   4832856   -8192   -0.169%
compile   19926480  19922432  -4048   -0.020%
cover     5281816   5277720   -4096   -0.078%
link      6734648   6730552   -4096   -0.061%
nm        4366240   4358048   -8192   -0.188%
objdump   4755968   4747776   -8192   -0.172%
pprof     14653060  14612100  -40960  -0.280%
trace     11805940  11777268  -28672  -0.243%
vet       7185560   7181416   -4144   -0.058%
total     113588440 113465560 -122880 -0.108%

And not just by removing unnecessary symbols;
the program text shrinks a bit as well.

Fixes #38554

Change-Id: I8381ae6084ae145a5e0cd9410c451e52c0dc51c8
Reviewed-on: https://go-review.googlesource.com/c/go/+/229704
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
Reviewed-by: Keith Randall <khr@golang.org>
src/cmd/compile/internal/ssa/gen/generic.rules
src/cmd/compile/internal/ssa/rewrite.go
src/cmd/compile/internal/ssa/rewritegeneric.go
test/codegen/issue38554.go [new file with mode: 0644]

index 328585bbb6ad5ca60e690b017f5371add822a07b..5d64e2635854be4a39aa3c0996e3a6795bd5e0b0 100644 (file)
        => (Zero {t} [n] dst1 mem)
 (Move {t} [n] dst1 src mem:(VarDef (Zero {t} [n] dst0 _))) && isSamePtr(src, dst0)
        => (Zero {t} [n] dst1 mem)
+(Move {t} [n] dst (Addr {sym} (SB)) mem) && symIsROZero(sym) => (Zero {t} [n] dst mem)
 
 // Don't Store to variables that are about to be overwritten by Move/Zero.
 (Zero {t1} [n] p1 store:(Store {t2} (OffPtr [o2] p2) _ mem))
index 0522a955dd5471fdef499732e4d963d725b7b497..4572c7db20cf7c450e2c457bfbd12746e55382aa 100644 (file)
@@ -1381,6 +1381,20 @@ func symIsRO(sym interface{}) bool {
        return lsym.Type == objabi.SRODATA && len(lsym.R) == 0
 }
 
+// symIsROZero reports whether sym is a read-only global whose data contains all zeros.
+func symIsROZero(sym Sym) bool {
+       lsym := sym.(*obj.LSym)
+       if lsym.Type != objabi.SRODATA || len(lsym.R) != 0 {
+               return false
+       }
+       for _, b := range lsym.P {
+               if b != 0 {
+                       return false
+               }
+       }
+       return true
+}
+
 // read8 reads one byte from the read-only global sym at offset off.
 func read8(sym interface{}, off int64) uint8 {
        lsym := sym.(*obj.LSym)
index d0f6363d13a15cb39fad294a387a84ae8c371042..fc2c78eb03014369bf8a8e294319a9d8e03ca780 100644 (file)
@@ -12447,6 +12447,31 @@ func rewriteValuegeneric_OpMove(v *Value) bool {
                v.AddArg2(dst1, mem)
                return true
        }
+       // match: (Move {t} [n] dst (Addr {sym} (SB)) mem)
+       // cond: symIsROZero(sym)
+       // result: (Zero {t} [n] dst mem)
+       for {
+               n := auxIntToInt64(v.AuxInt)
+               t := auxToType(v.Aux)
+               dst := v_0
+               if v_1.Op != OpAddr {
+                       break
+               }
+               sym := auxToSym(v_1.Aux)
+               v_1_0 := v_1.Args[0]
+               if v_1_0.Op != OpSB {
+                       break
+               }
+               mem := v_2
+               if !(symIsROZero(sym)) {
+                       break
+               }
+               v.reset(OpZero)
+               v.AuxInt = int64ToAuxInt(n)
+               v.Aux = typeToAux(t)
+               v.AddArg2(dst, mem)
+               return true
+       }
        // match: (Move {t1} [n] dst1 src1 store:(Store {t2} op:(OffPtr [o2] dst2) _ mem))
        // cond: isSamePtr(dst1, dst2) && store.Uses == 1 && n >= o2 + t2.Size() && disjoint(src1, n, op, t2.Size()) && clobber(store)
        // result: (Move {t1} [n] dst1 src1 mem)
diff --git a/test/codegen/issue38554.go b/test/codegen/issue38554.go
new file mode 100644 (file)
index 0000000..84db847
--- /dev/null
@@ -0,0 +1,15 @@
+// asmcheck
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that we are zeroing directly instead of
+// copying a large zero value. Issue 38554.
+
+package codegen
+
+func retlarge() [256]byte {
+       // amd64:-"DUFFCOPY"
+       return [256]byte{}
+}