(This is an expanded version of issue (https://github.com/WebAssembly/spec/issues/446))
Multi-precision arithmetic requires special handling. This is available in some form in all ISAs, but not currently available in webasm.
There are basically three ways of doing this (it seems to me), none of which is especially palatable in the context of the current design:
Option 1. Add a special flags register, together with instructions that do arithmetic with that register.
This is the traditional approach in mainstream hardware.
You get instructions like
addc
which will add two numbers, and the value of the carry flag, and set the carry flag on the result.
This is not pleasant because it adds a special register.
Option 2.
Support a form of 60bit arithmetic with 4 bits for flags.
Option 3.
Support multi-word arithmetic: addition takes 3 arguments and produces 2 outputs.
This approach will do the least damage to the existing ISA and register architecture. However, this will be hard to map to existing hardware efficiently (not all hardware ISAs support loading the flags register directly.
However it is done, multi-precision arithmetic is quite important and very hard to emulate without some simple hardware support.
Seems to me that for option 3 there are plausible optimizations that would make this practical. Suppose {i32,i64}.addc takes three inputs, op2 on the top, op1 below, carry at the bottom and produces two outputs, result on top and carry below it. For the sake of argument assume the carry is always the same type as the other operands. Define addc only to use the low bit of the carry and for the carry left after the operation to be zero or one. Things are now reasonably set up for a multi-word add, say. In a suitably unrolled loop a JIT/Wasm compiler really ought to be able to see that it is the carry that is being propagated, and generate good code. (And if the loop is not unrolled then loop overhead will dilute the carry extraction/insertion anyway.) I think worst-case branch-free code for carry extraction should be mov rd, 0; adc rd, 0
; for insertion, something like and rc, 1; add rc, ~0
where rc is a register that contains a value to be treated as a carry.
On ARM, consuming a carry is separate from producing a carry: ADC consumes, ADC.S consumes and produces, ADD.S only produces. Would we want all these variants? And what about overflow?
(There might be a fourth option, where we add a operate-and-branch-on-condition operation which both produces a result and branches to a label or not, eg, i32.addc op1 op2 carry L
would branch to L on carry set and fall through on carry clear, and either way leave a result on the stack, but it seems harder to use in general than the three options you suggested.)
Is there someone willing to champion this proposal? We'd need proposed semantics, binary encoding, and I'd like at least a least of usecases and an implementation with performance numbers for these usecases (compare current MVP WebAssembly, with this proposed addition, and native code).
In principle, I would be willing to champion this.
However, personal changes mean that I have limited resources for at least the next few months.
———
Frank McCabe
Senior Software Architect
Phone: 650-740 6673 | Email: [email protected] yourname@instartlogic.com
Instart Logic | 450 Lambert Ave, Palo Alto, CA 94306 | instartlogic.com http://instartlogic.com/
On May 11, 2017, at 10:14 AM, JF Bastien notifications@github.com wrote:
Is there someone willing to champion this proposal? We'd need proposed semantics, binary encoding, and I'd like at least a least of usecases and an implementation with performance numbers for these usecases (compare current MVP WebAssembly, with this proposed addition, and native code).
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub https://github.com/WebAssembly/design/issues/1021#issuecomment-300856161, or mute the thread https://github.com/notifications/unsubscribe-auth/ADfCzd9le4ufXm6DSsArpfXCYsGdV7UIks5r40H5gaJpZM4MrKma.
I'll likely have time to devote to this though not very much until June or so, and then into the fall. IMO this functionality is fairly important, and I think the overflow flag is as important as the carry flag though with different use cases (dynamic languages' fixnum -> bignum transition).
Discussed this with some Mozilla folk today. In summary:
Has there been any progress on this issue? Carry and borrow are needed to implementing modern cryptograpy (e.g. SIDH) efficiently. Big number addition without ADDC is multiple factors slower than with. The same applies to subtraction and multiplication.
I think we're at least waiting for multi-value to be finished so that we can easily express an operation with more than one result. Multi-value is "almost there".
Most helpful comment
Has there been any progress on this issue? Carry and borrow are needed to implementing modern cryptograpy (e.g. SIDH) efficiently. Big number addition without ADDC is multiple factors slower than with. The same applies to subtraction and multiplication.