================
@@ -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:
I'm worried that on a 32-bit machine, a 16-byte (128-bit) atomic might need a
helper function that isn't available there. I checked the output: it calls the
always-present general helper in `libatomic` (lock-based, since the hardware
can't do 16-byte atomics), not a missing one. This is new ground (the old
128-bit type isn't allowed on 32-bit at all), but it resolves correctly.
https://github.com/llvm/llvm-project/pull/204815
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits