llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Hui (huixie90)
<details>
<summary>Changes</summary>
- **[clang] allow fetch_{min,max} for atomic pointer types**
- **add sema and codegen test**
- **format**
---
Full diff: https://github.com/llvm/llvm-project/pull/182699.diff
3 Files Affected:
- (modified) clang/lib/Sema/SemaChecking.cpp (+7-2)
- (modified) clang/test/CodeGen/atomic-ops.c (+18-2)
- (modified) clang/test/Sema/atomic-ops.c (+8-3)
``````````diff
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 0ea41ff1f613e..ed93db68e8434 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -4589,6 +4589,9 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange,
SourceRange ExprRange,
// Bit mask for extra allowed value types other than integers for atomic
// arithmetic operations. Add/sub allow pointer and floating point. Min/max
// allow floating point.
+
+ bool TakesPointerDiffForAtomicPointer = false;
+
enum ArithOpExtraValueType {
AOEVT_None = 0,
AOEVT_Pointer = 1,
@@ -4640,6 +4643,7 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange,
SourceRange ExprRange,
case AtomicExpr::AO__hip_atomic_fetch_sub:
ArithAllows = AOEVT_Pointer | AOEVT_FP;
Form = Arithmetic;
+ TakesPointerDiffForAtomicPointer = true;
break;
case AtomicExpr::AO__atomic_fetch_max:
case AtomicExpr::AO__atomic_fetch_min:
@@ -4655,7 +4659,7 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange,
SourceRange ExprRange,
case AtomicExpr::AO__opencl_atomic_fetch_min:
case AtomicExpr::AO__hip_atomic_fetch_max:
case AtomicExpr::AO__hip_atomic_fetch_min:
- ArithAllows = AOEVT_FP;
+ ArithAllows = AOEVT_Pointer | AOEVT_FP;
Form = Arithmetic;
break;
case AtomicExpr::AO__c11_atomic_fetch_and:
@@ -4971,7 +4975,8 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange,
SourceRange ExprRange,
// passed by address. For the rest, GNU uses by-address and C11 uses
// by-value.
assert(Form != Load);
- if (Form == Arithmetic && ValType->isPointerType())
+ if (Form == Arithmetic && ValType->isPointerType() &&
+ TakesPointerDiffForAtomicPointer)
Ty = Context.getPointerDiffType();
else if (Form == Init || Form == Arithmetic)
Ty = ValType;
diff --git a/clang/test/CodeGen/atomic-ops.c b/clang/test/CodeGen/atomic-ops.c
index 97d3d3ba10065..cc1ecd817d932 100644
--- a/clang/test/CodeGen/atomic-ops.c
+++ b/clang/test/CodeGen/atomic-ops.c
@@ -720,7 +720,7 @@ void test_underaligned(void) {
__atomic_compare_exchange(&aligned_a, &aligned_b, &aligned_c, 1,
memory_order_seq_cst, memory_order_seq_cst);
}
-void test_c11_minmax(_Atomic(int) * si, _Atomic(unsigned) * ui, _Atomic(short)
* ss, _Atomic(unsigned char) * uc, _Atomic(long long) * sll) {
+void test_c11_minmax(_Atomic(int) * si, _Atomic(unsigned) * ui, _Atomic(short)
* ss, _Atomic(unsigned char) * uc, _Atomic(long long) * sll, _Atomic(int*) *
aip, int* ip) {
// CHECK-LABEL: @test_c11_minmax
// CHECK: atomicrmw max ptr {{.*}} acquire, align 4
@@ -747,9 +747,13 @@ void test_c11_minmax(_Atomic(int) * si, _Atomic(unsigned)
* ui, _Atomic(short) *
// CHECK: atomicrmw min ptr {{.*}} acquire, align 8
*sll = __c11_atomic_fetch_min(sll, 42, memory_order_acquire);
+ // CHECK: atomicrmw umax ptr {{.*}} acquire, align 4
+ __c11_atomic_fetch_max(aip, ip, memory_order_acquire);
+ // CHECK: atomicrmw umin ptr {{.*}} acquire, align 4
+ __c11_atomic_fetch_min(aip, ip, memory_order_acquire);
}
-void test_minmax_postop(int *si, unsigned *ui, unsigned short *us, signed char
*sc, unsigned long long *ull) {
+void test_minmax_postop(int *si, unsigned *ui, unsigned short *us, signed char
*sc, unsigned long long *ull, int **ip) {
int val = 42;
// CHECK-LABEL: @test_minmax_postop
@@ -795,6 +799,18 @@ void test_minmax_postop(int *si, unsigned *ui, unsigned
short *us, signed char *
// CHECK: store i64 [[NEW]], ptr
*ull = __atomic_min_fetch(ull, 42, memory_order_release);
+ // CHECK: [[OLD:%.*]] = atomicrmw umax ptr [[PTR:%.*]], i32 [[RHS:%.*]]
release, align 4
+ // CHECK: [[TST:%.*]] = icmp ugt i32 [[OLD]], [[RHS]]
+ // CHECK: [[NEW:%.*]] = select i1 [[TST]], i32 [[OLD]], i32 [[RHS]]
+ // CHECK: store i32 [[NEW]], ptr
+ *ip = __atomic_max_fetch(ip, si, memory_order_release);
+
+ // CHECK: [[OLD:%.*]] = atomicrmw umin ptr [[PTR:%.*]], i32 [[RHS:%.*]]
release, align 4
+ // CHECK: [[TST:%.*]] = icmp ult i32 [[OLD]], [[RHS]]
+ // CHECK: [[NEW:%.*]] = select i1 [[TST]], i32 [[OLD]], i32 [[RHS]]
+ // CHECK: store i32 [[NEW]], ptr
+ *ip = __atomic_min_fetch(ip, si, memory_order_release);
+
}
#endif
diff --git a/clang/test/Sema/atomic-ops.c b/clang/test/Sema/atomic-ops.c
index 0e39777a0172c..4b0e8eac05ba5 100644
--- a/clang/test/Sema/atomic-ops.c
+++ b/clang/test/Sema/atomic-ops.c
@@ -225,12 +225,14 @@ void f(_Atomic(int) *i, const _Atomic(int) *ci,
__c11_atomic_fetch_add(d, 1.0, memory_order_seq_cst);
__c11_atomic_fetch_add(ld, 1.0, memory_order_seq_cst); // fp80-error {{must
be a pointer to atomic integer, pointer or supported floating point type}}
__c11_atomic_fetch_min(i, 1, memory_order_seq_cst);
- __c11_atomic_fetch_min(p, 1, memory_order_seq_cst); // expected-error {{must
be a pointer to atomic integer or supported floating point type}}
+ __c11_atomic_fetch_min(p, I, memory_order_seq_cst);
+ __c11_atomic_fetch_min(p, 1, memory_order_seq_cst); // expected-error
{{incompatible integer to pointer conversion passing 'int' to parameter of type
'int *'}}
__c11_atomic_fetch_min(f, 1.0f, memory_order_seq_cst);
__c11_atomic_fetch_min(d, 1.0, memory_order_seq_cst);
__c11_atomic_fetch_min(ld, 1.0, memory_order_seq_cst); // fp80-error {{must
be a pointer to atomic integer or supported floating point type}}
__c11_atomic_fetch_max(i, 1, memory_order_seq_cst);
- __c11_atomic_fetch_max(p, 1, memory_order_seq_cst); // expected-error {{must
be a pointer to atomic integer or supported floating point type}}
+ __c11_atomic_fetch_max(p, I, memory_order_seq_cst);
+ __c11_atomic_fetch_max(p, 1, memory_order_seq_cst); // expected-error
{{incompatible integer to pointer conversion passing 'int' to parameter of type
'int *'}}
__c11_atomic_fetch_max(f, 1.0f, memory_order_seq_cst);
__c11_atomic_fetch_max(d, 1.0, memory_order_seq_cst);
__c11_atomic_fetch_max(ld, 1.0, memory_order_seq_cst); // fp80-error {{must
be a pointer to atomic integer or supported floating point type}}
@@ -242,9 +244,12 @@ void f(_Atomic(int) *i, const _Atomic(int) *ci,
__atomic_fetch_sub(s1, 3, memory_order_seq_cst); // expected-error {{must be
a pointer to integer, pointer or supported floating point type}}
__atomic_fetch_min(F, 3, memory_order_seq_cst);
__atomic_fetch_min(D, 3, memory_order_seq_cst);
+ __atomic_fetch_min(P, I, memory_order_seq_cst);
+ __atomic_fetch_min(P, 3, memory_order_seq_cst); // expected-error
{{incompatible integer to pointer conversion passing 'int' to parameter of type
'int *'}}
__atomic_fetch_max(F, 3, memory_order_seq_cst);
__atomic_fetch_max(D, 3, memory_order_seq_cst);
- __atomic_fetch_max(P, 3, memory_order_seq_cst); // expected-error {{must be
a pointer to integer or supported floating point type}}
+ __atomic_fetch_max(P, I, memory_order_seq_cst);
+ __atomic_fetch_max(P, 3, memory_order_seq_cst); // expected-error
{{incompatible integer to pointer conversion passing 'int' to parameter of type
'int *'}}
__atomic_fetch_max(p, 3); // expected-error {{too few
arguments to function call, expected 3, have 2}}
__atomic_fetch_uinc(F, 1, memory_order_seq_cst); // expected-error {{address
argument to atomic operation must be a pointer to integer}}
``````````
</details>
https://github.com/llvm/llvm-project/pull/182699
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits