delena created this revision.
delena added reviewers: igorb, t.p.northover, ABataev, jfb, rjmccall.
Herald added subscribers: cfe-commits, Anastasia.
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.
The similar set __sync_fetch_and_min* sets the sequentially-consistent
ordering.
We use them for OpenCL 1.2, which supports atomic operations with "relaxed"
ordering.
Repository:
rC Clang
https://reviews.llvm.org/D46386
Files:
include/clang/Basic/Builtins.def
lib/AST/Expr.cpp
lib/CodeGen/CGAtomic.cpp
lib/Sema/SemaChecking.cpp
test/Sema/atomic-ops.c
Index: test/Sema/atomic-ops.c
===================================================================
--- test/Sema/atomic-ops.c
+++ test/Sema/atomic-ops.c
@@ -173,6 +173,7 @@
__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 integer or pointer}}
__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 +457,34 @@
(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_fetch_umin(p, val, memory_order_relaxed);
+ (void)__atomic_fetch_umin(p, val, memory_order_acquire);
+ (void)__atomic_fetch_umin(p, val, memory_order_consume);
+ (void)__atomic_fetch_umin(p, val, memory_order_release);
+ (void)__atomic_fetch_umin(p, val, memory_order_acq_rel);
+ (void)__atomic_fetch_umin(p, val, memory_order_seq_cst);
+
+ (void)__atomic_fetch_umax(p, val, memory_order_relaxed);
+ (void)__atomic_fetch_umax(p, val, memory_order_acquire);
+ (void)__atomic_fetch_umax(p, val, memory_order_consume);
+ (void)__atomic_fetch_umax(p, val, memory_order_release);
+ (void)__atomic_fetch_umax(p, val, memory_order_acq_rel);
+ (void)__atomic_fetch_umax(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);
Index: lib/Sema/SemaChecking.cpp
===================================================================
--- lib/Sema/SemaChecking.cpp
+++ lib/Sema/SemaChecking.cpp
@@ -3037,6 +3037,7 @@
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:
@@ -3090,6 +3091,14 @@
Form = Arithmetic;
break;
+ case AtomicExpr::AO__atomic_fetch_min:
+ case AtomicExpr::AO__atomic_fetch_max:
+ case AtomicExpr::AO__atomic_fetch_umin:
+ case AtomicExpr::AO__atomic_fetch_umax:
+ IsMinMax = true;
+ Form = Arithmetic;
+ break;
+
case AtomicExpr::AO__c11_atomic_exchange:
case AtomicExpr::AO__opencl_atomic_exchange:
case AtomicExpr::AO__atomic_exchange_n:
@@ -3172,12 +3181,13 @@
// 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 || IsMinMax) && !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 (!IsAddSub && !IsMinMax && !ValType->isIntegerType()) {
Diag(DRE->getLocStart(), diag::err_atomic_op_bitwise_needs_atomic_int)
<< IsC11 << Ptr->getType() << Ptr->getSourceRange();
return ExprError();
Index: lib/CodeGen/CGAtomic.cpp
===================================================================
--- lib/CodeGen/CGAtomic.cpp
+++ lib/CodeGen/CGAtomic.cpp
@@ -633,6 +633,18 @@
case AtomicExpr::AO__atomic_fetch_nand:
Op = llvm::AtomicRMWInst::Nand;
break;
+ case AtomicExpr::AO__atomic_fetch_min:
+ Op = llvm::AtomicRMWInst::Min;
+ break;
+ case AtomicExpr::AO__atomic_fetch_max:
+ Op = llvm::AtomicRMWInst::Max;
+ break;
+ case AtomicExpr::AO__atomic_fetch_umin:
+ Op = llvm::AtomicRMWInst::UMin;
+ break;
+ case AtomicExpr::AO__atomic_fetch_umax:
+ Op = llvm::AtomicRMWInst::UMax;
+ break;
}
llvm::Value *LoadVal1 = CGF.Builder.CreateLoad(Val1);
@@ -859,6 +871,10 @@
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:
+ case AtomicExpr::AO__atomic_fetch_umin:
+ case AtomicExpr::AO__atomic_fetch_umax:
Val1 = EmitValToTemp(*this, E->getVal1());
break;
}
@@ -913,6 +929,10 @@
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:
+ case AtomicExpr::AO__atomic_fetch_umin:
+ case AtomicExpr::AO__atomic_fetch_umax:
// For these, only library calls for certain sizes exist.
UseOptimizedLibcall = true;
break;
@@ -1095,13 +1115,17 @@
AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),
MemTy, E->getExprLoc(), sizeChars);
break;
+ case AtomicExpr::AO__atomic_fetch_min:
+ case AtomicExpr::AO__atomic_fetch_umin:
case AtomicExpr::AO__opencl_atomic_fetch_min:
LibCallName = E->getValueType()->isSignedIntegerType()
? "__atomic_fetch_min"
: "__atomic_fetch_umin";
AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),
LoweredMemTy, E->getExprLoc(), sizeChars);
break;
+ case AtomicExpr::AO__atomic_fetch_max:
+ case AtomicExpr::AO__atomic_fetch_umax:
case AtomicExpr::AO__opencl_atomic_fetch_max:
LibCallName = E->getValueType()->isSignedIntegerType()
? "__atomic_fetch_max"
Index: lib/AST/Expr.cpp
===================================================================
--- lib/AST/Expr.cpp
+++ lib/AST/Expr.cpp
@@ -4051,6 +4051,10 @@
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:
+ case AO__atomic_fetch_umin:
+ case AO__atomic_fetch_umax:
return 3;
case AO__opencl_atomic_store:
Index: include/clang/Basic/Builtins.def
===================================================================
--- include/clang/Basic/Builtins.def
+++ include/clang/Basic/Builtins.def
@@ -721,6 +721,12 @@
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, "v.", "t")
+ATOMIC_BUILTIN(__atomic_fetch_max, "v.", "t")
+ATOMIC_BUILTIN(__atomic_fetch_umin, "v.", "t")
+ATOMIC_BUILTIN(__atomic_fetch_umax, "v.", "t")
+
#undef ATOMIC_BUILTIN
// Non-overloaded atomic builtins.
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits