================
@@ -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

Reply via email to