4ad/go.arm64

cmd/7g: 64-bit arithmetics problems

minux opened this issue · 13 comments

/test/64bit.go test failed badly.

only test00 passed.

Here is the test log, in case you can't build that program with replacement runtime:
https://gist.github.com/minux/14161c014f6057f94b88

Minux, are your actively looking at this? I can pick it up in about 12 hours.

Thanks. You keep finding the issues, we'll try to fix 'em.
On 15 Feb 2015 19:34, "Minux Ma" notifications@github.com wrote:

I'm not working on this issue.

I'm working on enhancing rt and running other tests to find out as many
backend problems as possible.


Reply to this email directly or view it on GitHub
https://github.com/4ad/go/issues/108#issuecomment-74408881.

We generate the following code for uint64 mod:

   11c0c:       9aca092b        udiv    x11, x9, x10
   11c10:       9baa7d6b        umull   x11, w11, w10
   11c14:       cb0b0129        sub     x9, x9, x11

It should use MUL instead of UMULL, which is for 32-bit multiplies.
In fact, we generates bad code for all 64-bit signed/unsigned multiply.

I agree, this is supposed to be v mod const(16).

On Mon, Feb 16, 2015 at 4:53 PM, Minux Ma notifications@github.com wrote:

We generate the following code for uint64 mod:

11c0c: 9aca092b udiv x11, x9, x10
11c10: 9baa7d6b umull x11, w11, w10
11c14: cb0b0129 sub x9, x9, x11

It should use MUL instead of UMULL, which is for 32-bit multiplies.
In fact, we generates bad code for all 64-bit signed/unsigned multiply.


Reply to this email directly or view it on GitHub
https://github.com/4ad/go/issues/108#issuecomment-74462942.

OK, after fixing the 64-bit mul issue, 64bit.go only reports shift issues.

See 2nd revision of https://gist.github.com/minux/14161c014f6057f94b88.

int64 1 << uint64 8 = 1 should be 0

eh ? shouldn't this be 256. I'm obviously missing something fundamental

On Mon, Feb 16, 2015 at 5:07 PM, Minux Ma notifications@github.com wrote:

OK, after fixing the 64-bit mul issue, 64bit.go only reports shift issues.

See 2nd revision of https://gist.github.com/minux/14161c014f6057f94b88.


Reply to this email directly or view it on GitHub
https://github.com/4ad/go/issues/108#issuecomment-74463761.

You're right. Something is still not quite right.

printuint is still not working correctly.

For example, println(1<<64-1) gives "5".

This program:

package main

func udiv(x, y uint64) (q, r uint64) {
        sh := 0
        for y+y > y && y+y <= x {
                sh++
                y <<= 1
        }
        for ; sh >= 0; sh-- {
                q <<= 1
                if x >= y {
                        x -= y
                        q |= 1
                }
                y >>= 1
        }
        return q, x
}

func main() {
    q, r := udiv(0, 1<<64-1)
    if q != 0 {
        println("BUG", q, r)
    }
}

Produces "BUG 1 1" output. However, udiv(0, anything) should return 0, 0.

The real problem:

        var a, b uint64
        a = 1<<64-1
        b = 5
        if a < b {
                println("BUG")
        }

prints out BUG on arm64.

Another difference between arm64 and ppc64x. Power has different
comparison instructions for signed and unsigned, but ARM uses different
condition jumps.

After fixing this issue, both divmod.go and 64bit.go passed.