]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: deduplicate instructions when rewrite func results
authorYoulin Feng <fengyoulin@live.com>
Tue, 29 Jul 2025 10:53:29 +0000 (18:53 +0800)
committerJorropo <jorropo.pgm@gmail.com>
Wed, 30 Jul 2025 16:38:10 +0000 (09:38 -0700)
After CL 628075, do not rely on the memory arg of an OpLocalAddr.

Fixes #74788

Change-Id: I4e893241e3949bb8f2d93c8b88cc102e155b725d
Reviewed-on: https://go-review.googlesource.com/c/go/+/691275
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Jorropo <jorropo.pgm@gmail.com>
Reviewed-by: Mark Freeman <mark@golang.org>
src/cmd/compile/internal/ssa/expand_calls.go
src/cmd/internal/testdir/testdir_test.go
test/codegen/README
test/codegen/issue74788.go [new file with mode: 0644]

index fb281f2f8452cb7b49f5ee89641ed0b342f7b904..272b653ca3c6cef84c5a9983bcc92fb49a65c714 100644 (file)
@@ -243,11 +243,8 @@ func (x *expandState) rewriteFuncResults(v *Value, b *Block, aux *AuxCall) {
                if len(aRegs) > 0 {
                        result = &allResults
                } else {
-                       if a.Op == OpLoad && a.Args[0].Op == OpLocalAddr {
-                               addr := a.Args[0]
-                               if addr.MemoryArg() == a.MemoryArg() && addr.Aux == aux.NameOfResult(i) {
-                                       continue // Self move to output parameter
-                               }
+                       if a.Op == OpLoad && a.Args[0].Op == OpLocalAddr && a.Args[0].Aux == aux.NameOfResult(i) {
+                               continue // Self move to output parameter
                        }
                }
                rc.init(aRegs, aux.abiInfo, result, auxBase, auxOffset)
index 483a9ec33c67987725f3c7fa8aba7edb0b39c060..666645873bbc701f7ff96743958baeedd88a0444 100644 (file)
@@ -1462,9 +1462,10 @@ func (t test) wantedErrors(file, short string) (errs []wantedError) {
 
 const (
        // Regexp to match a single opcode check: optionally begin with "-" (to indicate
-       // a negative check), followed by a string literal enclosed in "" or ``. For "",
+       // a negative check) or a positive number (to specify the expected number of
+       // matches), followed by a string literal enclosed in "" or ``. For "",
        // backslashes must be handled.
-       reMatchCheck = `-?(?:\x60[^\x60]*\x60|"(?:[^"\\]|\\.)*")`
+       reMatchCheck = `(-|[1-9]\d*)?(?:\x60[^\x60]*\x60|"(?:[^"\\]|\\.)*")`
 )
 
 var (
@@ -1516,6 +1517,8 @@ type wantedAsmOpcode struct {
        fileline string         // original source file/line (eg: "/path/foo.go:45")
        line     int            // original source line
        opcode   *regexp.Regexp // opcode check to be performed on assembly output
+       expected int            // expected number of matches
+       actual   int            // actual number that matched
        negative bool           // true if the check is supposed to fail rather than pass
        found    bool           // true if the opcode check matched at least one in the output
 }
@@ -1622,9 +1625,16 @@ func (t test) wantedAsmOpcodes(fn string) asmChecks {
 
                        for _, m := range rxAsmCheck.FindAllString(allchecks, -1) {
                                negative := false
+                               expected := 0
                                if m[0] == '-' {
                                        negative = true
                                        m = m[1:]
+                               } else if '1' <= m[0] && m[0] <= '9' {
+                                       for '0' <= m[0] && m[0] <= '9' {
+                                               expected *= 10
+                                               expected += int(m[0] - '0')
+                                               m = m[1:]
+                                       }
                                }
 
                                rxsrc, err := strconv.Unquote(m)
@@ -1650,6 +1660,7 @@ func (t test) wantedAsmOpcodes(fn string) asmChecks {
                                                ops[env] = make(map[string][]wantedAsmOpcode)
                                        }
                                        ops[env][lnum] = append(ops[env][lnum], wantedAsmOpcode{
+                                               expected: expected,
                                                negative: negative,
                                                fileline: lnum,
                                                line:     i + 1,
@@ -1698,7 +1709,8 @@ func (t test) asmCheck(outStr string, fn string, env buildEnv, fullops map[strin
                // run the checks.
                if ops, found := fullops[srcFileLine]; found {
                        for i := range ops {
-                               if !ops[i].found && ops[i].opcode.FindString(asm) != "" {
+                               if (!ops[i].found || ops[i].expected > 0) && ops[i].opcode.FindString(asm) != "" {
+                                       ops[i].actual++
                                        ops[i].found = true
                                }
                        }
@@ -1714,6 +1726,9 @@ func (t test) asmCheck(outStr string, fn string, env buildEnv, fullops map[strin
                        if o.negative == o.found {
                                failed = append(failed, o)
                        }
+                       if o.expected > 0 && o.expected != o.actual {
+                               failed = append(failed, o)
+                       }
                }
        }
        if len(failed) == 0 {
@@ -1737,6 +1752,8 @@ func (t test) asmCheck(outStr string, fn string, env buildEnv, fullops map[strin
 
                if o.negative {
                        fmt.Fprintf(&errbuf, "%s:%d: %s: wrong opcode found: %q\n", t.goFileName(), o.line, env, o.opcode.String())
+               } else if o.expected > 0 {
+                       fmt.Fprintf(&errbuf, "%s:%d: %s: wrong number of opcodes: %q\n", t.goFileName(), o.line, env, o.opcode.String())
                } else {
                        fmt.Fprintf(&errbuf, "%s:%d: %s: opcode not found: %q\n", t.goFileName(), o.line, env, o.opcode.String())
                }
index 19a73d031c7670f0bb330a448414d2aa42e0bd08..33b9fbc49c0e322b670c4b1c064b1310449e79ff 100644 (file)
@@ -98,6 +98,13 @@ For example:
 verifies that NO memmove call is present in the assembly generated for
 the copy() line.
 
+The expected number of matches for the regexp can be specified using a
+positive number:
+
+  func fb(a [4]int) (r [4]int) {
+          // amd64:2`MOVUPS[^,]+, X0$`,2`MOVUPS\sX0,[^\n]+$`
+          return a
+  }
 
 - Architecture specifiers
 
diff --git a/test/codegen/issue74788.go b/test/codegen/issue74788.go
new file mode 100644 (file)
index 0000000..d04a89b
--- /dev/null
@@ -0,0 +1,17 @@
+// asmcheck
+
+// Copyright 2025 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 codegen
+
+func fa(a [2]int) (r [2]int) {
+       // amd64:1`MOVUPS[^,]+, X0$`,1`MOVUPS\sX0,[^\n]+$`
+       return a
+}
+
+func fb(a [4]int) (r [4]int) {
+       // amd64:2`MOVUPS[^,]+, X0$`,2`MOVUPS\sX0,[^\n]+$`
+       return a
+}