Hacker News new | ask | show | jobs
by camel-cdr 14 days ago
> Out-of-order pipelines actually have a really elegant way of handling flags, they just store a copy of the flags register on every ROB entry.

And yet, flag writing instructions are usually half the throughput on regular ALU instructions, on modern wide ooo designs. [1, 2]

But I generally agree, there is a good way of handling them, it's hust unclear to me how expensive it is. It can't be that expensive, but apparently it is expensive enough, to not put a mask register write port on all integer execution units.

[1] https://dougallj.github.io/applecpu/firestorm-int.html (see how ADD is 6-issue and ADDS 3-issue)

[2] https://developer.arm.com/documentation/111027/4-0/ (again 8-issue ADD, but 4-issue ADDS)

1 comments

I wonder if the issue is actually the cost of calculating the flags.

N and C are basically free (copy of bit 63, and it's carry out), V is an extra gate or two, but Z requires a full 64-bit wide NOR gate.

Or it might be about making the register file holding the flags smaller (only 3R3W, instead of 6R6W), along with simplifying the associated bypass network and routing (the first three ALUs are also the only units that can consume flags).

When I say ooo cpus get flag handling for "essentially free", I'm only actually talking about the complexity of tracking "implicit state", and that it can be done without extra latency. You still need to spend transistors to support renaming flags, and to actually calculate and storing the flags.

I can see an argument for an ISA that got rid of the N and Z flags, but kept C/V (potentially merged into a single flag). You can trivially reconstruct N/Z from the result register, but not C/V.

That seems like a weird thing to save on, for architectures that have expensive but rarely used things like CLZ on all ALUs.

But I hadn't considered the ISA design option of only carry flag, no seperate cmp and branch, before.

Huh, it does have CLZ on all ALUs (And CLZ can actually be used to reduce the cost of checking for all zeros).

So it must be something about limiting the complexity of the flags register file and/or its bypass network.

> But I hadn't considered the ISA design option of only carry flag, no seperate cmp and branch, before.

Well, RISC-V does have a decent point: Most of the time you simply don't need flags. The only area this approach falls apart is detecting overflow or add-with-carry.

So, why not just cover that flaw by adding a carry/overflow flag.

The counter-argument is that as soon has you "ruin the purity of the design" by adding one flag, you might as well add the complete set of all four. Then you can simply branch instruction encodings, and use the extra bits for something else (like seperate set-flags versions of all the ALU instructions)

> So, why not just cover that flaw by adding a carry/overflow flag.

Actually, why not just have a single generic 1-bit flag?

You could still have cmp + branch, but now you put the comparison type into the cmp. This gives you a larger branch range again. A flag setting add/sub could also simply set that flag on carry. cmov works, some form of ccmp also works.

Designing an ISA arround carry flags certainly gives you many goodies: cmov, adc, ccmp, larger branch range
Well, cmov is absolutely possible without flags. You see such "select" instructions all the time on GPUs. Doesn't even require an extra instruction, cmp + cmov is two instructions, seqz + select is two.

But it does require three input registers. One for a control value, plus the two options. And RISC-V has a thing about not requiring three input registers.... Yeah, I'm not a fan of RISC-V.

One of the other major advantages of flags is it allowed for a cheap third input to certain instructions (like cmov, adc, ccmp), without requiring a full 3R1W register file.

The fact that it's possible to design a viable ISA without flags is really neat, it was absolutely worth trying. But MIPS already proved it was possible, and showed all the downsides, it did not need to be tried a second time with RISC-V.

> Well, cmov is absolutely possible without flags. You see such "select" instructions all the time on GPUs

Well, yes, because GPUs need 3r1w anyways, for fmadd, and because a dedicated cmov (blen/merge) is a lot more important in those workloads. RVV also has "cmov" vmerge and full predication in general.

RISC-V wants to avoid needing to 3r1w on the integer side.

> But it does require three input registers. One for a control value, plus the two options. And RISC-V has a thing about not requiring three input registers.... Yeah, I'm not a fan of RISC-V.

Arm also tried to avoid 3R1W on the scalar integer side. It's really only madd (on one or two ALUs) and some of the complex load/store ops, which are usually cracked.

My guess is that arm has 3R1W integer instructions, because they needed load/store pair for code density. That means they have to support renaming 3R1W integer instructions, so you may as well add integer madd. I don't think they would've added 3r1w if it wasn't for the complex load/stores.

> One of the other major advantages of flags is it allowed for a cheap third input to certain instructions (like cmov, adc, ccmp), without requiring a full 3R1W register file.

Exactlty. Although I don't think the 3R1W instructions increase the register file size that much, because it grows linear with read ports and you usually don't need the full read bandwidth on very wide cores, as you can do port stealing. I think it's mostly about rename.

> But MIPS already proved it was possible, and showed all the downsides, it did not need to be tried a second time with RISC-V.

I think it's a fine way to design an ISA, however Zicond should've been on the base ISA.