Hi Nigel,
Running Dan's test on my arm64 mac:
% gh pr checkout 1
branch 'failure' set up to track 'origin/failure'.
Switched to a new branch 'failure'
% bisect -compile fma go test
bisect: run: checking target with all changes disabled
bisect: run: GOCOMPILEDEBUG=fmahash=n go test... ok (1193 matches)
bisect: run: GOCOMPILEDEBUG=fmahash=n go test... ok (1193 matches)
bisect: checking target with all changes enabled
bisect: run: GOCOMPILEDEBUG=fmahash=y go test... FAIL (1193 matches)
bisect: run: GOCOMPILEDEBUG=fmahash=y go test... FAIL (1193 matches)
bisect: target succeeds with no changes, fails with all changes
bisect: searching for minimal set of enabled changes causing failure
bisect: run: GOCOMPILEDEBUG=fmahash=+0 go test... ok (618 matches)
bisect: run: GOCOMPILEDEBUG=fmahash=+0 go test... ok (618 matches)
bisect: run: GOCOMPILEDEBUG=fmahash=+1 go test... FAIL (575 matches)
bisect: run: GOCOMPILEDEBUG=fmahash=+1 go test... FAIL (575 matches)
bisect: run: GOCOMPILEDEBUG=fmahash=+01 go test... FAIL (282 matches)
bisect: run: GOCOMPILEDEBUG=fmahash=+01 go test... FAIL (282 matches)
bisect: run: GOCOMPILEDEBUG=fmahash=+001 go test... ok (132 matches)
bisect: run: GOCOMPILEDEBUG=fmahash=+001 go test... ok (132 matches)
...
bisect: FOUND failing change set
--- change set #1 (enabling changes causes failure)
../../pkg/mod/golang.org/x/im...@v0.15.0/draw/impl.go:6231:8
---
bisect: checking for more failures
bisect: run: GOCOMPILEDEBUG=fmahash=-x47dfdb5 go test... FAIL (1192 matches)
bisect: run: GOCOMPILEDEBUG=fmahash=-x47dfdb5 go test... FAIL (1192 matches)
bisect: target still fails; searching for more bad changes
bisect: run: GOCOMPILEDEBUG=fmahash=+0-x47dfdb5 go test... ok (618 matches)
bisect: run: GOCOMPILEDEBUG=fmahash=+0-x47dfdb5 go test... ok (618 matches)
bisect: run: GOCOMPILEDEBUG=fmahash=+1-x47dfdb5 go test... ok (574 matches)
...
bisect: FOUND failing change set
--- change set #2 (enabling changes causes failure)
../../pkg/mod/golang.org/x/im...@v0.15.0/draw/impl.go:6229:8
../../pkg/mod/golang.org/x/im...@v0.15.0/draw/impl.go:6230:8
---
bisect: checking for more failures
bisect: run: GOCOMPILEDEBUG=fmahash=-x8386cd4-xcdf7947-x47dfdb5 go test... ok (1190 matches)
bisect: run: GOCOMPILEDEBUG=fmahash=-x8386cd4-xcdf7947-x47dfdb5 go test... ok (1190 matches)
bisect: target succeeds with all remaining changes enabled
%
This output is saying that if you enable FMA usage on line 6231
that alone causes the test failure, and separately if you enable FMA
on both lines 6229 and 6230, that also causes the failure
(but either of those lines by itself is not sufficient to cause the failure).
And yes, writing float64(x*y) forces the float64 rounding after the
multiply, which disables hoisting it into an FMA.
So we can add those to image/draw and that fixes the test:
% git clone https://go.googlesource.com/image
% go work init . image
% go test
...
FAIL
% ed image/draw/impl.go
269624
6231
pb += p[2] * c.weight
s;p.2.*;float64(&)
pb += float64(p[2] * c.weight)
6229
pr += p[0] * c.weight
s;p.0.*;float64(&)
pr += float64(p[0] * c.weight)
6230
pg += p[1] * c.weight
s;p.1.*;float64(&)
pg += float64(p[1] * c.weight)
w
269651
q
% go test
PASS
ok github.com/kortschak/gifscaleissue 0.160s
% git -C image diff
diff --git a/draw/impl.go b/draw/impl.go
index 94ee826..f52ba20 100644
--- a/draw/impl.go
+++ b/draw/impl.go
@@ -6226,9 +6226,9 @@ func (z *kernelScaler) scaleY_RGBA64Image_Src(dst RGBA64Image, dr, adr image.Rec
var pr, pg, pb, pa float64
for _, c := range z.vertical.contribs[s.i:s.j] {
p := &tmp[c.coord*z.dw+dx]
- pr += p[0] * c.weight
- pg += p[1] * c.weight
- pb += p[2] * c.weight
+ pr += float64(p[0] * c.weight)
+ pg += float64(p[1] * c.weight)
+ pb += float64(p[2] * c.weight)
pa += p[3] * c.weight
}
%
Of course, there may be other multiplies (such as the one after the changed lines)
that might want to disable FMAs to keep other tests passing. They're just not
necessary to keep this test passing.
If you want a list of every FMA generated in the program, that's a subset of the
output of GOCOMPILEDEBUG=fmahash=vy go test.
Best,
Russ