================
@@ -1144,6 +1322,27 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
LValue AtomicVal = MakeAddrLValue(Ptr, AtomicTy);
AtomicInfo Atomics(*this, AtomicVal);
+ // A `_BitInt(N)` read-modify-write whose value width has padding bits, or
+ // whose size forces a libcall, cannot use a single atomicrmw: the op would
+ // carry into / compare the padding bits, and no arbitrary-width
+ // __atomic_fetch_* libcall exists. Emit a compare-exchange loop instead.
+ // Bitwise and/or/xor are exact even with padding, so only the wide case
needs
+ // the loop for them. load/store/exchange/compare_exchange keep their paths.
+ if (MemTy->isBitIntType()) {
+ llvm::AtomicRMWInst::BinOp BinOp;
+ bool RMWReturnsNew;
+ if (classifyBitIntRMW(E->getOp(), MemTy->isSignedIntegerType(), BinOp,
+ RMWReturnsNew)) {
+ bool WideOrNonPow2 = (Size & (Size - 1)) != 0 || Size > 16;
+ bool Bitwise = BinOp == llvm::AtomicRMWInst::And ||
+ BinOp == llvm::AtomicRMWInst::Or ||
+ BinOp == llvm::AtomicRMWInst::Xor;
+ if (WideOrNonPow2 || (hasBitIntPadding(MemTy, getContext()) && !Bitwise))
----------------
xroche wrote:
I see your point, but clear_padding only covers atomic_ref's
store/exchange/compare-exchange; std::atomic never calls it and every fetch_add
goes straight to the compiler, so the arithmetic has to be handled here (and
the plain C _Atomic(_BitInt) this fixes, #60904, never sees libc++ at all).
On the padding form itself, I lean toward zeroing the write-back to match
clear_padding and GCC rather than sign-extending, but since this is effectively
the ABI, I'd rather settle it here first.
https://github.com/llvm/llvm-project/pull/204815
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits