In modern OoOE CPUs the flag register is renamed, like all other architectural registers, so it does not hinder in any way the parallel execution.

OoOE CPUs need hundreds of registers in order to not hinder the parallel execution, so even the 32 general-purpose registers are not enough, so they must be renamed. Once register renaming is implemented, it does not matter any more if there is a single architectural flags register.

When a cheaper solution than register renaming is desired, the correct solution was that of IBM POWER (1990), where there are 8 flag registers (with 4 flags in each, so the total size is 32 bits). That allows the parallel execution of up to 8 instructions per cycle, even without register renaming.

The superior IBM POWER ISA was implemented even in microcontrollers that were smaller and cheaper than the current RISC-V cores.

An alternative solution to having a flags register is to implement instructions with 3 input operands and 2 output operands. In this case, for the instructions that generate flags, they are stored in the second output registers.

In reality, all the 4 basic arithmetic operations with integers have 3 inputs and 2 outputs, when defined correctly. They are redefined to have 2 inputs and 1 output only to allow cheaper hardware, and in this case the additional input and additional output may be enabled only for some of the instructions, where they are stored in special registers, like the flag register, or in some ISAs in special extension registers used for multiplication/division/rotation/shifting.

> That allows the parallel execution of up to 8 instructions per cycle, even without register renaming

Though, PowerPC implementations (like the PowerPC 750) do have renaming of condition registers, which allows them to speculatively execute CR write instructions (though the PowerPC 750 can't speculatively read a CR, it can only speculate one branch at a time).

But I suspect other justification for renaming CRs, is that register renaming is actually how the PowerPC designs from that era handled hazard detection and result forwarding (and maybe why such designs only a few renaming registers, six GPRs and six FPRs on the 750)

What really hindered flags and OOOE were instructions that only partially updated flag bits. For example if increment sets the overflow and zero flags but doesn't change the negative flag, it has a dependency on the old value of the flags register and a chain of increments must be serialised. Not fundamentally, but yes if you treat flags as a single register.

If you fix that by saying that every instruction sets the whole flags register, then it only makes sense to read the flags register in the very next instruction after setting it, and you may as well combine those into one single instruction and then you don't need the register at all.

Exception is ADC chains which both read and set the register. I think RISC-V doesn't support them?

What you say about partially updated flag registers is right.

Because of this, most modern ISAs take care so that the flags register is always updated completely.

In legacy ISAs, like in x86-64 where the carry flag is updated or not updated separately from the other flags, it is handled by the CPU as a distinct register, so the carry flag is renamed independently of the other flags.

Moreover, in x86-64 the overflow flag can be used as second carry flag in some instructions. Having 2 carry flags permits the elimination of some functional dependencies between instructions that would not be eliminated by the renaming of a single carry flag (renaming solves only resource dependencies, not data dependencies).