diff --git a/projects/go.dev/dev-simd/README.md b/projects/go.dev/dev-simd/README.md new file mode 100644 index 0000000000..c2e6be7ec3 --- /dev/null +++ b/projects/go.dev/dev-simd/README.md @@ -0,0 +1,84 @@ +# Go — `dev.simd` SIMD toolchain + +A build of the Go toolchain from upstream Go's experimental **`dev.simd`** branch +(targeting Go 1.27), which adds the **`simd/archsimd`** package: portable SIMD +*intrinsics* you write in plain Go — no cgo, no hand-written assembly. The +compiler lowers them to real vector instructions on: + +- **amd64** — AVX2 / AVX-512 +- **arm64** — NEON + +## Why this package + +`simd/archsimd` is not in a released Go yet. amd64 support shipped in Go 1.26 +behind `GOEXPERIMENT=simd`; **arm64 (NEON) only exists on the `dev.simd` branch** +and is slated for Go 1.27. This package lets you **build and benchmark SIMD Go +code today**, on both amd64 and Apple-Silicon/arm64, before 1.27 is released — +reproducibly, from a pinned commit. + +It is a **pinned snapshot of a moving dev branch**, so it is intentionally +experimental and version-pinned (see *Versioning*). For released Go, use +[`go.dev`](https://pkgx.dev/pkgs/go.dev/). + +## Usage + +This package deliberately does **not** claim the `go` / `gofmt` commands (so it +never shadows the canonical `go.dev`). Use it explicitly with `+`: + +```sh +# which toolchain is it? +pkgx +go.dev/dev-simd -- go version # go version go1.27 ... + +# build / run SIMD code (set the experiment flag) +GOEXPERIMENT=simd pkgx +go.dev/dev-simd -- go build ./... +GOEXPERIMENT=simd pkgx +go.dev/dev-simd -- go test ./... +``` + +A minimal program that uses the intrinsics: + +```go +package main + +import ( + "fmt" + + "simd/archsimd" +) + +func main() { + // 4-wide u32 vector add (NEON on arm64, SSE/AVX on amd64) + a := archsimd.LoadUint32x4([]uint32{1, 2, 3, 4}) + b := archsimd.LoadUint32x4([]uint32{10, 20, 30, 40}) + var out [4]uint32 + a.Add(b).Store(out[:]) + fmt.Println(out) // [11 22 33 44] +} +``` + +```sh +GOEXPERIMENT=simd pkgx +go.dev/dev-simd -- go run . +``` + +The `simd/archsimd` package only compiles under `GOEXPERIMENT=simd`; without the +flag your code uses its normal (scalar) path. + +## Versioning + +`dev.simd` has no release tags, so each version is a **pinned commit**, named by +that commit's date in CalVer `YYYY.M.D.HH.MM.SS`: + +```sh +pkgx +go.dev/dev-simd@2026.6.1.17.4.35 -- go version # a specific snapshot +``` + +Newer commits get higher (later-dated) versions, so the latest snapshot is the +default. The exact upstream commit for each version is recorded in the recipe. + +## Caveats + +- **Experimental.** `simd/archsimd` is outside the Go 1 compatibility promise; + its API can change. This is a dev-branch snapshot, not a Go release. +- **`GOEXPERIMENT=simd` is required** to compile code that imports + `simd/archsimd`. +- For production, prefer released [`go.dev`](https://pkgx.dev/pkgs/go.dev/) — + amd64 SIMD lands in Go 1.26, arm64 SIMD in Go 1.27. diff --git a/projects/go.dev/dev-simd/package.yml b/projects/go.dev/dev-simd/package.yml new file mode 100644 index 0000000000..cd018ef221 --- /dev/null +++ b/projects/go.dev/dev-simd/package.yml @@ -0,0 +1,97 @@ +# Go toolchain built from the experimental `dev.simd` branch (targeting Go 1.27), +# which adds the `simd/archsimd` SIMD intrinsics for amd64 (AVX2/AVX-512) AND +# arm64 (NEON). Lets you build cgo-free, assembly-free SIMD code with +# `GOEXPERIMENT=simd` before Go 1.27 is released. +# +# `dev.simd` is a moving branch with no tags, so each packaged version is a +# PINNED COMMIT. The version is the commit's committer date as CalVer +# (YYYY.M.D.HH.MM.SS) — meaningful, monotonic, and parseable (no SemVer +# pre-release, which brewkit can't parse). The build fetches that exact commit. +# +# To add another snapshot: append its CalVer to `versions:` and a matching +# `) SHA= ;;` arm to the case in build.script. +display-name: Go (dev.simd SIMD intrinsics) + +distributable: ~ # no single archive; each version fetches its pinned commit + +versions: + - 2026.6.1.17.4.35 # go.googlesource.com/go dev.simd @ 0e5948dc (2026-06-01) + +# Deliberately NO `provides:` and NO `interprets:`. This package ships bin/go and +# bin/gofmt just like go.dev, so claiming them here would make the bare `pkgx go` +# / `.go` interpreter ambiguous between the two. pkgx has no `conflicts:` field; +# the idiomatic mutual exclusion is to let the canonical `go.dev` own those +# command/interpreter names and use this experimental toolchain only explicitly: +# +# pkgx +go.dev/dev-simd -- go build ... # opt-in; never shadows go.dev +# +# (`+pkg` puts this package's bin/ on PATH regardless of `provides`.) + +dependencies: + openssl.org: 1 # for ca-certificates + +build: + dependencies: + curl.se: '*' # fetch the pinned commit archive + gnu.org/m4: 1 + go.dev: '*' # bootstrap toolchain + working-directory: src + # will only segfault if updated with patchelf + skip: fix-patchelf + script: + # Map this version -> the dev.simd commit it pins, and fetch that exact + # source. GitHub mirrors go.googlesource.com/go; the archive needs the full + # 40-char SHA. + - run: | + case "{{version.raw}}" in + 2026.6.1.17.4.35) SHA=0e5948dc597c831b0c235cc0b3d34fa7587ddd47 ;; + *) echo "no commit mapping for version {{version.raw}}" >&2; exit 1 ;; + esac + curl -Lf "https://github.com/golang/go/archive/${SHA}.tar.gz" | tar xz --strip-components=1 + # No .git in the archive and dev.simd has no VERSION file, so cmd/dist + # can't derive a version; synthesize one (functional toolchain; the + # pinned commit above is the real identity of the snapshot). + test -f VERSION || echo "go1.27" > VERSION + working-directory: $SRCROOT + + - ./make.bash + + # cleanup + install the GOROOT + - rm -f *.{bash,bat,rc} Make.dist + - run: find . -mindepth 1 -delete + working-directory: ${{ prefix }} + - run: | + cp -a api bin doc lib misc pkg src test "{{prefix}}" + if test -f go.env; then cp go.env "{{prefix}}"; fi + if test -f VERSION; then cp VERSION "{{prefix}}"; fi + working-directory: $SRCROOT + env: + # `make.bash` complains about unset GOCACHE and HOME otherwise + GOCACHE: "$SRCROOT/.gocache" + GOROOT_FINAL: ${{ prefix }} + GOROOT_BOOTSTRAP: ${{ deps.go.dev.prefix }} + +test: + env: + GOEXPERIMENT: simd # the whole point of this package + script: | + mv $FIXTURE $FIXTURE.go + # 1) the toolchain works + test "Hello World" = "$(go run $FIXTURE.go)" + # 2) the experimental SIMD package is present and builds under the flag + go build -o /dev/null $FIXTURE.go + fixture: | + package main + + import ( + "fmt" + + "simd/archsimd" + ) + + func main() { + // Compiles only when the simd intrinsics package exists (GOEXPERIMENT=simd). + // AVX2() is defined on every GOARCH (false off amd64), so this is portable. + _ = archsimd.X86.AVX2() + fmt.Println("Hello World") + }