mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-24 10:00:45 +02:00
We expect that PF is written more often than it's read, so we want to get the expensive popcount out of the hot path. (Thank you to Dougall for suggesting that.) There are two cases: 1. PF is written by an integer instruction. In this case, we calculate with the formula `popcount(x ^ 1) & 1`. 2. PF is written by a float instruction, copying a host flag. What we really want is to defer the relatively expensive popcount. So, to unify these cases, we have integer instructions write `x ^ 1` and (unchanged) float instructions write the host flag. Then, when reading PF, we do `popcount(value) & 1` on the byte read in. If PF is written but not read, this saves the expensive popcount and leaves only the cheap xor. If PF is written by an integer op and read, this maybe shuffles some code but does not materially change anything. If PF is written by a float op and read, this is worse because now we're doing an extra pointless popcount. This is a tradeoff... However, this is only relevant to unordered float comparisons, which I expect to be obscure for games. So this should be worth it over all (for games, if not weird numerical computing workloads). How does this connect to my register zeroing quest? The constant folding code doesn't currently deal with FPRs and I'm not in a mood to change this. So before, a block ending with `xor eax, eax` would still do a popcount for PF. Now it just writes a constant 1 since the xor constant folds and the popcount never happens at all. Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>