https://github.com/huixie90 updated https://github.com/llvm/llvm-project/pull/182699
>From 4fe6ea8161d3be9867f4158b057f305e48de934e Mon Sep 17 00:00:00 2001 From: Hui Xie <[email protected]> Date: Sat, 21 Feb 2026 19:24:11 +0000 Subject: [PATCH 1/5] [clang] allow fetch_{min,max} for atomic pointer types --- clang/lib/Sema/SemaChecking.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 0ea41ff1f613e..88f34419cb30f 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,7 @@ 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; >From 183638d68d5ac3799dd5bcfcace6ffb38fa39282 Mon Sep 17 00:00:00 2001 From: Hui Xie <[email protected]> Date: Sat, 21 Feb 2026 20:09:15 +0000 Subject: [PATCH 2/5] add sema and codegen test --- clang/test/CodeGen/atomic-ops.c | 20 ++++++++++++++++++-- clang/test/Sema/atomic-ops.c | 11 ++++++++--- 2 files changed, 26 insertions(+), 5 deletions(-) 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}} >From 8c3d432043c35302c35797ff5c0c83b69de679d3 Mon Sep 17 00:00:00 2001 From: Hui Xie <[email protected]> Date: Sat, 21 Feb 2026 20:11:25 +0000 Subject: [PATCH 3/5] format --- clang/lib/Sema/SemaChecking.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 88f34419cb30f..ed93db68e8434 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -4975,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() && TakesPointerDiffForAtomicPointer) + if (Form == Arithmetic && ValType->isPointerType() && + TakesPointerDiffForAtomicPointer) Ty = Context.getPointerDiffType(); else if (Form == Init || Form == Arithmetic) Ty = ValType; >From 9d8800f6ad985a44dd4b9ac6668aa9c4760e9952 Mon Sep 17 00:00:00 2001 From: Hui Xie <[email protected]> Date: Sat, 21 Feb 2026 21:05:03 +0000 Subject: [PATCH 4/5] update test --- clang/test/Sema/atomic-ops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/test/Sema/atomic-ops.c b/clang/test/Sema/atomic-ops.c index 4b0e8eac05ba5..33dafd6e3c870 100644 --- a/clang/test/Sema/atomic-ops.c +++ b/clang/test/Sema/atomic-ops.c @@ -229,13 +229,13 @@ void f(_Atomic(int) *i, const _Atomic(int) *ci, __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_min(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_max(i, 1, memory_order_seq_cst); __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}} + __c11_atomic_fetch_max(ld, 1.0, memory_order_seq_cst); // fp80-error {{must be a pointer to atomic integer, pointer or supported floating point type}} __atomic_fetch_add(i, 3, memory_order_seq_cst); // expected-error {{pointer to integer, pointer or supported floating point type}} __atomic_fetch_sub(I, 3, memory_order_seq_cst); >From 17579935a340ac5df1649adbe2d9f45d7375158d Mon Sep 17 00:00:00 2001 From: Hui Xie <[email protected]> Date: Sun, 22 Mar 2026 11:38:40 +0000 Subject: [PATCH 5/5] address review comments --- clang/test/CodeGen/atomic-ops.c | 147 ++++++++++++++++++++++++++++---- 1 file changed, 131 insertions(+), 16 deletions(-) diff --git a/clang/test/CodeGen/atomic-ops.c b/clang/test/CodeGen/atomic-ops.c index cc1ecd817d932..bfbbd1e09be28 100644 --- a/clang/test/CodeGen/atomic-ops.c +++ b/clang/test/CodeGen/atomic-ops.c @@ -721,36 +721,151 @@ void test_underaligned(void) { } 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 + // CHECK-LABEL: @test_c11_minmax( + // CHECK-SAME: ptr noundef [[SI_ARG:%.*]], ptr noundef [[UI_ARG:%.*]], ptr noundef [[SS_ARG:%.*]], ptr noundef [[UC_ARG:%.*]], ptr noundef [[SLL_ARG:%.*]], ptr noundef [[AIP_ARG:%.*]], ptr noundef [[IP_ARG:%.*]]) + + // CHECK: store ptr [[SI_ARG]], ptr [[SI_ADDR:%.*]], align 4 + // CHECK: store ptr [[UI_ARG]], ptr [[UI_ADDR:%.*]], align 4 + // CHECK: store ptr [[SS_ARG]], ptr [[SS_ADDR:%.*]], align 4 + // CHECK: store ptr [[UC_ARG]], ptr [[UC_ADDR:%.*]], align 4 + // CHECK: store ptr [[SLL_ARG]], ptr [[SLL_ADDR:%.*]], align 4 + // CHECK: store ptr [[AIP_ARG]], ptr [[AIP_ADDR:%.*]], align 4 + // CHECK: store ptr [[IP_ARG]], ptr [[IP_ADDR:%.*]], align 4 + + // CHECK: [[SI_LOC:%.*]] = load ptr, ptr [[SI_ADDR]], align 4 + // CHECK-NEXT: store i32 42, ptr {{.*}}, align 4 + // CHECK-NEXT: [[SI_RHS:%.*]] = load i32, ptr {{.*}}, align 4 + // CHECK-NEXT: [[SI_OLD:%.*]] = atomicrmw max ptr [[SI_LOC]], i32 [[SI_RHS]] acquire, align 4 + // CHECK-NEXT: store i32 [[SI_OLD]], ptr {{.*}}, align 4 + // CHECK-NEXT: [[SI_RES:%.*]] = load i32, ptr {{.*}}, align 4 + // CHECK-NEXT: [[SI_LOC2:%.*]] = load ptr, ptr [[SI_ADDR]], align 4 + // CHECK-NEXT: store atomic i32 [[SI_RES]], ptr [[SI_LOC2]] seq_cst, align 4 *si = __c11_atomic_fetch_max(si, 42, memory_order_acquire); - // CHECK: atomicrmw min ptr {{.*}} acquire, align 4 + // CHECK: [[SI_LOC3:%.*]] = load ptr, ptr [[SI_ADDR]], align 4 + // CHECK-NEXT: store i32 42, ptr {{.*}}, align 4 + // CHECK-NEXT: [[SI_RHS2:%.*]] = load i32, ptr {{.*}}, align 4 + // CHECK-NEXT: [[SI_OLD2:%.*]] = atomicrmw min ptr [[SI_LOC3]], i32 [[SI_RHS2]] acquire, align 4 + // CHECK-NEXT: store i32 [[SI_OLD2]], ptr {{.*}}, align 4 + // CHECK-NEXT: [[SI_RES2:%.*]] = load i32, ptr {{.*}}, align 4 + // CHECK-NEXT: [[SI_LOC4:%.*]] = load ptr, ptr [[SI_ADDR]], align 4 + // CHECK-NEXT: store atomic i32 [[SI_RES2]], ptr [[SI_LOC4]] seq_cst, align 4 *si = __c11_atomic_fetch_min(si, 42, memory_order_acquire); - // CHECK: atomicrmw umax ptr {{.*}} acquire, align 4 + + // CHECK: [[UI_LOC:%.*]] = load ptr, ptr [[UI_ADDR]], align 4 + // CHECK-NEXT: store i32 42, ptr {{.*}}, align 4 + // CHECK-NEXT: [[UI_RHS:%.*]] = load i32, ptr {{.*}}, align 4 + // CHECK-NEXT: [[UI_OLD:%.*]] = atomicrmw umax ptr [[UI_LOC]], i32 [[UI_RHS]] acquire, align 4 + // CHECK-NEXT: store i32 [[UI_OLD]], ptr {{.*}}, align 4 + // CHECK-NEXT: [[UI_RES:%.*]] = load i32, ptr {{.*}}, align 4 + // CHECK-NEXT: [[UI_LOC2:%.*]] = load ptr, ptr [[UI_ADDR]], align 4 + // CHECK-NEXT: store atomic i32 [[UI_RES]], ptr [[UI_LOC2]] seq_cst, align 4 *ui = __c11_atomic_fetch_max(ui, 42, memory_order_acquire); - // CHECK: atomicrmw umin ptr {{.*}} acquire, align 4 + // CHECK: [[UI_LOC3:%.*]] = load ptr, ptr [[UI_ADDR]], align 4 + // CHECK-NEXT: store i32 42, ptr {{.*}}, align 4 + // CHECK-NEXT: [[UI_RHS2:%.*]] = load i32, ptr {{.*}}, align 4 + // CHECK-NEXT: [[UI_OLD2:%.*]] = atomicrmw umin ptr [[UI_LOC3]], i32 [[UI_RHS2]] acquire, align 4 + // CHECK-NEXT: store i32 [[UI_OLD2]], ptr {{.*}}, align 4 + // CHECK-NEXT: [[UI_RES2:%.*]] = load i32, ptr {{.*}}, align 4 + // CHECK-NEXT: [[UI_LOC4:%.*]] = load ptr, ptr [[UI_ADDR]], align 4 + // CHECK-NEXT: store atomic i32 [[UI_RES2]], ptr [[UI_LOC4]] seq_cst, align 4 *ui = __c11_atomic_fetch_min(ui, 42, memory_order_acquire); - // CHECK: atomicrmw max ptr {{.*}} acquire, align 2 + // CHECK: [[SS_LOC:%.*]] = load ptr, ptr [[SS_ADDR]], align 4 + // CHECK-NEXT: store i16 42, ptr {{.*}}, align 2 + // CHECK-NEXT: [[SS_RHS:%.*]] = load i16, ptr {{.*}}, align 2 + // CHECK-NEXT: [[SS_OLD:%.*]] = atomicrmw max ptr [[SS_LOC]], i16 [[SS_RHS]] acquire, align 2 + // CHECK-NEXT: store i16 [[SS_OLD]], ptr {{.*}}, align 2 + // CHECK-NEXT: [[SS_RES:%.*]] = load i16, ptr {{.*}}, align 2 + // CHECK-NEXT: [[SS_LOC2:%.*]] = load ptr, ptr [[SS_ADDR]], align 4 + // CHECK-NEXT: store atomic i16 [[SS_RES]], ptr [[SS_LOC2]] seq_cst, align 2 *ss = __c11_atomic_fetch_max(ss, 42, memory_order_acquire); - // CHECK: atomicrmw min ptr {{.*}} acquire, align 2 + // CHECK: [[SS_LOC3:%.*]] = load ptr, ptr [[SS_ADDR]], align 4 + // CHECK-NEXT: store i16 42, ptr {{.*}}, align 2 + // CHECK-NEXT: [[SS_RHS2:%.*]] = load i16, ptr {{.*}}, align 2 + // CHECK-NEXT: [[SS_OLD2:%.*]] = atomicrmw min ptr [[SS_LOC3]], i16 [[SS_RHS2]] acquire, align 2 + // CHECK-NEXT: store i16 [[SS_OLD2]], ptr {{.*}}, align 2 + // CHECK-NEXT: [[SS_RES2:%.*]] = load i16, ptr {{.*}}, align 2 + // CHECK-NEXT: [[SS_LOC4:%.*]] = load ptr, ptr [[SS_ADDR]], align 4 + // CHECK-NEXT: store atomic i16 [[SS_RES2]], ptr [[SS_LOC4]] seq_cst, align 2 *ss = __c11_atomic_fetch_min(ss, 42, memory_order_acquire); - // CHECK: atomicrmw umax ptr {{.*}} acquire, align 1 + // CHECK: [[UC_LOC:%.*]] = load ptr, ptr [[UC_ADDR]], align 4 + // CHECK-NEXT: store i8 42, ptr {{.*}}, align 1 + // CHECK-NEXT: [[UC_RHS:%.*]] = load i8, ptr {{.*}}, align 1 + // CHECK-NEXT: [[UC_OLD:%.*]] = atomicrmw umax ptr [[UC_LOC]], i8 [[UC_RHS]] acquire, align 1 + // CHECK-NEXT: store i8 [[UC_OLD]], ptr {{.*}}, align 1 + // CHECK-NEXT: [[UC_RES:%.*]] = load i8, ptr {{.*}}, align 1 + // CHECK-NEXT: [[UC_LOC2:%.*]] = load ptr, ptr [[UC_ADDR]], align 4 + // CHECK-NEXT: store atomic i8 [[UC_RES]], ptr [[UC_LOC2]] seq_cst, align 1 *uc = __c11_atomic_fetch_max(uc, 42, memory_order_acquire); - // CHECK: atomicrmw umin ptr {{.*}} acquire, align 1 + // CHECK: [[UC_LOC3:%.*]] = load ptr, ptr [[UC_ADDR]], align 4 + // CHECK-NEXT: store i8 42, ptr {{.*}}, align 1 + // CHECK-NEXT: [[UC_RHS2:%.*]] = load i8, ptr {{.*}}, align 1 + // CHECK-NEXT: [[UC_OLD2:%.*]] = atomicrmw umin ptr [[UC_LOC3]], i8 [[UC_RHS2]] acquire, align 1 + // CHECK-NEXT: store i8 [[UC_OLD2]], ptr {{.*}}, align 1 + // CHECK-NEXT: [[UC_RES2:%.*]] = load i8, ptr {{.*}}, align 1 + // CHECK-NEXT: [[UC_LOC4:%.*]] = load ptr, ptr [[UC_ADDR]], align 4 + // CHECK-NEXT: store atomic i8 [[UC_RES2]], ptr [[UC_LOC4]] seq_cst, align 1 *uc = __c11_atomic_fetch_min(uc, 42, memory_order_acquire); - // CHECK: atomicrmw max ptr {{.*}} acquire, align 8 + // CHECK: [[SLL_LOC:%.*]] = load ptr, ptr [[SLL_ADDR]], align 4 + // CHECK-NEXT: store i64 42, ptr {{.*}}, align 4 + // CHECK-NEXT: [[SLL_RHS:%.*]] = load i64, ptr {{.*}}, align 4 + // CHECK-NEXT: [[SLL_OLD:%.*]] = atomicrmw max ptr [[SLL_LOC]], i64 [[SLL_RHS]] acquire, align 8 + // CHECK-NEXT: store i64 [[SLL_OLD]], ptr {{.*}}, align 8 + // CHECK-NEXT: [[SLL_RES:%.*]] = load i64, ptr {{.*}}, align 8 + // CHECK-NEXT: [[SLL_LOC2:%.*]] = load ptr, ptr [[SLL_ADDR]], align 4 + // CHECK-NEXT: store atomic i64 [[SLL_RES]], ptr [[SLL_LOC2]] seq_cst, align 8 *sll = __c11_atomic_fetch_max(sll, 42, memory_order_acquire); - // CHECK: atomicrmw min ptr {{.*}} acquire, align 8 + // CHECK: [[SLL_LOC3:%.*]] = load ptr, ptr [[SLL_ADDR]], align 4 + // CHECK-NEXT: store i64 42, ptr {{.*}}, align 4 + // CHECK-NEXT: [[SLL_RHS2:%.*]] = load i64, ptr {{.*}}, align 4 + // CHECK-NEXT: [[SLL_OLD2:%.*]] = atomicrmw min ptr [[SLL_LOC3]], i64 [[SLL_RHS2]] acquire, align 8 + // CHECK-NEXT: store i64 [[SLL_OLD2]], ptr {{.*}}, align 8 + // CHECK-NEXT: [[SLL_RES2:%.*]] = load i64, ptr {{.*}}, align 8 + // CHECK-NEXT: [[SLL_LOC4:%.*]] = load ptr, ptr [[SLL_ADDR]], align 4 + // CHECK-NEXT: store atomic i64 [[SLL_RES2]], ptr [[SLL_LOC4]] seq_cst, 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); + // CHECK: [[AIP_LOC:%.*]] = load ptr, ptr [[AIP_ADDR]], align 4 + // CHECK-NEXT: [[IP_LOAD:%.*]] = load ptr, ptr [[IP_ADDR]], align 4 + // CHECK-NEXT: store ptr [[IP_LOAD]], ptr {{.*}}, align 4 + // CHECK-NEXT: [[AIP_RHS:%.*]] = load i32, ptr {{.*}}, align 4 + // CHECK-NEXT: [[AIP_OLD:%.*]] = atomicrmw umax ptr [[AIP_LOC]], i32 [[AIP_RHS]] acquire, align 4 + // CHECK-NEXT: store i32 [[AIP_OLD]], ptr {{.*}}, align 4 + // CHECK-NEXT: [[AIP_RES:%.*]] = load ptr, ptr {{.*}}, align 4 + // CHECK-NEXT: [[AIP_LOC2:%.*]] = load ptr, ptr [[AIP_ADDR]], align 4 + // CHECK-NEXT: store atomic ptr [[AIP_RES]], ptr [[AIP_LOC2]] seq_cst, align 4 + *aip = __c11_atomic_fetch_max(aip, ip, memory_order_acquire); + // CHECK: [[AIP_LOC3:%.*]] = load ptr, ptr [[AIP_ADDR]], align 4 + // CHECK-NEXT: [[IP_LOAD2:%.*]] = load ptr, ptr [[IP_ADDR]], align 4 + // CHECK-NEXT: store ptr [[IP_LOAD2]], ptr {{.*}}, align 4 + // CHECK-NEXT: [[AIP_RHS2:%.*]] = load i32, ptr {{.*}}, align 4 + // CHECK-NEXT: [[AIP_OLD2:%.*]] = atomicrmw umin ptr [[AIP_LOC3]], i32 [[AIP_RHS2]] acquire, align 4 + // CHECK-NEXT: store i32 [[AIP_OLD2]], ptr {{.*}}, align 4 + // CHECK-NEXT: [[AIP_RES2:%.*]] = load ptr, ptr {{.*}}, align 4 + // CHECK-NEXT: [[AIP_LOC4:%.*]] = load ptr, ptr [[AIP_ADDR]], align 4 + // CHECK-NEXT: store atomic ptr [[AIP_RES2]], ptr [[AIP_LOC4]] seq_cst, align 4 + *aip = __c11_atomic_fetch_min(aip, ip, memory_order_acquire); + + // CHECK: [[AIP_N1:%.*]] = load ptr, ptr [[AIP_ADDR]], align 4 + // CHECK-NEXT: store ptr null, ptr {{.*}}, align 4 + // CHECK-NEXT: [[AIP_N1_RHS:%.*]] = load i32, ptr {{.*}}, align 4 + // CHECK-NEXT: [[AIP_N1_OLD:%.*]] = atomicrmw umax ptr [[AIP_N1]], i32 [[AIP_N1_RHS]] acquire, align 4 + // CHECK-NEXT: store i32 [[AIP_N1_OLD]], ptr {{.*}}, align 4 + // CHECK-NEXT: [[AIP_N1_RES:%.*]] = load ptr, ptr {{.*}}, align 4 + // CHECK-NEXT: [[AIP_N1_DST:%.*]] = load ptr, ptr [[AIP_ADDR]], align 4 + // CHECK-NEXT: store atomic ptr [[AIP_N1_RES]], ptr [[AIP_N1_DST]] seq_cst, align 4 + *aip = __c11_atomic_fetch_max(aip, NULL, memory_order_acquire); + // CHECK: [[AIP_N2:%.*]] = load ptr, ptr [[AIP_ADDR]], align 4 + // CHECK-NEXT: store ptr null, ptr {{.*}}, align 4 + // CHECK-NEXT: [[AIP_N2_RHS:%.*]] = load i32, ptr {{.*}}, align 4 + // CHECK-NEXT: [[AIP_N2_OLD:%.*]] = atomicrmw umin ptr [[AIP_N2]], i32 [[AIP_N2_RHS]] acquire, align 4 + // CHECK-NEXT: store i32 [[AIP_N2_OLD]], ptr {{.*}}, align 4 + // CHECK-NEXT: [[AIP_N2_RES:%.*]] = load ptr, ptr {{.*}}, align 4 + // CHECK-NEXT: [[AIP_N2_DST:%.*]] = load ptr, ptr [[AIP_ADDR]], align 4 + // CHECK-NEXT: store atomic ptr [[AIP_N2_RES]], ptr [[AIP_N2_DST]] seq_cst, align 4 + *aip = __c11_atomic_fetch_min(aip, NULL, memory_order_acquire); } void test_minmax_postop(int *si, unsigned *ui, unsigned short *us, signed char *sc, unsigned long long *ull, int **ip) { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
