News for hackers. Stuff that matters.
Re:RISC-V formal spec public review by ncmncm on Friday June 21, 2019 @12:48AM (#20239950)
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 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.

Re:RISC-V formal spec public review by astrange on Friday June 21, 2019 @02:53AM (#20240467)
> 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.

Re:RISC-V formal spec public review by fluffything on Friday June 21, 2019 @05:33AM (#20241091)
They can't guess, which is why they all offer `__builtin_expect` to control them (which people often wrap in LIKELY/UNLIKELY macros).
Re:RISC-V formal spec public review by astrange on Friday June 21, 2019 @07:12AM (#20241455)
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 by dooglius on Friday June 21, 2019 @09:43AM (#20242396)
Clang does have __builtin_unpredictable, but last I checked it doesn't actually seem to have an effect.
Re:RISC-V formal spec public review by a1369209993 on Friday June 21, 2019 @04:13AM (#20240803)
> 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.

Re:RISC-V formal spec public review by ncmncm on Friday June 21, 2019 @08:57AM (#20242096)
Branches are in a different category than moves and ALU ops, for instruction reordering.
Re:RISC-V formal spec public review by a1369209993 on Friday June 21, 2019 @01:10PM (#20244420)
> Aside from implementation details
Re:RISC-V formal spec public review by ncmncm on Friday June 21, 2019 @08:34PM (#20247309)
Performance is 100% implementation details, from top to bottom. And the only reason anybody uses a cmov instruction is for hoped-for better performance.

There is hope that it doesn't squat a precious branch-prediction slot, hope that it doesn't incur a branch misprediction pipeline stall if it's taken, or not taken, hope that fewer instructions translates to fewer clock cycles, hope that what looks like a copy really just does a register-renaming accounting trick, ...

Re:RISC-V formal spec public review by devit on Friday June 21, 2019 @05:40AM (#20241118)
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)

Re:RISC-V formal spec public review by mellum on Friday June 21, 2019 @07:39AM (#20241577)
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 by ncmncm on Friday June 21, 2019 @09:14AM (#20242214)
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 by Veedrac on Friday June 21, 2019 @11:16AM (#20243242)
Unless I've understood you poorly, this is confused.

The issue with CMOV is primarily that it's a three operand instruction. If it was a two-instruction operation, it would just be arithmetic, and nobody would care.

A minor, secondary issue is that conditional moves have a data dependency on both of the source operands, unlike conditional branch and move, which means that they are often slower than a predictable branch and move on a fast processor. However, this doesn't matter all that much, because they're optional, so just don't use them when they aren't a good fit.

Re:RISC-V formal spec public review by ncmncm on Friday June 21, 2019 @12:57PM (#20244266)
It probably is confused.