================
@@ -1109,6 +1299,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;
----------------
xroche wrote:
Edit: Why not just emit the simple atomic and let the backend handle it ?
For ordinary 64/128-bit sizes we already do. The hand-written loop is only for
two cases the single instruction can't handle: odd sizes (37 bits), where it
would corrupt the padding bits, and sizes over 128 bits, where no hardware
instruction or ready-made library add exists.
https://github.com/llvm/llvm-project/pull/204815
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits