From c83b975f1fb9d11e10b5aa25029ae9bb5fa80e07 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Wed, 7 Sep 2011 01:41:24 +0000 Subject: [PATCH] Switch clang over to using fence/atomicrmw/cmpxchg instead of the intrinsics (which will go away). LLVM CodeGen does almost exactly the same thing with these and the old intrinsics, so I'm reasonably confident this will not break anything. There are still a few issues which need to be resolved with code generation for atomic load and store, so I'm not converting the places which need those for now. I'm not entirely sure what to do about __builtin_llvm_memory_barrier: the fence instruction doesn't expose all the possibilities which can be expressed by __builtin_llvm_memory_barrier. I would appreciate hearing from anyone who is using this intrinsic. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@139216 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGBuiltin.cpp | 105 +++----- test/CodeGen/2008-03-05-syncPtr.c | 19 +- test/CodeGen/2010-01-13-MemBarrier.c | 8 +- test/CodeGen/Atomics-no64bit.c | 172 ------------- test/CodeGen/Atomics.c | 352 +++++++++++++-------------- test/CodeGen/atomic.c | 109 +++------ 6 files changed, 261 insertions(+), 504 deletions(-) delete mode 100644 test/CodeGen/Atomics-no64bit.c diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 70652d8cd0..642bf15e1b 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -27,20 +27,6 @@ using namespace clang; using namespace CodeGen; using namespace llvm; -static void EmitMemoryBarrier(CodeGenFunction &CGF, - bool LoadLoad, bool LoadStore, - bool StoreLoad, bool StoreStore, - bool Device) { - Value *True = CGF.Builder.getTrue(); - Value *False = CGF.Builder.getFalse(); - Value *C[5] = { LoadLoad ? True : False, - LoadStore ? True : False, - StoreLoad ? True : False, - StoreStore ? True : False, - Device ? True : False }; - CGF.Builder.CreateCall(CGF.CGM.getIntrinsic(Intrinsic::memory_barrier), C); -} - /// Emit the conversions required to turn the given value into an /// integer of the given size. static Value *EmitToInt(CodeGenFunction &CGF, llvm::Value *V, @@ -65,25 +51,11 @@ static Value *EmitFromInt(CodeGenFunction &CGF, llvm::Value *V, return V; } -// The atomic builtins are also full memory barriers. This is a utility for -// wrapping a call to the builtins with memory barriers. -static Value *EmitCallWithBarrier(CodeGenFunction &CGF, Value *Fn, - ArrayRef Args) { - // FIXME: We need a target hook for whether this applies to device memory or - // not. - bool Device = true; - - // Create barriers both before and after the call. - EmitMemoryBarrier(CGF, true, true, true, true, Device); - Value *Result = CGF.Builder.CreateCall(Fn, Args); - EmitMemoryBarrier(CGF, true, true, true, true, Device); - return Result; -} - /// Utility to insert an atomic instruction based on Instrinsic::ID /// and the expression node. static RValue EmitBinaryAtomic(CodeGenFunction &CGF, - Intrinsic::ID Id, const CallExpr *E) { + llvm::AtomicRMWInst::BinOp Kind, + const CallExpr *E) { QualType T = E->getType(); assert(E->getArg(0)->getType()->isPointerType()); assert(CGF.getContext().hasSameUnqualifiedType(T, @@ -99,16 +71,15 @@ static RValue EmitBinaryAtomic(CodeGenFunction &CGF, CGF.getContext().getTypeSize(T)); llvm::Type *IntPtrType = IntType->getPointerTo(AddrSpace); - llvm::Type *IntrinsicTypes[2] = { IntType, IntPtrType }; - llvm::Value *AtomF = CGF.CGM.getIntrinsic(Id, IntrinsicTypes); - llvm::Value *Args[2]; Args[0] = CGF.Builder.CreateBitCast(DestPtr, IntPtrType); Args[1] = CGF.EmitScalarExpr(E->getArg(1)); llvm::Type *ValueType = Args[1]->getType(); Args[1] = EmitToInt(CGF, Args[1], T, IntType); - llvm::Value *Result = EmitCallWithBarrier(CGF, AtomF, Args); + llvm::Value *Result = + CGF.Builder.CreateAtomicRMW(Kind, Args[0], Args[1], + llvm::SequentiallyConsistent); Result = EmitFromInt(CGF, Result, T, ValueType); return RValue::get(Result); } @@ -117,7 +88,8 @@ static RValue EmitBinaryAtomic(CodeGenFunction &CGF, /// the expression node, where the return value is the result of the /// operation. static RValue EmitBinaryAtomicPost(CodeGenFunction &CGF, - Intrinsic::ID Id, const CallExpr *E, + llvm::AtomicRMWInst::BinOp Kind, + const CallExpr *E, Instruction::BinaryOps Op) { QualType T = E->getType(); assert(E->getArg(0)->getType()->isPointerType()); @@ -134,16 +106,15 @@ static RValue EmitBinaryAtomicPost(CodeGenFunction &CGF, CGF.getContext().getTypeSize(T)); llvm::Type *IntPtrType = IntType->getPointerTo(AddrSpace); - llvm::Type *IntrinsicTypes[2] = { IntType, IntPtrType }; - llvm::Value *AtomF = CGF.CGM.getIntrinsic(Id, IntrinsicTypes); - llvm::Value *Args[2]; Args[1] = CGF.EmitScalarExpr(E->getArg(1)); llvm::Type *ValueType = Args[1]->getType(); Args[1] = EmitToInt(CGF, Args[1], T, IntType); Args[0] = CGF.Builder.CreateBitCast(DestPtr, IntPtrType); - llvm::Value *Result = EmitCallWithBarrier(CGF, AtomF, Args); + llvm::Value *Result = + CGF.Builder.CreateAtomicRMW(Kind, Args[0], Args[1], + llvm::SequentiallyConsistent); Result = CGF.Builder.CreateBinOp(Op, Result, Args[1]); Result = EmitFromInt(CGF, Result, T, ValueType); return RValue::get(Result); @@ -780,76 +751,76 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, case Builtin::BI__sync_fetch_and_add_4: case Builtin::BI__sync_fetch_and_add_8: case Builtin::BI__sync_fetch_and_add_16: - return EmitBinaryAtomic(*this, Intrinsic::atomic_load_add, E); + return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::Add, E); case Builtin::BI__sync_fetch_and_sub_1: case Builtin::BI__sync_fetch_and_sub_2: case Builtin::BI__sync_fetch_and_sub_4: case Builtin::BI__sync_fetch_and_sub_8: case Builtin::BI__sync_fetch_and_sub_16: - return EmitBinaryAtomic(*this, Intrinsic::atomic_load_sub, E); + return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::Sub, E); case Builtin::BI__sync_fetch_and_or_1: case Builtin::BI__sync_fetch_and_or_2: case Builtin::BI__sync_fetch_and_or_4: case Builtin::BI__sync_fetch_and_or_8: case Builtin::BI__sync_fetch_and_or_16: - return EmitBinaryAtomic(*this, Intrinsic::atomic_load_or, E); + return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::Or, E); case Builtin::BI__sync_fetch_and_and_1: case Builtin::BI__sync_fetch_and_and_2: case Builtin::BI__sync_fetch_and_and_4: case Builtin::BI__sync_fetch_and_and_8: case Builtin::BI__sync_fetch_and_and_16: - return EmitBinaryAtomic(*this, Intrinsic::atomic_load_and, E); + return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::And, E); case Builtin::BI__sync_fetch_and_xor_1: case Builtin::BI__sync_fetch_and_xor_2: case Builtin::BI__sync_fetch_and_xor_4: case Builtin::BI__sync_fetch_and_xor_8: case Builtin::BI__sync_fetch_and_xor_16: - return EmitBinaryAtomic(*this, Intrinsic::atomic_load_xor, E); + return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::Xor, E); // Clang extensions: not overloaded yet. case Builtin::BI__sync_fetch_and_min: - return EmitBinaryAtomic(*this, Intrinsic::atomic_load_min, E); + return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::Min, E); case Builtin::BI__sync_fetch_and_max: - return EmitBinaryAtomic(*this, Intrinsic::atomic_load_max, E); + return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::Max, E); case Builtin::BI__sync_fetch_and_umin: - return EmitBinaryAtomic(*this, Intrinsic::atomic_load_umin, E); + return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::UMin, E); case Builtin::BI__sync_fetch_and_umax: - return EmitBinaryAtomic(*this, Intrinsic::atomic_load_umax, E); + return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::UMax, E); case Builtin::BI__sync_add_and_fetch_1: case Builtin::BI__sync_add_and_fetch_2: case Builtin::BI__sync_add_and_fetch_4: case Builtin::BI__sync_add_and_fetch_8: case Builtin::BI__sync_add_and_fetch_16: - return EmitBinaryAtomicPost(*this, Intrinsic::atomic_load_add, E, + return EmitBinaryAtomicPost(*this, llvm::AtomicRMWInst::Add, E, llvm::Instruction::Add); case Builtin::BI__sync_sub_and_fetch_1: case Builtin::BI__sync_sub_and_fetch_2: case Builtin::BI__sync_sub_and_fetch_4: case Builtin::BI__sync_sub_and_fetch_8: case Builtin::BI__sync_sub_and_fetch_16: - return EmitBinaryAtomicPost(*this, Intrinsic::atomic_load_sub, E, + return EmitBinaryAtomicPost(*this, llvm::AtomicRMWInst::Sub, E, llvm::Instruction::Sub); case Builtin::BI__sync_and_and_fetch_1: case Builtin::BI__sync_and_and_fetch_2: case Builtin::BI__sync_and_and_fetch_4: case Builtin::BI__sync_and_and_fetch_8: case Builtin::BI__sync_and_and_fetch_16: - return EmitBinaryAtomicPost(*this, Intrinsic::atomic_load_and, E, + return EmitBinaryAtomicPost(*this, llvm::AtomicRMWInst::And, E, llvm::Instruction::And); case Builtin::BI__sync_or_and_fetch_1: case Builtin::BI__sync_or_and_fetch_2: case Builtin::BI__sync_or_and_fetch_4: case Builtin::BI__sync_or_and_fetch_8: case Builtin::BI__sync_or_and_fetch_16: - return EmitBinaryAtomicPost(*this, Intrinsic::atomic_load_or, E, + return EmitBinaryAtomicPost(*this, llvm::AtomicRMWInst::Or, E, llvm::Instruction::Or); case Builtin::BI__sync_xor_and_fetch_1: case Builtin::BI__sync_xor_and_fetch_2: case Builtin::BI__sync_xor_and_fetch_4: case Builtin::BI__sync_xor_and_fetch_8: case Builtin::BI__sync_xor_and_fetch_16: - return EmitBinaryAtomicPost(*this, Intrinsic::atomic_load_xor, E, + return EmitBinaryAtomicPost(*this, llvm::AtomicRMWInst::Xor, E, llvm::Instruction::Xor); case Builtin::BI__sync_val_compare_and_swap_1: @@ -866,9 +837,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, llvm::IntegerType::get(getLLVMContext(), getContext().getTypeSize(T)); llvm::Type *IntPtrType = IntType->getPointerTo(AddrSpace); - llvm::Type *IntrinsicTypes[2] = { IntType, IntPtrType }; - Value *AtomF = CGM.getIntrinsic(Intrinsic::atomic_cmp_swap, - IntrinsicTypes); Value *Args[3]; Args[0] = Builder.CreateBitCast(DestPtr, IntPtrType); @@ -877,7 +845,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, Args[1] = EmitToInt(*this, Args[1], T, IntType); Args[2] = EmitToInt(*this, EmitScalarExpr(E->getArg(2)), T, IntType); - Value *Result = EmitCallWithBarrier(*this, AtomF, Args); + Value *Result = Builder.CreateAtomicCmpXchg(Args[0], Args[1], Args[2], + llvm::SequentiallyConsistent); Result = EmitFromInt(*this, Result, T, ValueType); return RValue::get(Result); } @@ -896,9 +865,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, llvm::IntegerType::get(getLLVMContext(), getContext().getTypeSize(T)); llvm::Type *IntPtrType = IntType->getPointerTo(AddrSpace); - llvm::Type *IntrinsicTypes[2] = { IntType, IntPtrType }; - Value *AtomF = CGM.getIntrinsic(Intrinsic::atomic_cmp_swap, - IntrinsicTypes); Value *Args[3]; Args[0] = Builder.CreateBitCast(DestPtr, IntPtrType); @@ -906,7 +872,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, Args[2] = EmitToInt(*this, EmitScalarExpr(E->getArg(2)), T, IntType); Value *OldVal = Args[1]; - Value *PrevVal = EmitCallWithBarrier(*this, AtomF, Args); + Value *PrevVal = Builder.CreateAtomicCmpXchg(Args[0], Args[1], Args[2], + llvm::SequentiallyConsistent); Value *Result = Builder.CreateICmpEQ(PrevVal, OldVal); // zext bool to int. Result = Builder.CreateZExt(Result, ConvertType(E->getType())); @@ -918,14 +885,14 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, case Builtin::BI__sync_swap_4: case Builtin::BI__sync_swap_8: case Builtin::BI__sync_swap_16: - return EmitBinaryAtomic(*this, Intrinsic::atomic_swap, E); + return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::Xchg, E); case Builtin::BI__sync_lock_test_and_set_1: case Builtin::BI__sync_lock_test_and_set_2: case Builtin::BI__sync_lock_test_and_set_4: case Builtin::BI__sync_lock_test_and_set_8: case Builtin::BI__sync_lock_test_and_set_16: - return EmitBinaryAtomic(*this, Intrinsic::atomic_swap, E); + return EmitBinaryAtomic(*this, llvm::AtomicRMWInst::Xchg, E); case Builtin::BI__sync_lock_release_1: case Builtin::BI__sync_lock_release_2: @@ -937,13 +904,21 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, cast(Ptr->getType())->getElementType(); llvm::StoreInst *Store = Builder.CreateStore(llvm::Constant::getNullValue(ElTy), Ptr); + // FIXME: This is completely, utterly wrong; it only even sort-of works + // on x86. Store->setVolatile(true); return RValue::get(0); } case Builtin::BI__sync_synchronize: { - // We assume like gcc appears to, that this only applies to cached memory. - EmitMemoryBarrier(*this, true, true, true, true, false); + // We assume this is supposed to correspond to a C++0x-style + // sequentially-consistent fence (i.e. this is only usable for + // synchonization, not device I/O or anything like that). This intrinsic + // is really badly designed in the sense that in theory, there isn't + // any way to safely use it... but in practice, it mostly works + // to use it with non-atomic loads and stores to get acquire/release + // semantics. + Builder.CreateFence(llvm::SequentiallyConsistent); return RValue::get(0); } diff --git a/test/CodeGen/2008-03-05-syncPtr.c b/test/CodeGen/2008-03-05-syncPtr.c index 3cabcfef19..784295ce68 100644 --- a/test/CodeGen/2008-03-05-syncPtr.c +++ b/test/CodeGen/2008-03-05-syncPtr.c @@ -1,27 +1,40 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - | grep llvm.atomic -// XFAIL: sparc-sun-solaris2|arm -// Feature currently implemented only for x86, alpha, powerpc. +// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s int* foo(int** a, int* b, int* c) { return __sync_val_compare_and_swap (a, b, c); } +// CHECK: define i32* @foo +// CHECK: cmpxchg int foo2(int** a, int* b, int* c) { return __sync_bool_compare_and_swap (a, b, c); } +// CHECK: define i32 @foo2 +// CHECK: cmpxchg int* foo3(int** a, int b) { return __sync_fetch_and_add (a, b); } +// CHECK: define i32* @foo3 +// CHECK: atomicrmw add + int* foo4(int** a, int b) { return __sync_fetch_and_sub (a, b); } +// CHECK: define i32* @foo4 +// CHECK: atomicrmw sub + int* foo5(int** a, int* b) { return __sync_lock_test_and_set (a, b); } +// CHECK: define i32* @foo5 +// CHECK: atomicrmw xchg + int* foo6(int** a, int*** b) { return __sync_lock_test_and_set (a, b); } +// CHECK: define i32* @foo6 +// CHECK: atomicrmw xchg diff --git a/test/CodeGen/2010-01-13-MemBarrier.c b/test/CodeGen/2010-01-13-MemBarrier.c index 32ad97ca46..c2b0acdab3 100644 --- a/test/CodeGen/2010-01-13-MemBarrier.c +++ b/test/CodeGen/2010-01-13-MemBarrier.c @@ -2,10 +2,10 @@ // XFAIL: sparc // rdar://7536390 -unsigned t(unsigned *ptr, unsigned val) { +typedef unsigned __INT32_TYPE__ uint32_t; + +unsigned t(uint32_t *ptr, uint32_t val) { // CHECK: @t - // CHECK: call void @llvm.memory.barrier - // CHECK-NEXT: call i32 @llvm.atomic.swap.i32 - // CHECK-NEXT: call void @llvm.memory.barrier + // CHECK: atomicrmw xchg i32* {{.*}} seq_cst return __sync_lock_test_and_set(ptr, val); } diff --git a/test/CodeGen/Atomics-no64bit.c b/test/CodeGen/Atomics-no64bit.c deleted file mode 100644 index b57b27a4d5..0000000000 --- a/test/CodeGen/Atomics-no64bit.c +++ /dev/null @@ -1,172 +0,0 @@ -// Test frontend handling of __sync builtins. -// Modified from a gcc testcase. -// RUN: %clang_cc1 -emit-llvm %s -o - | grep atomic | count 129 -// RUN: %clang_cc1 -emit-llvm %s -o - | grep p0i8 | count 43 -// RUN: %clang_cc1 -emit-llvm %s -o - | grep p0i16 | count 43 -// RUN: %clang_cc1 -emit-llvm %s -o - | grep p0i32 | count 43 -// RUN: %clang_cc1 -emit-llvm %s -o - | grep volatile | count 6 - -// Currently this is implemented only for Alpha, X86, PowerPC. -// Add your target here if it doesn't work. -// This version of the test does not include long long. -// XFAIL: sparc - -signed char sc; -unsigned char uc; -signed short ss; -unsigned short us; -signed int si; -unsigned int ui; - -void test_op_ignore (void) -{ - (void) __sync_fetch_and_add (&sc, 1); - (void) __sync_fetch_and_add (&uc, 1); - (void) __sync_fetch_and_add (&ss, 1); - (void) __sync_fetch_and_add (&us, 1); - (void) __sync_fetch_and_add (&si, 1); - (void) __sync_fetch_and_add (&ui, 1); - - (void) __sync_fetch_and_sub (&sc, 1); - (void) __sync_fetch_and_sub (&uc, 1); - (void) __sync_fetch_and_sub (&ss, 1); - (void) __sync_fetch_and_sub (&us, 1); - (void) __sync_fetch_and_sub (&si, 1); - (void) __sync_fetch_and_sub (&ui, 1); - - (void) __sync_fetch_and_or (&sc, 1); - (void) __sync_fetch_and_or (&uc, 1); - (void) __sync_fetch_and_or (&ss, 1); - (void) __sync_fetch_and_or (&us, 1); - (void) __sync_fetch_and_or (&si, 1); - (void) __sync_fetch_and_or (&ui, 1); - - (void) __sync_fetch_and_xor (&sc, 1); - (void) __sync_fetch_and_xor (&uc, 1); - (void) __sync_fetch_and_xor (&ss, 1); - (void) __sync_fetch_and_xor (&us, 1); - (void) __sync_fetch_and_xor (&si, 1); - (void) __sync_fetch_and_xor (&ui, 1); - - (void) __sync_fetch_and_and (&sc, 1); - (void) __sync_fetch_and_and (&uc, 1); - (void) __sync_fetch_and_and (&ss, 1); - (void) __sync_fetch_and_and (&us, 1); - (void) __sync_fetch_and_and (&si, 1); - (void) __sync_fetch_and_and (&ui, 1); - -} - -void test_fetch_and_op (void) -{ - sc = __sync_fetch_and_add (&sc, 11); - uc = __sync_fetch_and_add (&uc, 11); - ss = __sync_fetch_and_add (&ss, 11); - us = __sync_fetch_and_add (&us, 11); - si = __sync_fetch_and_add (&si, 11); - ui = __sync_fetch_and_add (&ui, 11); - - sc = __sync_fetch_and_sub (&sc, 11); - uc = __sync_fetch_and_sub (&uc, 11); - ss = __sync_fetch_and_sub (&ss, 11); - us = __sync_fetch_and_sub (&us, 11); - si = __sync_fetch_and_sub (&si, 11); - ui = __sync_fetch_and_sub (&ui, 11); - - sc = __sync_fetch_and_or (&sc, 11); - uc = __sync_fetch_and_or (&uc, 11); - ss = __sync_fetch_and_or (&ss, 11); - us = __sync_fetch_and_or (&us, 11); - si = __sync_fetch_and_or (&si, 11); - ui = __sync_fetch_and_or (&ui, 11); - - sc = __sync_fetch_and_xor (&sc, 11); - uc = __sync_fetch_and_xor (&uc, 11); - ss = __sync_fetch_and_xor (&ss, 11); - us = __sync_fetch_and_xor (&us, 11); - si = __sync_fetch_and_xor (&si, 11); - ui = __sync_fetch_and_xor (&ui, 11); - - sc = __sync_fetch_and_and (&sc, 11); - uc = __sync_fetch_and_and (&uc, 11); - ss = __sync_fetch_and_and (&ss, 11); - us = __sync_fetch_and_and (&us, 11); - si = __sync_fetch_and_and (&si, 11); - ui = __sync_fetch_and_and (&ui, 11); - -} - -void test_op_and_fetch (void) -{ - sc = __sync_add_and_fetch (&sc, uc); - uc = __sync_add_and_fetch (&uc, uc); - ss = __sync_add_and_fetch (&ss, uc); - us = __sync_add_and_fetch (&us, uc); - si = __sync_add_and_fetch (&si, uc); - ui = __sync_add_and_fetch (&ui, uc); - - sc = __sync_sub_and_fetch (&sc, uc); - uc = __sync_sub_and_fetch (&uc, uc); - ss = __sync_sub_and_fetch (&ss, uc); - us = __sync_sub_and_fetch (&us, uc); - si = __sync_sub_and_fetch (&si, uc); - ui = __sync_sub_and_fetch (&ui, uc); - - sc = __sync_or_and_fetch (&sc, uc); - uc = __sync_or_and_fetch (&uc, uc); - ss = __sync_or_and_fetch (&ss, uc); - us = __sync_or_and_fetch (&us, uc); - si = __sync_or_and_fetch (&si, uc); - ui = __sync_or_and_fetch (&ui, uc); - - sc = __sync_xor_and_fetch (&sc, uc); - uc = __sync_xor_and_fetch (&uc, uc); - ss = __sync_xor_and_fetch (&ss, uc); - us = __sync_xor_and_fetch (&us, uc); - si = __sync_xor_and_fetch (&si, uc); - ui = __sync_xor_and_fetch (&ui, uc); - - sc = __sync_and_and_fetch (&sc, uc); - uc = __sync_and_and_fetch (&uc, uc); - ss = __sync_and_and_fetch (&ss, uc); - us = __sync_and_and_fetch (&us, uc); - si = __sync_and_and_fetch (&si, uc); - ui = __sync_and_and_fetch (&ui, uc); - -} - -void test_compare_and_swap (void) -{ - sc = __sync_val_compare_and_swap (&sc, uc, sc); - uc = __sync_val_compare_and_swap (&uc, uc, sc); - ss = __sync_val_compare_and_swap (&ss, uc, sc); - us = __sync_val_compare_and_swap (&us, uc, sc); - si = __sync_val_compare_and_swap (&si, uc, sc); - ui = __sync_val_compare_and_swap (&ui, uc, sc); - - ui = __sync_bool_compare_and_swap (&sc, uc, sc); - ui = __sync_bool_compare_and_swap (&uc, uc, sc); - ui = __sync_bool_compare_and_swap (&ss, uc, sc); - ui = __sync_bool_compare_and_swap (&us, uc, sc); - ui = __sync_bool_compare_and_swap (&si, uc, sc); - ui = __sync_bool_compare_and_swap (&ui, uc, sc); -} - -void test_lock (void) -{ - sc = __sync_lock_test_and_set (&sc, 1); - uc = __sync_lock_test_and_set (&uc, 1); - ss = __sync_lock_test_and_set (&ss, 1); - us = __sync_lock_test_and_set (&us, 1); - si = __sync_lock_test_and_set (&si, 1); - ui = __sync_lock_test_and_set (&ui, 1); - - __sync_synchronize (); - - __sync_lock_release (&sc); - __sync_lock_release (&uc); - __sync_lock_release (&ss); - __sync_lock_release (&us); - __sync_lock_release (&si); - __sync_lock_release (&ui); -} diff --git a/test/CodeGen/Atomics.c b/test/CodeGen/Atomics.c index 36a82ae449..e5a5812f46 100644 --- a/test/CodeGen/Atomics.c +++ b/test/CodeGen/Atomics.c @@ -1,15 +1,6 @@ // Test frontend handling of __sync builtins. // Modified from a gcc testcase. -// RUN: %clang_cc1 -emit-llvm %s -o - | grep atomic | count 172 -// RUN: %clang_cc1 -emit-llvm %s -o - | grep p0i8 | count 43 -// RUN: %clang_cc1 -emit-llvm %s -o - | grep p0i16 | count 43 -// RUN: %clang_cc1 -emit-llvm %s -o - | grep p0i32 | count 43 -// RUN: %clang_cc1 -emit-llvm %s -o - | grep volatile | count 8 - -// Currently this is implemented only for Alpha, X86, PowerPC. -// Add your target here if it doesn't work. -// PPC32 does not translate the long long variants, so fails this test. -// XFAIL: sparc,powerpc +// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s signed char sc; unsigned char uc; @@ -20,193 +11,194 @@ unsigned int ui; signed long long sll; unsigned long long ull; -void test_op_ignore (void) +void test_op_ignore (void) // CHECK: define void @test_op_ignore { - (void) __sync_fetch_and_add (&sc, 1); - (void) __sync_fetch_and_add (&uc, 1); - (void) __sync_fetch_and_add (&ss, 1); - (void) __sync_fetch_and_add (&us, 1); - (void) __sync_fetch_and_add (&si, 1); - (void) __sync_fetch_and_add (&ui, 1); - (void) __sync_fetch_and_add (&sll, 1); - (void) __sync_fetch_and_add (&ull, 1); - - (void) __sync_fetch_and_sub (&sc, 1); - (void) __sync_fetch_and_sub (&uc, 1); - (void) __sync_fetch_and_sub (&ss, 1); - (void) __sync_fetch_and_sub (&us, 1); - (void) __sync_fetch_and_sub (&si, 1); - (void) __sync_fetch_and_sub (&ui, 1); - (void) __sync_fetch_and_sub (&sll, 1); - (void) __sync_fetch_and_sub (&ull, 1); - - (void) __sync_fetch_and_or (&sc, 1); - (void) __sync_fetch_and_or (&uc, 1); - (void) __sync_fetch_and_or (&ss, 1); - (void) __sync_fetch_and_or (&us, 1); - (void) __sync_fetch_and_or (&si, 1); - (void) __sync_fetch_and_or (&ui, 1); - (void) __sync_fetch_and_or (&sll, 1); - (void) __sync_fetch_and_or (&ull, 1); - - (void) __sync_fetch_and_xor (&sc, 1); - (void) __sync_fetch_and_xor (&uc, 1); - (void) __sync_fetch_and_xor (&ss, 1); - (void) __sync_fetch_and_xor (&us, 1); - (void) __sync_fetch_and_xor (&si, 1); - (void) __sync_fetch_and_xor (&ui, 1); - (void) __sync_fetch_and_xor (&sll, 1); - (void) __sync_fetch_and_xor (&ull, 1); - - (void) __sync_fetch_and_and (&sc, 1); - (void) __sync_fetch_and_and (&uc, 1); - (void) __sync_fetch_and_and (&ss, 1); - (void) __sync_fetch_and_and (&us, 1); - (void) __sync_fetch_and_and (&si, 1); - (void) __sync_fetch_and_and (&ui, 1); - (void) __sync_fetch_and_and (&sll, 1); - (void) __sync_fetch_and_and (&ull, 1); + (void) __sync_fetch_and_add (&sc, 1); // CHECK: atomicrmw add i8 + (void) __sync_fetch_and_add (&uc, 1); // CHECK: atomicrmw add i8 + (void) __sync_fetch_and_add (&ss, 1); // CHECK: atomicrmw add i16 + (void) __sync_fetch_and_add (&us, 1); // CHECK: atomicrmw add i16 + (void) __sync_fetch_and_add (&si, 1); // CHECK: atomicrmw add i32 + (void) __sync_fetch_and_add (&ui, 1); // CHECK: atomicrmw add i32 + (void) __sync_fetch_and_add (&sll, 1); // CHECK: atomicrmw add i64 + (void) __sync_fetch_and_add (&ull, 1); // CHECK: atomicrmw add i64 + + (void) __sync_fetch_and_sub (&sc, 1); // CHECK: atomicrmw sub i8 + (void) __sync_fetch_and_sub (&uc, 1); // CHECK: atomicrmw sub i8 + (void) __sync_fetch_and_sub (&ss, 1); // CHECK: atomicrmw sub i16 + (void) __sync_fetch_and_sub (&us, 1); // CHECK: atomicrmw sub i16 + (void) __sync_fetch_and_sub (&si, 1); // CHECK: atomicrmw sub i32 + (void) __sync_fetch_and_sub (&ui, 1); // CHECK: atomicrmw sub i32 + (void) __sync_fetch_and_sub (&sll, 1); // CHECK: atomicrmw sub i64 + (void) __sync_fetch_and_sub (&ull, 1); // CHECK: atomicrmw sub i64 + + (void) __sync_fetch_and_or (&sc, 1); // CHECK: atomicrmw or i8 + (void) __sync_fetch_and_or (&uc, 1); // CHECK: atomicrmw or i8 + (void) __sync_fetch_and_or (&ss, 1); // CHECK: atomicrmw or i16 + (void) __sync_fetch_and_or (&us, 1); // CHECK: atomicrmw or i16 + (void) __sync_fetch_and_or (&si, 1); // CHECK: atomicrmw or i32 + (void) __sync_fetch_and_or (&ui, 1); // CHECK: atomicrmw or i32 + (void) __sync_fetch_and_or (&sll, 1); // CHECK: atomicrmw or i64 + (void) __sync_fetch_and_or (&ull, 1); // CHECK: atomicrmw or i64 + + (void) __sync_fetch_and_xor (&sc, 1); // CHECK: atomicrmw xor i8 + (void) __sync_fetch_and_xor (&uc, 1); // CHECK: atomicrmw xor i8 + (void) __sync_fetch_and_xor (&ss, 1); // CHECK: atomicrmw xor i16 + (void) __sync_fetch_and_xor (&us, 1); // CHECK: atomicrmw xor i16 + (void) __sync_fetch_and_xor (&si, 1); // CHECK: atomicrmw xor i32 + (void) __sync_fetch_and_xor (&ui, 1); // CHECK: atomicrmw xor i32 + (void) __sync_fetch_and_xor (&sll, 1); // CHECK: atomicrmw xor i64 + (void) __sync_fetch_and_xor (&ull, 1); // CHECK: atomicrmw xor i64 + + (void) __sync_fetch_and_and (&sc, 1); // CHECK: atomicrmw and i8 + (void) __sync_fetch_and_and (&uc, 1); // CHECK: atomicrmw and i8 + (void) __sync_fetch_and_and (&ss, 1); // CHECK: atomicrmw and i16 + (void) __sync_fetch_and_and (&us, 1); // CHECK: atomicrmw and i16 + (void) __sync_fetch_and_and (&si, 1); // CHECK: atomicrmw and i32 + (void) __sync_fetch_and_and (&ui, 1); // CHECK: atomicrmw and i32 + (void) __sync_fetch_and_and (&sll, 1); // CHECK: atomicrmw and i64 + (void) __sync_fetch_and_and (&ull, 1); // CHECK: atomicrmw and i64 } -void test_fetch_and_op (void) +void test_fetch_and_op (void) // CHECK: define void @test_fetch_and_op { - sc = __sync_fetch_and_add (&sc, 11); - uc = __sync_fetch_and_add (&uc, 11); - ss = __sync_fetch_and_add (&ss, 11); - us = __sync_fetch_and_add (&us, 11); - si = __sync_fetch_and_add (&si, 11); - ui = __sync_fetch_and_add (&ui, 11); - sll = __sync_fetch_and_add (&sll, 11); - ull = __sync_fetch_and_add (&ull, 11); - - sc = __sync_fetch_and_sub (&sc, 11); - uc = __sync_fetch_and_sub (&uc, 11); - ss = __sync_fetch_and_sub (&ss, 11); - us = __sync_fetch_and_sub (&us, 11); - si = __sync_fetch_and_sub (&si, 11); - ui = __sync_fetch_and_sub (&ui, 11); - sll = __sync_fetch_and_sub (&sll, 11); - ull = __sync_fetch_and_sub (&ull, 11); - - sc = __sync_fetch_and_or (&sc, 11); - uc = __sync_fetch_and_or (&uc, 11); - ss = __sync_fetch_and_or (&ss, 11); - us = __sync_fetch_and_or (&us, 11); - si = __sync_fetch_and_or (&si, 11); - ui = __sync_fetch_and_or (&ui, 11); - sll = __sync_fetch_and_or (&sll, 11); - ull = __sync_fetch_and_or (&ull, 11); - - sc = __sync_fetch_and_xor (&sc, 11); - uc = __sync_fetch_and_xor (&uc, 11); - ss = __sync_fetch_and_xor (&ss, 11); - us = __sync_fetch_and_xor (&us, 11); - si = __sync_fetch_and_xor (&si, 11); - ui = __sync_fetch_and_xor (&ui, 11); - sll = __sync_fetch_and_xor (&sll, 11); - ull = __sync_fetch_and_xor (&ull, 11); - - sc = __sync_fetch_and_and (&sc, 11); - uc = __sync_fetch_and_and (&uc, 11); - ss = __sync_fetch_and_and (&ss, 11); - us = __sync_fetch_and_and (&us, 11); - si = __sync_fetch_and_and (&si, 11); - ui = __sync_fetch_and_and (&ui, 11); - sll = __sync_fetch_and_and (&sll, 11); - ull = __sync_fetch_and_and (&ull, 11); + sc = __sync_fetch_and_add (&sc, 11); // CHECK: atomicrmw add + uc = __sync_fetch_and_add (&uc, 11); // CHECK: atomicrmw add + ss = __sync_fetch_and_add (&ss, 11); // CHECK: atomicrmw add + us = __sync_fetch_and_add (&us, 11); // CHECK: atomicrmw add + si = __sync_fetch_and_add (&si, 11); // CHECK: atomicrmw add + ui = __sync_fetch_and_add (&ui, 11); // CHECK: atomicrmw add + sll = __sync_fetch_and_add (&sll, 11); // CHECK: atomicrmw add + ull = __sync_fetch_and_add (&ull, 11); // CHECK: atomicrmw add + + sc = __sync_fetch_and_sub (&sc, 11); // CHECK: atomicrmw sub + uc = __sync_fetch_and_sub (&uc, 11); // CHECK: atomicrmw sub + ss = __sync_fetch_and_sub (&ss, 11); // CHECK: atomicrmw sub + us = __sync_fetch_and_sub (&us, 11); // CHECK: atomicrmw sub + si = __sync_fetch_and_sub (&si, 11); // CHECK: atomicrmw sub + ui = __sync_fetch_and_sub (&ui, 11); // CHECK: atomicrmw sub + sll = __sync_fetch_and_sub (&sll, 11); // CHECK: atomicrmw sub + ull = __sync_fetch_and_sub (&ull, 11); // CHECK: atomicrmw sub + + sc = __sync_fetch_and_or (&sc, 11); // CHECK: atomicrmw or + uc = __sync_fetch_and_or (&uc, 11); // CHECK: atomicrmw or + ss = __sync_fetch_and_or (&ss, 11); // CHECK: atomicrmw or + us = __sync_fetch_and_or (&us, 11); // CHECK: atomicrmw or + si = __sync_fetch_and_or (&si, 11); // CHECK: atomicrmw or + ui = __sync_fetch_and_or (&ui, 11); // CHECK: atomicrmw or + sll = __sync_fetch_and_or (&sll, 11); // CHECK: atomicrmw or + ull = __sync_fetch_and_or (&ull, 11); // CHECK: atomicrmw or + + sc = __sync_fetch_and_xor (&sc, 11); // CHECK: atomicrmw xor + uc = __sync_fetch_and_xor (&uc, 11); // CHECK: atomicrmw xor + ss = __sync_fetch_and_xor (&ss, 11); // CHECK: atomicrmw xor + us = __sync_fetch_and_xor (&us, 11); // CHECK: atomicrmw xor + si = __sync_fetch_and_xor (&si, 11); // CHECK: atomicrmw xor + ui = __sync_fetch_and_xor (&ui, 11); // CHECK: atomicrmw xor + sll = __sync_fetch_and_xor (&sll, 11); // CHECK: atomicrmw xor + ull = __sync_fetch_and_xor (&ull, 11); // CHECK: atomicrmw xor + + sc = __sync_fetch_and_and (&sc, 11); // CHECK: atomicrmw and + uc = __sync_fetch_and_and (&uc, 11); // CHECK: atomicrmw and + ss = __sync_fetch_and_and (&ss, 11); // CHECK: atomicrmw and + us = __sync_fetch_and_and (&us, 11); // CHECK: atomicrmw and + si = __sync_fetch_and_and (&si, 11); // CHECK: atomicrmw and + ui = __sync_fetch_and_and (&ui, 11); // CHECK: atomicrmw and + sll = __sync_fetch_and_and (&sll, 11); // CHECK: atomicrmw and + ull = __sync_fetch_and_and (&ull, 11); // CHECK: atomicrmw and } void test_op_and_fetch (void) { - sc = __sync_add_and_fetch (&sc, uc); - uc = __sync_add_and_fetch (&uc, uc); - ss = __sync_add_and_fetch (&ss, uc); - us = __sync_add_and_fetch (&us, uc); - si = __sync_add_and_fetch (&si, uc); - ui = __sync_add_and_fetch (&ui, uc); - sll = __sync_add_and_fetch (&sll, uc); - ull = __sync_add_and_fetch (&ull, uc); - - sc = __sync_sub_and_fetch (&sc, uc); - uc = __sync_sub_and_fetch (&uc, uc); - ss = __sync_sub_and_fetch (&ss, uc); - us = __sync_sub_and_fetch (&us, uc); - si = __sync_sub_and_fetch (&si, uc); - ui = __sync_sub_and_fetch (&ui, uc); - sll = __sync_sub_and_fetch (&sll, uc); - ull = __sync_sub_and_fetch (&ull, uc); - - sc = __sync_or_and_fetch (&sc, uc); - uc = __sync_or_and_fetch (&uc, uc); - ss = __sync_or_and_fetch (&ss, uc); - us = __sync_or_and_fetch (&us, uc); - si = __sync_or_and_fetch (&si, uc); - ui = __sync_or_and_fetch (&ui, uc); - sll = __sync_or_and_fetch (&sll, uc); - ull = __sync_or_and_fetch (&ull, uc); - - sc = __sync_xor_and_fetch (&sc, uc); - uc = __sync_xor_and_fetch (&uc, uc); - ss = __sync_xor_and_fetch (&ss, uc); - us = __sync_xor_and_fetch (&us, uc); - si = __sync_xor_and_fetch (&si, uc); - ui = __sync_xor_and_fetch (&ui, uc); - sll = __sync_xor_and_fetch (&sll, uc); - ull = __sync_xor_and_fetch (&ull, uc); - - sc = __sync_and_and_fetch (&sc, uc); - uc = __sync_and_and_fetch (&uc, uc); - ss = __sync_and_and_fetch (&ss, uc); - us = __sync_and_and_fetch (&us, uc); - si = __sync_and_and_fetch (&si, uc); - ui = __sync_and_and_fetch (&ui, uc); - sll = __sync_and_and_fetch (&sll, uc); - ull = __sync_and_and_fetch (&ull, uc); + sc = __sync_add_and_fetch (&sc, uc); // CHECK: atomicrmw add + uc = __sync_add_and_fetch (&uc, uc); // CHECK: atomicrmw add + ss = __sync_add_and_fetch (&ss, uc); // CHECK: atomicrmw add + us = __sync_add_and_fetch (&us, uc); // CHECK: atomicrmw add + si = __sync_add_and_fetch (&si, uc); // CHECK: atomicrmw add + ui = __sync_add_and_fetch (&ui, uc); // CHECK: atomicrmw add + sll = __sync_add_and_fetch (&sll, uc); // CHECK: atomicrmw add + ull = __sync_add_and_fetch (&ull, uc); // CHECK: atomicrmw add + + sc = __sync_sub_and_fetch (&sc, uc); // CHECK: atomicrmw sub + uc = __sync_sub_and_fetch (&uc, uc); // CHECK: atomicrmw sub + ss = __sync_sub_and_fetch (&ss, uc); // CHECK: atomicrmw sub + us = __sync_sub_and_fetch (&us, uc); // CHECK: atomicrmw sub + si = __sync_sub_and_fetch (&si, uc); // CHECK: atomicrmw sub + ui = __sync_sub_and_fetch (&ui, uc); // CHECK: atomicrmw sub + sll = __sync_sub_and_fetch (&sll, uc); // CHECK: atomicrmw sub + ull = __sync_sub_and_fetch (&ull, uc); // CHECK: atomicrmw sub + + sc = __sync_or_and_fetch (&sc, uc); // CHECK: atomicrmw or + uc = __sync_or_and_fetch (&uc, uc); // CHECK: atomicrmw or + ss = __sync_or_and_fetch (&ss, uc); // CHECK: atomicrmw or + us = __sync_or_and_fetch (&us, uc); // CHECK: atomicrmw or + si = __sync_or_and_fetch (&si, uc); // CHECK: atomicrmw or + ui = __sync_or_and_fetch (&ui, uc); // CHECK: atomicrmw or + sll = __sync_or_and_fetch (&sll, uc); // CHECK: atomicrmw or + ull = __sync_or_and_fetch (&ull, uc); // CHECK: atomicrmw or + + sc = __sync_xor_and_fetch (&sc, uc); // CHECK: atomicrmw xor + uc = __sync_xor_and_fetch (&uc, uc); // CHECK: atomicrmw xor + ss = __sync_xor_and_fetch (&ss, uc); // CHECK: atomicrmw xor + us = __sync_xor_and_fetch (&us, uc); // CHECK: atomicrmw xor + si = __sync_xor_and_fetch (&si, uc); // CHECK: atomicrmw xor + ui = __sync_xor_and_fetch (&ui, uc); // CHECK: atomicrmw xor + sll = __sync_xor_and_fetch (&sll, uc); // CHECK: atomicrmw xor + ull = __sync_xor_and_fetch (&ull, uc); // CHECK: atomicrmw xor + + sc = __sync_and_and_fetch (&sc, uc); // CHECK: atomicrmw and + uc = __sync_and_and_fetch (&uc, uc); // CHECK: atomicrmw and + ss = __sync_and_and_fetch (&ss, uc); // CHECK: atomicrmw and + us = __sync_and_and_fetch (&us, uc); // CHECK: atomicrmw and + si = __sync_and_and_fetch (&si, uc); // CHECK: atomicrmw and + ui = __sync_and_and_fetch (&ui, uc); // CHECK: atomicrmw and + sll = __sync_and_and_fetch (&sll, uc); // CHECK: atomicrmw and + ull = __sync_and_and_fetch (&ull, uc); // CHECK: atomicrmw and } void test_compare_and_swap (void) { - sc = __sync_val_compare_and_swap (&sc, uc, sc); - uc = __sync_val_compare_and_swap (&uc, uc, sc); - ss = __sync_val_compare_and_swap (&ss, uc, sc); - us = __sync_val_compare_and_swap (&us, uc, sc); - si = __sync_val_compare_and_swap (&si, uc, sc); - ui = __sync_val_compare_and_swap (&ui, uc, sc); - sll = __sync_val_compare_and_swap (&sll, uc, sc); - ull = __sync_val_compare_and_swap (&ull, uc, sc); - - ui = __sync_bool_compare_and_swap (&sc, uc, sc); - ui = __sync_bool_compare_and_swap (&uc, uc, sc); - ui = __sync_bool_compare_and_swap (&ss, uc, sc); - ui = __sync_bool_compare_and_swap (&us, uc, sc); - ui = __sync_bool_compare_and_swap (&si, uc, sc); - ui = __sync_bool_compare_and_swap (&ui, uc, sc); - ui = __sync_bool_compare_and_swap (&sll, uc, sc); - ui = __sync_bool_compare_and_swap (&ull, uc, sc); + sc = __sync_val_compare_and_swap (&sc, uc, sc); // CHECK: cmpxchg i8 + uc = __sync_val_compare_and_swap (&uc, uc, sc); // CHECK: cmpxchg i8 + ss = __sync_val_compare_and_swap (&ss, uc, sc); // CHECK: cmpxchg i16 + us = __sync_val_compare_and_swap (&us, uc, sc); // CHECK: cmpxchg i16 + si = __sync_val_compare_and_swap (&si, uc, sc); // CHECK: cmpxchg i32 + ui = __sync_val_compare_and_swap (&ui, uc, sc); // CHECK: cmpxchg i32 + sll = __sync_val_compare_and_swap (&sll, uc, sc); // CHECK: cmpxchg i64 + ull = __sync_val_compare_and_swap (&ull, uc, sc); // CHECK: cmpxchg i64 + + ui = __sync_bool_compare_and_swap (&sc, uc, sc); // CHECK: cmpxchg + ui = __sync_bool_compare_and_swap (&uc, uc, sc); // CHECK: cmpxchg + ui = __sync_bool_compare_and_swap (&ss, uc, sc); // CHECK: cmpxchg + ui = __sync_bool_compare_and_swap (&us, uc, sc); // CHECK: cmpxchg + ui = __sync_bool_compare_and_swap (&si, uc, sc); // CHECK: cmpxchg + ui = __sync_bool_compare_and_swap (&ui, uc, sc); // CHECK: cmpxchg + ui = __sync_bool_compare_and_swap (&sll, uc, sc); // CHECK: cmpxchg + ui = __sync_bool_compare_and_swap (&ull, uc, sc); // CHECK: cmpxchg } void test_lock (void) { - sc = __sync_lock_test_and_set (&sc, 1); - uc = __sync_lock_test_and_set (&uc, 1); - ss = __sync_lock_test_and_set (&ss, 1); - us = __sync_lock_test_and_set (&us, 1); - si = __sync_lock_test_and_set (&si, 1); - ui = __sync_lock_test_and_set (&ui, 1); - sll = __sync_lock_test_and_set (&sll, 1); - ull = __sync_lock_test_and_set (&ull, 1); - - __sync_synchronize (); - - __sync_lock_release (&sc); - __sync_lock_release (&uc); - __sync_lock_release (&ss); - __sync_lock_release (&us); - __sync_lock_release (&si); - __sync_lock_release (&ui); - __sync_lock_release (&sll); - __sync_lock_release (&ull); + sc = __sync_lock_test_and_set (&sc, 1); // CHECK: atomicrmw xchg i8 + uc = __sync_lock_test_and_set (&uc, 1); // CHECK: atomicrmw xchg i8 + ss = __sync_lock_test_and_set (&ss, 1); // CHECK: atomicrmw xchg i16 + us = __sync_lock_test_and_set (&us, 1); // CHECK: atomicrmw xchg i16 + si = __sync_lock_test_and_set (&si, 1); // CHECK: atomicrmw xchg i32 + ui = __sync_lock_test_and_set (&ui, 1); // CHECK: atomicrmw xchg i32 + sll = __sync_lock_test_and_set (&sll, 1); // CHECK: atomicrmw xchg i64 + ull = __sync_lock_test_and_set (&ull, 1); // CHECK: atomicrmw xchg i64 + + __sync_synchronize (); // CHECK: fence seq_cst + + // FIXME: These are wrong! + __sync_lock_release (&sc); // CHECK: store volatile + __sync_lock_release (&uc); // CHECK: store volatile + __sync_lock_release (&ss); // CHECK: store volatile + __sync_lock_release (&us); // CHECK: store volatile + __sync_lock_release (&si); // CHECK: store volatile + __sync_lock_release (&ui); // CHECK: store volatile + __sync_lock_release (&sll); // CHECK: store volatile + __sync_lock_release (&ull); // CHECK: store volatile } diff --git a/test/CodeGen/atomic.c b/test/CodeGen/atomic.c index 97e12ebe8c..a0adac8e1c 100644 --- a/test/CodeGen/atomic.c +++ b/test/CodeGen/atomic.c @@ -10,118 +10,76 @@ int atomic(void) { int cmp = 0; old = __sync_fetch_and_add(&val, 1); - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) - // CHECK: call i32 @llvm.atomic.load.add.i32.p0i32(i32* %val, i32 1) - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) + // CHECK: atomicrmw add i32* %val, i32 1 seq_cst old = __sync_fetch_and_sub(&valc, 2); - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) - // CHECK: call i8 @llvm.atomic.load.sub.i8.p0i8(i8* %valc, i8 2) - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) + // CHECK: atomicrmw sub i8* %valc, i8 2 seq_cst old = __sync_fetch_and_min(&val, 3); - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) - // CHECK: call i32 @llvm.atomic.load.min.i32.p0i32(i32* %val, i32 3) - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) + // CHECK: atomicrmw min i32* %val, i32 3 seq_cst old = __sync_fetch_and_max(&val, 4); - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) - // CHECK: call i32 @llvm.atomic.load.max.i32.p0i32(i32* %val, i32 4) - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) + // CHECK: atomicrmw max i32* %val, i32 4 seq_cst old = __sync_fetch_and_umin(&uval, 5u); - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) - // CHECK: call i32 @llvm.atomic.load.umin.i32.p0i32(i32* %uval, i32 5) - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) + // CHECK: atomicrmw umin i32* %uval, i32 5 seq_cst old = __sync_fetch_and_umax(&uval, 6u); - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) - // CHECK: call i32 @llvm.atomic.load.umax.i32.p0i32(i32* %uval, i32 6) - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) + // CHECK: atomicrmw umax i32* %uval, i32 6 seq_cst old = __sync_lock_test_and_set(&val, 7); - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) - // CHECK: call i32 @llvm.atomic.swap.i32.p0i32(i32* %val, i32 7) - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) + // CHECK: atomicrmw xchg i32* %val, i32 7 seq_cst old = __sync_swap(&val, 8); - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) - // CHECK: call i32 @llvm.atomic.swap.i32.p0i32(i32* %val, i32 8) - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) + // CHECK: atomicrmw xchg i32* %val, i32 8 seq_cst old = __sync_val_compare_and_swap(&val, 4, 1976); - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) - // CHECK: call i32 @llvm.atomic.cmp.swap.i32.p0i32(i32* %val, i32 4, i32 1976) - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) + // CHECK: cmpxchg i32* %val, i32 4, i32 1976 seq_cst old = __sync_bool_compare_and_swap(&val, 4, 1976); - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) - // CHECK: call i32 @llvm.atomic.cmp.swap.i32.p0i32(i32* %val, i32 4, i32 1976) - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) + // CHECK: cmpxchg i32* %val, i32 4, i32 1976 seq_cst old = __sync_fetch_and_and(&val, 0x9); - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) - // CHECK: call i32 @llvm.atomic.load.and.i32.p0i32(i32* %val, i32 9) - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) + // CHECK: atomicrmw and i32* %val, i32 9 seq_cst old = __sync_fetch_and_or(&val, 0xa); - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) - // CHECK: call i32 @llvm.atomic.load.or.i32.p0i32(i32* %val, i32 10) - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) + // CHECK: atomicrmw or i32* %val, i32 10 seq_cst old = __sync_fetch_and_xor(&val, 0xb); - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) - // CHECK: call i32 @llvm.atomic.load.xor.i32.p0i32(i32* %val, i32 11) - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) + // CHECK: atomicrmw xor i32* %val, i32 11 seq_cst old = __sync_add_and_fetch(&val, 1); - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) - // CHECK: call i32 @llvm.atomic.load.add.i32.p0i32(i32* %val, i32 1) - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) + // CHECK: atomicrmw add i32* %val, i32 1 seq_cst old = __sync_sub_and_fetch(&val, 2); - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) - // CHECK: call i32 @llvm.atomic.load.sub.i32.p0i32(i32* %val, i32 2) - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) + // CHECK: atomicrmw sub i32* %val, i32 2 seq_cst old = __sync_and_and_fetch(&valc, 3); - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) - // CHECK: call i8 @llvm.atomic.load.and.i8.p0i8(i8* %valc, i8 3) - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) + // CHECK: atomicrmw and i8* %valc, i8 3 seq_cst old = __sync_or_and_fetch(&valc, 4); - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) - // CHECK: call i8 @llvm.atomic.load.or.i8.p0i8(i8* %valc, i8 4) - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) + // CHECK: atomicrmw or i8* %valc, i8 4 seq_cst old = __sync_xor_and_fetch(&valc, 5); - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) - // CHECK: call i8 @llvm.atomic.load.xor.i8.p0i8(i8* %valc, i8 5) - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) - + // CHECK: atomicrmw xor i8* %valc, i8 5 seq_cst __sync_val_compare_and_swap((void **)0, (void *)0, (void *)0); - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) - // CHECK: call i32 @llvm.atomic.cmp.swap.i32.p0i32(i32* null, i32 0, i32 0) - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) + // CHECK: cmpxchg i32* null, i32 0, i32 0 seq_cst if ( __sync_val_compare_and_swap(&valb, 0, 1)) { - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) - // CHECK: call i8 @llvm.atomic.cmp.swap.i8.p0i8(i8* %valb, i8 0, i8 1) - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) + // CHECK: cmpxchg i8* %valb, i8 0, i8 1 seq_cst old = 42; } __sync_bool_compare_and_swap((void **)0, (void *)0, (void *)0); - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) - // CHECK: call i32 @llvm.atomic.cmp.swap.i32.p0i32(i32* null, i32 0, i32 0) - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) + // CHECK: cmpxchg i32* null, i32 0, i32 0 seq_cst __sync_lock_release(&val); + // FIXME: WRONG! // CHECK: store volatile i32 0, i32* __sync_synchronize (); - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 false) + // CHECK: fence seq_cst return old; } @@ -130,6 +88,7 @@ int atomic(void) { void release_return(int *lock) { // Ensure this is actually returning void all the way through. return __sync_lock_release(lock); + // FIXME: WRONG! // CHECK: store volatile i32 0, i32* } @@ -138,21 +97,11 @@ void release_return(int *lock) { // CHECK: @addrspace void addrspace(int __attribute__((address_space(256))) * P) { __sync_bool_compare_and_swap(P, 0, 1); - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) - // CHECK: call i32 @llvm.atomic.cmp.swap.i32.p256i32(i32 addrspace(256)*{{.*}}, i32 0, i32 1) - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) - - + // CHECK: cmpxchg i32 addrspace(256)*{{.*}}, i32 0, i32 1 seq_cst + __sync_val_compare_and_swap(P, 0, 1); - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) - // CHECK: call i32 @llvm.atomic.cmp.swap.i32.p256i32(i32 addrspace(256)*{{.*}}, i32 0, i32 1) - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) - - + // CHECK: cmpxchg i32 addrspace(256)*{{.*}}, i32 0, i32 1 seq_cst + __sync_xor_and_fetch(P, 123); - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) - // CHECK: call i32 @llvm.atomic.load.xor.i32.p256i32(i32 addrspace(256)* {{.*}}, i32 123) - // CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) - + // CHECK: atomicrmw xor i32 addrspace(256)*{{.*}}, i32 123 seq_cst } - -- 2.50.1