[clang] [CIR] Add support for atomic fmaximum/fminimum/fmaximumnum/fminimumnum (PR #211845)
Sirui Mu via cfe-commits
cfe-commits at lists.llvm.org
Fri Jul 24 09:24:26 PDT 2026
https://github.com/Lancern created https://github.com/llvm/llvm-project/pull/211845
This patch adds CIR support for the following atomic builtin functions:
- `__atomic_fetch_fmaximum`
- `__atomic_fetch_fminimum`
- `__atomic_fetch_fmaximumnum`
- `__atomic_fetch_fminimumnum`
The scoped versions of these atomic builtin functions are supported as well.
Specifically, this patch contains the following changes:
- It updates the `cir.atomic.fetch` operation and adds new fetch operators including `maximum`, `minimum`, `maximumnum`, and `minimumnum`. These operators accept floating-point inputs only.
- It updates the LLVM lowering of the `cir.atomic.fetch` operation. The LLVM lowering now will lower `maximum`, `minimum`, `maximumnum`, and `minimumnum` atomic fetch operators to the corresponding LLVM `atomicrmw` operations, which are `fmaximum`, `fminimum`, `fmaximumnum`, and `fminimumnum`, respectively, aligning with the OGCG behavior.
- It updates the CIRGen path for atomic operations and add supports for these atomic builtin functions.
Assisted-by: GitHub Copilot / gpt-5.4 xhigh
>From 64da1c668b2b348016199a715432911d0d5d2c34 Mon Sep 17 00:00:00 2001
From: Sirui Mu <msrlancern at gmail.com>
Date: Fri, 24 Jul 2026 23:58:30 +0800
Subject: [PATCH] [CIR] Add support for atomic
fmaximum/fminimum/fmaximumnum/fminimumnum
This patch adds CIR support for the following atomic builtin functions:
- `__atomic_fetch_fmaximum`
- `__atomic_fetch_fminimum`
- `__atomic_fetch_fmaximumnum`
- `__atomic_fetch_fminimumnum`
The scoped versions of these atomic builtin functions are supported as well.
Specifically, this patch contains the following changes:
- It updates the `cir.atomic.fetch` operation and adds new fetch operators
including `maximum`, `minimum`, `maximumnum`, and `minimumnum`. These
operators accept floating-point inputs only.
- It updates the LLVM lowering of the `cir.atomic.fetch` operation. The LLVM
lowering now will lower `maximum`, `minimum`, `maximumnum`, and `minimumnum`
atomic fetch operators to the corresponding LLVM `atomicrmw` operations, which
are `fmaximum`, `fminimum`, `fmaximumnum`, and `fminimumnum`, respectively,
aligning with the OGCG behavior.
- It updates the CIRGen path for atomic operations and add supports for these
atomic builtin functions.
Assisted-by: GitHub Copilot / gpt-5.4 xhigh
---
clang/include/clang/CIR/Dialect/IR/CIROps.td | 26 +++++-
clang/lib/CIR/CodeGen/CIRGenAtomic.cpp | 45 ++++++++--
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 18 +++-
.../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 15 +++-
clang/test/CIR/CodeGen/atomic-scoped.c | 84 +++++++++++++++++++
clang/test/CIR/CodeGen/atomic.c | 60 +++++++++++++
clang/test/CIR/IR/invalid-atomic.cir | 10 ++-
7 files changed, 243 insertions(+), 15 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 25b634f0e96f6..b0f654a54bacd 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -8375,7 +8375,14 @@ def CIR_AtomicFetchKind : CIR_I32EnumAttr<
I32EnumAttrCase<"Max", 6, "max">,
I32EnumAttrCase<"Min", 7, "min">,
I32EnumAttrCase<"UIncWrap", 8, "uinc_wrap">,
- I32EnumAttrCase<"UDecWrap", 9, "udec_wrap">
+ I32EnumAttrCase<"UDecWrap", 9, "udec_wrap">,
+ // The primary difference between Max, Maximum, and MaximumNum is primarily
+ // about how they handle floating-point inputs. See the description of the
+ // CIR_AtomicFetchOp for more information.
+ I32EnumAttrCase<"Maximum", 10, "maximum">,
+ I32EnumAttrCase<"Minimum", 11, "minimum">,
+ I32EnumAttrCase<"MaximumNum", 12, "maximum_num">,
+ I32EnumAttrCase<"MinimumNum", 13, "minimum_num">
]>;
def CIR_AtomicFetchOp : CIR_Op<"atomic.fetch", [
@@ -8389,7 +8396,8 @@ def CIR_AtomicFetchOp : CIR_Op<"atomic.fetch", [
builtin functions `__atomic_<binop>_fetch`, `__atomic_fetch_<binop>`, and
`__c11_atomic_fetch_<binop>`, where `<binop>` is one of the following binary
opcodes: `add`, `sub`, `and`, `xor`, `or`, `nand`, `max`, `min`,
- `uinc_wrap`, and `udec_wrap`.
+ `uinc_wrap`, `udec_wrap`, `maximum`, `minimum`, `maximum_num`, and
+ `minimum_num`.
This operation takes 2 arguments: a pointer `ptr` and a value `val`. The
type of `val` must match the pointee type of `ptr`. If the binary operation
@@ -8403,6 +8411,20 @@ def CIR_AtomicFetchOp : CIR_Op<"atomic.fetch", [
operation. Otherwise, the result of this operation is the result of the
binary operation.
+ The primary difference between `max`, `maximum`, and `maximum_num` is how
+ they handle floating-point inputs:
+
+ - `max` on floating-point inputs corresponds to the `atomicrmw fmax` LLVM
+ instruction.
+ - `maximum` corresponds to the `atomicrmw fmaximum` LLVM instruction.
+ - `maximum_num` corresponds to the `atomicrmw fmaximumnum` LLVM instruction.
+
+ Similar rules apply to `min`, `minimum`, and `minimum_num`. See the
+ reference for the LLVM instruction `atomicrmw` for more information.
+
+ The operation `maximum`, `minimum`, `maximum_num`, and `minimum_num` only
+ accept floating-point inputs.
+
Example:
%res = cir.atomic.fetch add seq_cst %ptr, %val
: (!cir.ptr<!s32i>, !s32i) -> !s32i
diff --git a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
index 6eacf29923603..b89095a0c4b37 100644
--- a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
@@ -749,6 +749,20 @@ static void emitAtomicOp(CIRGenFunction &cgf, AtomicExpr *expr, Address dest,
handleFetchOp(cir::AtomicFetchKind::Min);
break;
+ case AtomicExpr::AO__atomic_fetch_fminimum:
+ case AtomicExpr::AO__scoped_atomic_fetch_fminimum:
+ assert(expr->getValueType()->isFloatingType() &&
+ "fminimum operations only support floating-point types");
+ handleFetchOp(cir::AtomicFetchKind::Minimum);
+ break;
+
+ case AtomicExpr::AO__atomic_fetch_fminimum_num:
+ case AtomicExpr::AO__scoped_atomic_fetch_fminimum_num:
+ assert(expr->getValueType()->isFloatingType() &&
+ "fminimum_num operations only support floating-point types");
+ handleFetchOp(cir::AtomicFetchKind::MinimumNum);
+ break;
+
case AtomicExpr::AO__atomic_max_fetch:
case AtomicExpr::AO__scoped_atomic_max_fetch:
fetchFirst = false;
@@ -759,6 +773,20 @@ static void emitAtomicOp(CIRGenFunction &cgf, AtomicExpr *expr, Address dest,
handleFetchOp(cir::AtomicFetchKind::Max);
break;
+ case AtomicExpr::AO__atomic_fetch_fmaximum:
+ case AtomicExpr::AO__scoped_atomic_fetch_fmaximum:
+ assert(expr->getValueType()->isFloatingType() &&
+ "fmaximum operations only support floating-point types");
+ handleFetchOp(cir::AtomicFetchKind::Maximum);
+ break;
+
+ case AtomicExpr::AO__atomic_fetch_fmaximum_num:
+ case AtomicExpr::AO__scoped_atomic_fetch_fmaximum_num:
+ assert(expr->getValueType()->isFloatingType() &&
+ "fmaximum_num operations only support floating-point types");
+ handleFetchOp(cir::AtomicFetchKind::MaximumNum);
+ break;
+
case AtomicExpr::AO__atomic_and_fetch:
case AtomicExpr::AO__scoped_atomic_and_fetch:
fetchFirst = false;
@@ -864,15 +892,6 @@ static void emitAtomicOp(CIRGenFunction &cgf, AtomicExpr *expr, Address dest,
case AtomicExpr::AO__hip_atomic_fetch_xor:
case AtomicExpr::AO__opencl_atomic_fetch_xor:
- case AtomicExpr::AO__atomic_fetch_fmaximum:
- case AtomicExpr::AO__atomic_fetch_fmaximum_num:
- case AtomicExpr::AO__atomic_fetch_fminimum:
- case AtomicExpr::AO__atomic_fetch_fminimum_num:
- case AtomicExpr::AO__scoped_atomic_fetch_fmaximum:
- case AtomicExpr::AO__scoped_atomic_fetch_fmaximum_num:
- case AtomicExpr::AO__scoped_atomic_fetch_fminimum:
- case AtomicExpr::AO__scoped_atomic_fetch_fminimum_num:
-
cgf.cgm.errorNYI(expr->getSourceRange(), "emitAtomicOp: expr op NYI");
return;
}
@@ -1482,6 +1501,10 @@ RValue CIRGenFunction::emitAtomicExpr(AtomicExpr *e) {
case AtomicExpr::AO__scoped_atomic_fetch_max:
case AtomicExpr::AO__scoped_atomic_fetch_min:
case AtomicExpr::AO__scoped_atomic_fetch_sub:
+ case AtomicExpr::AO__scoped_atomic_fetch_fminimum:
+ case AtomicExpr::AO__scoped_atomic_fetch_fmaximum:
+ case AtomicExpr::AO__scoped_atomic_fetch_fminimum_num:
+ case AtomicExpr::AO__scoped_atomic_fetch_fmaximum_num:
case AtomicExpr::AO__scoped_atomic_add_fetch:
case AtomicExpr::AO__scoped_atomic_max_fetch:
case AtomicExpr::AO__scoped_atomic_min_fetch:
@@ -1518,6 +1541,10 @@ RValue CIRGenFunction::emitAtomicExpr(AtomicExpr *e) {
case AtomicExpr::AO__atomic_fetch_udec:
case AtomicExpr::AO__scoped_atomic_fetch_uinc:
case AtomicExpr::AO__scoped_atomic_fetch_udec:
+ case AtomicExpr::AO__atomic_fetch_fminimum:
+ case AtomicExpr::AO__atomic_fetch_fmaximum:
+ case AtomicExpr::AO__atomic_fetch_fminimum_num:
+ case AtomicExpr::AO__atomic_fetch_fmaximum_num:
val1 = emitValToTemp(*this, e->getVal1());
break;
}
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 590b206f8258d..9a7a46d8f44ff 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -4269,9 +4269,23 @@ LogicalResult cir::AtomicFetchOp::verify() {
getBinop() != cir::AtomicFetchKind::Sub &&
getBinop() != cir::AtomicFetchKind::Max &&
getBinop() != cir::AtomicFetchKind::Min &&
+ getBinop() != cir::AtomicFetchKind::Maximum &&
+ getBinop() != cir::AtomicFetchKind::Minimum &&
+ getBinop() != cir::AtomicFetchKind::MaximumNum &&
+ getBinop() != cir::AtomicFetchKind::MinimumNum &&
!mlir::isa<cir::IntType>(getVal().getType()))
- return emitError("only atomic add, sub, max, and min operation could "
- "operate on floating-point values");
+ return emitError("only atomic add, sub, max, min, maximum, minimum, "
+ "maximum_num, and minimum_num operation could operate on "
+ "floating-point values");
+
+ if ((getBinop() == cir::AtomicFetchKind::Maximum ||
+ getBinop() == cir::AtomicFetchKind::Minimum ||
+ getBinop() == cir::AtomicFetchKind::MaximumNum ||
+ getBinop() == cir::AtomicFetchKind::MinimumNum) &&
+ !mlir::isa<cir::FPTypeInterface>(getVal().getType()))
+ return emitError("atomic maximum, minimum, maximum_num, and minimum_num "
+ "operation could only operate on floating-point values");
+
return success();
}
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 6a02fb5c017bb..979aed513f595 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -1156,6 +1156,14 @@ getLLVMAtomicBinOp(cir::AtomicFetchKind k, bool isInt, bool isSignedInt) {
return mlir::LLVM::AtomicBinOp::uinc_wrap;
case cir::AtomicFetchKind::UDecWrap:
return mlir::LLVM::AtomicBinOp::udec_wrap;
+ case cir::AtomicFetchKind::Maximum:
+ return mlir::LLVM::AtomicBinOp::fmaximum;
+ case cir::AtomicFetchKind::Minimum:
+ return mlir::LLVM::AtomicBinOp::fminimum;
+ case cir::AtomicFetchKind::MaximumNum:
+ return mlir::LLVM::AtomicBinOp::fmaximumnum;
+ case cir::AtomicFetchKind::MinimumNum:
+ return mlir::LLVM::AtomicBinOp::fminimumnum;
}
llvm_unreachable("Unknown atomic fetch opcode");
}
@@ -1183,7 +1191,12 @@ static llvm::StringLiteral getLLVMBinopForPostAtomic(cir::AtomicFetchKind k,
llvm_unreachable("handled in buildMinMaxPostOp");
case cir::AtomicFetchKind::UIncWrap:
case cir::AtomicFetchKind::UDecWrap:
- llvm_unreachable("uinc_wrap and udec_wrap are always fetch_first");
+ case cir::AtomicFetchKind::Maximum:
+ case cir::AtomicFetchKind::Minimum:
+ case cir::AtomicFetchKind::MaximumNum:
+ case cir::AtomicFetchKind::MinimumNum:
+ llvm_unreachable("uinc_wrap, udec_wrap, maximum, minimum, maximum_num, and "
+ "minimum_num are always fetch_first");
}
llvm_unreachable("Unknown atomic fetch opcode");
}
diff --git a/clang/test/CIR/CodeGen/atomic-scoped.c b/clang/test/CIR/CodeGen/atomic-scoped.c
index 41dfecae102e9..991f19bcbbd7c 100644
--- a/clang/test/CIR/CodeGen/atomic-scoped.c
+++ b/clang/test/CIR/CodeGen/atomic-scoped.c
@@ -349,6 +349,90 @@ void scoped_atomic_max_fetch(int *ptr, int *value) {
// OGCG: atomicrmw max ptr %{{.+}}, i32 %{{.+}} seq_cst, align 4
}
+void scoped_atomic_fetch_fminimum(float *ptr, float value) {
+ // CIR-BEFORE-TL-LABEL: @scoped_atomic_fetch_fminimum
+ // CIR-LABEL: @scoped_atomic_fetch_fminimum
+ // LLVM-LABEL: @scoped_atomic_fetch_fminimum
+ // OGCG-LABEL: @scoped_atomic_fetch_fminimum
+
+ __scoped_atomic_fetch_fminimum(ptr, value, __ATOMIC_SEQ_CST,
+ __MEMORY_SCOPE_SINGLE);
+ // CIR-BEFORE-TL: cir.atomic.fetch minimum seq_cst syncscope(single_thread) fetch_first %{{.+}}, %{{.+}} : (!cir.ptr<!cir.float>, !cir.float) -> !cir.float
+ // CIR: cir.atomic.fetch minimum seq_cst syncscope(system) fetch_first %{{.+}}, %{{.+}} : (!cir.ptr<!cir.float>, !cir.float) -> !cir.float
+ // LLVM: atomicrmw fminimum ptr %{{.+}}, float %{{.+}} seq_cst, align 4
+ // OGCG: atomicrmw fminimum ptr %{{.+}}, float %{{.+}} seq_cst, align 4
+
+ __scoped_atomic_fetch_fminimum(ptr, value, __ATOMIC_SEQ_CST,
+ __MEMORY_SCOPE_SYSTEM);
+ // CIR-BEFORE-TL: cir.atomic.fetch minimum seq_cst syncscope(system) fetch_first %{{.+}}, %{{.+}} : (!cir.ptr<!cir.float>, !cir.float) -> !cir.float
+ // CIR: cir.atomic.fetch minimum seq_cst syncscope(system) fetch_first %{{.+}}, %{{.+}} : (!cir.ptr<!cir.float>, !cir.float) -> !cir.float
+ // LLVM: atomicrmw fminimum ptr %{{.+}}, float %{{.+}} seq_cst, align 4
+ // OGCG: atomicrmw fminimum ptr %{{.+}}, float %{{.+}} seq_cst, align 4
+}
+
+void scoped_atomic_fetch_fmaximum(float *ptr, float value) {
+ // CIR-BEFORE-TL-LABEL: @scoped_atomic_fetch_fmaximum
+ // CIR-LABEL: @scoped_atomic_fetch_fmaximum
+ // LLVM-LABEL: @scoped_atomic_fetch_fmaximum
+ // OGCG-LABEL: @scoped_atomic_fetch_fmaximum
+
+ __scoped_atomic_fetch_fmaximum(ptr, value, __ATOMIC_SEQ_CST,
+ __MEMORY_SCOPE_SINGLE);
+ // CIR-BEFORE-TL: cir.atomic.fetch maximum seq_cst syncscope(single_thread) fetch_first %{{.+}}, %{{.+}} : (!cir.ptr<!cir.float>, !cir.float) -> !cir.float
+ // CIR: cir.atomic.fetch maximum seq_cst syncscope(system) fetch_first %{{.+}}, %{{.+}} : (!cir.ptr<!cir.float>, !cir.float) -> !cir.float
+ // LLVM: atomicrmw fmaximum ptr %{{.+}}, float %{{.+}} seq_cst, align 4
+ // OGCG: atomicrmw fmaximum ptr %{{.+}}, float %{{.+}} seq_cst, align 4
+
+ __scoped_atomic_fetch_fmaximum(ptr, value, __ATOMIC_SEQ_CST,
+ __MEMORY_SCOPE_SYSTEM);
+ // CIR-BEFORE-TL: cir.atomic.fetch maximum seq_cst syncscope(system) fetch_first %{{.+}}, %{{.+}} : (!cir.ptr<!cir.float>, !cir.float) -> !cir.float
+ // CIR: cir.atomic.fetch maximum seq_cst syncscope(system) fetch_first %{{.+}}, %{{.+}} : (!cir.ptr<!cir.float>, !cir.float) -> !cir.float
+ // LLVM: atomicrmw fmaximum ptr %{{.+}}, float %{{.+}} seq_cst, align 4
+ // OGCG: atomicrmw fmaximum ptr %{{.+}}, float %{{.+}} seq_cst, align 4
+}
+
+void scoped_atomic_fetch_fminimum_num(float *ptr, float value) {
+ // CIR-BEFORE-TL-LABEL: @scoped_atomic_fetch_fminimum_num
+ // CIR-LABEL: @scoped_atomic_fetch_fminimum_num
+ // LLVM-LABEL: @scoped_atomic_fetch_fminimum_num
+ // OGCG-LABEL: @scoped_atomic_fetch_fminimum_num
+
+ __scoped_atomic_fetch_fminimum_num(ptr, value, __ATOMIC_SEQ_CST,
+ __MEMORY_SCOPE_SINGLE);
+ // CIR-BEFORE-TL: cir.atomic.fetch minimum_num seq_cst syncscope(single_thread) fetch_first %{{.+}}, %{{.+}} : (!cir.ptr<!cir.float>, !cir.float) -> !cir.float
+ // CIR: cir.atomic.fetch minimum_num seq_cst syncscope(system) fetch_first %{{.+}}, %{{.+}} : (!cir.ptr<!cir.float>, !cir.float) -> !cir.float
+ // LLVM: atomicrmw fminimumnum ptr %{{.+}}, float %{{.+}} seq_cst, align 4
+ // OGCG: atomicrmw fminimumnum ptr %{{.+}}, float %{{.+}} seq_cst, align 4
+
+ __scoped_atomic_fetch_fminimum_num(ptr, value, __ATOMIC_SEQ_CST,
+ __MEMORY_SCOPE_SYSTEM);
+ // CIR-BEFORE-TL: cir.atomic.fetch minimum_num seq_cst syncscope(system) fetch_first %{{.+}}, %{{.+}} : (!cir.ptr<!cir.float>, !cir.float) -> !cir.float
+ // CIR: cir.atomic.fetch minimum_num seq_cst syncscope(system) fetch_first %{{.+}}, %{{.+}} : (!cir.ptr<!cir.float>, !cir.float) -> !cir.float
+ // LLVM: atomicrmw fminimumnum ptr %{{.+}}, float %{{.+}} seq_cst, align 4
+ // OGCG: atomicrmw fminimumnum ptr %{{.+}}, float %{{.+}} seq_cst, align 4
+}
+
+void scoped_atomic_fetch_fmaximum_num(float *ptr, float value) {
+ // CIR-BEFORE-TL-LABEL: @scoped_atomic_fetch_fmaximum_num
+ // CIR-LABEL: @scoped_atomic_fetch_fmaximum_num
+ // LLVM-LABEL: @scoped_atomic_fetch_fmaximum_num
+ // OGCG-LABEL: @scoped_atomic_fetch_fmaximum_num
+
+ __scoped_atomic_fetch_fmaximum_num(ptr, value, __ATOMIC_SEQ_CST,
+ __MEMORY_SCOPE_SINGLE);
+ // CIR-BEFORE-TL: cir.atomic.fetch maximum_num seq_cst syncscope(single_thread) fetch_first %{{.+}}, %{{.+}} : (!cir.ptr<!cir.float>, !cir.float) -> !cir.float
+ // CIR: cir.atomic.fetch maximum_num seq_cst syncscope(system) fetch_first %{{.+}}, %{{.+}} : (!cir.ptr<!cir.float>, !cir.float) -> !cir.float
+ // LLVM: atomicrmw fmaximumnum ptr %{{.+}}, float %{{.+}} seq_cst, align 4
+ // OGCG: atomicrmw fmaximumnum ptr %{{.+}}, float %{{.+}} seq_cst, align 4
+
+ __scoped_atomic_fetch_fmaximum_num(ptr, value, __ATOMIC_SEQ_CST,
+ __MEMORY_SCOPE_SYSTEM);
+ // CIR-BEFORE-TL: cir.atomic.fetch maximum_num seq_cst syncscope(system) fetch_first %{{.+}}, %{{.+}} : (!cir.ptr<!cir.float>, !cir.float) -> !cir.float
+ // CIR: cir.atomic.fetch maximum_num seq_cst syncscope(system) fetch_first %{{.+}}, %{{.+}} : (!cir.ptr<!cir.float>, !cir.float) -> !cir.float
+ // LLVM: atomicrmw fmaximumnum ptr %{{.+}}, float %{{.+}} seq_cst, align 4
+ // OGCG: atomicrmw fmaximumnum ptr %{{.+}}, float %{{.+}} seq_cst, align 4
+}
+
void scoped_atomic_fetch_and(int *ptr, int *value) {
// CIR-BEFORE-TL-LABEL: @scoped_atomic_fetch_and
// CIR-LABEL: @scoped_atomic_fetch_and
diff --git a/clang/test/CIR/CodeGen/atomic.c b/clang/test/CIR/CodeGen/atomic.c
index 1d6114a5e298b..bbacab6dd22cc 100644
--- a/clang/test/CIR/CodeGen/atomic.c
+++ b/clang/test/CIR/CodeGen/atomic.c
@@ -1569,6 +1569,66 @@ float c11_atomic_fetch_max_fp(_Atomic(float) *ptr, float value) {
// OGCG-NEXT: store float %[[RES]], ptr %{{.+}}, align 4
}
+float atomic_fetch_fminimum_fp(float *ptr, float value) {
+ // CIR-LABEL: @atomic_fetch_fminimum_fp
+ // LLVM-LABEL: @atomic_fetch_fminimum_fp
+ // OGCG-LABEL: @atomic_fetch_fminimum_fp
+
+ return __atomic_fetch_fminimum(ptr, value, __ATOMIC_SEQ_CST);
+ // CIR: %{{.+}} = cir.atomic.fetch minimum seq_cst syncscope(system) fetch_first %{{.+}}, %{{.+}} : (!cir.ptr<!cir.float>, !cir.float) -> !cir.float
+
+ // LLVM: %[[RES:.+]] = atomicrmw fminimum ptr %{{.+}}, float %{{.+}} seq_cst, align 4
+ // LLVM-NEXT: store float %[[RES]], ptr %{{.+}}, align 4
+
+ // OGCG: %[[RES:.+]] = atomicrmw fminimum ptr %{{.+}}, float %{{.+}} seq_cst, align 4
+ // OGCG-NEXT: store float %[[RES]], ptr %{{.+}}, align 4
+}
+
+float atomic_fetch_fmaximum_fp(float *ptr, float value) {
+ // CIR-LABEL: @atomic_fetch_fmaximum_fp
+ // LLVM-LABEL: @atomic_fetch_fmaximum_fp
+ // OGCG-LABEL: @atomic_fetch_fmaximum_fp
+
+ return __atomic_fetch_fmaximum(ptr, value, __ATOMIC_SEQ_CST);
+ // CIR: %{{.+}} = cir.atomic.fetch maximum seq_cst syncscope(system) fetch_first %{{.+}}, %{{.+}} : (!cir.ptr<!cir.float>, !cir.float) -> !cir.float
+
+ // LLVM: %[[RES:.+]] = atomicrmw fmaximum ptr %{{.+}}, float %{{.+}} seq_cst, align 4
+ // LLVM-NEXT: store float %[[RES]], ptr %{{.+}} align 4
+
+ // OGCG: %[[RES:.+]] = atomicrmw fmaximum ptr %{{.+}}, float %{{.+}} seq_cst, align 4
+ // OGCG-NEXT: store float %[[RES]], ptr %{{.+}} align 4
+}
+
+float atomic_fetch_fminimum_num_fp(float *ptr, float value) {
+ // CIR-LABEL: @atomic_fetch_fminimum_num_fp
+ // LLVM-LABEL: @atomic_fetch_fminimum_num_fp
+ // OGCG-LABEL: @atomic_fetch_fminimum_num_fp
+
+ return __atomic_fetch_fminimum_num(ptr, value, __ATOMIC_SEQ_CST);
+ // CIR: %{{.+}} = cir.atomic.fetch minimum_num seq_cst syncscope(system) fetch_first %{{.+}}, %{{.+}} : (!cir.ptr<!cir.float>, !cir.float) -> !cir.float
+
+ // LLVM: %[[RES:.+]] = atomicrmw fminimumnum ptr %{{.+}}, float %{{.+}} seq_cst, align 4
+ // LLVM-NEXT: store float %[[RES]], ptr %{{.+}} align 4
+
+ // OGCG: %[[RES:.+]] = atomicrmw fminimumnum ptr %{{.+}}, float %{{.+}} seq_cst, align 4
+ // OGCG-NEXT: store float %[[RES]], ptr %{{.+}} align 4
+}
+
+float atomic_fetch_fmaximum_num_fp(float *ptr, float value) {
+ // CIR-LABEL: @atomic_fetch_fmaximum_num_fp
+ // LLVM-LABEL: @atomic_fetch_fmaximum_num_fp
+ // OGCG-LABEL: @atomic_fetch_fmaximum_num_fp
+
+ return __atomic_fetch_fmaximum_num(ptr, value, __ATOMIC_SEQ_CST);
+ // CIR: %{{.+}} = cir.atomic.fetch maximum_num seq_cst syncscope(system) fetch_first %{{.+}}, %{{.+}} : (!cir.ptr<!cir.float>, !cir.float) -> !cir.float
+
+ // LLVM: %[[RES:.+]] = atomicrmw fmaximumnum ptr %{{.+}}, float %{{.+}} seq_cst, align 4
+ // LLVM-NEXT: store float %[[RES]], ptr %{{.+}} align 4
+
+ // OGCG: %[[RES:.+]] = atomicrmw fmaximumnum ptr %{{.+}}, float %{{.+}} seq_cst, align 4
+ // OGCG-NEXT: store float %[[RES]], ptr %{{.+}} align 4
+}
+
int atomic_fetch_and(int *ptr, int value) {
// CIR-LABEL: @atomic_fetch_and
// LLVM-LABEL: @atomic_fetch_and
diff --git a/clang/test/CIR/IR/invalid-atomic.cir b/clang/test/CIR/IR/invalid-atomic.cir
index e3ab3bfd43fb6..9a1bf41b93c7e 100644
--- a/clang/test/CIR/IR/invalid-atomic.cir
+++ b/clang/test/CIR/IR/invalid-atomic.cir
@@ -1,7 +1,15 @@
// RUN: cir-opt %s -verify-diagnostics -split-input-file
+!s32i = !cir.int<s, 32>
+
cir.func @f1(%arg0: !cir.ptr<!cir.float>, %arg1: !cir.float) {
- // expected-error @below {{only atomic add, sub, max, and min operation could operate on floating-point values}}
+ // expected-error @below {{only atomic add, sub, max, min, maximum, minimum, maximum_num, and minimum_num operation could operate on floating-point values}}
%0 = cir.atomic.fetch and seq_cst syncscope(system) %arg0, %arg1 : (!cir.ptr<!cir.float>, !cir.float) -> !cir.float
cir.return
}
+
+cir.func @f2(%arg0: !cir.ptr<!s32i>, %arg1: !s32i) {
+ // expected-error @below {{atomic maximum, minimum, maximum_num, and minimum_num operation could only operate on floating-point values}}
+ %0 = cir.atomic.fetch maximum seq_cst syncscope(system) %arg0, %arg1 : (!cir.ptr<!s32i>, !s32i) -> !s32i
+ cir.return
+}
More information about the cfe-commits
mailing list