https://github.com/huixie90 updated 
https://github.com/llvm/llvm-project/pull/182699

>From c964d8425faceae3c6bda9bb892df47f9ed57c05 Mon Sep 17 00:00:00 2001
From: Hui Xie <[email protected]>
Date: Sat, 21 Feb 2026 19:24:11 +0000
Subject: [PATCH 1/7] [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 406f03a17f7ebe..539216e3169799 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -5237,6 +5237,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,
@@ -5292,6 +5295,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_fminimum:
   case AtomicExpr::AO__atomic_fetch_fmaximum:
@@ -5318,7 +5322,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_Int | AOEVT_FP;
+    ArithAllows = AOEVT_Pointer | AOEVT_Int | AOEVT_FP;
     Form = Arithmetic;
     break;
   case AtomicExpr::AO__c11_atomic_fetch_and:
@@ -5641,7 +5645,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 a36c8f582fc3b44a9657e5a007b0715028a0cbff Mon Sep 17 00:00:00 2001
From: Hui Xie <[email protected]>
Date: Sat, 21 Feb 2026 20:09:15 +0000
Subject: [PATCH 2/7] 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 c2318c85129566..ddc165475986ec 100644
--- a/clang/test/CodeGen/atomic-ops.c
+++ b/clang/test/CodeGen/atomic-ops.c
@@ -736,7 +736,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
@@ -763,9 +763,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
 
@@ -811,6 +815,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 cebbc78ea22624..c70c2a382b60f2 100644
--- a/clang/test/Sema/atomic-ops.c
+++ b/clang/test/Sema/atomic-ops.c
@@ -243,12 +243,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}}
@@ -260,9 +262,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_fminimum(F, 3, memory_order_seq_cst);
   __atomic_fetch_fminimum(D, 3, memory_order_seq_cst);

>From 889b5544422dd32c00e7390f6e98707205193f77 Mon Sep 17 00:00:00 2001
From: Hui Xie <[email protected]>
Date: Sat, 21 Feb 2026 20:11:25 +0000
Subject: [PATCH 3/7] 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 539216e3169799..44fff2dbf23445 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -5645,7 +5645,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 1c6330aada1e5ebec500eef0f1880a36d4ac9d66 Mon Sep 17 00:00:00 2001
From: Hui Xie <[email protected]>
Date: Sat, 21 Feb 2026 21:05:03 +0000
Subject: [PATCH 4/7] 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 c70c2a382b60f2..1b27fa38cddc2f 100644
--- a/clang/test/Sema/atomic-ops.c
+++ b/clang/test/Sema/atomic-ops.c
@@ -247,13 +247,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 2524d99dfc5a9ff3a3e8d2b7f6e2abe04b040ff4 Mon Sep 17 00:00:00 2001
From: Hui Xie <[email protected]>
Date: Sun, 22 Mar 2026 11:38:40 +0000
Subject: [PATCH 5/7] 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 ddc165475986ec..58b3c3672d8e9f 100644
--- a/clang/test/CodeGen/atomic-ops.c
+++ b/clang/test/CodeGen/atomic-ops.c
@@ -737,36 +737,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) {

>From 2feb69ec867fcf544aa4ae93492aeecfae838104 Mon Sep 17 00:00:00 2001
From: Hui Xie <[email protected]>
Date: Mon, 23 Mar 2026 09:50:55 +0000
Subject: [PATCH 6/7] added c++ tests for c++ nullptr

---
 clang/test/CodeGenCXX/atomic-ops.cpp | 100 +++++++++++++++++++++++++++
 clang/test/SemaCXX/atomic-ops.cpp    |   8 +++
 2 files changed, 108 insertions(+)
 create mode 100644 clang/test/CodeGenCXX/atomic-ops.cpp

diff --git a/clang/test/CodeGenCXX/atomic-ops.cpp 
b/clang/test/CodeGenCXX/atomic-ops.cpp
new file mode 100644
index 00000000000000..d6e51df97f9612
--- /dev/null
+++ b/clang/test/CodeGenCXX/atomic-ops.cpp
@@ -0,0 +1,100 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py 
UTC_ARGS: --version 6
+// RUN: %clang_cc1 %s -emit-llvm -o - -triple=i686-apple-darwin9 | FileCheck %s
+
+namespace FetchMinMax {
+
+// CHECK-LABEL: define void 
@_ZN11FetchMinMax16test_c11_min_ptrEPU7_AtomicPiS0_(
+// CHECK-SAME: ptr noundef [[AIP:%.*]], ptr noundef [[IP:%.*]]) 
#[[ATTR0:[0-9]+]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[AIP_ADDR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:    [[IP_ADDR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:    [[DOTATOMICTMP:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:    [[ATOMIC_TEMP:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:    store ptr [[AIP]], ptr [[AIP_ADDR]], align 4
+// CHECK-NEXT:    store ptr [[IP]], ptr [[IP_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[AIP_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[IP_ADDR]], align 4
+// CHECK-NEXT:    store ptr [[TMP1]], ptr [[DOTATOMICTMP]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[DOTATOMICTMP]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = atomicrmw umin ptr [[TMP0]], i32 [[TMP2]] 
monotonic, align 4
+// CHECK-NEXT:    store i32 [[TMP3]], ptr [[ATOMIC_TEMP]], align 4
+// CHECK-NEXT:    [[TMP4:%.*]] = load ptr, ptr [[ATOMIC_TEMP]], align 4
+// CHECK-NEXT:    [[TMP5:%.*]] = load ptr, ptr [[AIP_ADDR]], align 4
+// CHECK-NEXT:    store atomic ptr [[TMP4]], ptr [[TMP5]] seq_cst, align 4
+// CHECK-NEXT:    ret void
+//
+void test_c11_min_ptr(_Atomic(int*) * aip, int* ip) {
+  *aip = __c11_atomic_fetch_min(aip, ip, 0);
+}
+
+// CHECK-LABEL: define void 
@_ZN11FetchMinMax16test_c11_max_ptrEPU7_AtomicPiS0_(
+// CHECK-SAME: ptr noundef [[AIP:%.*]], ptr noundef [[IP:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[AIP_ADDR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:    [[IP_ADDR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:    [[DOTATOMICTMP:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:    [[ATOMIC_TEMP:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:    store ptr [[AIP]], ptr [[AIP_ADDR]], align 4
+// CHECK-NEXT:    store ptr [[IP]], ptr [[IP_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[AIP_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[IP_ADDR]], align 4
+// CHECK-NEXT:    store ptr [[TMP1]], ptr [[DOTATOMICTMP]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[DOTATOMICTMP]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = atomicrmw umax ptr [[TMP0]], i32 [[TMP2]] 
monotonic, align 4
+// CHECK-NEXT:    store i32 [[TMP3]], ptr [[ATOMIC_TEMP]], align 4
+// CHECK-NEXT:    [[TMP4:%.*]] = load ptr, ptr [[ATOMIC_TEMP]], align 4
+// CHECK-NEXT:    [[TMP5:%.*]] = load ptr, ptr [[AIP_ADDR]], align 4
+// CHECK-NEXT:    store atomic ptr [[TMP4]], ptr [[TMP5]] seq_cst, align 4
+// CHECK-NEXT:    ret void
+//
+void test_c11_max_ptr(_Atomic(int*) * aip, int* ip) {
+  *aip = __c11_atomic_fetch_max(aip, ip, 0);
+}
+
+// CHECK-LABEL: define void 
@_ZN11FetchMinMax20test_c11_min_nullptrEPU7_AtomicPiS0_(
+// CHECK-SAME: ptr noundef [[AIP:%.*]], ptr noundef [[IP:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[AIP_ADDR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:    [[IP_ADDR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:    [[DOTATOMICTMP:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:    [[ATOMIC_TEMP:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:    store ptr [[AIP]], ptr [[AIP_ADDR]], align 4
+// CHECK-NEXT:    store ptr [[IP]], ptr [[IP_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[AIP_ADDR]], align 4
+// CHECK-NEXT:    store ptr null, ptr [[DOTATOMICTMP]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[DOTATOMICTMP]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = atomicrmw umin ptr [[TMP0]], i32 [[TMP1]] 
monotonic, align 4
+// CHECK-NEXT:    store i32 [[TMP2]], ptr [[ATOMIC_TEMP]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = load ptr, ptr [[ATOMIC_TEMP]], align 4
+// CHECK-NEXT:    [[TMP4:%.*]] = load ptr, ptr [[AIP_ADDR]], align 4
+// CHECK-NEXT:    store atomic ptr [[TMP3]], ptr [[TMP4]] seq_cst, align 4
+// CHECK-NEXT:    ret void
+//
+void test_c11_min_nullptr(_Atomic(int*) * aip, int* ip) {
+  *aip = __c11_atomic_fetch_min(aip, nullptr, 0);
+}
+
+// CHECK-LABEL: define void 
@_ZN11FetchMinMax20test_c11_max_nullptrEPU7_AtomicPiS0_(
+// CHECK-SAME: ptr noundef [[AIP:%.*]], ptr noundef [[IP:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[AIP_ADDR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:    [[IP_ADDR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:    [[DOTATOMICTMP:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:    [[ATOMIC_TEMP:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:    store ptr [[AIP]], ptr [[AIP_ADDR]], align 4
+// CHECK-NEXT:    store ptr [[IP]], ptr [[IP_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[AIP_ADDR]], align 4
+// CHECK-NEXT:    store ptr null, ptr [[DOTATOMICTMP]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[DOTATOMICTMP]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = atomicrmw umax ptr [[TMP0]], i32 [[TMP1]] 
monotonic, align 4
+// CHECK-NEXT:    store i32 [[TMP2]], ptr [[ATOMIC_TEMP]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = load ptr, ptr [[ATOMIC_TEMP]], align 4
+// CHECK-NEXT:    [[TMP4:%.*]] = load ptr, ptr [[AIP_ADDR]], align 4
+// CHECK-NEXT:    store atomic ptr [[TMP3]], ptr [[TMP4]] seq_cst, align 4
+// CHECK-NEXT:    ret void
+//
+void test_c11_max_nullptr(_Atomic(int*) * aip, int* ip) {
+  *aip = __c11_atomic_fetch_max(aip, nullptr, 0);
+}
+
+}
diff --git a/clang/test/SemaCXX/atomic-ops.cpp 
b/clang/test/SemaCXX/atomic-ops.cpp
index 30d829d1e97d79..cf9b20a905d0e4 100644
--- a/clang/test/SemaCXX/atomic-ops.cpp
+++ b/clang/test/SemaCXX/atomic-ops.cpp
@@ -22,3 +22,11 @@ void f() {
   __atomic_store(p, p, __ATOMIC_RELAXED);
   __atomic_compare_exchange(p, p, q, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
 }
+
+using nullptr_t = decltype(nullptr);
+
+void atomic_minmax_nullptr_t(_Atomic(nullptr_t)* an) {
+  *an = __c11_atomic_fetch_max(an, nullptr, 0); // expected-error{{address 
argument to atomic operation must be a pointer to atomic integer, pointer or 
supported floating point type ('_Atomic(nullptr_t) *' invalid)}}
+  *an = __c11_atomic_fetch_min(an, nullptr, 0); // expected-error{{address 
argument to atomic operation must be a pointer to atomic integer, pointer or 
supported floating point type ('_Atomic(nullptr_t) *' invalid)}}
+
+}

>From 659de6a4af655a5fd7b3dddc671359b95520e1b2 Mon Sep 17 00:00:00 2001
From: Hui Xie <[email protected]>
Date: Mon, 2 Nov 2026 20:48:18 +0000
Subject: [PATCH 7/7] rebase and fix

---
 clang/lib/CodeGen/CGAtomic.cpp       | 11 ++++++
 clang/test/CodeGen/atomic-ops.c      | 38 ++++++++++++-------
 clang/test/CodeGenCXX/atomic-ops.cpp | 56 ++++++++++++++++------------
 3 files changed, 67 insertions(+), 38 deletions(-)

diff --git a/clang/lib/CodeGen/CGAtomic.cpp b/clang/lib/CodeGen/CGAtomic.cpp
index cd7b278eab15d9..90be8e4ab502c5 100644
--- a/clang/lib/CodeGen/CGAtomic.cpp
+++ b/clang/lib/CodeGen/CGAtomic.cpp
@@ -831,6 +831,15 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr 
*E, Address Dest,
   }
 
   llvm::Value *LoadVal1 = CGF.Builder.CreateLoad(Val1);
+
+  llvm::Type *OrigVal1Ty = LoadVal1->getType();
+  const bool IsPointerMinMax =
+      OrigVal1Ty->isPointerTy() &&
+      (Op == llvm::AtomicRMWInst::UMin || Op == llvm::AtomicRMWInst::UMax);
+  if (IsPointerMinMax)
+    LoadVal1 = CGF.Builder.CreatePtrToInt(
+        LoadVal1, CGF.CGM.getDataLayout().getIntPtrType(OrigVal1Ty));
+
   llvm::AtomicRMWInst *RMWI =
       CGF.emitAtomicRMWInst(Op, Ptr, LoadVal1, Order, Scope, E);
   RMWI->setVolatile(E->isVolatile());
@@ -848,6 +857,8 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr 
*E, Address Dest,
   if (E->getOp() == AtomicExpr::AO__atomic_nand_fetch ||
       E->getOp() == AtomicExpr::AO__scoped_atomic_nand_fetch)
     Result = CGF.Builder.CreateNot(Result);
+  if (IsPointerMinMax)
+    Result = CGF.Builder.CreateIntToPtr(Result, OrigVal1Ty);
   auto *I = CGF.Builder.CreateStore(Result, Dest);
   CGF.addInstToCurrentSourceAtom(I, Result);
 }
diff --git a/clang/test/CodeGen/atomic-ops.c b/clang/test/CodeGen/atomic-ops.c
index 58b3c3672d8e9f..58f09f891480bc 100644
--- a/clang/test/CodeGen/atomic-ops.c
+++ b/clang/test/CodeGen/atomic-ops.c
@@ -846,9 +846,11 @@ void test_c11_minmax(_Atomic(int) * si, _Atomic(unsigned) 
* ui, _Atomic(short) *
   // 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_RHS:%.*]] = load ptr, ptr {{.*}}, align 4
+  // CHECK-NEXT: [[AIP_RHS_INT:%.*]] = ptrtoint ptr [[AIP_RHS]] to i32
+  // CHECK-NEXT: [[AIP_OLD:%.*]] = atomicrmw umax ptr [[AIP_LOC]], i32 
[[AIP_RHS_INT]] acquire, align 4
+  // CHECK-NEXT: [[AIP_OLD_PTR:%.*]] = inttoptr i32 [[AIP_OLD]] to ptr
+  // CHECK-NEXT: store ptr [[AIP_OLD_PTR]], 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
@@ -856,9 +858,11 @@ void test_c11_minmax(_Atomic(int) * si, _Atomic(unsigned) 
* ui, _Atomic(short) *
   // 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_RHS2:%.*]] = load ptr, ptr {{.*}}, align 4
+  // CHECK-NEXT: [[AIP_RHS2_INT:%.*]] = ptrtoint ptr [[AIP_RHS2]] to i32
+  // CHECK-NEXT: [[AIP_OLD2:%.*]] = atomicrmw umin ptr [[AIP_LOC3]], i32 
[[AIP_RHS2_INT]] acquire, align 4
+  // CHECK-NEXT: [[AIP_OLD2_PTR:%.*]] = inttoptr i32 [[AIP_OLD2]] to ptr
+  // CHECK-NEXT: store ptr [[AIP_OLD2_PTR]], 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
@@ -866,18 +870,22 @@ void test_c11_minmax(_Atomic(int) * si, _Atomic(unsigned) 
* ui, _Atomic(short) *
 
   // 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_RHS:%.*]] = load ptr, ptr {{.*}}, align 4
+  // CHECK-NEXT: [[AIP_N1_RHS_INT:%.*]] = ptrtoint ptr [[AIP_N1_RHS]] to i32
+  // CHECK-NEXT: [[AIP_N1_OLD:%.*]] = atomicrmw umax ptr [[AIP_N1]], i32 
[[AIP_N1_RHS_INT]] acquire, align 4
+  // CHECK-NEXT: [[AIP_N1_OLD_PTR:%.*]] = inttoptr i32 [[AIP_N1_OLD]] to ptr
+  // CHECK-NEXT: store ptr [[AIP_N1_OLD_PTR]], 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_RHS:%.*]] = load ptr, ptr {{.*}}, align 4
+  // CHECK-NEXT: [[AIP_N2_RHS_INT:%.*]] = ptrtoint ptr [[AIP_N2_RHS]] to i32
+  // CHECK-NEXT: [[AIP_N2_OLD:%.*]] = atomicrmw umin ptr [[AIP_N2]], i32 
[[AIP_N2_RHS_INT]] acquire, align 4
+  // CHECK-NEXT: [[AIP_N2_OLD_PTR:%.*]] = inttoptr i32 [[AIP_N2_OLD]] to ptr
+  // CHECK-NEXT: store ptr [[AIP_N2_OLD_PTR]], 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
@@ -933,13 +941,15 @@ void test_minmax_postop(int *si, unsigned *ui, unsigned 
short *us, signed char *
   // 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
+  // CHECK: [[NEW_PTR:%.*]] = inttoptr i32 [[NEW]] to ptr
+  // CHECK: store ptr [[NEW_PTR]], 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
+  // CHECK: [[NEW_PTR:%.*]] = inttoptr i32 [[NEW]] to ptr
+  // CHECK: store ptr [[NEW_PTR]], ptr
   *ip = __atomic_min_fetch(ip, si, memory_order_release);
 
 }
diff --git a/clang/test/CodeGenCXX/atomic-ops.cpp 
b/clang/test/CodeGenCXX/atomic-ops.cpp
index d6e51df97f9612..355b51acb2d989 100644
--- a/clang/test/CodeGenCXX/atomic-ops.cpp
+++ b/clang/test/CodeGenCXX/atomic-ops.cpp
@@ -15,12 +15,14 @@ namespace FetchMinMax {
 // CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[AIP_ADDR]], align 4
 // CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[IP_ADDR]], align 4
 // CHECK-NEXT:    store ptr [[TMP1]], ptr [[DOTATOMICTMP]], align 4
-// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[DOTATOMICTMP]], align 4
-// CHECK-NEXT:    [[TMP3:%.*]] = atomicrmw umin ptr [[TMP0]], i32 [[TMP2]] 
monotonic, align 4
-// CHECK-NEXT:    store i32 [[TMP3]], ptr [[ATOMIC_TEMP]], align 4
-// CHECK-NEXT:    [[TMP4:%.*]] = load ptr, ptr [[ATOMIC_TEMP]], align 4
-// CHECK-NEXT:    [[TMP5:%.*]] = load ptr, ptr [[AIP_ADDR]], align 4
-// CHECK-NEXT:    store atomic ptr [[TMP4]], ptr [[TMP5]] seq_cst, align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[DOTATOMICTMP]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = ptrtoint ptr [[TMP2]] to i32
+// CHECK-NEXT:    [[TMP4:%.*]] = atomicrmw umin ptr [[TMP0]], i32 [[TMP3]] 
monotonic, align 4
+// CHECK-NEXT:    [[TMP5:%.*]] = inttoptr i32 [[TMP4]] to ptr
+// CHECK-NEXT:    store ptr [[TMP5]], ptr [[ATOMIC_TEMP]], align 4
+// CHECK-NEXT:    [[TMP6:%.*]] = load ptr, ptr [[ATOMIC_TEMP]], align 4
+// CHECK-NEXT:    [[TMP7:%.*]] = load ptr, ptr [[AIP_ADDR]], align 4
+// CHECK-NEXT:    store atomic ptr [[TMP6]], ptr [[TMP7]] seq_cst, align 4
 // CHECK-NEXT:    ret void
 //
 void test_c11_min_ptr(_Atomic(int*) * aip, int* ip) {
@@ -39,12 +41,14 @@ void test_c11_min_ptr(_Atomic(int*) * aip, int* ip) {
 // CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[AIP_ADDR]], align 4
 // CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[IP_ADDR]], align 4
 // CHECK-NEXT:    store ptr [[TMP1]], ptr [[DOTATOMICTMP]], align 4
-// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[DOTATOMICTMP]], align 4
-// CHECK-NEXT:    [[TMP3:%.*]] = atomicrmw umax ptr [[TMP0]], i32 [[TMP2]] 
monotonic, align 4
-// CHECK-NEXT:    store i32 [[TMP3]], ptr [[ATOMIC_TEMP]], align 4
-// CHECK-NEXT:    [[TMP4:%.*]] = load ptr, ptr [[ATOMIC_TEMP]], align 4
-// CHECK-NEXT:    [[TMP5:%.*]] = load ptr, ptr [[AIP_ADDR]], align 4
-// CHECK-NEXT:    store atomic ptr [[TMP4]], ptr [[TMP5]] seq_cst, align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[DOTATOMICTMP]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = ptrtoint ptr [[TMP2]] to i32
+// CHECK-NEXT:    [[TMP4:%.*]] = atomicrmw umax ptr [[TMP0]], i32 [[TMP3]] 
monotonic, align 4
+// CHECK-NEXT:    [[TMP5:%.*]] = inttoptr i32 [[TMP4]] to ptr
+// CHECK-NEXT:    store ptr [[TMP5]], ptr [[ATOMIC_TEMP]], align 4
+// CHECK-NEXT:    [[TMP6:%.*]] = load ptr, ptr [[ATOMIC_TEMP]], align 4
+// CHECK-NEXT:    [[TMP7:%.*]] = load ptr, ptr [[AIP_ADDR]], align 4
+// CHECK-NEXT:    store atomic ptr [[TMP6]], ptr [[TMP7]] seq_cst, align 4
 // CHECK-NEXT:    ret void
 //
 void test_c11_max_ptr(_Atomic(int*) * aip, int* ip) {
@@ -62,12 +66,14 @@ void test_c11_max_ptr(_Atomic(int*) * aip, int* ip) {
 // CHECK-NEXT:    store ptr [[IP]], ptr [[IP_ADDR]], align 4
 // CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[AIP_ADDR]], align 4
 // CHECK-NEXT:    store ptr null, ptr [[DOTATOMICTMP]], align 4
-// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[DOTATOMICTMP]], align 4
-// CHECK-NEXT:    [[TMP2:%.*]] = atomicrmw umin ptr [[TMP0]], i32 [[TMP1]] 
monotonic, align 4
-// CHECK-NEXT:    store i32 [[TMP2]], ptr [[ATOMIC_TEMP]], align 4
-// CHECK-NEXT:    [[TMP3:%.*]] = load ptr, ptr [[ATOMIC_TEMP]], align 4
-// CHECK-NEXT:    [[TMP4:%.*]] = load ptr, ptr [[AIP_ADDR]], align 4
-// CHECK-NEXT:    store atomic ptr [[TMP3]], ptr [[TMP4]] seq_cst, align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[DOTATOMICTMP]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i32
+// CHECK-NEXT:    [[TMP3:%.*]] = atomicrmw umin ptr [[TMP0]], i32 [[TMP2]] 
monotonic, align 4
+// CHECK-NEXT:    [[TMP4:%.*]] = inttoptr i32 [[TMP3]] to ptr
+// CHECK-NEXT:    store ptr [[TMP4]], ptr [[ATOMIC_TEMP]], align 4
+// CHECK-NEXT:    [[TMP5:%.*]] = load ptr, ptr [[ATOMIC_TEMP]], align 4
+// CHECK-NEXT:    [[TMP6:%.*]] = load ptr, ptr [[AIP_ADDR]], align 4
+// CHECK-NEXT:    store atomic ptr [[TMP5]], ptr [[TMP6]] seq_cst, align 4
 // CHECK-NEXT:    ret void
 //
 void test_c11_min_nullptr(_Atomic(int*) * aip, int* ip) {
@@ -85,12 +91,14 @@ void test_c11_min_nullptr(_Atomic(int*) * aip, int* ip) {
 // CHECK-NEXT:    store ptr [[IP]], ptr [[IP_ADDR]], align 4
 // CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[AIP_ADDR]], align 4
 // CHECK-NEXT:    store ptr null, ptr [[DOTATOMICTMP]], align 4
-// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[DOTATOMICTMP]], align 4
-// CHECK-NEXT:    [[TMP2:%.*]] = atomicrmw umax ptr [[TMP0]], i32 [[TMP1]] 
monotonic, align 4
-// CHECK-NEXT:    store i32 [[TMP2]], ptr [[ATOMIC_TEMP]], align 4
-// CHECK-NEXT:    [[TMP3:%.*]] = load ptr, ptr [[ATOMIC_TEMP]], align 4
-// CHECK-NEXT:    [[TMP4:%.*]] = load ptr, ptr [[AIP_ADDR]], align 4
-// CHECK-NEXT:    store atomic ptr [[TMP3]], ptr [[TMP4]] seq_cst, align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[DOTATOMICTMP]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i32
+// CHECK-NEXT:    [[TMP3:%.*]] = atomicrmw umax ptr [[TMP0]], i32 [[TMP2]] 
monotonic, align 4
+// CHECK-NEXT:    [[TMP4:%.*]] = inttoptr i32 [[TMP3]] to ptr
+// CHECK-NEXT:    store ptr [[TMP4]], ptr [[ATOMIC_TEMP]], align 4
+// CHECK-NEXT:    [[TMP5:%.*]] = load ptr, ptr [[ATOMIC_TEMP]], align 4
+// CHECK-NEXT:    [[TMP6:%.*]] = load ptr, ptr [[AIP_ADDR]], align 4
+// CHECK-NEXT:    store atomic ptr [[TMP5]], ptr [[TMP6]] seq_cst, align 4
 // CHECK-NEXT:    ret void
 //
 void test_c11_max_nullptr(_Atomic(int*) * aip, int* ip) {

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to