r222798 - CodeGen: Fix emission of __atomic_compare_exchange
David Majnemer
david.majnemer at gmail.com
Tue Nov 25 15:44:33 PST 2014
Author: majnemer
Date: Tue Nov 25 17:44:32 2014
New Revision: 222798
URL: http://llvm.org/viewvc/llvm-project?rev=222798&view=rev
Log:
CodeGen: Fix emission of __atomic_compare_exchange
We (wrongly) discarded the return value of the call.
Modified:
cfe/trunk/lib/CodeGen/CGAtomic.cpp
cfe/trunk/test/CodeGen/atomic-ops.c
Modified: cfe/trunk/lib/CodeGen/CGAtomic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGAtomic.cpp?rev=222798&r1=222797&r2=222798&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGAtomic.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGAtomic.cpp Tue Nov 25 17:44:32 2014
@@ -588,8 +588,11 @@ RValue CodeGenFunction::EmitAtomicExpr(A
break;
}
- if (!E->getType()->isVoidType() && !Dest)
- Dest = CreateMemTemp(E->getType(), ".atomicdst");
+ auto GetDest = [&] {
+ if (!E->getType()->isVoidType() && !Dest)
+ Dest = CreateMemTemp(E->getType(), ".atomicdst");
+ return Dest;
+ };
// Use a library call. See: http://gcc.gnu.org/wiki/Atomic/GCCMM/LIbrary .
if (UseLibcall) {
@@ -729,32 +732,29 @@ RValue CodeGenFunction::EmitAtomicExpr(A
} else {
// Value is returned through parameter before the order.
RetTy = getContext().VoidTy;
- Args.add(RValue::get(EmitCastToVoidPtr(Dest)),
- getContext().VoidPtrTy);
+ Args.add(RValue::get(EmitCastToVoidPtr(Dest)), getContext().VoidPtrTy);
}
}
// order is always the last parameter
Args.add(RValue::get(Order),
getContext().IntTy);
- const CGFunctionInfo &FuncInfo =
- CGM.getTypes().arrangeFreeFunctionCall(RetTy, Args,
- FunctionType::ExtInfo(), RequiredArgs::All);
- llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FuncInfo);
- llvm::Constant *Func = CGM.CreateRuntimeFunction(FTy, LibCallName);
- RValue Res = EmitCall(FuncInfo, Func, ReturnValueSlot(), Args);
- if (!RetTy->isVoidType()) {
- if (UseOptimizedLibcall) {
- if (HaveRetTy)
- return Res;
- llvm::StoreInst *StoreDest = Builder.CreateStore(
- Res.getScalarVal(),
- Builder.CreateBitCast(Dest, FTy->getReturnType()->getPointerTo()));
- StoreDest->setAlignment(Align);
- }
- }
- if (E->getType()->isVoidType())
+ RValue Res = emitAtomicLibcall(*this, LibCallName, RetTy, Args);
+ // The value is returned directly from the libcall.
+ if (HaveRetTy && !RetTy->isVoidType())
+ return Res;
+ // The value is returned via an explicit out param.
+ if (RetTy->isVoidType())
return RValue::get(nullptr);
+ // The value is returned directly for optimized libcalls but the caller is
+ // expected an out-param.
+ if (UseOptimizedLibcall) {
+ llvm::Value *ResVal = Res.getScalarVal();
+ llvm::StoreInst *StoreDest = Builder.CreateStore(
+ ResVal,
+ Builder.CreateBitCast(GetDest(), ResVal->getType()->getPointerTo()));
+ StoreDest->setAlignment(Align);
+ }
return convertTempToRValue(Dest, E->getType(), E->getExprLoc());
}
@@ -767,7 +767,7 @@ RValue CodeGenFunction::EmitAtomicExpr(A
llvm::Type *ITy =
llvm::IntegerType::get(getLLVMContext(), Size * 8);
- llvm::Value *OrigDest = Dest;
+ llvm::Value *OrigDest = GetDest();
Ptr = Builder.CreateBitCast(
Ptr, ITy->getPointerTo(Ptr->getType()->getPointerAddressSpace()));
if (Val1) Val1 = Builder.CreateBitCast(Val1, ITy->getPointerTo());
Modified: cfe/trunk/test/CodeGen/atomic-ops.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/atomic-ops.c?rev=222798&r1=222797&r2=222798&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/atomic-ops.c (original)
+++ cfe/trunk/test/CodeGen/atomic-ops.c Tue Nov 25 17:44:32 2014
@@ -383,14 +383,23 @@ struct foo structAtomicExchange() {
}
int structAtomicCmpExchange() {
// CHECK-LABEL: @structAtomicCmpExchange
+ // CHECK: %[[x_mem:.*]] = alloca i8
_Bool x = __atomic_compare_exchange(&smallThing, &thing1, &thing2, 1, 5, 5);
- // CHECK: call zeroext i1 @__atomic_compare_exchange(i32 3, {{.*}} @smallThing{{.*}} @thing1{{.*}} @thing2
+ // CHECK: %[[call1:.*]] = call zeroext i1 @__atomic_compare_exchange(i32 3, {{.*}} @smallThing{{.*}} @thing1{{.*}} @thing2
+ // CHECK: %[[zext1:.*]] = zext i1 %[[call1]] to i8
+ // CHECK: store i8 %[[zext1]], i8* %[[x_mem]], align 1
+ // CHECK: %[[x:.*]] = load i8* %[[x_mem]]
+ // CHECK: %[[x_bool:.*]] = trunc i8 %[[x]] to i1
+ // CHECK: %[[conv1:.*]] = zext i1 %[[x_bool]] to i32
struct foo f = {0};
struct foo g = {0};
g.big[12] = 12;
return x & __c11_atomic_compare_exchange_strong(&bigAtomic, &f, g, 5, 5);
- // CHECK: call zeroext i1 @__atomic_compare_exchange(i32 512, i8* bitcast ({{.*}} @bigAtomic to i8*),
+ // CHECK: %[[call2:.*]] = call zeroext i1 @__atomic_compare_exchange(i32 512, i8* bitcast ({{.*}} @bigAtomic to i8*),
+ // CHECK: %[[conv2:.*]] = zext i1 %[[call2]] to i32
+ // CHECK: %[[and:.*]] = and i32 %[[conv1]], %[[conv2]]
+ // CHECK: ret i32 %[[and]]
}
// Check that no atomic operations are used in any initialisation of _Atomic
More information about the cfe-commits
mailing list