Live data from Hacker News

RISC-V formal spec public review

github.com

21–30 of 38 posts

Re: RISC-V formal spec public review

#21
post #3

Well, this is progress. I wonder how many counterparts to delay slots, stack windows, conditional moves, and other embarrassments we are inadvertently enshrining. There's nothing like hindsight to make you facepalm. (The crypto extension is my bet ATM for most-likely-to-embarrass. But that's without reading it.) The only way to approach this project sensibly is to assume every single FPGA produced after some near fut…

I dislike the lack of arithmetic instructions with built-in trap on overflow (even imprecise with a fence could be fine), but maybe that's too expensive to do in hardware.

Re: RISC-V formal spec public review

#22
post #21
post #3

Well, this is progress. I wonder how many counterparts to delay slots, stack windows, conditional moves, and other embarrassments we are inadvertently enshrining. There's nothing like hindsight to make you facepalm. (The crypto extension is my bet ATM for most-likely-to-embarrass. But that's without reading it.) The only way to approach this project sensibly is to assume every single FPGA produced after some near fut…

I dislike the lack of arithmetic instructions with built-in trap on overflow (even imprecise with a fence could be fine), but maybe that's too expensive to do in hardware.

FYI, here is the rationale section on that subject:

We did not include special instruction set support for overflow checks on integer arithmetic operations in the base instruction set, as many overflow checks can be cheaply implemented using RISC-V branches. Overflow checking for unsigned addition requires only a single additional branch instruction after the addition: add t0, t1, t2; bltu t0, t1, overflow.

For signed addition, if one operand’s sign is known, overflow checking requires only a single branch after the addition: addi t0, t1, +imm; blt t0, t1, overflow. This covers the common case of addition with an immediate operand.

For general signed addition, three additional instructions after the addition are required, leveraging the observation that the sum should be less than one of the operands if and only if the other operand is negative.

              add t0, t1, t2
              slti t3, t2, 0
              slt t4, t0, t1
              bne t3, t4, overflow
In RV64, checks of 32-bit signed additions can be optimized further by comparing the results of ADD and ADDW on the operands.

Re: RISC-V formal spec public review

#23

Earlier quoted context omitted.

> Cmov is one of the methods to mitigate Spectre because Intel refuses to speculate loads in them. Sure, this is what makes it good for mispredictable branches - data decompression for instance. If you can't speculate ahead, it's a waste of space in the branch prediction buffer to do it. But I definitely wish it was a builtin function instead of the compiler generating it, because none of them can guess when to use i…

They can't guess, which is why they all offer `__builtin_expect` to control them (which people often wrap in LIKELY/UNLIKELY macros).

Yes, but we need the opposite. There's no way to say a branch has no expected value.

Re: RISC-V formal spec public review

#24
post #20
post #5

Earlier quoted context omitted.

Conditional moves depend on state left over from the last instruction. But when you want to re-order your instructions to keep all your functional units busy, keeping the conditional moves right makes a big mess. They're fine as micro-ops after you've scheduled them all, but are lousy at the ISA level. Intel and AMD make it work by throwing another 10,000 or 100,000 transistors at it. It is better to let macro-op fus…

Isn't cmov just a normal instruction with 3 source operands? Or do you mean that the problem is having 3 instead of 2 source operands? Or that one of the operands is the flag register on x86-like architecture? (but you can just use a normal register being nonzero)

Having 3 input operands is definitely an issue. In the Alpha EV6 architecture, it was decided only 2 inputs are supported, so a CMOV would need to be split into two actual instructions, the first of which setting the 65th bit of one of the operands to the result of the test and the other selecting the correct output. Thus, CMOV had 2 cycles latency and still required extra hardware resources to implement.

Re: RISC-V formal spec public review

#25
post #21

Earlier quoted context omitted.

I dislike the lack of arithmetic instructions with built-in trap on overflow (even imprecise with a fence could be fine), but maybe that's too expensive to do in hardware.

FYI, here is the rationale section on that subject: We did not include special instruction set support for overflow checks on integer arithmetic operations in the base instruction set, as many overflow checks can be cheaply implemented using RISC-V branches. Overflow checking for unsigned addition requires only a single additional branch instruction after the addition: add t0, t1, t2; bltu t0, t1, overflow. For signe…

For an ISA whose main use will be IoT (at least in the beginning), this isn't good..

Rust didn't put integer overflow checks in release mode because current CPU don't provide "free" integer overflow detection, RISC V is even a regression over MIPS here..

Re: RISC-V formal spec public review

#26
post #21

Earlier quoted context omitted.

I dislike the lack of arithmetic instructions with built-in trap on overflow (even imprecise with a fence could be fine), but maybe that's too expensive to do in hardware.

FYI, here is the rationale section on that subject: We did not include special instruction set support for overflow checks on integer arithmetic operations in the base instruction set, as many overflow checks can be cheaply implemented using RISC-V branches. Overflow checking for unsigned addition requires only a single additional branch instruction after the addition: add t0, t1, t2; bltu t0, t1, overflow. For signe…

This is kind of a poor argument, since it applies equally to any request to add instructions to RISC that can be implemented by other instructions. A 4:1 increase in cost isn't brilliant either.

The problem is that few high level languages support this well either. Having an instruction that traps like division by zero isn't great, because it's quite expensive to turn a machine trap into a high-level exception.

What I would like to try is a separate "addsat" instruction which (a) provides saturating arithmetic and (b) sets a flag if saturation has applied, but does not clear it if it has not been applied. That allows you to write a bunch of arithmetic in a natural way (a1b1 + a2b2 - a3*b3) etc, and only at the end test for overflow. It would behave more like a propagating integer NaN. Since it's a flag rather than a trap a high-level language can more easily convert it to an exception, or provide other processing.

(Saturation arithmetic is useful on its own in some cases, but usually for 8 or 16 bit values)

Re: RISC-V formal spec public review

#27
post #5

Earlier quoted context omitted.

Conditional moves depend on state left over from the last instruction. But when you want to re-order your instructions to keep all your functional units busy, keeping the conditional moves right makes a big mess. They're fine as micro-ops after you've scheduled them all, but are lousy at the ISA level. Intel and AMD make it work by throwing another 10,000 or 100,000 transistors at it. It is better to let macro-op fus…

> Conditional moves depend on state left over from the last instruction. So, literally exactly the same state that conditional branch instructions depend on? Aside from implementation details (like >Intel refuses to speculate loads in them<, which, to be fair, might be its own problem), "cmovz D S" is just "jnz skip ; mov D S ; skip:" without the useless branch overhead.

Branches are in a different category than moves and ALU ops, for instruction reordering.

Re: RISC-V formal spec public review

#28
post #25

Earlier quoted context omitted.

FYI, here is the rationale section on that subject: We did not include special instruction set support for overflow checks on integer arithmetic operations in the base instruction set, as many overflow checks can be cheaply implemented using RISC-V branches. Overflow checking for unsigned addition requires only a single additional branch instruction after the addition: add t0, t1, t2; bltu t0, t1, overflow. For signe…

For an ISA whose main use will be IoT (at least in the beginning), this isn't good.. Rust didn't put integer overflow checks in release mode because current CPU don't provide "free" integer overflow detection, RISC V is even a regression over MIPS here..

[deleted]

Re: RISC-V formal spec public review

#29
post #20
post #5

Earlier quoted context omitted.

Conditional moves depend on state left over from the last instruction. But when you want to re-order your instructions to keep all your functional units busy, keeping the conditional moves right makes a big mess. They're fine as micro-ops after you've scheduled them all, but are lousy at the ISA level. Intel and AMD make it work by throwing another 10,000 or 100,000 transistors at it. It is better to let macro-op fus…

Isn't cmov just a normal instruction with 3 source operands? Or do you mean that the problem is having 3 instead of 2 source operands? Or that one of the operands is the flag register on x86-like architecture? (but you can just use a normal register being nonzero)

That one of the operands is the flag register, affected by other instructions you might want to schedule. RISC-V might have its own way to mitigate this.

Re: RISC-V formal spec public review

#30
post #26

Earlier quoted context omitted.

FYI, here is the rationale section on that subject: We did not include special instruction set support for overflow checks on integer arithmetic operations in the base instruction set, as many overflow checks can be cheaply implemented using RISC-V branches. Overflow checking for unsigned addition requires only a single additional branch instruction after the addition: add t0, t1, t2; bltu t0, t1, overflow. For signe…

This is kind of a poor argument, since it applies equally to any request to add instructions to RISC that can be implemented by other instructions. A 4:1 increase in cost isn't brilliant either. The problem is that few high level languages support this well either. Having an instruction that traps like division by zero isn't great, because it's quite expensive to turn a machine trap into a high-level exception. What…

See also these topics: macro-op fusion, compressed instructions, extensions.

RISC-V publishes (at least for some cores) the preferred order that you have to emit instructions in order for those to be recognized and fused into efficient micro ops. The compressed (C) extension means that instructions don't take up too much extra space in the I-cache.

Of course we don't know -- because very high performance RISC-V chips don't (yet) exist -- if this will really work when the silicon hits the road, but the plan makes some sense and has the (IMHO) large advantage that it keeps the standard small and easy to implement (in those cases where you don't much care about performance).

There are also extensions, which RISC-V formalizes properly. You can with relative ease add your own addsat instruction through a private extension, and (with somewhat more difficulty) propose a public extension if this is generally useful.

Post reply on HN