Author: Sirui Mu
Date: 2026-07-25T12:22:52+08:00
New Revision: bf7b5a0fedb924e7f3db3423cbeb97c343c37b25

URL: 
https://github.com/llvm/llvm-project/commit/bf7b5a0fedb924e7f3db3423cbeb97c343c37b25
DIFF: 
https://github.com/llvm/llvm-project/commit/bf7b5a0fedb924e7f3db3423cbeb97c343c37b25.diff

LOG: [CIR] Add support for atomic fmaximum/fminimum/fmaximumnum/fminimumnum 
(#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

Added: 
    

Modified: 
    clang/include/clang/CIR/Dialect/IR/CIROps.td
    clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
    clang/lib/CIR/Dialect/IR/CIRDialect.cpp
    clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
    clang/test/CIR/CodeGen/atomic-scoped.c
    clang/test/CIR/CodeGen/atomic.c
    clang/test/CIR/IR/invalid-atomic.cir

Removed: 
    


################################################################################
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 
diff erence 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 
diff erence 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 f269349d81551..a305c135539e9 100644
--- a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
@@ -763,6 +763,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;
@@ -773,6 +787,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;
@@ -878,15 +906,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;
   }
@@ -1496,6 +1515,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:
@@ -1532,6 +1555,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 7b28e4209c6d8..b30172431cbfc 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 0ae4167aed7a2..d6b93c387f2bd 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
+}


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

Reply via email to