Skip to content

internal/loopir: reject a constant offset that puts an index below zero - #1

Merged
thesyncim merged 4 commits into
masterfrom
fix-negative-constant-offset
Nov 1, 2026
Merged

thesyncim merged 4 commits into
masterfrom
fix-negative-constant-offset

Conversation

@thesyncim

@thesyncim thesyncim commented Oct 31, 2026 •

Copy link
Copy Markdown
Owner

Stacked on #4.

loopvec writes a _simd.go that doesn't compile for a loop like this:

for i := 0; i < 16; i++ {
	dst[i] = a[i-20] + 1
}

The length check comes out as _ = a[16-21]:

invalid argument: index 16 - 21 (constant -5 of type int) must not be negative

toolexec falls back, but -split and -w leave the broken file behind.

A loop like that panics as soon as it runs, and so does one whose first index is a negative constant (a[i-1] starting at 0). Both are now rejected with their own reason, the same way a constant limit of zero or less already is. a[i-1] starting at 1 is still rewritten.

The checks parsed the start and limit as text, so named constants and constant expressions (const s0 = 0; for i := s0; ..., for i := 1 - 1; ...) slipped through. Constant bounds are now written out as their value. A side effect is that the short-loop rule now sees named constant trip counts too: in goav1, a 3-iteration for x := range restorationExtraHorz is no longer vectorized. The vectorized set of std and gonum doesn't change.

@thesyncim thesyncim closed this Oct 31, 2026
@thesyncim thesyncim reopened this Oct 31, 2026
ubuntu-latest is now ubuntu-26.04, which has no qemu-user-static
package, so every run fails at the install step and skips the arm64
tsvc run, the golden check, fmt and lint. qemu-user ships the static
emulators there; link qemu-aarch64-static to it when the name is
missing, as the Makefile runs that name.
@thesyncim
thesyncim force-pushed the fix-negative-constant-offset branch 2 times, most recently from 4d49970 to 922738c Compare October 31, 2026 19:56
@thesyncim thesyncim changed the title internal/loopir: reject a constant offset that puts every index below zero internal/loopir: reject a constant offset that puts an index below zero Oct 31, 2026
Go tip writes export data in iexport version 4, which encodes float
constants exactly. x/tools v0.51.0, and the v0.52.0 release, read only
up to version 3, so on tip go/packages fails for every package:

  cannot import "math" (unstable iexport format version 4, just rebuild
  compiler and std library), export data is newer version - update tool

and every script that runs loopvec fails in the tip job. x/tools master
reads version 4 (golang/tools@966056e2637c). Update to it until a release
includes it. The pinned toolchain is unaffected.
@thesyncim
thesyncim force-pushed the fix-negative-constant-offset branch from 922738c to 1aa6273 Compare October 31, 2026 20:50
go1.27.3 is the latest 1.27 release. Its simd package is the same as
go1.27.1's, so the capability table only changes in its header, and
the -methods crash (golang/go#80657) is still there, as
flag_methods_ice.txt checks. go.mod keeps go 1.27.1: that is the first
release whose simd package loopvec's output compiles against
(go1.27.0's ShiftAllRight takes a uint8).
A read at a negative constant offset in a loop with a constant limit, such
as dst[i] = a[i-20] + 1 in a loop that stops before 16, was rewritten into
code that does not compile: the length check of the vector loop is
_ = a[16-21], a negative constant index. -split wrote that file, and the
toolexec wrapper fell back to the original package.

Such a loop panics as soon as it runs, as does one whose first index is
a negative constant (a[i-1] in a loop from 0). Both are now left alone
with their own reason, the way a constant limit of zero or less already
is. A read whose indexes can all be zero or more (a[i-1] from 1) is
still rewritten.

The checks read the start and limit as text, so a named constant or a
constant expression (const s0 = 0; for i := s0; ...) slipped past them.
A constant start or limit is now spelled as its value, which also lets
the short-loop rule see a named constant trip count: goav1's
for x := range restorationExtraHorz, three iterations, is no longer
rewritten.

The vectorized set of std and gonum does not change.
@thesyncim
thesyncim force-pushed the fix-negative-constant-offset branch from 1aa6273 to 087660e Compare October 31, 2026 21:50
@thesyncim
thesyncim merged commit acbfe88 into master Nov 1, 2026
2 checks passed
mauri870 pushed a commit that referenced this pull request Nov 4, 2026
The runners have moved to ubuntu-26.04, so this is the qemu part of #1
you said you'd take when that happened. `qemu-user-static` has no
installation candidate there, so every PR now fails at that step and the
arm64 runs, the golden check, fmt and lint get skipped. You can see it
on #7, #9 and #19, where Build, Test and the amd64 tsvc run all pass
first. master's last run predates the move, so the next push will hit it
too.

`qemu-user` has the static emulators on 26.04, just without the
`-static` names, so this installs that and links `qemu-aarch64-static`
when it's missing, since the Makefile runs that name. It's been passing
on my fork's ubuntu-26.04 runners, and this PR's own CI runs it too.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant