go/analyis/passes/asmdecl: allow loading both parts of a complex with one instruction

Update golang/go#35264

Change-Id: I4317c75cc5acc592ab739b0aab4cd85280858219
Reviewed-on: https://go-review.googlesource.com/c/tools/+/204537
Reviewed-by: Alan Donovan <adonovan@google.com>
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/go/analysis/passes/asmdecl/asmdecl.go b/go/analysis/passes/asmdecl/asmdecl.go
index 6e7a76e..c2e89ee 100644
--- a/go/analysis/passes/asmdecl/asmdecl.go
+++ b/go/analysis/passes/asmdecl/asmdecl.go
@@ -661,6 +661,10 @@
 				src = 4
 				break
 			}
+			if op == "MOVO" || op == "MOVOU" {
+				src = 16
+				break
+			}
 			if strings.HasPrefix(op, "SET") {
 				// SETEQ, etc
 				src = 1
@@ -736,6 +740,11 @@
 		vk = v.inner[0].kind
 		vs = v.inner[0].size
 		vt = v.inner[0].typ
+	case asmComplex:
+		// Allow a single instruction to load both parts of a complex.
+		if int(kind) == vs {
+			kind = asmComplex
+		}
 	}
 	if addr {
 		vk = asmKind(archDef.ptrSize)
diff --git a/go/analysis/passes/asmdecl/testdata/src/a/asm1.s b/go/analysis/passes/asmdecl/testdata/src/a/asm1.s
index 9af8612..b39130f 100644
--- a/go/analysis/passes/asmdecl/testdata/src/a/asm1.s
+++ b/go/analysis/passes/asmdecl/testdata/src/a/asm1.s
@@ -228,7 +228,6 @@
 
 TEXT ·argcomplex(SB),0,$24 // want `wrong argument size 0; expected \$\.\.\.-24`
 	MOVSS	x+0(FP), X0 // want `invalid MOVSS of x\+0\(FP\); complex64 is 8-byte value containing x_real\+0\(FP\) and x_imag\+4\(FP\)`
-	MOVSD	x+0(FP), X0 // want `invalid MOVSD of x\+0\(FP\); complex64 is 8-byte value containing x_real\+0\(FP\) and x_imag\+4\(FP\)`
 	MOVSS	x_real+0(FP), X0
 	MOVSD	x_real+0(FP), X0 // want `invalid MOVSD of x_real\+0\(FP\); real\(complex64\) is 4-byte value`
 	MOVSS	x_real+4(FP), X0 // want `invalid offset x_real\+4\(FP\); expected x_real\+0\(FP\)`
@@ -242,6 +241,13 @@
 	MOVSS	y_imag+16(FP), X0 // want `invalid MOVSS of y_imag\+16\(FP\); imag\(complex128\) is 8-byte value`
 	MOVSD	y_imag+16(FP), X0
 	MOVSS	y_imag+24(FP), X0 // want `invalid offset y_imag\+24\(FP\); expected y_imag\+16\(FP\)`
+	// Loading both parts of a complex is ok: see issue 35264.
+	MOVSD	x+0(FP), X0
+	MOVO	y+8(FP), X0
+	MOVOU	y+8(FP), X0
+	// These are not ok.
+	MOVO	x+0(FP), X0 // want `invalid MOVO of x\+0\(FP\); complex64 is 8-byte value containing x_real\+0\(FP\) and x_imag\+4\(FP\)`
+	MOVOU	x+0(FP), X0 // want `invalid MOVOU of x\+0\(FP\); complex64 is 8-byte value containing x_real\+0\(FP\) and x_imag\+4\(FP\)`
 	RET
 
 TEXT ·argstruct(SB),0,$64 // want `wrong argument size 0; expected \$\.\.\.-24`