cmd/compile: make duplicate anonymous interface output deterministic

Taking over CL 162240, the original CL hasn't been making progress.
I just took the parts that fix the immediate issue. I left the
signatslice changes out, I don't think they are necessary.

Fixes #30202

Change-Id: I5b347605f0841dd925d5a73150b8bf269fa82464
Reviewed-on: https://go-review.googlesource.com/c/go/+/183852
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/src/cmd/compile/internal/gc/reflect.go b/src/cmd/compile/internal/gc/reflect.go
index 9b26ba1..c2d9ba2 100644
--- a/src/cmd/compile/internal/gc/reflect.go
+++ b/src/cmd/compile/internal/gc/reflect.go
@@ -1659,7 +1659,17 @@
 	// they refer to byte or uint8, such as **byte vs **uint8,
 	// the types' ShortStrings can be identical.
 	// To preserve deterministic sort ordering, sort these by String().
-	return a[i].regular < a[j].regular
+	if a[i].regular != a[j].regular {
+		return a[i].regular < a[j].regular
+	}
+	// Identical anonymous interfaces defined in different locations
+	// will be equal for the above checks, but different in DWARF output.
+	// Sort by source position to ensure deterministic order.
+	// See issues 27013 and 30202.
+	if a[i].t.Etype == types.TINTER && a[i].t.Methods().Len() > 0 {
+		return a[i].t.Methods().Index(0).Pos.Before(a[j].t.Methods().Index(0).Pos)
+	}
+	return false
 }
 func (a typesByString) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
 
diff --git a/src/cmd/compile/internal/gc/reproduciblebuilds_test.go b/src/cmd/compile/internal/gc/reproduciblebuilds_test.go
index 9173f80..59d1edb 100644
--- a/src/cmd/compile/internal/gc/reproduciblebuilds_test.go
+++ b/src/cmd/compile/internal/gc/reproduciblebuilds_test.go
@@ -18,6 +18,7 @@
 	tests := []string{
 		"issue20272.go",
 		"issue27013.go",
+		"issue30202.go",
 	}
 
 	testenv.MustHaveGoBuild(t)
@@ -38,7 +39,9 @@
 			defer os.Remove(tmp.Name())
 			defer tmp.Close()
 			for i := 0; i < iters; i++ {
-				out, err := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-o", tmp.Name(), filepath.Join("testdata", "reproducible", test)).CombinedOutput()
+				// Note: use -c 2 to expose any nondeterminism which is the result
+				// of the runtime scheduler.
+				out, err := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-c", "2", "-o", tmp.Name(), filepath.Join("testdata", "reproducible", test)).CombinedOutput()
 				if err != nil {
 					t.Fatalf("failed to compile: %v\n%s", err, out)
 				}
diff --git a/src/cmd/compile/internal/gc/testdata/reproducible/issue30202.go b/src/cmd/compile/internal/gc/testdata/reproducible/issue30202.go
new file mode 100644
index 0000000..7b5de2c
--- /dev/null
+++ b/src/cmd/compile/internal/gc/testdata/reproducible/issue30202.go
@@ -0,0 +1,17 @@
+// Copyright 2019 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.
+
+package p
+
+func A(x interface {
+	X() int
+}) int {
+	return x.X()
+}
+
+func B(x interface {
+	X() int
+}) int {
+	return x.X()
+}