From: Youlin Feng Date: Tue, 29 Jul 2025 10:53:29 +0000 (+0800) Subject: cmd/compile: deduplicate instructions when rewrite func results X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=cc571dab91e73413cf2ba1546a4ba485038cf2d1;p=gostls13.git cmd/compile: deduplicate instructions when rewrite func results 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 Reviewed-by: David Chase Reviewed-by: Jorropo Reviewed-by: Mark Freeman --- diff --git a/src/cmd/compile/internal/ssa/expand_calls.go b/src/cmd/compile/internal/ssa/expand_calls.go index fb281f2f84..272b653ca3 100644 --- a/src/cmd/compile/internal/ssa/expand_calls.go +++ b/src/cmd/compile/internal/ssa/expand_calls.go @@ -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) diff --git a/src/cmd/internal/testdir/testdir_test.go b/src/cmd/internal/testdir/testdir_test.go index 483a9ec33c..666645873b 100644 --- a/src/cmd/internal/testdir/testdir_test.go +++ b/src/cmd/internal/testdir/testdir_test.go @@ -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()) } diff --git a/test/codegen/README b/test/codegen/README index 19a73d031c..33b9fbc49c 100644 --- a/test/codegen/README +++ b/test/codegen/README @@ -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 index 0000000000..d04a89b42e --- /dev/null +++ b/test/codegen/issue74788.go @@ -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 +}