[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