diff options
| author | David Majnemer <david.majnemer@gmail.com> | 2014-03-10 21:35:33 +0000 |
|---|---|---|
| committer | David Majnemer <david.majnemer@gmail.com> | 2014-03-10 21:35:33 +0000 |
| commit | 938bc1ea843e6e5d64d4d4c33df5ccf40d677344 (patch) | |
| tree | 820adfbbaa9ea06e26434b68f537e6b391bf5023 /clang/lib/CodeGen | |
| parent | 02a0dd8dd1ed2c3ff532618290e0040ad70dbbf1 (diff) | |
| download | bcm5719-llvm-938bc1ea843e6e5d64d4d4c33df5ccf40d677344.tar.gz bcm5719-llvm-938bc1ea843e6e5d64d4d4c33df5ccf40d677344.zip | |
IRGen: __c11/__atomic compare-and-exchange should respect the standard
Summary:
'Expected' should only be modified if the operation fails.
This fixes PR18899.
Reviewers: chandlerc, rsmith, rjmccall
CC: cfe-commits
Differential Revision: http://llvm-reviews.chandlerc.com/D2922
llvm-svn: 203493
Diffstat (limited to 'clang/lib/CodeGen')
| -rw-r--r-- | clang/lib/CodeGen/CGAtomic.cpp | 46 |
1 files changed, 36 insertions, 10 deletions
diff --git a/clang/lib/CodeGen/CGAtomic.cpp b/clang/lib/CodeGen/CGAtomic.cpp index cb92f9ad226..88655774044 100644 --- a/clang/lib/CodeGen/CGAtomic.cpp +++ b/clang/lib/CodeGen/CGAtomic.cpp @@ -201,16 +201,42 @@ EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, llvm::Value *Dest, case AtomicExpr::AO__atomic_compare_exchange_n: { // Note that cmpxchg only supports specifying one ordering and // doesn't support weak cmpxchg, at least at the moment. - llvm::LoadInst *LoadVal1 = CGF.Builder.CreateLoad(Val1); - LoadVal1->setAlignment(Align); - llvm::LoadInst *LoadVal2 = CGF.Builder.CreateLoad(Val2); - LoadVal2->setAlignment(Align); - llvm::AtomicCmpXchgInst *CXI = - CGF.Builder.CreateAtomicCmpXchg(Ptr, LoadVal1, LoadVal2, Order); - CXI->setVolatile(E->isVolatile()); - llvm::StoreInst *StoreVal1 = CGF.Builder.CreateStore(CXI, Val1); - StoreVal1->setAlignment(Align); - llvm::Value *Cmp = CGF.Builder.CreateICmpEQ(CXI, LoadVal1); + + llvm::LoadInst *Expected = CGF.Builder.CreateLoad(Val1); + Expected->setAlignment(Align); + llvm::LoadInst *Desired = CGF.Builder.CreateLoad(Val2); + Desired->setAlignment(Align); + llvm::AtomicCmpXchgInst *Old = + CGF.Builder.CreateAtomicCmpXchg(Ptr, Expected, Desired, Order); + Old->setVolatile(E->isVolatile()); + + // Cmp holds the result of the compare-exchange operation: true on success, + // false on failure. + llvm::Value *Cmp = CGF.Builder.CreateICmpEQ(Old, Expected); + + // This basic block is used to hold the store instruction if the operation + // failed. + llvm::BasicBlock *StoreExpectedBB = + CGF.createBasicBlock("cmpxchg.store_expected", CGF.CurFn); + + // This basic block is the exit point of the operation, we should end up + // here regardless of whether or not the operation succeeded. + llvm::BasicBlock *ContinueBB = + CGF.createBasicBlock("cmpxchg.continue", CGF.CurFn); + + // Update Expected if Expected isn't equal to Old, otherwise branch to the + // exit point. + CGF.Builder.CreateCondBr(Cmp, ContinueBB, StoreExpectedBB); + + CGF.Builder.SetInsertPoint(StoreExpectedBB); + // Update the memory at Expected with Old's value. + llvm::StoreInst *StoreExpected = CGF.Builder.CreateStore(Old, Val1); + StoreExpected->setAlignment(Align); + // Finally, branch to the exit point. + CGF.Builder.CreateBr(ContinueBB); + + CGF.Builder.SetInsertPoint(ContinueBB); + // Update the memory at Dest with Cmp's value. CGF.EmitStoreOfScalar(Cmp, CGF.MakeAddrLValue(Dest, E->getType())); return; } |

