Skip to content
Open
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
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