From: David Majnemer Date: Fri, 12 Dec 2014 08:16:09 +0000 (+0000) Subject: CodeGen: Loads/stores to allocas for atomic ops shouldn't be volatile X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=18e77997e548c6243ac784c764b672411107e4cf;p=clang CodeGen: Loads/stores to allocas for atomic ops shouldn't be volatile Don't inherit the volatile-ness of the input pointer to the volatile operation for memory allocated on the side. This fixes PR17306. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@224110 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGAtomic.cpp b/lib/CodeGen/CGAtomic.cpp index f492a06866..49f98b2a07 100644 --- a/lib/CodeGen/CGAtomic.cpp +++ b/lib/CodeGen/CGAtomic.cpp @@ -588,9 +588,12 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) { break; } + QualType RValTy = E->getType().getUnqualifiedType(); + auto GetDest = [&] { - if (!E->getType()->isVoidType() && !Dest) - Dest = CreateMemTemp(E->getType(), ".atomicdst"); + if (!RValTy->isVoidType() && !Dest) { + Dest = CreateMemTemp(RValTy, ".atomicdst"); + } return Dest; }; @@ -755,7 +758,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) { Builder.CreateBitCast(GetDest(), ResVal->getType()->getPointerTo())); StoreDest->setAlignment(Align); } - return convertTempToRValue(Dest, E->getType(), E->getExprLoc()); + return convertTempToRValue(Dest, RValTy, E->getExprLoc()); } bool IsStore = E->getOp() == AtomicExpr::AO__c11_atomic_store || @@ -810,9 +813,9 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) { // enforce that in general. break; } - if (E->getType()->isVoidType()) + if (RValTy->isVoidType()) return RValue::get(nullptr); - return convertTempToRValue(OrigDest, E->getType(), E->getExprLoc()); + return convertTempToRValue(OrigDest, RValTy, E->getExprLoc()); } // Long case, when Order isn't obviously constant. @@ -878,9 +881,9 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E, llvm::Value *Dest) { // Cleanup and return Builder.SetInsertPoint(ContBB); - if (E->getType()->isVoidType()) + if (RValTy->isVoidType()) return RValue::get(nullptr); - return convertTempToRValue(OrigDest, E->getType(), E->getExprLoc()); + return convertTempToRValue(OrigDest, RValTy, E->getExprLoc()); } llvm::Value *AtomicInfo::emitCastToAtomicIntPointer(llvm::Value *addr) const { diff --git a/test/CodeGen/atomic-ops.c b/test/CodeGen/atomic-ops.c index 576e401a91..559b135413 100644 --- a/test/CodeGen/atomic-ops.c +++ b/test/CodeGen/atomic-ops.c @@ -564,7 +564,39 @@ int PR21643() { // CHECK: store i32 %[[new]], i32* %[[atomicdst]], align 4 // CHECK: %[[ret:.*]] = load i32* %[[atomicdst]], align 4 // CHECK: ret i32 %[[ret]] +} + +int PR17306_1(volatile _Atomic(int) *i) { + // CHECK-LABEL: @PR17306_1 + // CHECK: %[[i_addr:.*]] = alloca i32 + // CHECK-NEXT: %[[atomicdst:.*]] = alloca i32 + // CHECK-NEXT: store i32* %i, i32** %[[i_addr]] + // CHECK-NEXT: %[[addr:.*]] = load i32** %[[i_addr]] + // CHECK-NEXT: %[[res:.*]] = load atomic volatile i32* %[[addr]] seq_cst + // CHECK-NEXT: store i32 %[[res]], i32* %[[atomicdst]] + // CHECK-NEXT: %[[retval:.*]] = load i32* %[[atomicdst]] + // CHECK-NEXT: ret i32 %[[retval]] + return __c11_atomic_load(i, memory_order_seq_cst); +} +int PR17306_2(volatile int *i, int value) { + // CHECK-LABEL: @PR17306_2 + // CHECK: %[[i_addr:.*]] = alloca i32* + // CHECK-NEXT: %[[value_addr:.*]] = alloca i32 + // CHECK-NEXT: %[[atomictmp:.*]] = alloca i32 + // CHECK-NEXT: %[[atomicdst:.*]] = alloca i32 + // CHECK-NEXT: store i32* %i, i32** %[[i_addr]] + // CHECK-NEXT: store i32 %value, i32* %[[value_addr]] + // CHECK-NEXT: %[[i_lval:.*]] = load i32** %[[i_addr]] + // CHECK-NEXT: %[[value:.*]] = load i32* %[[value_addr]] + // CHECK-NEXT: store i32 %[[value]], i32* %[[atomictmp]] + // CHECK-NEXT: %[[value_lval:.*]] = load i32* %[[atomictmp]] + // CHECK-NEXT: %[[old_val:.*]] = atomicrmw volatile add i32* %[[i_lval]], i32 %[[value_lval]] seq_cst + // CHECK-NEXT: %[[new_val:.*]] = add i32 %[[old_val]], %[[value_lval]] + // CHECK-NEXT: store i32 %[[new_val]], i32* %[[atomicdst]] + // CHECK-NEXT: %[[retval:.*]] = load i32* %[[atomicdst]] + // CHECK-NEXT: ret i32 %[[retval]] + return __atomic_add_fetch(i, value, memory_order_seq_cst); } #endif