Go: cmd/compile: testing/quick misbehaves on Nexus 9 linux/arm64

Created on 31 Mar 2017  ·  3Comments  ·  Source: golang/go

testing/quick's int64 chooser is written to return values in the range [-2⁶²,2⁶²).
That's a mistake; fixing that is #19808.

But the code should run as written, and yet on @dr2chase's Nexus 9
running a linux/arm64 toolchain built from a android/arm64 toolchain
cross-compiled from elsewhere, empirically it generates values outside
that range. (That helped find #19807.)

Using a linux/arm64 toolchain built from a linux/arm64 toolchain
cross-compiled from elsewhere on an Odroid works correctly.

Before fixing testing/quick to generate the full range, we should figure
out why the current code generates values outside the narrower range
in this configuration.

math/rand's (*Rand).Int63 says:

return r.src.Int63()

and (*rngSource).Int63 says:

return int64(rng.Uint64() & _MASK)

where:

const (
    _MAX  = 1 << 63
    _MASK = _MAX - 1
)

and then testing/quick's randInt64 function does:

return rand.Int63() - 1<<62

So either the & _MASK or the - 1<<62 is not doing its job.

It could be that the Nexus 9 ARM64 hardware is buggy.
It could be that the android/arm64 toolchain being used for
bootstrap on the Nexus 9 is buggy, causing the natively compiled
linux/arm64 toolchain to be buggy, causing the testing/quick
code to generate unexpected values. We don't know.

FrozenDueToAge

Most helpful comment

The following C program misbehaves on the problematic system.

#include <stdio.h>

typedef unsigned long long uvlong;

uvlong f() { return ~0ull; }
uvlong g() { return (f() << 1) >> 1; }

int main() {
    for (int i = 0;; i++) {
        if ((long long)g() < 0) {
            printf("%d\n", i);
        }
    }
    return 0;
}

After 20k-50k iterations the loop starts printing i on every iteration.

Not Go's fault. We'll see about reporting this elsewhere.

All 3 comments

CL https://golang.org/cl/39152 mentions this issue.

The following C program misbehaves on the problematic system.

#include <stdio.h>

typedef unsigned long long uvlong;

uvlong f() { return ~0ull; }
uvlong g() { return (f() << 1) >> 1; }

int main() {
    for (int i = 0;; i++) {
        if ((long long)g() < 0) {
            printf("%d\n", i);
        }
    }
    return 0;
}

After 20k-50k iterations the loop starts printing i on every iteration.

Not Go's fault. We'll see about reporting this elsewhere.

CL https://golang.org/cl/39310 mentions this issue.

Was this page helpful?
0 / 5 - 0 ratings