]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: add logging for large (>= 128 byte) copies
authorDavid Chase <drchase@google.com>
Sun, 3 Nov 2019 03:57:11 +0000 (23:57 -0400)
committerDavid Chase <drchase@google.com>
Fri, 3 Apr 2020 17:24:48 +0000 (17:24 +0000)
For 1.15, unless someone really wants it in 1.14.

A performance-sensitive user thought this would be useful,
though "large" was not well-defined.  If 128 is large,
there are 139 static instances of "large" copies in the compiler
itself.

Includes test.

Change-Id: I81f20c62da59d37072429f3a22c1809e6fb2946d
Reviewed-on: https://go-review.googlesource.com/c/go/+/205066
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
20 files changed:
src/cmd/compile/internal/logopt/logopt_test.go
src/cmd/compile/internal/ssa/gen/386.rules
src/cmd/compile/internal/ssa/gen/AMD64.rules
src/cmd/compile/internal/ssa/gen/ARM.rules
src/cmd/compile/internal/ssa/gen/ARM64.rules
src/cmd/compile/internal/ssa/gen/MIPS.rules
src/cmd/compile/internal/ssa/gen/MIPS64.rules
src/cmd/compile/internal/ssa/gen/PPC64.rules
src/cmd/compile/internal/ssa/gen/S390X.rules
src/cmd/compile/internal/ssa/gen/Wasm.rules
src/cmd/compile/internal/ssa/rewrite.go
src/cmd/compile/internal/ssa/rewrite386.go
src/cmd/compile/internal/ssa/rewriteAMD64.go
src/cmd/compile/internal/ssa/rewriteARM.go
src/cmd/compile/internal/ssa/rewriteARM64.go
src/cmd/compile/internal/ssa/rewriteMIPS.go
src/cmd/compile/internal/ssa/rewriteMIPS64.go
src/cmd/compile/internal/ssa/rewritePPC64.go
src/cmd/compile/internal/ssa/rewriteS390X.go
src/cmd/compile/internal/ssa/rewriteWasm.go

index 98b8a710c563220fd3ed21c994948e107f0063a5..0b974fc31e3e0a6eee33b4a371001be92f6a29d6 100644 (file)
@@ -38,6 +38,12 @@ func want(t *testing.T, out string, desired string) {
        }
 }
 
+func wantN(t *testing.T, out string, desired string, n int) {
+       if strings.Count(out, desired) != n {
+               t.Errorf("expected exactly %d occurences of %s in \n%s", n, desired, out)
+       }
+}
+
 func TestLogOpt(t *testing.T) {
        t.Parallel()
 
@@ -75,7 +81,70 @@ func TestLogOpt(t *testing.T) {
 
        })
 
+       // replace d (dir)  with t ("tmpdir") and convert path separators to '/'
+       normalize := func(out []byte, d, t string) string {
+               s := string(out)
+               s = strings.ReplaceAll(s, d, t)
+               s = strings.ReplaceAll(s, string(os.PathSeparator), "/")
+               return s
+       }
+
+       // Ensure that <128 byte copies are not reported and that 128-byte copies are.
+       // Check at both 1 and 8-byte alignments.
+       t.Run("Copy", func(t *testing.T) {
+               const copyCode = `package x
+func s128a1(x *[128]int8) [128]int8 { 
+       return *x
+}
+func s127a1(x *[127]int8) [127]int8 {
+       return *x
+}
+func s16a8(x *[16]int64) [16]int64 {
+       return *x
+}
+func s15a8(x *[15]int64) [15]int64 {
+       return *x
+}
+`
+               copy := filepath.Join(dir, "copy.go")
+               if err := ioutil.WriteFile(copy, []byte(copyCode), 0644); err != nil {
+                       t.Fatal(err)
+               }
+               outcopy := filepath.Join(dir, "copy.o")
+
+               // On not-amd64, test the host architecture and os
+               arches := []string{runtime.GOARCH}
+               goos0 := runtime.GOOS
+               if runtime.GOARCH == "amd64" { // Test many things with "linux" (wasm will get "js")
+                       arches = []string{"arm", "arm64", "386", "amd64", "mips", "mips64", "ppc64le", "s390x", "wasm"}
+                       goos0 = "linux"
+               }
+
+               for _, arch := range arches {
+                       t.Run(arch, func(t *testing.T) {
+                               goos := goos0
+                               if arch == "wasm" {
+                                       goos = "js"
+                               }
+                               _, err := testCopy(t, dir, arch, goos, copy, outcopy)
+                               if err != nil {
+                                       t.Error("-json=0,file://log/opt should have succeeded")
+                               }
+                               logged, err := ioutil.ReadFile(filepath.Join(dir, "log", "opt", "x", "copy.json"))
+                               if err != nil {
+                                       t.Error("-json=0,file://log/opt missing expected log file")
+                               }
+                               slogged := normalize(logged, string(uriIfy(dir)), string(uriIfy("tmpdir")))
+                               t.Logf("%s", slogged)
+                               want(t, slogged, `{"range":{"start":{"line":3,"character":2},"end":{"line":3,"character":2}},"severity":3,"code":"copy","source":"go compiler","message":"128 bytes"}`)
+                               want(t, slogged, `{"range":{"start":{"line":9,"character":2},"end":{"line":9,"character":2}},"severity":3,"code":"copy","source":"go compiler","message":"128 bytes"}`)
+                               wantN(t, slogged, `"code":"copy"`, 2)
+                       })
+               }
+       })
+
        // Some architectures don't fault on nil dereference, so nilchecks are eliminated differently.
+       // The N-way copy test also doesn't need to run N-ways N times.
        if runtime.GOARCH != "amd64" {
                return
        }
@@ -83,14 +152,6 @@ func TestLogOpt(t *testing.T) {
        t.Run("Success", func(t *testing.T) {
                // This test is supposed to succeed
 
-               // replace d (dir)  with t ("tmpdir") and convert path separators to '/'
-               normalize := func(out []byte, d, t string) string {
-                       s := string(out)
-                       s = strings.ReplaceAll(s, d, t)
-                       s = strings.ReplaceAll(s, string(os.PathSeparator), "/")
-                       return s
-               }
-
                // Note 'file://' is the I-Know-What-I-Am-Doing way of specifying a file, also to deal with corner cases for Windows.
                _, err := testLogOptDir(t, dir, "-json=0,file://log/opt", src, outfile)
                if err != nil {
@@ -131,3 +192,15 @@ func testLogOptDir(t *testing.T, dir, flag, src, outfile string) (string, error)
        t.Logf("%s", out)
        return string(out), err
 }
+
+func testCopy(t *testing.T, dir, goarch, goos, src, outfile string) (string, error) {
+       // Notice the specified import path "x"
+       run := []string{testenv.GoToolPath(t), "tool", "compile", "-p", "x", "-json=0,file://log/opt", "-o", outfile, src}
+       t.Log(run)
+       cmd := exec.Command(run[0], run[1:]...)
+       cmd.Dir = dir
+       cmd.Env = []string{"GOARCH=" + goarch, "GOOS=" + goos}
+       out, err := cmd.CombinedOutput()
+       t.Logf("%s", out)
+       return string(out), err
+}
index 2c48994a5fc382db34be09f87f56aac27702086c..a396b75c70301b545c2a19e56eb0253733a62e35 100644 (file)
 // Medium copying uses a duff device.
 (Move [s] dst src mem)
        && s > 8 && s <= 4*128 && s%4 == 0
-       && !config.noDuffDevice ->
+       && !config.noDuffDevice && logLargeCopy(v, s) ->
        (DUFFCOPY [10*(128-s/4)] dst src mem)
 // 10 and 128 are magic constants.  10 is the number of bytes to encode:
 //     MOVL    (SI), CX
 // and 128 is the number of such blocks. See src/runtime/duff_386.s:duffcopy.
 
 // Large copying uses REP MOVSL.
-(Move [s] dst src mem) && (s > 4*128 || config.noDuffDevice) && s%4 == 0 ->
+(Move [s] dst src mem) && (s > 4*128 || config.noDuffDevice) && s%4 == 0 && logLargeCopy(v, s) ->
        (REPMOVSL dst src (MOVLconst [s/4]) mem)
 
 // Lowering Zero instructions
index b5133d6c14dd132806538cd34ef84b91a4ccd458..2c9fe4a59bd6cb0d580805271ac0515a3ebf47eb 100644 (file)
 // Medium copying uses a duff device.
 (Move [s] dst src mem)
        && s > 64 && s <= 16*64 && s%16 == 0
-       && !config.noDuffDevice ->
+       && !config.noDuffDevice && logLargeCopy(v, s) ->
        (DUFFCOPY [14*(64-s/16)] dst src mem)
 // 14 and 64 are magic constants.  14 is the number of bytes to encode:
 //     MOVUPS  (SI), X0
 // and 64 is the number of such blocks. See src/runtime/duff_amd64.s:duffcopy.
 
 // Large copying uses REP MOVSQ.
-(Move [s] dst src mem) && (s > 16*64 || config.noDuffDevice) && s%8 == 0 ->
+(Move [s] dst src mem) && (s > 16*64 || config.noDuffDevice) && s%8 == 0 && logLargeCopy(v, s) ->
        (REPMOVSQ dst src (MOVQconst [s/8]) mem)
 
 // Lowering Zero instructions
index 839d701b8cc24a5bb53fad8bd8ed9d36d23a5982..3f41cc2a721c4e88214706b7a6ed4adabd275063 100644 (file)
 // 8 and 128 are magic constants, see runtime/mkduff.go
 (Move [s] {t} dst src mem)
        && s%4 == 0 && s > 4 && s <= 512
-       && t.(*types.Type).Alignment()%4 == 0 && !config.noDuffDevice ->
+       && t.(*types.Type).Alignment()%4 == 0 && !config.noDuffDevice && logLargeCopy(v, s) ->
        (DUFFCOPY [8 * (128 - s/4)] dst src mem)
 
 // Large move uses a loop
 (Move [s] {t} dst src mem)
-       && (s > 512 || config.noDuffDevice) || t.(*types.Type).Alignment()%4 != 0 ->
+       && ((s > 512 || config.noDuffDevice) || t.(*types.Type).Alignment()%4 != 0) && logLargeCopy(v, s) ->
        (LoweredMove [t.(*types.Type).Alignment()]
                dst
                src
index 61994a15a1f7474f11793e12a3b634bf0a5394cd..6c8213798ecb55539dc8421e9409576f2578d91d 100644 (file)
 // medium move uses a duff device
 (Move [s] dst src mem)
        && s > 32 && s <= 16*64 && s%16 == 8
-       && !config.noDuffDevice ->
+       && !config.noDuffDevice && logLargeCopy(v, s) ->
        (MOVDstore [s-8] dst (MOVDload [s-8] src mem)
                (DUFFCOPY <types.TypeMem> [8*(64-(s-8)/16)] dst src mem))
 (Move [s] dst src mem)
        && s > 32 && s <= 16*64 && s%16 == 0
-       && !config.noDuffDevice ->
+       && !config.noDuffDevice && logLargeCopy(v, s) ->
        (DUFFCOPY [8 * (64 - s/16)] dst src mem)
 // 8 is the number of bytes to encode:
 //
 
 // large move uses a loop
 (Move [s] dst src mem)
-       && s > 24 && s%8 == 0 ->
+       && s > 24 && s%8 == 0 && logLargeCopy(v, s) ->
        (LoweredMove
                dst
                src
index 9ac8e5f47129154189dcd6c0858dd17dec41961d..eed74b6abca48bd367c383367d57a6a3858d093a 100644 (file)
 
 // large or unaligned move uses a loop
 (Move [s] {t} dst src mem)
-       && (s > 16 || t.(*types.Type).Alignment()%4 != 0) ->
+       && (s > 16 && logLargeCopy(v, s) || t.(*types.Type).Alignment()%4 != 0) ->
        (LoweredMove [t.(*types.Type).Alignment()]
                dst
                src
index be05dc71c0420e5ded91f2d004d5f15b993926d5..63f6cb08f4b65cbc29ba16bc4f0eaae7658dda07 100644 (file)
 // medium move uses a duff device
 (Move [s] {t} dst src mem)
        && s%8 == 0 && s >= 24 && s <= 8*128 && t.(*types.Type).Alignment()%8 == 0
-       && !config.noDuffDevice ->
+       && !config.noDuffDevice && logLargeCopy(v, s)  ->
        (DUFFCOPY [16 * (128 - s/8)] dst src mem)
 // 16 and 128 are magic constants.  16 is the number of bytes to encode:
 //     MOVV    (R1), R23
 
 // large or unaligned move uses a loop
 (Move [s] {t} dst src mem)
-       && s > 24 || t.(*types.Type).Alignment()%8 != 0 ->
+       && s > 24 && logLargeCopy(v, s) || t.(*types.Type).Alignment()%8 != 0 ->
        (LoweredMove [t.(*types.Type).Alignment()]
                dst
                src
index be7a9858efda60247fb841d7a8fceb604c297de5..0c182a6222e5ea8e3785b6fa446f3b6a79dbc888 100644 (file)
 
 // Large move uses a loop. Since the address is computed and the
 // offset is zero, any alignment can be used.
-(Move [s] dst src mem) && s > 8 ->
+(Move [s] dst src mem) && s > 8 && logLargeCopy(v, s) ->
         (LoweredMove [s] dst src mem)
 
 // Calls
index 2084179edc6307f1d8253c2754215f60025aeff2..d8c27c7ce15fa5649d925b01642e0e4c5e631b06 100644 (file)
                        (MOVWstore dst (MOVWZload src mem) mem)))
 
 // MVC for other moves. Use up to 4 instructions (sizes up to 1024 bytes).
-(Move [s] dst src mem) && s > 0 && s <= 256 ->
+(Move [s] dst src mem) && s > 0 && s <= 256 && logLargeCopy(v, s) ->
        (MVC [makeValAndOff(s, 0)] dst src mem)
-(Move [s] dst src mem) && s > 256 && s <= 512 ->
+(Move [s] dst src mem) && s > 256 && s <= 512 && logLargeCopy(v, s) ->
        (MVC [makeValAndOff(s-256, 256)] dst src (MVC [makeValAndOff(256, 0)] dst src mem))
-(Move [s] dst src mem) && s > 512 && s <= 768 ->
+(Move [s] dst src mem) && s > 512 && s <= 768 && logLargeCopy(v, s) ->
        (MVC [makeValAndOff(s-512, 512)] dst src (MVC [makeValAndOff(256, 256)] dst src (MVC [makeValAndOff(256, 0)] dst src mem)))
-(Move [s] dst src mem) && s > 768 && s <= 1024 ->
+(Move [s] dst src mem) && s > 768 && s <= 1024 && logLargeCopy(v, s) ->
        (MVC [makeValAndOff(s-768, 768)] dst src (MVC [makeValAndOff(256, 512)] dst src (MVC [makeValAndOff(256, 256)] dst src (MVC [makeValAndOff(256, 0)] dst src mem))))
 
 // Move more than 1024 bytes using a loop.
-(Move [s] dst src mem) && s > 1024 ->
+(Move [s] dst src mem) && s > 1024 && logLargeCopy(v, s) ->
        (LoweredMove [s%256] dst src (ADD <src.Type> src (MOVDconst [(s/256)*256])) mem)
 
 // Lowering Zero instructions
 (Zero [s] destptr mem) && s > 0 && s <= 1024 ->
        (CLEAR [makeValAndOff(s, 0)] destptr mem)
 
-// Move more than 1024 bytes using a loop.
+// Zero more than 1024 bytes using a loop.
 (Zero [s] destptr mem) && s > 1024 ->
        (LoweredZero [s%256] destptr (ADDconst <destptr.Type> destptr [(s/256)*256]) mem)
 
index bf2b904baf0381779abaa6daf2d6997b711c434a..56ac188685c368370f2715108317177704078246 100644 (file)
                        (I64Store dst (I64Load src mem) mem)))
 
 // Large copying uses helper.
-(Move [s] dst src mem) && s%8 == 0 ->
+(Move [s] dst src mem) && s%8 == 0 && logLargeCopy(v, s) ->
        (LoweredMove [s/8] dst src mem)
 
 // Lowering Zero instructions
index 727fd2402d7f52f83ee48f9762218a3758ca6058..a7979b273fc912c3f0b9ffde6023b13578a08694 100644 (file)
@@ -5,6 +5,7 @@
 package ssa
 
 import (
+       "cmd/compile/internal/logopt"
        "cmd/compile/internal/types"
        "cmd/internal/obj"
        "cmd/internal/objabi"
@@ -1084,6 +1085,19 @@ func isInlinableMemmove(dst, src *Value, sz int64, c *Config) bool {
        return false
 }
 
+// logLargeCopy logs the occurrence of a large copy.
+// The best place to do this is in the rewrite rules where the size of the move is easy to find.
+// "Large" is arbitrarily chosen to be 128 bytes; this may change.
+func logLargeCopy(v *Value, s int64) bool {
+       if s < 128 {
+               return true
+       }
+       if logopt.Enabled() {
+               logopt.LogOpt(v.Pos, "copy", "lower", v.Block.Func.Name, fmt.Sprintf("%d bytes", s))
+       }
+       return true
+}
+
 // hasSmallRotate reports whether the architecture has rotate instructions
 // for sizes < 32-bit.  This is used to decide whether to promote some rotations.
 func hasSmallRotate(c *Config) bool {
index 2a0a92bb839316076f8d54618f1f8a404e4f5f2e..59a9edee8faf0f818a1d40f0c7cf41772d482657 100644 (file)
@@ -10046,14 +10046,14 @@ func rewriteValue386_OpMove(v *Value) bool {
                return true
        }
        // match: (Move [s] dst src mem)
-       // cond: s > 8 && s <= 4*128 && s%4 == 0 && !config.noDuffDevice
+       // cond: s > 8 && s <= 4*128 && s%4 == 0 && !config.noDuffDevice && logLargeCopy(v, s)
        // result: (DUFFCOPY [10*(128-s/4)] dst src mem)
        for {
                s := v.AuxInt
                dst := v_0
                src := v_1
                mem := v_2
-               if !(s > 8 && s <= 4*128 && s%4 == 0 && !config.noDuffDevice) {
+               if !(s > 8 && s <= 4*128 && s%4 == 0 && !config.noDuffDevice && logLargeCopy(v, s)) {
                        break
                }
                v.reset(Op386DUFFCOPY)
@@ -10062,14 +10062,14 @@ func rewriteValue386_OpMove(v *Value) bool {
                return true
        }
        // match: (Move [s] dst src mem)
-       // cond: (s > 4*128 || config.noDuffDevice) && s%4 == 0
+       // cond: (s > 4*128 || config.noDuffDevice) && s%4 == 0 && logLargeCopy(v, s)
        // result: (REPMOVSL dst src (MOVLconst [s/4]) mem)
        for {
                s := v.AuxInt
                dst := v_0
                src := v_1
                mem := v_2
-               if !((s > 4*128 || config.noDuffDevice) && s%4 == 0) {
+               if !((s > 4*128 || config.noDuffDevice) && s%4 == 0 && logLargeCopy(v, s)) {
                        break
                }
                v.reset(Op386REPMOVSL)
index e4d86485d4fc6d9ef14c49882dfc131551555124..d6ea57d6496596790558ad33a124e17fe4cf77ef 100644 (file)
@@ -31632,14 +31632,14 @@ func rewriteValueAMD64_OpMove(v *Value) bool {
                return true
        }
        // match: (Move [s] dst src mem)
-       // cond: s > 64 && s <= 16*64 && s%16 == 0 && !config.noDuffDevice
+       // cond: s > 64 && s <= 16*64 && s%16 == 0 && !config.noDuffDevice && logLargeCopy(v, s)
        // result: (DUFFCOPY [14*(64-s/16)] dst src mem)
        for {
                s := v.AuxInt
                dst := v_0
                src := v_1
                mem := v_2
-               if !(s > 64 && s <= 16*64 && s%16 == 0 && !config.noDuffDevice) {
+               if !(s > 64 && s <= 16*64 && s%16 == 0 && !config.noDuffDevice && logLargeCopy(v, s)) {
                        break
                }
                v.reset(OpAMD64DUFFCOPY)
@@ -31648,14 +31648,14 @@ func rewriteValueAMD64_OpMove(v *Value) bool {
                return true
        }
        // match: (Move [s] dst src mem)
-       // cond: (s > 16*64 || config.noDuffDevice) && s%8 == 0
+       // cond: (s > 16*64 || config.noDuffDevice) && s%8 == 0 && logLargeCopy(v, s)
        // result: (REPMOVSQ dst src (MOVQconst [s/8]) mem)
        for {
                s := v.AuxInt
                dst := v_0
                src := v_1
                mem := v_2
-               if !((s > 16*64 || config.noDuffDevice) && s%8 == 0) {
+               if !((s > 16*64 || config.noDuffDevice) && s%8 == 0 && logLargeCopy(v, s)) {
                        break
                }
                v.reset(OpAMD64REPMOVSQ)
index 91ef5fe14f9d3aadc5b54538ee5b81eeba547b78..6af335698d61c2c24ec4ce89ce8687b1463edab6 100644 (file)
@@ -15228,7 +15228,7 @@ func rewriteValueARM_OpMove(v *Value) bool {
                return true
        }
        // match: (Move [s] {t} dst src mem)
-       // cond: s%4 == 0 && s > 4 && s <= 512 && t.(*types.Type).Alignment()%4 == 0 && !config.noDuffDevice
+       // cond: s%4 == 0 && s > 4 && s <= 512 && t.(*types.Type).Alignment()%4 == 0 && !config.noDuffDevice && logLargeCopy(v, s)
        // result: (DUFFCOPY [8 * (128 - s/4)] dst src mem)
        for {
                s := v.AuxInt
@@ -15236,7 +15236,7 @@ func rewriteValueARM_OpMove(v *Value) bool {
                dst := v_0
                src := v_1
                mem := v_2
-               if !(s%4 == 0 && s > 4 && s <= 512 && t.(*types.Type).Alignment()%4 == 0 && !config.noDuffDevice) {
+               if !(s%4 == 0 && s > 4 && s <= 512 && t.(*types.Type).Alignment()%4 == 0 && !config.noDuffDevice && logLargeCopy(v, s)) {
                        break
                }
                v.reset(OpARMDUFFCOPY)
@@ -15245,7 +15245,7 @@ func rewriteValueARM_OpMove(v *Value) bool {
                return true
        }
        // match: (Move [s] {t} dst src mem)
-       // cond: (s > 512 || config.noDuffDevice) || t.(*types.Type).Alignment()%4 != 0
+       // cond: ((s > 512 || config.noDuffDevice) || t.(*types.Type).Alignment()%4 != 0) && logLargeCopy(v, s)
        // result: (LoweredMove [t.(*types.Type).Alignment()] dst src (ADDconst <src.Type> src [s-moveSize(t.(*types.Type).Alignment(), config)]) mem)
        for {
                s := v.AuxInt
@@ -15253,7 +15253,7 @@ func rewriteValueARM_OpMove(v *Value) bool {
                dst := v_0
                src := v_1
                mem := v_2
-               if !((s > 512 || config.noDuffDevice) || t.(*types.Type).Alignment()%4 != 0) {
+               if !(((s > 512 || config.noDuffDevice) || t.(*types.Type).Alignment()%4 != 0) && logLargeCopy(v, s)) {
                        break
                }
                v.reset(OpARMLoweredMove)
index 4d1ed50d9b3d4e03df731c2373576ea5849b2a3f..f6f77e9bb6368b25a6946c91daf40f0649f02b44 100644 (file)
@@ -23742,14 +23742,14 @@ func rewriteValueARM64_OpMove(v *Value) bool {
                return true
        }
        // match: (Move [s] dst src mem)
-       // cond: s > 32 && s <= 16*64 && s%16 == 8 && !config.noDuffDevice
+       // cond: s > 32 && s <= 16*64 && s%16 == 8 && !config.noDuffDevice && logLargeCopy(v, s)
        // result: (MOVDstore [s-8] dst (MOVDload [s-8] src mem) (DUFFCOPY <types.TypeMem> [8*(64-(s-8)/16)] dst src mem))
        for {
                s := v.AuxInt
                dst := v_0
                src := v_1
                mem := v_2
-               if !(s > 32 && s <= 16*64 && s%16 == 8 && !config.noDuffDevice) {
+               if !(s > 32 && s <= 16*64 && s%16 == 8 && !config.noDuffDevice && logLargeCopy(v, s)) {
                        break
                }
                v.reset(OpARM64MOVDstore)
@@ -23764,14 +23764,14 @@ func rewriteValueARM64_OpMove(v *Value) bool {
                return true
        }
        // match: (Move [s] dst src mem)
-       // cond: s > 32 && s <= 16*64 && s%16 == 0 && !config.noDuffDevice
+       // cond: s > 32 && s <= 16*64 && s%16 == 0 && !config.noDuffDevice && logLargeCopy(v, s)
        // result: (DUFFCOPY [8 * (64 - s/16)] dst src mem)
        for {
                s := v.AuxInt
                dst := v_0
                src := v_1
                mem := v_2
-               if !(s > 32 && s <= 16*64 && s%16 == 0 && !config.noDuffDevice) {
+               if !(s > 32 && s <= 16*64 && s%16 == 0 && !config.noDuffDevice && logLargeCopy(v, s)) {
                        break
                }
                v.reset(OpARM64DUFFCOPY)
@@ -23780,14 +23780,14 @@ func rewriteValueARM64_OpMove(v *Value) bool {
                return true
        }
        // match: (Move [s] dst src mem)
-       // cond: s > 24 && s%8 == 0
+       // cond: s > 24 && s%8 == 0 && logLargeCopy(v, s)
        // result: (LoweredMove dst src (ADDconst <src.Type> src [s-8]) mem)
        for {
                s := v.AuxInt
                dst := v_0
                src := v_1
                mem := v_2
-               if !(s > 24 && s%8 == 0) {
+               if !(s > 24 && s%8 == 0 && logLargeCopy(v, s)) {
                        break
                }
                v.reset(OpARM64LoweredMove)
index 5815874db9413bd585474d66aa69ef132090cef7..9459a56b826d234cfd8cc16dbbf18f857bc3cdcc 100644 (file)
@@ -5263,7 +5263,7 @@ func rewriteValueMIPS_OpMove(v *Value) bool {
                return true
        }
        // match: (Move [s] {t} dst src mem)
-       // cond: (s > 16 || t.(*types.Type).Alignment()%4 != 0)
+       // cond: (s > 16 && logLargeCopy(v, s) || t.(*types.Type).Alignment()%4 != 0)
        // result: (LoweredMove [t.(*types.Type).Alignment()] dst src (ADDconst <src.Type> src [s-moveSize(t.(*types.Type).Alignment(), config)]) mem)
        for {
                s := v.AuxInt
@@ -5271,7 +5271,7 @@ func rewriteValueMIPS_OpMove(v *Value) bool {
                dst := v_0
                src := v_1
                mem := v_2
-               if !(s > 16 || t.(*types.Type).Alignment()%4 != 0) {
+               if !(s > 16 && logLargeCopy(v, s) || t.(*types.Type).Alignment()%4 != 0) {
                        break
                }
                v.reset(OpMIPSLoweredMove)
index 125c33d0029ed2d46a34bcec68248f8c533c4188..360fdebe85a8a4cba6173a0c696c7f0cc8f16ef8 100644 (file)
@@ -5533,7 +5533,7 @@ func rewriteValueMIPS64_OpMove(v *Value) bool {
                return true
        }
        // match: (Move [s] {t} dst src mem)
-       // cond: s%8 == 0 && s >= 24 && s <= 8*128 && t.(*types.Type).Alignment()%8 == 0 && !config.noDuffDevice
+       // cond: s%8 == 0 && s >= 24 && s <= 8*128 && t.(*types.Type).Alignment()%8 == 0 && !config.noDuffDevice && logLargeCopy(v, s)
        // result: (DUFFCOPY [16 * (128 - s/8)] dst src mem)
        for {
                s := v.AuxInt
@@ -5541,7 +5541,7 @@ func rewriteValueMIPS64_OpMove(v *Value) bool {
                dst := v_0
                src := v_1
                mem := v_2
-               if !(s%8 == 0 && s >= 24 && s <= 8*128 && t.(*types.Type).Alignment()%8 == 0 && !config.noDuffDevice) {
+               if !(s%8 == 0 && s >= 24 && s <= 8*128 && t.(*types.Type).Alignment()%8 == 0 && !config.noDuffDevice && logLargeCopy(v, s)) {
                        break
                }
                v.reset(OpMIPS64DUFFCOPY)
@@ -5550,7 +5550,7 @@ func rewriteValueMIPS64_OpMove(v *Value) bool {
                return true
        }
        // match: (Move [s] {t} dst src mem)
-       // cond: s > 24 || t.(*types.Type).Alignment()%8 != 0
+       // cond: s > 24 && logLargeCopy(v, s) || t.(*types.Type).Alignment()%8 != 0
        // result: (LoweredMove [t.(*types.Type).Alignment()] dst src (ADDVconst <src.Type> src [s-moveSize(t.(*types.Type).Alignment(), config)]) mem)
        for {
                s := v.AuxInt
@@ -5558,7 +5558,7 @@ func rewriteValueMIPS64_OpMove(v *Value) bool {
                dst := v_0
                src := v_1
                mem := v_2
-               if !(s > 24 || t.(*types.Type).Alignment()%8 != 0) {
+               if !(s > 24 && logLargeCopy(v, s) || t.(*types.Type).Alignment()%8 != 0) {
                        break
                }
                v.reset(OpMIPS64LoweredMove)
index d5568b696f13cb95431ab4c82695568b773b13bb..a2ee60a86ef91d129fecb8a67c2ec0b086a604e3 100644 (file)
@@ -3486,14 +3486,14 @@ func rewriteValuePPC64_OpMove(v *Value) bool {
                return true
        }
        // match: (Move [s] dst src mem)
-       // cond: s > 8
+       // cond: s > 8 && logLargeCopy(v, s)
        // result: (LoweredMove [s] dst src mem)
        for {
                s := v.AuxInt
                dst := v_0
                src := v_1
                mem := v_2
-               if !(s > 8) {
+               if !(s > 8 && logLargeCopy(v, s)) {
                        break
                }
                v.reset(OpPPC64LoweredMove)
index 7dd2e7633b9967117f6dba66db263f662f98474d..83f8d31f82149e5216b02b5efc17ccf8d204b755 100644 (file)
@@ -3303,14 +3303,14 @@ func rewriteValueS390X_OpMove(v *Value) bool {
                return true
        }
        // match: (Move [s] dst src mem)
-       // cond: s > 0 && s <= 256
+       // cond: s > 0 && s <= 256 && logLargeCopy(v, s)
        // result: (MVC [makeValAndOff(s, 0)] dst src mem)
        for {
                s := v.AuxInt
                dst := v_0
                src := v_1
                mem := v_2
-               if !(s > 0 && s <= 256) {
+               if !(s > 0 && s <= 256 && logLargeCopy(v, s)) {
                        break
                }
                v.reset(OpS390XMVC)
@@ -3319,14 +3319,14 @@ func rewriteValueS390X_OpMove(v *Value) bool {
                return true
        }
        // match: (Move [s] dst src mem)
-       // cond: s > 256 && s <= 512
+       // cond: s > 256 && s <= 512 && logLargeCopy(v, s)
        // result: (MVC [makeValAndOff(s-256, 256)] dst src (MVC [makeValAndOff(256, 0)] dst src mem))
        for {
                s := v.AuxInt
                dst := v_0
                src := v_1
                mem := v_2
-               if !(s > 256 && s <= 512) {
+               if !(s > 256 && s <= 512 && logLargeCopy(v, s)) {
                        break
                }
                v.reset(OpS390XMVC)
@@ -3338,14 +3338,14 @@ func rewriteValueS390X_OpMove(v *Value) bool {
                return true
        }
        // match: (Move [s] dst src mem)
-       // cond: s > 512 && s <= 768
+       // cond: s > 512 && s <= 768 && logLargeCopy(v, s)
        // result: (MVC [makeValAndOff(s-512, 512)] dst src (MVC [makeValAndOff(256, 256)] dst src (MVC [makeValAndOff(256, 0)] dst src mem)))
        for {
                s := v.AuxInt
                dst := v_0
                src := v_1
                mem := v_2
-               if !(s > 512 && s <= 768) {
+               if !(s > 512 && s <= 768 && logLargeCopy(v, s)) {
                        break
                }
                v.reset(OpS390XMVC)
@@ -3360,14 +3360,14 @@ func rewriteValueS390X_OpMove(v *Value) bool {
                return true
        }
        // match: (Move [s] dst src mem)
-       // cond: s > 768 && s <= 1024
+       // cond: s > 768 && s <= 1024 && logLargeCopy(v, s)
        // result: (MVC [makeValAndOff(s-768, 768)] dst src (MVC [makeValAndOff(256, 512)] dst src (MVC [makeValAndOff(256, 256)] dst src (MVC [makeValAndOff(256, 0)] dst src mem))))
        for {
                s := v.AuxInt
                dst := v_0
                src := v_1
                mem := v_2
-               if !(s > 768 && s <= 1024) {
+               if !(s > 768 && s <= 1024 && logLargeCopy(v, s)) {
                        break
                }
                v.reset(OpS390XMVC)
@@ -3385,14 +3385,14 @@ func rewriteValueS390X_OpMove(v *Value) bool {
                return true
        }
        // match: (Move [s] dst src mem)
-       // cond: s > 1024
+       // cond: s > 1024 && logLargeCopy(v, s)
        // result: (LoweredMove [s%256] dst src (ADD <src.Type> src (MOVDconst [(s/256)*256])) mem)
        for {
                s := v.AuxInt
                dst := v_0
                src := v_1
                mem := v_2
-               if !(s > 1024) {
+               if !(s > 1024 && logLargeCopy(v, s)) {
                        break
                }
                v.reset(OpS390XLoweredMove)
index be1b51e7aa794ba3b344e20ae2b3f5236b61b402..20d7d521965ac71dfff2c6ac3ce5f6c2cf8e1154 100644 (file)
@@ -2104,14 +2104,14 @@ func rewriteValueWasm_OpMove(v *Value) bool {
                return true
        }
        // match: (Move [s] dst src mem)
-       // cond: s%8 == 0
+       // cond: s%8 == 0 && logLargeCopy(v, s)
        // result: (LoweredMove [s/8] dst src mem)
        for {
                s := v.AuxInt
                dst := v_0
                src := v_1
                mem := v_2
-               if !(s%8 == 0) {
+               if !(s%8 == 0 && logLargeCopy(v, s)) {
                        break
                }
                v.reset(OpWasmLoweredMove)