6 ms·
RISC-V formal spec public review
- nagisa 7y agoIs over. > The Public Review period is: March 29, 2019 through May 13, 2019
- ncmncm 7y agoWell, 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 future point will have at least one, and more typically dozens of RISC-V cores scattered around like the multipliers you see in them now, just to try to be competitive. Personally, I am banking my enthusiasm for when the Bitmanip extension goes in.
- astrange 7y agoWhat's wrong with conditional moves? They're good for mispredictable branches, although I liked them better on PPC which had 8 condition/flags registers instead of just 1.
- ncmncm 7y agoConditional 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 fusion hardware identify opportunities to convert a branch-over-move sequence, all by itself. RISC-V is supposed to be all about powerful macro-op fusion. Clang is really aggressive about generating cmovs. On Gcc you can still use (x & -c) expressions to get nicely pipelined conditional expressions, but Clang stomps them all to cmovs. Cmov is one of the methods to mitigate Spectre because Intel refuses to speculate loads in them. So, cmov from memory pessimizes your code in cases where you aren't worried what might be sharing your cache.
- astrange 7y ago> 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 it.
- fluffything 7y agoThey can't guess, which is why they all offer `__builtin_expect` to control them (which people often wrap in LIKELY/UNLIKELY macros).
- a1369209993 7y ago> 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.
- ncmncm 7y agoBranches are in a different category than moves and ALU ops, for instruction reordering.
- devit 7y agoI 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.
- waterhouse 7y agoFYI, 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.
- renox 7y agoFor 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 7y ago[deleted]
- 0815test 7y ago> Rust didn't put integer overflow checks in release mode because current CPU don't provide "free" integer overflow detection Not really; the main performance drawback of obligate overflow checks is excessively-constrained semantics of the resulting code making optimization harder, not the direct CPU cost of checking. There are other ways of detecting possible overflows, and Rust does check for overflow in debug mode (this is specifically in order to ensure that most Rust code will work properly even when checks are enabled, and will not simply end up relying on underspecified semantics.)
- mrob 7y agoCompressed versions of the load/store instructions don't support 8bit or 16bit values, so in situations where you most care about memory usage you're forced to use the full size versions.
- edflsafoiewq 7y agoHow easy is it to do bigint arithmetic in RISC-V?
- Dylan16807 7y agoIt has perfectly good add and multiply instructions, so uh easy? What at an ISA level would make it hard?
- ncmncm 7y agoConnecting from one word to the next. Do you have to do 32-bit multiplications so as to retain the high half of the result, or does a 64-bit multiply deliver the high 64 bits of the result somewhere? Also there is stuff about the carry from 64-bit addition. (Substitute 16 and 32, for 32-bit units.)
- deleted 7y ago[deleted]
- Dylan16807 7y agoThere are instructions to get the top half of a multiply, and a suggested ordering so that the chip can deliver both halves with only one calculation. There's no carry flag but I'd say it's still easy to work around that.
- deleted 7y ago[deleted]
- waterhouse 7y agoSpecifically, I think the "sltu" (set if less than, unsigned) instruction is useful for carries. When you add two unsigned integers, the result is smaller than the inputs if and only if an overflow occurred. ; a1:a0 * a2 --> a5:a4:a3 ; using t0 as temp reg mulhu a5, a1, a2 mulu a4, a1, a2 mulhu t0, a0, a2 mulu a3, a0, a2 add a4, a4, t0 ; carry a 1 or a 0, overwriting t0 sltu t0, a4, t0 add a5, a5, t0 (edit: switched a1 and a0 for consistency)