#2104·gonum

internal/asm/c64: AMD64 DotcInc and DotuInc scalar tails read 16 bytes for one complex64

Author: jamestjspCreated Sep 8, 2026Updated Sep 8, 2026

Upstream master 2b52c28fc756441b75b3af99cddc1649f4439ded; AMD64 ASM, no SIMD experiment.

Save as asm_dot_repro_test.go in the repository root. Run:

bash
GOEXPERIMENT= go test -run '^TestUpstreamDotTail/DotuInc

```go
//go:build linux || darwin

package gonum_test

import (
	"gonum.org/v1/gonum/internal/asm/c64"
	"runtime"
	"syscall"
	"testing"
	"unsafe"
)

func TestUpstreamDotTail(t *testing.T) {
	for _, conjugate := range []bool{false, true} {
		name := "DotuInc"
		if conjugate {
			name = "DotcInc"
		}
		t.Run(name, func(t *testing.T) {
			page := syscall.Getpagesize()
			mem, err := syscall.Mmap(-1, 0, 2*page, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_ANON|syscall.MAP_PRIVATE)
			if err != nil {
				t.Fatal(err)
			}
			defer syscall.Munmap(mem)
			if err := syscall.Mprotect(mem[page:], syscall.PROT_NONE); err != nil {
				t.Fatal(err)
			}
			y := unsafe.Slice((*complex64)(unsafe.Pointer(&mem[page-8])), 1)
			y[0] = 3 + 4i
			x := []complex64{1 + 2i}
			got, want := complex64(0), complex64(-5+10i)
			if conjugate {
				got = c64.DotcInc(x, y, 1, 1, 1, 0, 0)
				want = 11 - 2i
			} else {
				got = c64.DotuInc(x, y, 1, 1, 1, 0, 0)
			}
			runtime.KeepAlive(mem)
			if got != want {
				t.Fatalf("got %v want %v", got, want)
			}
		})
	}
}

ASM may terminate the process; use ulimit -c 0. Go 1.27.1/Rosetta: original tail faults; repaired ASM and noasm controls pass. Native AMD64 pending. -count=1 -timeout=5s . GOEXPERIMENT= go test -run '^TestUpstreamDotTail/DotcInc

go
//go:build linux || darwin

package gonum_test

import (
	"gonum.org/v1/gonum/internal/asm/c64"
	"runtime"
	"syscall"
	"testing"
	"unsafe"
)

func TestUpstreamDotTail(t *testing.T) {
	for _, conjugate := range []bool{false, true} {
		name := "DotuInc"
		if conjugate {
			name = "DotcInc"
		}
		t.Run(name, func(t *testing.T) {
			page := syscall.Getpagesize()
			mem, err := syscall.Mmap(-1, 0, 2*page, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_ANON|syscall.MAP_PRIVATE)
			if err != nil {
				t.Fatal(err)
			}
			defer syscall.Munmap(mem)
			if err := syscall.Mprotect(mem[page:], syscall.PROT_NONE); err != nil {
				t.Fatal(err)
			}
			y := unsafe.Slice((*complex64)(unsafe.Pointer(&mem[page-8])), 1)
			y[0] = 3 + 4i
			x := []complex64{1 + 2i}
			got, want := complex64(0), complex64(-5+10i)
			if conjugate {
				got = c64.DotcInc(x, y, 1, 1, 1, 0, 0)
				want = 11 - 2i
			} else {
				got = c64.DotuInc(x, y, 1, 1, 1, 0, 0)
			}
			runtime.KeepAlive(mem)
			if got != want {
				t.Fatalf("got %v want %v", got, want)
			}
		})
	}
}

ASM may terminate the process; use ulimit -c 0. Verification: source audited; noasm control passed on darwin/arm64, Go 1.27.1. Fresh native AMD64 execution not yet verified. -count=1 -timeout=5s .


Add `-tags noasm` for the passing control.

```go
//go:build linux || darwin

package gonum_test

import (
	"gonum.org/v1/gonum/internal/asm/c64"
	"runtime"
	"syscall"
	"testing"
	"unsafe"
)

func TestUpstreamDotTail(t *testing.T) {
	for _, conjugate := range []bool{false, true} {
		name := "DotuInc"
		if conjugate {
			name = "DotcInc"
		}
		t.Run(name, func(t *testing.T) {
			page := syscall.Getpagesize()
			mem, err := syscall.Mmap(-1, 0, 2*page, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_ANON|syscall.MAP_PRIVATE)
			if err != nil {
				t.Fatal(err)
			}
			defer syscall.Munmap(mem)
			if err := syscall.Mprotect(mem[page:], syscall.PROT_NONE); err != nil {
				t.Fatal(err)
			}
			y := unsafe.Slice((*complex64)(unsafe.Pointer(&mem[page-8])), 1)
			y[0] = 3 + 4i
			x := []complex64{1 + 2i}
			got, want := complex64(0), complex64(-5+10i)
			if conjugate {
				got = c64.DotcInc(x, y, 1, 1, 1, 0, 0)
				want = 11 - 2i
			} else {
				got = c64.DotuInc(x, y, 1, 1, 1, 0, 0)
			}
			runtime.KeepAlive(mem)
			if got != want {
				t.Fatalf("got %v want %v", got, want)
			}
		})
	}
}

ASM may terminate the process; use ulimit -c 0. Verification: source audited; noasm control passed on darwin/arm64, Go 1.27.1. Fresh native AMD64 execution not yet verified.