https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103090
Bug ID: 103090 Summary: [i386] GCC should use the SF and ZF flags in some atomic_fetch_op sequences Product: gcc Version: 12.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: middle-end Assignee: unassigned at gcc dot gnu.org Reporter: thiago at kde dot org Target Milestone: --- Disclaimer: I don't know this code actually exists anywhere. But I've just come up with it. In Bug 102566, we optimised: bool tbit(std::atomic<int> &i) { return i.fetch_or(1, std::memory_order_relaxed) & 1; } To emit LOCK BTS. Similarly, fetch_xor got LOCK BTC and fetch_and got LOCK BTR. These all work because CF is set by the bit-test-and-op instructions. It occurs to me that LOCK AND, LOCK OR and LOCK XOR reliably set the SF, ZF, and PF flags according to the result, so they may be used too. I can't think of any time the PF flag would be useful and obviously ZF will not be set after a LOCK OR (unless you OR'ed zero, but why would you do that?). So possibilities are: static constexpr int signbit = 0x80000000; bool tsign1(std::atomic<int> &i) { int bit = 1; // any one or more bits, except for a constant sign bit return i.fetch_or(bit, std::memory_order_relaxed) & signbit; } bool tsign2(std::atomic<int> &i) { int bit = 1; // any one or more bits, except for a constant sign bit return i.fetch_xor(bit, std::memory_order_relaxed) & signbit; } bool tzero1(std::atomic<int> &i) { int bits = 1; // any one or more bits return i.fetch_and(bit, std::memory_order_relaxed) == 0; } bool tzero2(std::atomic<int> &i) { int bits = 1; // any one or more bits return i.fetch_xor(bit, std::memory_order_relaxed) == 0; } all of the above can be negated too (op != 0 and (op & signbit) == 0).