Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions .github/workflows/bench.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Bench

on:
pull_request:
branches: [master]

jobs:
bench:
name: bench (${{ matrix.run }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
run: [1, 2, 3]
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-go@v5
with:
go-version-file: go.mod
- name: CPU
run: |
go install golang.org/x/perf/cmd/benchstat@latest
lscpu | grep -E 'Model name'
grep -o -w -E 'avx2|avx512f' /proc/cpuinfo | sort -u
- name: Build master's and this branch's generated code
run: |
GOEXPERIMENT=simd go test -c -o after.test ./bench/
git show origin/master:bench/ops_simd.go > bench/ops_simd.go
GOEXPERIMENT=simd go test -c -o before.test ./bench/
git checkout bench/ops_simd.go
- name: Interleaved runs
run: |
for r in 1 2 3 4 5 6 7 8; do
for b in before after; do
GODEBUG=asyncpreemptoff=1 ./$b.test -test.run '^$' -test.bench . -test.benchtime=20ms -test.count=1 >> $b.txt
done
done
$(go env GOPATH)/bin/benchstat before.txt after.txt
- uses: actions/upload-artifact@v4
with:
name: bench-${{ matrix.run }}
path: "*.txt"
9 changes: 7 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,13 @@ jobs:
- name: Test tsvc (amd64, SIMD)
run: make tsvc-test

- name: Install qemu-user-static
run: sudo apt-get update && sudo apt-get install -y qemu-user-static
# ubuntu-26.04 has no qemu-user-static: qemu-user ships the static
# emulators there, without the -static names the Makefile runs.
- name: Install qemu-user
run: |
sudo apt-get update && sudo apt-get install -y qemu-user
command -v qemu-aarch64-static || sudo ln -s "$(command -v qemu-aarch64)" /usr/local/bin/qemu-aarch64-static
qemu-aarch64-static --version

- name: Test tsvc (arm64, qemu)
run: make tsvc-test-qemu-arm64
Expand Down
10 changes: 8 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,14 @@ reversal), no new dependence checking is needed, just a wider clause match.

`internal/rewrite/emit.go` never looks at the original statement's clauses —
it only uses `plan.Loop.Node.Pos()/.End()` to know what text span to replace,
and generates a **fixed forward** `for _i := 0; _i < bound; { ... }` template
driven entirely by the `Plan` (`Root`, `Dst`, `Bound`, ...).
and generates a **fixed forward** template driven entirely by the `Plan`
(`Root`, `Dst`, `Bound`, ...): every operand is cut to its window
(`x[start+off:][:_count]`) before the loop, then whole vectors while
`_i <= _count-_lanes`, then one partial vector for what is left. Keep both:
with every window exactly `_count` long and that condition, the compiler
proves each `window[_i:]` holds a whole vector and drops all bounds and length
checks from the main loop; slicing the original operands at `_i+off`, or
writing `_i+_lanes <= _count`, leaves them in (each worth 30-50% on arm64).
`Induction.Step` records the direction but the emitter ignores it. This means:
extending lowering to accept a new *loop clause shape* that still produces
the same kind of `Loop` (same body semantics) needs **zero** emitter changes.
Expand Down
12 changes: 7 additions & 5 deletions BUGS.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ gotip, "1.27.1" is the release toolchain loopvec is tested against.
| [#81845](https://github.com/golang/go/issues/81845) calls left unresolved when inlined into a package initializer | closed as a duplicate of [#80689](https://github.com/golang/go/issues/80689), which is open | loops in package-level `var x = func() {...}()` | not rewritten (the generated initializer fails to link), see `package_initializer_no_rewrite.txt` and `toolexec_package_initializer.txt` |
| [#81846](https://github.com/golang/go/issues/81846) `Float32s.Neg` rebuilds its sign constant every iteration | open | speed of negation loops | none; the loop is correct, only slower than it should be |
| [#81847](https://github.com/golang/go/issues/81847) `GOEXPERIMENT=simd` alone slows async preemption on AVX-512 | open | any benchmark comparing a scalar and a simd build | benchmark with `GODEBUG=asyncpreemptoff=1` |
| [#82001](https://github.com/golang/go/issues/82001) emulated `Load{Float64,Int64,Uint64}sPart` return `len(s)` | open | generated loops under `GODEBUG=simd=0` | none; the loops use the count `Load*Part` returns, as the package documents |
| [#82001](https://github.com/golang/go/issues/82001) emulated `Load{Float64,Int64,Uint64}sPart` return `len(s)` | open | nothing loopvec generates | the loops use `Load*Part` only for what is left after the last whole vector, where `len(s)` is the count loaded |
| [#82002](https://github.com/golang/go/issues/82002) `Min` and `Max` on floats differ from Go's for NaN and -0 | open | float `min`/`max` | not rewritten (`float min and max differ from Go's ...`) |

## #80657: simd in a method
Expand Down Expand Up @@ -76,10 +76,12 @@ regressions.
## #82001: emulated partial loads

With `GODEBUG=simd=0` the emulated `Load{Float64,Int64,Uint64}sPart` return `len(s)`
instead of the number of elements loaded. loopvec's loops advance by that count (the loop
shape the `simd` package documents), so in that mode a copy of ten `float64`s produces
`[1 2 0 0 0 0 0 0 0 0]` instead of the input. The hardware-backed mode gives the right
answer.
instead of the number of elements loaded. A loop that advances by that count on every
iteration (the loop shape the `simd` package documents) skips elements in that mode: a
copy of ten `float64`s produces `[1 2 0 0 0 0 0 0 0 0]` instead of the input. loopvec's
loops load whole vectors while one fits and use `Load*Part` only for what is left, fewer
elements than a vector holds, where `len(s)` is the number loaded, so they are not
affected. The hardware-backed mode gives the right answer either way.

## #82002: float `Min` and `Max`

Expand Down
Loading
Loading