Author: delena Date: Sun May 13 00:45:58 2018 New Revision: 332193 URL: http://llvm.org/viewvc/llvm-project?rev=332193&view=rev Log: Added atomic_fetch_min, max, umin, umax intrinsics to clang.
These intrinsics work exactly as all other atomic_fetch_* intrinsics and allow to create *atomicrmw* with ordering. Updated the clang-extensions document. Differential Revision: https://reviews.llvm.org/D46386 Modified: cfe/trunk/docs/LanguageExtensions.rst cfe/trunk/include/clang/Basic/Builtins.def cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/lib/AST/Expr.cpp cfe/trunk/lib/CodeGen/CGAtomic.cpp cfe/trunk/lib/Sema/SemaChecking.cpp cfe/trunk/test/CodeGen/Atomics.c cfe/trunk/test/Sema/atomic-ops.c Modified: cfe/trunk/docs/LanguageExtensions.rst URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LanguageExtensions.rst?rev=332193&r1=332192&r2=332193&view=diff ============================================================================== --- cfe/trunk/docs/LanguageExtensions.rst (original) +++ cfe/trunk/docs/LanguageExtensions.rst Sun May 13 00:45:58 2018 @@ -1975,6 +1975,32 @@ is disallowed in general). Support for constant expression evaluation for the above builtins be detected with ``__has_feature(cxx_constexpr_string_builtins)``. +Atomic Min/Max builtins with memory ordering +-------------------------------------------- + +There are two atomic builtins with min/max in-memory comparison and swap. +The syntax and semantics are similar to GCC-compatible __atomic_* builtins. + +* ``__atomic_fetch_min`` +* ``__atomic_fetch_max`` + +The builtins work with signed and unsigned integers and require to specify memory ordering. +The return value is the original value that was stored in memory before comparison. + +Example: + +.. code-block:: c + + unsigned int val = __atomic_fetch_min(unsigned int *pi, unsigned int ui, __ATOMIC_RELAXED); + +The third argument is one of the memory ordering specifiers ``__ATOMIC_RELAXED``, +``__ATOMIC_CONSUME``, ``__ATOMIC_ACQUIRE``, ``__ATOMIC_RELEASE``, +``__ATOMIC_ACQ_REL``, or ``__ATOMIC_SEQ_CST`` following C++11 memory model semantics. + +In terms or aquire-release ordering barriers these two operations are always +considered as operations with *load-store* semantics, even when the original value +is not actually modified after comparison. + .. _langext-__c11_atomic: __c11_atomic builtins @@ -2734,4 +2760,3 @@ Specifying Linker Options on ELF Targets The ``#pragma comment(lib, ...)`` directive is supported on all ELF targets. The second parameter is the library name (without the traditional Unix prefix of ``lib``). This allows you to provide an implicit link of dependent libraries. - Modified: cfe/trunk/include/clang/Basic/Builtins.def URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Builtins.def?rev=332193&r1=332192&r2=332193&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/Builtins.def (original) +++ cfe/trunk/include/clang/Basic/Builtins.def Sun May 13 00:45:58 2018 @@ -721,6 +721,10 @@ ATOMIC_BUILTIN(__opencl_atomic_fetch_xor ATOMIC_BUILTIN(__opencl_atomic_fetch_min, "v.", "t") ATOMIC_BUILTIN(__opencl_atomic_fetch_max, "v.", "t") +// GCC does not support these, they are a Clang extension. +ATOMIC_BUILTIN(__atomic_fetch_min, "iiD*i.", "t") +ATOMIC_BUILTIN(__atomic_fetch_max, "v.", "t") + #undef ATOMIC_BUILTIN // Non-overloaded atomic builtins. Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=332193&r1=332192&r2=332193&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sun May 13 00:45:58 2018 @@ -7127,6 +7127,8 @@ def err_atomic_op_needs_trivial_copy : E def err_atomic_op_needs_atomic_int_or_ptr : Error< "address argument to atomic operation must be a pointer to %select{|atomic }0" "integer or pointer (%1 invalid)">; +def err_atomic_op_needs_int32_or_ptr : Error< + "address argument to atomic operation must be a pointer to signed or unsigned 32-bit integer">; def err_atomic_op_bitwise_needs_atomic_int : Error< "address argument to bitwise atomic operation must be a pointer to " "%select{|atomic }0integer (%1 invalid)">; Modified: cfe/trunk/lib/AST/Expr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=332193&r1=332192&r2=332193&view=diff ============================================================================== --- cfe/trunk/lib/AST/Expr.cpp (original) +++ cfe/trunk/lib/AST/Expr.cpp Sun May 13 00:45:58 2018 @@ -4052,6 +4052,8 @@ unsigned AtomicExpr::getNumSubExprs(Atom case AO__atomic_or_fetch: case AO__atomic_xor_fetch: case AO__atomic_nand_fetch: + case AO__atomic_fetch_min: + case AO__atomic_fetch_max: return 3; case AO__opencl_atomic_store: Modified: cfe/trunk/lib/CodeGen/CGAtomic.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGAtomic.cpp?rev=332193&r1=332192&r2=332193&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGAtomic.cpp (original) +++ cfe/trunk/lib/CodeGen/CGAtomic.cpp Sun May 13 00:45:58 2018 @@ -591,11 +591,13 @@ static void EmitAtomicOp(CodeGenFunction break; case AtomicExpr::AO__opencl_atomic_fetch_min: + case AtomicExpr::AO__atomic_fetch_min: Op = E->getValueType()->isSignedIntegerType() ? llvm::AtomicRMWInst::Min : llvm::AtomicRMWInst::UMin; break; case AtomicExpr::AO__opencl_atomic_fetch_max: + case AtomicExpr::AO__atomic_fetch_max: Op = E->getValueType()->isSignedIntegerType() ? llvm::AtomicRMWInst::Max : llvm::AtomicRMWInst::UMax; break; @@ -859,6 +861,8 @@ RValue CodeGenFunction::EmitAtomicExpr(A case AtomicExpr::AO__atomic_or_fetch: case AtomicExpr::AO__atomic_xor_fetch: case AtomicExpr::AO__atomic_nand_fetch: + case AtomicExpr::AO__atomic_fetch_min: + case AtomicExpr::AO__atomic_fetch_max: Val1 = EmitValToTemp(*this, E->getVal1()); break; } @@ -913,6 +917,8 @@ RValue CodeGenFunction::EmitAtomicExpr(A case AtomicExpr::AO__atomic_or_fetch: case AtomicExpr::AO__atomic_sub_fetch: case AtomicExpr::AO__atomic_xor_fetch: + case AtomicExpr::AO__atomic_fetch_min: + case AtomicExpr::AO__atomic_fetch_max: // For these, only library calls for certain sizes exist. UseOptimizedLibcall = true; break; @@ -1095,6 +1101,7 @@ RValue CodeGenFunction::EmitAtomicExpr(A AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), MemTy, E->getExprLoc(), sizeChars); break; + case AtomicExpr::AO__atomic_fetch_min: case AtomicExpr::AO__opencl_atomic_fetch_min: LibCallName = E->getValueType()->isSignedIntegerType() ? "__atomic_fetch_min" @@ -1102,6 +1109,7 @@ RValue CodeGenFunction::EmitAtomicExpr(A AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), LoweredMemTy, E->getExprLoc(), sizeChars); break; + case AtomicExpr::AO__atomic_fetch_max: case AtomicExpr::AO__opencl_atomic_fetch_max: LibCallName = E->getValueType()->isSignedIntegerType() ? "__atomic_fetch_max" Modified: cfe/trunk/lib/Sema/SemaChecking.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=332193&r1=332192&r2=332193&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaChecking.cpp (original) +++ cfe/trunk/lib/Sema/SemaChecking.cpp Sun May 13 00:45:58 2018 @@ -3260,6 +3260,7 @@ ExprResult Sema::SemaAtomicOpsOverloaded Op == AtomicExpr::AO__atomic_exchange_n || Op == AtomicExpr::AO__atomic_compare_exchange_n; bool IsAddSub = false; + bool IsMinMax = false; switch (Op) { case AtomicExpr::AO__c11_atomic_init: @@ -3313,6 +3314,12 @@ ExprResult Sema::SemaAtomicOpsOverloaded Form = Arithmetic; break; + case AtomicExpr::AO__atomic_fetch_min: + case AtomicExpr::AO__atomic_fetch_max: + IsMinMax = true; + Form = Arithmetic; + break; + case AtomicExpr::AO__c11_atomic_exchange: case AtomicExpr::AO__opencl_atomic_exchange: case AtomicExpr::AO__atomic_exchange_n: @@ -3395,12 +3402,21 @@ ExprResult Sema::SemaAtomicOpsOverloaded // For an arithmetic operation, the implied arithmetic must be well-formed. if (Form == Arithmetic) { // gcc does not enforce these rules for GNU atomics, but we do so for sanity. - if (IsAddSub && !ValType->isIntegerType() && !ValType->isPointerType()) { + if (IsAddSub && !ValType->isIntegerType() + && !ValType->isPointerType()) { Diag(DRE->getLocStart(), diag::err_atomic_op_needs_atomic_int_or_ptr) << IsC11 << Ptr->getType() << Ptr->getSourceRange(); return ExprError(); } - if (!IsAddSub && !ValType->isIntegerType()) { + if (IsMinMax) { + const BuiltinType *BT = ValType->getAs<BuiltinType>(); + if (!BT || (BT->getKind() != BuiltinType::Int && + BT->getKind() != BuiltinType::UInt)) { + Diag(DRE->getLocStart(), diag::err_atomic_op_needs_int32_or_ptr); + return ExprError(); + } + } + if (!IsAddSub && !IsMinMax && !ValType->isIntegerType()) { Diag(DRE->getLocStart(), diag::err_atomic_op_bitwise_needs_atomic_int) << IsC11 << Ptr->getType() << Ptr->getSourceRange(); return ExprError(); Modified: cfe/trunk/test/CodeGen/Atomics.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/Atomics.c?rev=332193&r1=332192&r2=332193&view=diff ============================================================================== --- cfe/trunk/test/CodeGen/Atomics.c (original) +++ cfe/trunk/test/CodeGen/Atomics.c Sun May 13 00:45:58 2018 @@ -291,3 +291,10 @@ void test_lock (void) __sync_lock_release (&sll); // CHECK: store atomic {{.*}} release, align 8 __sync_lock_release (&ull); // CHECK: store atomic {{.*}} release, align 8 } + +void test_atomic(void) { + ui = __atomic_fetch_min(&ui, 5, __ATOMIC_RELAXED); // CHECK: atomicrmw umin {{.*}} monotonic + si = __atomic_fetch_min(&si, 5, __ATOMIC_SEQ_CST); // CHECK: atomicrmw min {{.*}} seq_cst + ui = __atomic_fetch_max(&ui, 5, __ATOMIC_ACQUIRE); // CHECK: atomicrmw umax {{.*}} acquire + si = __atomic_fetch_max(&si, 5, __ATOMIC_RELEASE); // CHECK: atomicrmw max {{.*}} release +} Modified: cfe/trunk/test/Sema/atomic-ops.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/atomic-ops.c?rev=332193&r1=332192&r2=332193&view=diff ============================================================================== --- cfe/trunk/test/Sema/atomic-ops.c (original) +++ cfe/trunk/test/Sema/atomic-ops.c Sun May 13 00:45:58 2018 @@ -173,6 +173,9 @@ void f(_Atomic(int) *i, const _Atomic(in __atomic_fetch_sub(P, 3, memory_order_seq_cst); __atomic_fetch_sub(D, 3, memory_order_seq_cst); // expected-error {{must be a pointer to integer or pointer}} __atomic_fetch_sub(s1, 3, memory_order_seq_cst); // expected-error {{must be a pointer to integer or pointer}} + __atomic_fetch_min(D, 3, memory_order_seq_cst); // expected-error {{must be a pointer to signed or unsigned 32-bit integer}} + __atomic_fetch_max(P, 3, memory_order_seq_cst); // expected-error {{must be a pointer to signed or unsigned 32-bit integer}} + __atomic_fetch_max(p, 3); // expected-error {{too few arguments to function call, expected 3, have 2}} __c11_atomic_fetch_and(i, 1, memory_order_seq_cst); __c11_atomic_fetch_and(p, 1, memory_order_seq_cst); // expected-error {{must be a pointer to atomic integer}} @@ -456,6 +459,20 @@ void memory_checks(_Atomic(int) *Ap, int (void)__atomic_fetch_nand(p, val, memory_order_acq_rel); (void)__atomic_fetch_nand(p, val, memory_order_seq_cst); + (void)__atomic_fetch_min(p, val, memory_order_relaxed); + (void)__atomic_fetch_min(p, val, memory_order_acquire); + (void)__atomic_fetch_min(p, val, memory_order_consume); + (void)__atomic_fetch_min(p, val, memory_order_release); + (void)__atomic_fetch_min(p, val, memory_order_acq_rel); + (void)__atomic_fetch_min(p, val, memory_order_seq_cst); + + (void)__atomic_fetch_max(p, val, memory_order_relaxed); + (void)__atomic_fetch_max(p, val, memory_order_acquire); + (void)__atomic_fetch_max(p, val, memory_order_consume); + (void)__atomic_fetch_max(p, val, memory_order_release); + (void)__atomic_fetch_max(p, val, memory_order_acq_rel); + (void)__atomic_fetch_max(p, val, memory_order_seq_cst); + (void)__atomic_and_fetch(p, val, memory_order_relaxed); (void)__atomic_and_fetch(p, val, memory_order_acquire); (void)__atomic_and_fetch(p, val, memory_order_consume); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits