Skip to content

Commit 0dc5bf9

Browse files
committed
[libc++] fix _Atomic c11 compare exchange does not update expected results
1 parent 90d5795 commit 0dc5bf9

File tree

1 file changed

+37
-24
lines changed

1 file changed

+37
-24
lines changed

clang/lib/CodeGen/CGAtomic.cpp

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,7 @@ bool AtomicInfo::emitMemSetZeroIfNecessary() const {
376376
static void emitAtomicCmpXchg(CodeGenFunction &CGF, AtomicExpr *E, bool IsWeak,
377377
Address Dest, Address Ptr,
378378
Address Val1, Address Val2,
379+
Address ExpectedResult,
379380
uint64_t Size,
380381
llvm::AtomicOrdering SuccessOrder,
381382
llvm::AtomicOrdering FailureOrder,
@@ -411,9 +412,17 @@ static void emitAtomicCmpXchg(CodeGenFunction &CGF, AtomicExpr *E, bool IsWeak,
411412

412413
CGF.Builder.SetInsertPoint(StoreExpectedBB);
413414
// Update the memory at Expected with Old's value.
414-
auto *I = CGF.Builder.CreateStore(Old, Val1);
415-
CGF.addInstToCurrentSourceAtom(I, Old);
416415

416+
llvm::Type *ExpectedType = ExpectedResult.getElementType();
417+
uint64_t OriginalSizeInBits = CGF.CGM.getDataLayout().getTypeSizeInBits(ExpectedType);
418+
if (OriginalSizeInBits / 8 == Size) {
419+
auto *I = CGF.Builder.CreateStore(Old, ExpectedResult);
420+
CGF.addInstToCurrentSourceAtom(I, Old);
421+
} else {
422+
// How to just store N bytes to ExpectedResult ?
423+
auto *I = CGF.Builder.CreateStore(Old, ExpectedResult);
424+
CGF.addInstToCurrentSourceAtom(I, Old);
425+
}
417426
// Finally, branch to the exit point.
418427
CGF.Builder.CreateBr(ContinueBB);
419428

@@ -428,6 +437,7 @@ static void emitAtomicCmpXchg(CodeGenFunction &CGF, AtomicExpr *E, bool IsWeak,
428437
static void emitAtomicCmpXchgFailureSet(CodeGenFunction &CGF, AtomicExpr *E,
429438
bool IsWeak, Address Dest, Address Ptr,
430439
Address Val1, Address Val2,
440+
Address ExpectedResult,
431441
llvm::Value *FailureOrderVal,
432442
uint64_t Size,
433443
llvm::AtomicOrdering SuccessOrder,
@@ -458,7 +468,7 @@ static void emitAtomicCmpXchgFailureSet(CodeGenFunction &CGF, AtomicExpr *E,
458468
// success argument". This condition has been lifted and the only
459469
// precondition is 31.7.2.18. Effectively treat this as a DR and skip
460470
// language version checks.
461-
emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, Size, SuccessOrder,
471+
emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, ExpectedResult, Size, SuccessOrder,
462472
FailureOrder, Scope);
463473
return;
464474
}
@@ -483,17 +493,17 @@ static void emitAtomicCmpXchgFailureSet(CodeGenFunction &CGF, AtomicExpr *E,
483493

484494
// Emit all the different atomics
485495
CGF.Builder.SetInsertPoint(MonotonicBB);
486-
emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2,
496+
emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, ExpectedResult,
487497
Size, SuccessOrder, llvm::AtomicOrdering::Monotonic, Scope);
488498
CGF.Builder.CreateBr(ContBB);
489499

490500
CGF.Builder.SetInsertPoint(AcquireBB);
491-
emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, Size, SuccessOrder,
501+
emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, ExpectedResult, Size, SuccessOrder,
492502
llvm::AtomicOrdering::Acquire, Scope);
493503
CGF.Builder.CreateBr(ContBB);
494504

495505
CGF.Builder.SetInsertPoint(SeqCstBB);
496-
emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, Size, SuccessOrder,
506+
emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, ExpectedResult, Size, SuccessOrder,
497507
llvm::AtomicOrdering::SequentiallyConsistent, Scope);
498508
CGF.Builder.CreateBr(ContBB);
499509

@@ -526,6 +536,7 @@ static llvm::Value *EmitPostAtomicMinMax(CGBuilderTy &Builder,
526536

527537
static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
528538
Address Ptr, Address Val1, Address Val2,
539+
Address ExpectedResult,
529540
llvm::Value *IsWeak, llvm::Value *FailureOrder,
530541
uint64_t Size, llvm::AtomicOrdering Order,
531542
llvm::SyncScope::ID Scope) {
@@ -542,21 +553,21 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
542553
case AtomicExpr::AO__hip_atomic_compare_exchange_strong:
543554
case AtomicExpr::AO__opencl_atomic_compare_exchange_strong:
544555
emitAtomicCmpXchgFailureSet(CGF, E, false, Dest, Ptr, Val1, Val2,
545-
FailureOrder, Size, Order, Scope);
556+
ExpectedResult, FailureOrder, Size, Order, Scope);
546557
return;
547558
case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
548559
case AtomicExpr::AO__opencl_atomic_compare_exchange_weak:
549560
case AtomicExpr::AO__hip_atomic_compare_exchange_weak:
550561
emitAtomicCmpXchgFailureSet(CGF, E, true, Dest, Ptr, Val1, Val2,
551-
FailureOrder, Size, Order, Scope);
562+
ExpectedResult, FailureOrder, Size, Order, Scope);
552563
return;
553564
case AtomicExpr::AO__atomic_compare_exchange:
554565
case AtomicExpr::AO__atomic_compare_exchange_n:
555566
case AtomicExpr::AO__scoped_atomic_compare_exchange:
556567
case AtomicExpr::AO__scoped_atomic_compare_exchange_n: {
557568
if (llvm::ConstantInt *IsWeakC = dyn_cast<llvm::ConstantInt>(IsWeak)) {
558569
emitAtomicCmpXchgFailureSet(CGF, E, IsWeakC->getZExtValue(), Dest, Ptr,
559-
Val1, Val2, FailureOrder, Size, Order, Scope);
570+
Val1, Val2, ExpectedResult, FailureOrder, Size, Order, Scope);
560571
} else {
561572
// Create all the relevant BB's
562573
llvm::BasicBlock *StrongBB =
@@ -570,12 +581,12 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
570581

571582
CGF.Builder.SetInsertPoint(StrongBB);
572583
emitAtomicCmpXchgFailureSet(CGF, E, false, Dest, Ptr, Val1, Val2,
573-
FailureOrder, Size, Order, Scope);
584+
ExpectedResult, FailureOrder, Size, Order, Scope);
574585
CGF.Builder.CreateBr(ContBB);
575586

576587
CGF.Builder.SetInsertPoint(WeakBB);
577588
emitAtomicCmpXchgFailureSet(CGF, E, true, Dest, Ptr, Val1, Val2,
578-
FailureOrder, Size, Order, Scope);
589+
ExpectedResult, FailureOrder, Size, Order, Scope);
579590
CGF.Builder.CreateBr(ContBB);
580591

581592
CGF.Builder.SetInsertPoint(ContBB);
@@ -785,6 +796,7 @@ EmitValToTemp(CodeGenFunction &CGF, Expr *E) {
785796

786797
static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *Expr, Address Dest,
787798
Address Ptr, Address Val1, Address Val2,
799+
Address OriginalVal1,
788800
llvm::Value *IsWeak, llvm::Value *FailureOrder,
789801
uint64_t Size, llvm::AtomicOrdering Order,
790802
llvm::Value *Scope) {
@@ -804,7 +816,7 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *Expr, Address Dest,
804816
Order, CGF.getLLVMContext());
805817
else
806818
SS = llvm::SyncScope::System;
807-
EmitAtomicOp(CGF, Expr, Dest, Ptr, Val1, Val2, IsWeak, FailureOrder, Size,
819+
EmitAtomicOp(CGF, Expr, Dest, Ptr, Val1, Val2, OriginalVal1, IsWeak, FailureOrder, Size,
808820
Order, SS);
809821
return;
810822
}
@@ -814,7 +826,7 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *Expr, Address Dest,
814826
auto SCID = CGF.getTargetHooks().getLLVMSyncScopeID(
815827
CGF.CGM.getLangOpts(), ScopeModel->map(SC->getZExtValue()),
816828
Order, CGF.CGM.getLLVMContext());
817-
EmitAtomicOp(CGF, Expr, Dest, Ptr, Val1, Val2, IsWeak, FailureOrder, Size,
829+
EmitAtomicOp(CGF, Expr, Dest, Ptr, Val1, Val2, OriginalVal1, IsWeak, FailureOrder, Size,
818830
Order, SCID);
819831
return;
820832
}
@@ -840,7 +852,7 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *Expr, Address Dest,
840852
SI->addCase(Builder.getInt32(S), B);
841853

842854
Builder.SetInsertPoint(B);
843-
EmitAtomicOp(CGF, Expr, Dest, Ptr, Val1, Val2, IsWeak, FailureOrder, Size,
855+
EmitAtomicOp(CGF, Expr, Dest, Ptr, Val1, Val2, OriginalVal1, IsWeak, FailureOrder, Size,
844856
Order,
845857
CGF.getTargetHooks().getLLVMSyncScopeID(CGF.CGM.getLangOpts(),
846858
ScopeModel->map(S),
@@ -1046,6 +1058,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
10461058
LValue AtomicVal = MakeAddrLValue(Ptr, AtomicTy);
10471059
AtomicInfo Atomics(*this, AtomicVal);
10481060

1061+
Address OriginalVal1 = Val1;
10491062
if (ShouldCastToIntPtrTy) {
10501063
Ptr = Atomics.castToAtomicIntPointer(Ptr);
10511064
if (Val1.isValid())
@@ -1289,30 +1302,30 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
12891302
if (llvm::isValidAtomicOrderingCABI(ord))
12901303
switch ((llvm::AtomicOrderingCABI)ord) {
12911304
case llvm::AtomicOrderingCABI::relaxed:
1292-
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
1305+
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, OriginalVal1, IsWeak, OrderFail, Size,
12931306
llvm::AtomicOrdering::Monotonic, Scope);
12941307
break;
12951308
case llvm::AtomicOrderingCABI::consume:
12961309
case llvm::AtomicOrderingCABI::acquire:
12971310
if (IsStore)
12981311
break; // Avoid crashing on code with undefined behavior
1299-
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
1312+
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, OriginalVal1, IsWeak, OrderFail, Size,
13001313
llvm::AtomicOrdering::Acquire, Scope);
13011314
break;
13021315
case llvm::AtomicOrderingCABI::release:
13031316
if (IsLoad)
13041317
break; // Avoid crashing on code with undefined behavior
1305-
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
1318+
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, OriginalVal1, IsWeak, OrderFail, Size,
13061319
llvm::AtomicOrdering::Release, Scope);
13071320
break;
13081321
case llvm::AtomicOrderingCABI::acq_rel:
13091322
if (IsLoad || IsStore)
13101323
break; // Avoid crashing on code with undefined behavior
1311-
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
1324+
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, OriginalVal1, IsWeak, OrderFail, Size,
13121325
llvm::AtomicOrdering::AcquireRelease, Scope);
13131326
break;
13141327
case llvm::AtomicOrderingCABI::seq_cst:
1315-
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
1328+
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, OriginalVal1, IsWeak, OrderFail, Size,
13161329
llvm::AtomicOrdering::SequentiallyConsistent, Scope);
13171330
break;
13181331
}
@@ -1348,12 +1361,12 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
13481361

13491362
// Emit all the different atomics
13501363
Builder.SetInsertPoint(MonotonicBB);
1351-
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
1364+
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, OriginalVal1, IsWeak, OrderFail, Size,
13521365
llvm::AtomicOrdering::Monotonic, Scope);
13531366
Builder.CreateBr(ContBB);
13541367
if (!IsStore) {
13551368
Builder.SetInsertPoint(AcquireBB);
1356-
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
1369+
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, OriginalVal1, IsWeak, OrderFail, Size,
13571370
llvm::AtomicOrdering::Acquire, Scope);
13581371
Builder.CreateBr(ContBB);
13591372
SI->addCase(Builder.getInt32((int)llvm::AtomicOrderingCABI::consume),
@@ -1363,22 +1376,22 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
13631376
}
13641377
if (!IsLoad) {
13651378
Builder.SetInsertPoint(ReleaseBB);
1366-
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
1379+
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, OriginalVal1, IsWeak, OrderFail, Size,
13671380
llvm::AtomicOrdering::Release, Scope);
13681381
Builder.CreateBr(ContBB);
13691382
SI->addCase(Builder.getInt32((int)llvm::AtomicOrderingCABI::release),
13701383
ReleaseBB);
13711384
}
13721385
if (!IsLoad && !IsStore) {
13731386
Builder.SetInsertPoint(AcqRelBB);
1374-
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
1387+
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, OriginalVal1, IsWeak, OrderFail, Size,
13751388
llvm::AtomicOrdering::AcquireRelease, Scope);
13761389
Builder.CreateBr(ContBB);
13771390
SI->addCase(Builder.getInt32((int)llvm::AtomicOrderingCABI::acq_rel),
13781391
AcqRelBB);
13791392
}
13801393
Builder.SetInsertPoint(SeqCstBB);
1381-
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
1394+
EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, OriginalVal1, IsWeak, OrderFail, Size,
13821395
llvm::AtomicOrdering::SequentiallyConsistent, Scope);
13831396
Builder.CreateBr(ContBB);
13841397
SI->addCase(Builder.getInt32((int)llvm::AtomicOrderingCABI::seq_cst),

0 commit comments

Comments
 (0)