Skip to content

Signed arithmetic miscompiled on AArch64

Currently the AArch64 NCG miscompiles signed, sub-word arithmetic. For instance, consider this program:

test(bits64 buffer) {
  return (%zx64(%quot(%lobits8(%neg(bits64[buffer + (1 :: bits64)])), (2 :: bits8))));
}

This should evaluate to -1 /[signed] 2 == 0.

However, with %9.2.1 it produces the incorrect result of 127 via following assembler:

test:                                                                                                    
.Lc3:
          # Load W64 from `buffer`
        mov x18, x22
        ldr x18, [ x18, 1 ]                                                                              
          # Negate
        neg x18, x18
          # Narrow W64 -> W8
        ubfm x18, x18, #0, #7 
          # Signed Divide by 2
        mov w17, #2
        sdiv w18, w18, w17
          # The above division is wrong: it encodes word-sized division but w18 contains
          # a (non-signed-extended) W8
        ubfm x18, x18, #0, #7
        mov x22, x18
        ldr x18, [ x20 ]
        br x18
Edited by Ben Gamari
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information