[clang] [libcxx] [clang] [libc++] fix _Atomic c11 compare exchange does not update expected results (PR #78707)
Eli Friedman via cfe-commits
cfe-commits at lists.llvm.org
Mon Jun 16 17:17:03 PDT 2025
================
@@ -411,7 +412,48 @@ static void emitAtomicCmpXchg(CodeGenFunction &CGF, AtomicExpr *E, bool IsWeak,
CGF.Builder.SetInsertPoint(StoreExpectedBB);
// Update the memory at Expected with Old's value.
- CGF.Builder.CreateStore(Old, Val1);
+llvm::Type *ExpectedType = ExpectedResult.getElementType();
+const llvm::DataLayout &DL = CGF.CGM.getDataLayout();
+uint64_t ExpectedSizeInBytes = DL.getTypeStoreSize(ExpectedType);
+
+if (ExpectedSizeInBytes == Size) {
+ // Sizes match: store directly
+ CGF.Builder.CreateStore(Old, ExpectedResult);
+
+} else {
+ // store only the first ExpectedSizeInBytes bytes of Old
+ llvm::Type *OldType = Old->getType();
+
+ llvm::Align SrcAlignLLVM = DL.getABITypeAlign(OldType);
+ llvm::Align DstAlignLLVM = DL.getABITypeAlign(ExpectedType);
+
+ clang::CharUnits SrcAlign = clang::CharUnits::fromQuantity(SrcAlignLLVM.value());
+ clang::CharUnits DstAlign = clang::CharUnits::fromQuantity(DstAlignLLVM.value());
+
+ // Allocate temporary storage for Old value
+ llvm::AllocaInst *Alloca = CGF.CreateTempAlloca(OldType, "old.tmp");
+
+ // Wrap into clang::CodeGen::Address with proper type and alignment
+ Address OldStorage(Alloca, OldType, SrcAlign);
+
+ // Store Old into this temporary
+ CGF.Builder.CreateStore(Old, OldStorage);
+
+ // Bitcast pointers to i8*
+ llvm::Type *I8PtrTy = llvm::PointerType::getUnqual(CGF.getLLVMContext());
+
+ llvm::Value *SrcPtr = CGF.Builder.CreateBitCast(OldStorage.getBasePointer(), I8PtrTy);
+ llvm::Value *DstPtr = CGF.Builder.CreateBitCast(ExpectedResult.getBasePointer(), I8PtrTy);
----------------
efriedma-quic wrote:
The code here is doing the right thing, roughly: doing an alloca+store+memcpy is fine. (SROA will usually end up optimizing it, but the exact sequence of instructions you need isn't consistent, so it's fine to rely on that.)
My suggestions are basically code cleanup: don't do redundant operations, compute alignment consistently, use appropriate helper methods.
https://github.com/llvm/llvm-project/pull/78707
More information about the cfe-commits
mailing list