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
