]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: randomize value order in block for testing
authorKeith Randall <khr@golang.org>
Mon, 5 Dec 2016 23:41:04 +0000 (15:41 -0800)
committerKeith Randall <khr@golang.org>
Wed, 28 Nov 2018 17:13:46 +0000 (17:13 +0000)
A little bit of compiler stress testing. Randomize the order
of the values in a block before every phase. This randomization
makes sure that we're not implicitly depending on that order.

Currently the random seed is a hash of the function name.
It provides determinism, but sacrifices some coverage.
Other arrangements are possible (env var, ...) but require
more setup.

Fixes #20178

Change-Id: Idae792a23264bd9a3507db6ba49b6d591a608e83
Reviewed-on: https://go-review.googlesource.com/c/33909
Reviewed-by: Cherry Zhang <cherryyz@google.com>
src/cmd/compile/internal/ssa/compile.go
src/cmd/compile/internal/ssa/nilcheck.go
test/run.go

index 96bc5f03c1c5c195c3c3c6bdf2282c3aeea0091e..29618e29c37fc442efd22ffbd779e81b26400a61 100644 (file)
@@ -8,7 +8,9 @@ import (
        "cmd/internal/objabi"
        "cmd/internal/src"
        "fmt"
+       "hash/crc32"
        "log"
+       "math/rand"
        "os"
        "regexp"
        "runtime"
@@ -29,6 +31,11 @@ func Compile(f *Func) {
                f.Logf("compiling %s\n", f.Name)
        }
 
+       var rnd *rand.Rand
+       if checkEnabled {
+               rnd = rand.New(rand.NewSource(int64(crc32.ChecksumIEEE(([]byte)(f.Name)))))
+       }
+
        // hook to print function & phase if panic happens
        phaseName := "init"
        defer func() {
@@ -68,6 +75,17 @@ func Compile(f *Func) {
                        runtime.ReadMemStats(&mStart)
                }
 
+               if checkEnabled && !f.scheduled {
+                       // Test that we don't depend on the value order, by randomizing
+                       // the order of values in each block. See issue 18169.
+                       for _, b := range f.Blocks {
+                               for i := 0; i < len(b.Values)-1; i++ {
+                                       j := i + rnd.Intn(len(b.Values)-i)
+                                       b.Values[i], b.Values[j] = b.Values[j], b.Values[i]
+                               }
+                       }
+               }
+
                tStart := time.Now()
                p.fn(f)
                tEnd := time.Now()
index e0669cf80c845f54408f31b9f51fa8718cbff03f..5f58e2d7ec1efa3d58c227daccf05a7bded5499a 100644 (file)
@@ -290,6 +290,6 @@ func nilcheckelim2(f *Func) {
                b.Values = b.Values[:i]
 
                // TODO: if b.Kind == BlockPlain, start the analysis in the subsequent block to find
-               // more unnecessary nil checks.  Would fix test/nilptr3_ssa.go:157.
+               // more unnecessary nil checks.  Would fix test/nilptr3.go:159.
        }
 }
index 39647d7252d15f54eb0b395c71fc8ab78c8b3512..e7976657dedd2a1a73a3e764ada15803c352fbf4 100644 (file)
@@ -559,6 +559,19 @@ func (t *test) run() {
                }
                args = args[1:]
        }
+       if action == "errorcheck" {
+               found := false
+               for i, f := range flags {
+                       if strings.HasPrefix(f, "-d=") {
+                               flags[i] = f + ",ssa/check/on"
+                               found = true
+                               break
+                       }
+               }
+               if !found {
+                       flags = append(flags, "-d=ssa/check/on")
+               }
+       }
 
        t.makeTempDir()
        if !*keep {