[clang] [CIR] Atomic fetch-and-update operations on pointers (PR #195537)

via cfe-commits cfe-commits at lists.llvm.org
Sun May 3 08:51:59 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clangir

Author: Sirui Mu (Lancern)

<details>
<summary>Changes</summary>

This patch adds support for atomic fetch-and-update operations on pointer inputs, including:

- C11 atomic operations: `__c11_atomic_fetch_add` and `__c11_atomic_fetch_sub` for pointer types;
- GNU atomic operations: `__atomic_fetch_add`, `__atomic_fetch_sub`, `__atomic_add_fetch`, and `__atomic_sub_fetch` for pointer types.

Assisted-by: Codex / GPT-5.5

---
Full diff: https://github.com/llvm/llvm-project/pull/195537.diff


2 Files Affected:

- (modified) clang/lib/CIR/CodeGen/CIRGenAtomic.cpp (+27-6) 
- (modified) clang/test/CIR/CodeGen/atomic.c (+196) 


``````````diff
diff --git a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
index e9bf89c91627f..de9d1987d0516 100644
--- a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
@@ -1103,19 +1103,40 @@ RValue CIRGenFunction::emitAtomicExpr(AtomicExpr *e) {
   case AtomicExpr::AO__c11_atomic_fetch_add:
   case AtomicExpr::AO__c11_atomic_fetch_sub:
     if (memTy->isPointerType()) {
-      cgm.errorNYI(e->getSourceRange(),
-                   "atomic fetch-and-add and fetch-and-sub for pointers");
-      return RValue::get(nullptr);
+      // For pointer arithmetic, we're required to do a bit of math:
+      // adding 1 to an int* is not the same as adding 1 to a uintptr_t.
+      // ... but only for the C11 builtins. The GNU builtins expect the
+      // user to multiply by sizeof(T).
+      QualType val1Ty = e->getVal1()->getType();
+      mlir::Location loc = getLoc(e->getSourceRange());
+      mlir::Value val1Scalar = emitScalarExpr(e->getVal1());
+      CharUnits pointeeIncAmt =
+          getContext().getTypeSizeInChars(memTy->getPointeeType());
+      mlir::Value inc = builder.getConstInt(loc, val1Scalar.getType(),
+                                            pointeeIncAmt.getQuantity());
+      val1Scalar = builder.createMul(loc, val1Scalar, inc);
+      val1 = createMemTemp(val1Ty, loc, ".atomictmp");
+      emitStoreOfScalar(val1Scalar, makeAddrLValue(val1, val1Ty),
+                        /*isInit=*/true);
     }
     [[fallthrough]];
   case AtomicExpr::AO__atomic_fetch_add:
-  case AtomicExpr::AO__atomic_fetch_max:
-  case AtomicExpr::AO__atomic_fetch_min:
   case AtomicExpr::AO__atomic_fetch_sub:
   case AtomicExpr::AO__atomic_add_fetch:
+  case AtomicExpr::AO__atomic_sub_fetch:
+    if (memTy->isPointerType()) {
+      // Fetch-and-update atomic operation on pointers should treat the pointer
+      // value as uintptr_t values
+      if (!val1.isValid())
+        val1 = emitValToTemp(*this, e->getVal1());
+      ptr = ptr.withElementType(builder, val1.getElementType());
+      break;
+    }
+    [[fallthrough]];
+  case AtomicExpr::AO__atomic_fetch_max:
+  case AtomicExpr::AO__atomic_fetch_min:
   case AtomicExpr::AO__atomic_max_fetch:
   case AtomicExpr::AO__atomic_min_fetch:
-  case AtomicExpr::AO__atomic_sub_fetch:
   case AtomicExpr::AO__c11_atomic_fetch_max:
   case AtomicExpr::AO__c11_atomic_fetch_min:
   case AtomicExpr::AO__scoped_atomic_fetch_add:
diff --git a/clang/test/CIR/CodeGen/atomic.c b/clang/test/CIR/CodeGen/atomic.c
index e6e45e787a37c..96296b39cb3fb 100644
--- a/clang/test/CIR/CodeGen/atomic.c
+++ b/clang/test/CIR/CodeGen/atomic.c
@@ -936,6 +936,37 @@ int atomic_fetch_add(int *ptr, int value) {
   // OGCG-NEXT: store i32 %[[RES]], ptr %{{.+}}, align 4
 }
 
+int *atomic_fetch_add_ptr(int **ptr, __PTRDIFF_TYPE__ value) {
+  // CIR-LABEL: @atomic_fetch_add_ptr
+  // LLVM-LABEL: @atomic_fetch_add_ptr
+  // OGCG-LABEL: @atomic_fetch_add_ptr
+
+  return __atomic_fetch_add(ptr, value, __ATOMIC_SEQ_CST);
+  // CIR:      %[[PTR:.+]] = cir.load align(8) %{{.+}} : !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>>, !cir.ptr<!cir.ptr<!s32i>>
+  // CIR:      %[[OFFSET:.+]] = cir.load align(8) %{{.+}} : !cir.ptr<!s64i>, !s64i
+  // CIR-NOT:  cir.mul
+  // CIR:      %[[PTR_INT:.+]] = cir.cast bitcast %[[PTR]] : !cir.ptr<!cir.ptr<!s32i>> -> !cir.ptr<!s64i>
+  // CIR:      %[[ADD:.+]] = cir.load align(8) %{{.+}} : !cir.ptr<!s64i>, !s64i
+  // CIR-NEXT: %[[RESULT:.+]] = cir.atomic.fetch add seq_cst syncscope(system) fetch_first %[[PTR_INT]], %[[ADD]] : (!cir.ptr<!s64i>, !s64i) -> !s64i
+  // CIR-NEXT: %[[RESULT_SLOT:.+]] = cir.cast bitcast %[[RESULT_TEMP_SLOT:.+]] : !cir.ptr<!cir.ptr<!s32i>> -> !cir.ptr<!s64i>
+  // CIR-NEXT: cir.store align(8) %[[RESULT]], %[[RESULT_SLOT]] : !s64i, !cir.ptr<!s64i>
+  // CIR-NEXT: %{{.+}} = cir.load align(8) %[[RESULT_TEMP_SLOT]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
+
+  // LLVM:      %[[PTR:.+]] = load ptr, ptr %{{.+}}, align 8
+  // LLVM:      %[[OFFSET:.+]] = load i64, ptr %{{.+}}, align 8
+  // LLVM-NOT:  mul
+  // LLVM:      %[[RESULT:.+]] = atomicrmw add ptr %[[PTR]], i64 %[[ADD:.+]] seq_cst, align 8
+  // LLVM-NEXT: store i64 %[[RESULT]], ptr %[[RESULT_SLOT:.+]], align 8
+  // LLVM-NEXT: %{{.+}} = load ptr, ptr %[[RESULT_SLOT]], align 8
+
+  // OGCG:      %[[PTR:.+]] = load ptr, ptr %{{.+}}, align 8
+  // OGCG:      %[[OFFSET:.+]] = load i64, ptr %{{.+}}, align 8
+  // OGCG-NOT:  mul
+  // OGCG:      %[[RESULT:.+]] = atomicrmw add ptr %[[PTR]], i64 %[[ADD:.+]] seq_cst, align 8
+  // OGCG-NEXT: store i64 %[[RESULT]], ptr %[[RESULT_SLOT:.+]], align 8
+  // OGCG-NEXT: %{{.+}} = load ptr, ptr %[[RESULT_SLOT]], align 8
+}
+
 int atomic_add_fetch(int *ptr, int value) {
   // CIR-LABEL: @atomic_add_fetch
   // LLVM-LABEL: @atomic_add_fetch
@@ -953,6 +984,39 @@ int atomic_add_fetch(int *ptr, int value) {
   // OGCG-NEXT: store i32 %[[RES]], ptr %{{.+}}, align 4
 }
 
+int *atomic_add_fetch_ptr(int **ptr, __PTRDIFF_TYPE__ value) {
+  // CIR-LABEL: @atomic_add_fetch_ptr
+  // LLVM-LABEL: @atomic_add_fetch_ptr
+  // OGCG-LABEL: @atomic_add_fetch_ptr
+
+  return __atomic_add_fetch(ptr, value, __ATOMIC_SEQ_CST);
+  // CIR:      %[[PTR:.+]] = cir.load align(8) %{{.+}} : !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>>, !cir.ptr<!cir.ptr<!s32i>>
+  // CIR:      %[[OFFSET:.+]] = cir.load align(8) %{{.+}} : !cir.ptr<!s64i>, !s64i
+  // CIR-NOT:  cir.mul
+  // CIR:      %[[PTR_INT:.+]] = cir.cast bitcast %[[PTR]] : !cir.ptr<!cir.ptr<!s32i>> -> !cir.ptr<!s64i>
+  // CIR:      %[[ADD:.+]] = cir.load align(8) %{{.+}} : !cir.ptr<!s64i>, !s64i
+  // CIR-NEXT: %[[RESULT:.+]] = cir.atomic.fetch add seq_cst syncscope(system) %[[PTR_INT]], %[[ADD]] : (!cir.ptr<!s64i>, !s64i) -> !s64i
+  // CIR-NEXT: %[[RESULT_SLOT:.+]] = cir.cast bitcast %[[RESULT_TEMP_SLOT:.+]] : !cir.ptr<!cir.ptr<!s32i>> -> !cir.ptr<!s64i>
+  // CIR-NEXT: cir.store align(8) %[[RESULT]], %[[RESULT_SLOT]] : !s64i, !cir.ptr<!s64i>
+  // CIR-NEXT: %{{.+}} = cir.load align(8) %[[RESULT_TEMP_SLOT]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
+
+  // LLVM:      %[[PTR:.+]] = load ptr, ptr %{{.+}}, align 8
+  // LLVM:      %[[OFFSET:.+]] = load i64, ptr %{{.+}}, align 8
+  // LLVM-NOT:  mul
+  // LLVM:      %[[OLD:.+]] = atomicrmw add ptr %[[PTR]], i64 %[[VAL:.+]] seq_cst, align 8
+  // LLVM-NEXT: %[[NEW:.+]] = add i64 %[[OLD]], %[[VAL]]
+  // LLVM-NEXT: store i64 %[[NEW]], ptr %[[RESULT_SLOT:.+]], align 8
+  // LLVM-NEXT: %{{.+}} = load ptr, ptr %[[RESULT_SLOT]], align 8
+
+  // OGCG:      %[[PTR:.+]] = load ptr, ptr %{{.+}}, align 8
+  // OGCG:      %[[OFFSET:.+]] = load i64, ptr %{{.+}}, align 8
+  // OGCG-NOT:  mul
+  // OGCG:      %[[OLD:.+]] = atomicrmw add ptr %[[PTR]], i64 %[[VAL:.+]] seq_cst, align 8
+  // OGCG-NEXT: %[[NEW:.+]] = add i64 %[[OLD]], %[[VAL]]
+  // OGCG-NEXT: store i64 %[[NEW]], ptr %[[RESULT_SLOT:.+]], align 8
+  // OGCG-NEXT: %{{.+}} = load ptr, ptr %[[RESULT_SLOT]], align 8
+}
+
 int c11_atomic_fetch_add(_Atomic(int) *ptr, int value) {
   // CIR-LABEL: @c11_atomic_fetch_add
   // LLVM-LABEL: @c11_atomic_fetch_add
@@ -968,6 +1032,40 @@ int c11_atomic_fetch_add(_Atomic(int) *ptr, int value) {
   // OGCG-NEXT: store i32 %[[RES]], ptr %{{.+}}, align 4
 }
 
+int *c11_atomic_fetch_add_ptr(_Atomic(int *) *ptr, __PTRDIFF_TYPE__ value) {
+  // CIR-LABEL: @c11_atomic_fetch_add_ptr
+  // LLVM-LABEL: @c11_atomic_fetch_add_ptr
+  // OGCG-LABEL: @c11_atomic_fetch_add_ptr
+
+  return __c11_atomic_fetch_add(ptr, value, __ATOMIC_SEQ_CST);
+  // CIR:      %[[OFFSET:.+]] = cir.load align(8) %{{.+}} : !cir.ptr<!s64i>, !s64i
+  // CIR-NEXT: %[[SIZE:.+]] = cir.const #cir.int<4> : !s64i
+  // CIR-NEXT: %[[ADD:.+]] = cir.mul %[[OFFSET]], %[[SIZE]] : !s64i
+  // CIR-NEXT: cir.store align(8) %[[ADD]], %[[ADD_SLOT:.+]] : !s64i, !cir.ptr<!s64i>
+  // CIR-NEXT: %[[PTR_INT:.+]] = cir.cast bitcast %{{.+}} : !cir.ptr<!cir.ptr<!s32i>> -> !cir.ptr<!s64i>
+  // CIR-NEXT: %[[ADD2:.+]] = cir.load align(8) %[[ADD_SLOT]] : !cir.ptr<!s64i>, !s64i
+  // CIR-NEXT: %[[RESULT:.+]] = cir.atomic.fetch add seq_cst syncscope(system) fetch_first %[[PTR_INT]], %[[ADD2]] : (!cir.ptr<!s64i>, !s64i) -> !s64i
+  // CIR-NEXT: %[[RESULT_SLOT:.+]] = cir.cast bitcast %[[RESULT_TEMP_SLOT:.+]] : !cir.ptr<!cir.ptr<!s32i>> -> !cir.ptr<!s64i>
+  // CIR-NEXT: cir.store align(8) %[[RESULT]], %[[RESULT_SLOT]] : !s64i, !cir.ptr<!s64i>
+  // CIR-NEXT: %{{.+}} = cir.load align(8) %[[RESULT_TEMP_SLOT]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
+
+  // LLVM:      %[[OFFSET:.+]] = load i64, ptr %{{.+}}, align 8
+  // LLVM-NEXT: %[[ADD:.+]] = mul i64 %[[OFFSET]], 4
+  // LLVM-NEXT: store i64 %[[ADD]], ptr %[[ADD_SLOT:.+]], align 8
+  // LLVM-NEXT: %[[ADD2:.+]] = load i64, ptr %[[ADD_SLOT]], align 8
+  // LLVM-NEXT: %[[RESULT:.+]] = atomicrmw add ptr %8, i64 %[[ADD2]] seq_cst, align 8
+  // LLVM-NEXT: store i64 %[[RESULT]], ptr %[[RESULT_SLOT:.+]], align 8
+  // LLVM-NEXT: %{{.+}} = load ptr, ptr %[[RESULT_SLOT]], align 8
+
+  // OGCG:      %[[OFFSET:.+]] = load i64, ptr %{{.+}}, align 8
+  // OGCG-NEXT: %[[ADD:.+]] = mul i64 %[[OFFSET]], 4
+  // OGCG-NEXT: store i64 %[[ADD]], ptr %[[ADD_SLOT:.+]], align 8
+  // OGCG-NEXT: %[[ADD2:.+]] = load i64, ptr %[[ADD_SLOT]], align 8
+  // OGCG-NEXT: %[[RESULT:.+]] = atomicrmw add ptr %0, i64 %[[ADD2]] seq_cst, align 8
+  // OGCG-NEXT: store i64 %[[RESULT]], ptr %[[RESULT_SLOT:.+]], align 8
+  // OGCG-NEXT: %{{.+}} = load ptr, ptr %[[RESULT_SLOT]], align 8
+}
+
 int atomic_fetch_sub(int *ptr, int value) {
   // CIR-LABEL: @atomic_fetch_sub
   // LLVM-LABEL: @atomic_fetch_sub
@@ -983,6 +1081,37 @@ int atomic_fetch_sub(int *ptr, int value) {
   // OGCG-NEXT: store i32 %[[RES]], ptr %{{.+}}, align 4
 }
 
+int *atomic_fetch_sub_ptr(int **ptr, __PTRDIFF_TYPE__ value) {
+  // CIR-LABEL: @atomic_fetch_sub_ptr
+  // LLVM-LABEL: @atomic_fetch_sub_ptr
+  // OGCG-LABEL: @atomic_fetch_sub_ptr
+
+  return __atomic_fetch_sub(ptr, value, __ATOMIC_SEQ_CST);
+  // CIR:      %[[PTR:.+]] = cir.load align(8) %{{.+}} : !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>>, !cir.ptr<!cir.ptr<!s32i>>
+  // CIR:      %[[OFFSET:.+]] = cir.load align(8) %{{.+}} : !cir.ptr<!s64i>, !s64i
+  // CIR-NOT:  cir.mul
+  // CIR:      %[[PTR_INT:.+]] = cir.cast bitcast %[[PTR]] : !cir.ptr<!cir.ptr<!s32i>> -> !cir.ptr<!s64i>
+  // CIR:      %[[SUB:.+]] = cir.load align(8) %{{.+}} : !cir.ptr<!s64i>, !s64i
+  // CIR-NEXT: %[[RESULT:.+]] = cir.atomic.fetch sub seq_cst syncscope(system) fetch_first %[[PTR_INT]], %[[SUB]] : (!cir.ptr<!s64i>, !s64i) -> !s64i
+  // CIR-NEXT: %[[RESULT_SLOT:.+]] = cir.cast bitcast %[[RESULT_TEMP_SLOT:.+]] : !cir.ptr<!cir.ptr<!s32i>> -> !cir.ptr<!s64i>
+  // CIR-NEXT: cir.store align(8) %[[RESULT]], %[[RESULT_SLOT]] : !s64i, !cir.ptr<!s64i>
+  // CIR-NEXT: %{{.+}} = cir.load align(8) %[[RESULT_TEMP_SLOT]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
+
+  // LLVM:      %[[PTR:.+]] = load ptr, ptr %{{.+}}, align 8
+  // LLVM:      %[[OFFSET:.+]] = load i64, ptr %{{.+}}, align 8
+  // LLVM-NOT:  mul
+  // LLVM:      %[[RESULT:.+]] = atomicrmw sub ptr %[[PTR]], i64 %[[SUB:.+]] seq_cst, align 8
+  // LLVM-NEXT: store i64 %[[RESULT]], ptr %[[RESULT_SLOT:.+]], align 8
+  // LLVM-NEXT: %{{.+}} = load ptr, ptr %[[RESULT_SLOT]], align 8
+
+  // OGCG:      %[[PTR:.+]] = load ptr, ptr %{{.+}}, align 8
+  // OGCG:      %[[OFFSET:.+]] = load i64, ptr %{{.+}}, align 8
+  // OGCG-NOT:  mul
+  // OGCG:      %[[RESULT:.+]] = atomicrmw sub ptr %[[PTR]], i64 %[[SUB:.+]] seq_cst, align 8
+  // OGCG-NEXT: store i64 %[[RESULT]], ptr %[[RESULT_SLOT:.+]], align 8
+  // OGCG-NEXT: %{{.+}} = load ptr, ptr %[[RESULT_SLOT]], align 8
+}
+
 int atomic_sub_fetch(int *ptr, int value) {
   // CIR-LABEL: @atomic_sub_fetch
   // LLVM-LABEL: @atomic_sub_fetch
@@ -1000,6 +1129,39 @@ int atomic_sub_fetch(int *ptr, int value) {
   // OGCG-NEXT: store i32 %[[RES]], ptr %{{.+}}, align 4
 }
 
+int *atomic_sub_fetch_ptr(int **ptr, __PTRDIFF_TYPE__ value) {
+  // CIR-LABEL: @atomic_sub_fetch_ptr
+  // LLVM-LABEL: @atomic_sub_fetch_ptr
+  // OGCG-LABEL: @atomic_sub_fetch_ptr
+
+  return __atomic_sub_fetch(ptr, value, __ATOMIC_SEQ_CST);
+  // CIR:      %[[PTR:.+]] = cir.load align(8) %{{.+}} : !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>>, !cir.ptr<!cir.ptr<!s32i>>
+  // CIR:      %[[OFFSET:.+]] = cir.load align(8) %{{.+}} : !cir.ptr<!s64i>, !s64i
+  // CIR-NOT:  cir.mul
+  // CIR:      %[[PTR_INT:.+]] = cir.cast bitcast %[[PTR]] : !cir.ptr<!cir.ptr<!s32i>> -> !cir.ptr<!s64i>
+  // CIR:      %[[SUB:.+]] = cir.load align(8) %{{.+}} : !cir.ptr<!s64i>, !s64i
+  // CIR-NEXT: %[[RESULT:.+]] = cir.atomic.fetch sub seq_cst syncscope(system) %[[PTR_INT]], %[[SUB]] : (!cir.ptr<!s64i>, !s64i) -> !s64i
+  // CIR-NEXT: %[[RESULT_SLOT:.+]] = cir.cast bitcast %[[RESULT_TEMP_SLOT:.+]] : !cir.ptr<!cir.ptr<!s32i>> -> !cir.ptr<!s64i>
+  // CIR-NEXT: cir.store align(8) %[[RESULT]], %[[RESULT_SLOT]] : !s64i, !cir.ptr<!s64i>
+  // CIR-NEXT: %{{.+}} = cir.load align(8) %[[RESULT_TEMP_SLOT]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
+
+  // LLVM:      %[[PTR:.+]] = load ptr, ptr %{{.+}}, align 8
+  // LLVM:      %[[OFFSET:.+]] = load i64, ptr %{{.+}}, align 8
+  // LLVM-NOT:  mul
+  // LLVM:      %[[OLD:.+]] = atomicrmw sub ptr %[[PTR]], i64 %[[VAL:.+]] seq_cst, align 8
+  // LLVM-NEXT: %[[NEW:.+]] = sub i64 %[[OLD]], %[[VAL]]
+  // LLVM-NEXT: store i64 %[[NEW]], ptr %[[RESULT_SLOT:.+]], align 8
+  // LLVM-NEXT: %{{.+}} = load ptr, ptr %[[RESULT_SLOT]], align 8
+
+  // OGCG:      %[[PTR:.+]] = load ptr, ptr %{{.+}}, align 8
+  // OGCG:      %[[OFFSET:.+]] = load i64, ptr %{{.+}}, align 8
+  // OGCG-NOT:  mul
+  // OGCG:      %[[OLD:.+]] = atomicrmw sub ptr %[[PTR]], i64 %[[VAL:.+]] seq_cst, align 8
+  // OGCG-NEXT: %[[NEW:.+]] = sub i64 %[[OLD]], %[[VAL]]
+  // OGCG-NEXT: store i64 %[[NEW]], ptr %[[RESULT_SLOT:.+]], align 8
+  // OGCG-NEXT: %{{.+}} = load ptr, ptr %[[RESULT_SLOT]], align 8
+}
+
 int c11_atomic_fetch_sub(_Atomic(int) *ptr, int value) {
   // CIR-LABEL: @c11_atomic_fetch_sub
   // LLVM-LABEL: @c11_atomic_fetch_sub
@@ -1015,6 +1177,40 @@ int c11_atomic_fetch_sub(_Atomic(int) *ptr, int value) {
   // OGCG-NEXT: store i32 %[[RES]], ptr %{{.+}}, align 4
 }
 
+int *c11_atomic_fetch_sub_ptr(_Atomic(int *) *ptr, __PTRDIFF_TYPE__ value) {
+  // CIR-LABEL: @c11_atomic_fetch_sub_ptr
+  // LLVM-LABEL: @c11_atomic_fetch_sub_ptr
+  // OGCG-LABEL: @c11_atomic_fetch_sub_ptr
+
+  return __c11_atomic_fetch_sub(ptr, value, __ATOMIC_SEQ_CST);
+  // CIR:      %[[OFFSET:.+]] = cir.load align(8) %{{.+}} : !cir.ptr<!s64i>, !s64i
+  // CIR-NEXT: %[[SIZE:.+]] = cir.const #cir.int<4> : !s64i
+  // CIR-NEXT: %[[ADD:.+]] = cir.mul %[[OFFSET]], %[[SIZE]] : !s64i
+  // CIR-NEXT: cir.store align(8) %[[ADD]], %[[ADD_SLOT:.+]] : !s64i, !cir.ptr<!s64i>
+  // CIR-NEXT: %[[PTR_INT:.+]] = cir.cast bitcast %{{.+}} : !cir.ptr<!cir.ptr<!s32i>> -> !cir.ptr<!s64i>
+  // CIR-NEXT: %[[ADD2:.+]] = cir.load align(8) %[[ADD_SLOT]] : !cir.ptr<!s64i>, !s64i
+  // CIR-NEXT: %[[RESULT:.+]] = cir.atomic.fetch sub seq_cst syncscope(system) fetch_first %[[PTR_INT]], %[[ADD2]] : (!cir.ptr<!s64i>, !s64i) -> !s64i
+  // CIR-NEXT: %[[RESULT_SLOT:.+]] = cir.cast bitcast %[[RESULT_TEMP_SLOT:.+]] : !cir.ptr<!cir.ptr<!s32i>> -> !cir.ptr<!s64i>
+  // CIR-NEXT: cir.store align(8) %[[RESULT]], %[[RESULT_SLOT]] : !s64i, !cir.ptr<!s64i>
+  // CIR-NEXT: %{{.+}} = cir.load align(8) %[[RESULT_TEMP_SLOT]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
+
+  // LLVM:      %[[OFFSET:.+]] = load i64, ptr %{{.+}}, align 8
+  // LLVM-NEXT: %[[ADD:.+]] = mul i64 %[[OFFSET]], 4
+  // LLVM-NEXT: store i64 %[[ADD]], ptr %[[ADD_SLOT:.+]], align 8
+  // LLVM-NEXT: %[[ADD2:.+]] = load i64, ptr %[[ADD_SLOT]], align 8
+  // LLVM-NEXT: %[[RESULT:.+]] = atomicrmw sub ptr %8, i64 %[[ADD2]] seq_cst, align 8
+  // LLVM-NEXT: store i64 %[[RESULT]], ptr %[[RESULT_SLOT:.+]], align 8
+  // LLVM-NEXT: %{{.+}} = load ptr, ptr %[[RESULT_SLOT]], align 8
+
+  // OGCG:      %[[OFFSET:.+]] = load i64, ptr %{{.+}}, align 8
+  // OGCG-NEXT: %[[ADD:.+]] = mul i64 %[[OFFSET]], 4
+  // OGCG-NEXT: store i64 %[[ADD]], ptr %[[ADD_SLOT:.+]], align 8
+  // OGCG-NEXT: %[[ADD2:.+]] = load i64, ptr %[[ADD_SLOT]], align 8
+  // OGCG-NEXT: %[[RESULT:.+]] = atomicrmw sub ptr %0, i64 %[[ADD2]] seq_cst, align 8
+  // OGCG-NEXT: store i64 %[[RESULT]], ptr %[[RESULT_SLOT:.+]], align 8
+  // OGCG-NEXT: %{{.+}} = load ptr, ptr %[[RESULT_SLOT]], align 8
+}
+
 float atomic_fetch_add_fp(float *ptr, float value) {
   // CIR-LABEL: @atomic_fetch_add_fp
   // LLVM-LABEL: @atomic_fetch_add_fp

``````````

</details>


https://github.com/llvm/llvm-project/pull/195537


More information about the cfe-commits mailing list