[llvm] [atomicrmw] fminimumnum/fmaximumnum support (PR #187030)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Mar 17 07:26:39 PDT 2026
https://github.com/gonzalobg created https://github.com/llvm/llvm-project/pull/187030
None
>From a0c99409ec2973ef1f01926f522a504e10908ca7 Mon Sep 17 00:00:00 2001
From: Gonzalo Brito Gadeschi <gonzalob at nvidia.com>
Date: Tue, 17 Mar 2026 07:25:48 -0700
Subject: [PATCH] [atomicrmw] fminimumnum/fmaximumnum support
---
llvm/docs/LangRef.rst | 6 +-
llvm/include/llvm-c/Core.h | 6 ++
llvm/include/llvm/AsmParser/LLToken.h | 2 +
llvm/include/llvm/Bitcode/LLVMBitCodes.h | 2 +
llvm/include/llvm/CodeGen/ISDOpcodes.h | 2 +
llvm/include/llvm/IR/Instructions.h | 10 +++
llvm/include/llvm/Support/TargetOpcodes.def | 2 +
llvm/include/llvm/Target/GenericOpcodes.td | 2 +
llvm/lib/AsmParser/LLLexer.cpp | 2 +
llvm/lib/AsmParser/LLParser.cpp | 8 ++
llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 4 +
llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 4 +
llvm/lib/CodeGen/AtomicExpandPass.cpp | 4 +
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 6 ++
.../SelectionDAG/SelectionDAGBuilder.cpp | 6 ++
llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp | 2 +
llvm/lib/IR/Core.cpp | 8 ++
llvm/lib/IR/Instructions.cpp | 4 +
.../AMDGPU/AMDGPULowerBufferFatPointers.cpp | 12 +++
llvm/lib/Transforms/Utils/LowerAtomic.cpp | 4 +
llvm/test/Assembler/atomic.ll | 18 ++++
llvm/test/Bitcode/compatibility.ll | 6 ++
.../GlobalISel/legalizer-info-validation.mir | 6 ++
.../AtomicExpand/AArch64/atomicrmw-fp.ll | 84 +++++++++++++++++++
24 files changed, 209 insertions(+), 1 deletion(-)
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 45a22f416dce1..13883883d3981 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -12128,6 +12128,8 @@ operation. The operation must be one of the following keywords:
- fmin
- fmaximum
- fminimum
+- fmaximumnum
+- fminimumnum
- uinc_wrap
- udec_wrap
- usub_cond
@@ -12137,7 +12139,7 @@ For most of these operations, the type of '<value>' must be an integer
type whose bit width is a power of two greater than or equal to eight.
For xchg, this
may also be a floating point or a pointer type with the same size constraints
-as integers. For fadd/fsub/fmax/fmin/fmaximum/fminimum, this must be a floating-point
+as integers. For fadd/fsub/fmax/fmin/fmaximum/fminimum/fmaximumnum/fminimumnum, this must be a floating-point
or fixed vector of floating-point type. The type of the '``<pointer>``'
operand must be a pointer to that type. If the ``atomicrmw`` is marked
as ``volatile``, then the optimizer is not allowed to modify the
@@ -12182,6 +12184,8 @@ operation argument:
- fmin: ``*ptr = minnum(*ptr, val)`` (match the `llvm.minnum.*` intrinsic)
- fmaximum: ``*ptr = maximum(*ptr, val)`` (match the `llvm.maximum.*` intrinsic)
- fminimum: ``*ptr = minimum(*ptr, val)`` (match the `llvm.minimum.*` intrinsic)
+- fmaximumnum: ``*ptr = maximumnum(*ptr, val)`` (match the `llvm.maximumnum.*` intrinsic)
+- fminimumnum: ``*ptr = minimumnum(*ptr, val)`` (match the `llvm.minimumnum.*` intrinsic)
- uinc_wrap: ``*ptr = (*ptr u>= val) ? 0 : (*ptr + 1)`` (increment value with wraparound to zero when incremented above input value)
- udec_wrap: ``*ptr = ((*ptr == 0) || (*ptr u> val)) ? val : (*ptr - 1)`` (decrement with wraparound to input value when decremented below zero).
- usub_cond: ``*ptr = (*ptr u>= val) ? *ptr - val : *ptr`` (subtract only if no unsigned overflow).
diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h
index 9dba8a905753a..ca71f4a90b41b 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -405,6 +405,12 @@ typedef enum {
LLVMAtomicRMWBinOpFMinimum, /**< Sets the value if it's smaller than the
original using an floating point comparison and
return the old one */
+ LLVMAtomicRMWBinOpFMaximumNum, /**< Sets the value if it's greater than the
+ original using an floating point comparison and
+ return the old one */
+ LLVMAtomicRMWBinOpFMinimumNum, /**< Sets the value if it's smaller than the
+ original using an floating point comparison and
+ return the old one */
} LLVMAtomicRMWBinOp;
typedef enum {
diff --git a/llvm/include/llvm/AsmParser/LLToken.h b/llvm/include/llvm/AsmParser/LLToken.h
index 6c92c82188f1a..d0827c9f5b8e9 100644
--- a/llvm/include/llvm/AsmParser/LLToken.h
+++ b/llvm/include/llvm/AsmParser/LLToken.h
@@ -291,6 +291,8 @@ enum Kind {
kw_fmin,
kw_fmaximum,
kw_fminimum,
+ kw_fmaximumnum,
+ kw_fminimumnum,
kw_uinc_wrap,
kw_udec_wrap,
kw_usub_cond,
diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
index 4ac3029175d0d..d9614bce54503 100644
--- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
@@ -520,6 +520,8 @@ enum RMWOperations {
RMW_USUB_SAT = 18,
RMW_FMAXIMUM = 19,
RMW_FMINIMUM = 20,
+ RMW_FMAXIMUMNUM = 21,
+ RMW_FMINIMUMNUM = 22,
};
/// OverflowingBinaryOperatorOptionalFlags - Flags for serializing
diff --git a/llvm/include/llvm/CodeGen/ISDOpcodes.h b/llvm/include/llvm/CodeGen/ISDOpcodes.h
index fa578f733d4e8..eac6faceafd0c 100644
--- a/llvm/include/llvm/CodeGen/ISDOpcodes.h
+++ b/llvm/include/llvm/CodeGen/ISDOpcodes.h
@@ -1411,6 +1411,8 @@ enum NodeType {
ATOMIC_LOAD_FMIN,
ATOMIC_LOAD_FMAXIMUM,
ATOMIC_LOAD_FMINIMUM,
+ ATOMIC_LOAD_FMAXIMUMNUM,
+ ATOMIC_LOAD_FMINIMUMNUM,
ATOMIC_LOAD_UINC_WRAP,
ATOMIC_LOAD_UDEC_WRAP,
ATOMIC_LOAD_USUB_COND,
diff --git a/llvm/include/llvm/IR/Instructions.h b/llvm/include/llvm/IR/Instructions.h
index 170b2899bcc4d..692dfe6dd19c4 100644
--- a/llvm/include/llvm/IR/Instructions.h
+++ b/llvm/include/llvm/IR/Instructions.h
@@ -765,6 +765,14 @@ class AtomicRMWInst : public Instruction {
/// \p minimum matches the behavior of \p llvm.minimum.*.
FMinimum,
+ /// *p = maximumnum(old, v)
+ /// \p maximumnum matches the behavior of \p llvm.maximumnum.*.
+ FMaximumNum,
+
+ /// *p = minimumnum(old, v)
+ /// \p minimumnum matches the behavior of \p llvm.minimumnum.*.
+ FMinimumNum,
+
/// Increment one up to a maximum value.
/// *p = (old u>= v) ? 0 : (old + 1)
UIncWrap,
@@ -829,6 +837,8 @@ class AtomicRMWInst : public Instruction {
case AtomicRMWInst::FMin:
case AtomicRMWInst::FMaximum:
case AtomicRMWInst::FMinimum:
+ case AtomicRMWInst::FMaximumNum:
+ case AtomicRMWInst::FMinimumNum:
return true;
default:
return false;
diff --git a/llvm/include/llvm/Support/TargetOpcodes.def b/llvm/include/llvm/Support/TargetOpcodes.def
index e1809e364ad83..6bfda3122141f 100644
--- a/llvm/include/llvm/Support/TargetOpcodes.def
+++ b/llvm/include/llvm/Support/TargetOpcodes.def
@@ -448,6 +448,8 @@ HANDLE_TARGET_OPCODE(G_ATOMICRMW_FMAX)
HANDLE_TARGET_OPCODE(G_ATOMICRMW_FMIN)
HANDLE_TARGET_OPCODE(G_ATOMICRMW_FMAXIMUM)
HANDLE_TARGET_OPCODE(G_ATOMICRMW_FMINIMUM)
+HANDLE_TARGET_OPCODE(G_ATOMICRMW_FMAXIMUMNUM)
+HANDLE_TARGET_OPCODE(G_ATOMICRMW_FMINIMUMNUM)
HANDLE_TARGET_OPCODE(G_ATOMICRMW_UINC_WRAP)
HANDLE_TARGET_OPCODE(G_ATOMICRMW_UDEC_WRAP)
HANDLE_TARGET_OPCODE(G_ATOMICRMW_USUB_COND)
diff --git a/llvm/include/llvm/Target/GenericOpcodes.td b/llvm/include/llvm/Target/GenericOpcodes.td
index b785847b53f0f..1ff6d0de3d8c4 100644
--- a/llvm/include/llvm/Target/GenericOpcodes.td
+++ b/llvm/include/llvm/Target/GenericOpcodes.td
@@ -1442,6 +1442,8 @@ def G_ATOMICRMW_FMAX : G_ATOMICRMW_OP;
def G_ATOMICRMW_FMIN : G_ATOMICRMW_OP;
def G_ATOMICRMW_FMAXIMUM : G_ATOMICRMW_OP;
def G_ATOMICRMW_FMINIMUM : G_ATOMICRMW_OP;
+def G_ATOMICRMW_FMAXIMUMNUM : G_ATOMICRMW_OP;
+def G_ATOMICRMW_FMINIMUMNUM : G_ATOMICRMW_OP;
def G_ATOMICRMW_UINC_WRAP : G_ATOMICRMW_OP;
def G_ATOMICRMW_UDEC_WRAP : G_ATOMICRMW_OP;
def G_ATOMICRMW_USUB_COND : G_ATOMICRMW_OP;
diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp
index bfc5f64a78838..320c230469573 100644
--- a/llvm/lib/AsmParser/LLLexer.cpp
+++ b/llvm/lib/AsmParser/LLLexer.cpp
@@ -778,6 +778,8 @@ lltok::Kind LLLexer::LexIdentifier() {
KEYWORD(umin); KEYWORD(fmax); KEYWORD(fmin);
KEYWORD(fmaximum);
KEYWORD(fminimum);
+ KEYWORD(fmaximumnum);
+ KEYWORD(fminimumnum);
KEYWORD(uinc_wrap);
KEYWORD(udec_wrap);
KEYWORD(usub_cond);
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 09b893b33786d..0c4e0a2996fce 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -9009,6 +9009,14 @@ int LLParser::parseAtomicRMW(Instruction *&Inst, PerFunctionState &PFS) {
Operation = AtomicRMWInst::FMinimum;
IsFP = true;
break;
+ case lltok::kw_fmaximumnum:
+ Operation = AtomicRMWInst::FMaximumNum;
+ IsFP = true;
+ break;
+ case lltok::kw_fminimumnum:
+ Operation = AtomicRMWInst::FMinimumNum;
+ IsFP = true;
+ break;
}
Lex.Lex(); // Eat the operation.
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index d6d28ca7b5ae7..073c1f5916089 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -1386,6 +1386,10 @@ static AtomicRMWInst::BinOp getDecodedRMWOperation(unsigned Val) {
return AtomicRMWInst::FMaximum;
case bitc::RMW_FMINIMUM:
return AtomicRMWInst::FMinimum;
+ case bitc::RMW_FMAXIMUMNUM:
+ return AtomicRMWInst::FMaximumNum;
+ case bitc::RMW_FMINIMUMNUM:
+ return AtomicRMWInst::FMinimumNum;
case bitc::RMW_UINC_WRAP:
return AtomicRMWInst::UIncWrap;
case bitc::RMW_UDEC_WRAP:
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index ce7449354ba8e..cdc6b2af9501a 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -712,6 +712,10 @@ static unsigned getEncodedRMWOperation(AtomicRMWInst::BinOp Op) {
return bitc::RMW_FMAXIMUM;
case AtomicRMWInst::FMinimum:
return bitc::RMW_FMINIMUM;
+ case AtomicRMWInst::FMaximumNum:
+ return bitc::RMW_FMAXIMUMNUM;
+ case AtomicRMWInst::FMinimumNum:
+ return bitc::RMW_FMINIMUMNUM;
case AtomicRMWInst::UIncWrap:
return bitc::RMW_UINC_WRAP;
case AtomicRMWInst::UDecWrap:
diff --git a/llvm/lib/CodeGen/AtomicExpandPass.cpp b/llvm/lib/CodeGen/AtomicExpandPass.cpp
index 341a4618dbb47..2bcd7fb3f62e7 100644
--- a/llvm/lib/CodeGen/AtomicExpandPass.cpp
+++ b/llvm/lib/CodeGen/AtomicExpandPass.cpp
@@ -967,6 +967,8 @@ static Value *performMaskedAtomicOp(AtomicRMWInst::BinOp Op,
case AtomicRMWInst::FMax:
case AtomicRMWInst::FMaximum:
case AtomicRMWInst::FMinimum:
+ case AtomicRMWInst::FMaximumNum:
+ case AtomicRMWInst::FMinimumNum:
case AtomicRMWInst::UIncWrap:
case AtomicRMWInst::UDecWrap:
case AtomicRMWInst::USubCond:
@@ -1881,6 +1883,8 @@ static ArrayRef<RTLIB::Libcall> GetRMWLibcall(AtomicRMWInst::BinOp Op) {
case AtomicRMWInst::FMin:
case AtomicRMWInst::FMaximum:
case AtomicRMWInst::FMinimum:
+ case AtomicRMWInst::FMaximumNum:
+ case AtomicRMWInst::FMinimumNum:
case AtomicRMWInst::FAdd:
case AtomicRMWInst::FSub:
case AtomicRMWInst::UIncWrap:
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index a7603dd272a92..346c37b04ac66 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -3598,6 +3598,12 @@ bool IRTranslator::translateAtomicRMW(const User &U,
case AtomicRMWInst::FMinimum:
Opcode = TargetOpcode::G_ATOMICRMW_FMINIMUM;
break;
+ case AtomicRMWInst::FMaximumNum:
+ Opcode = TargetOpcode::G_ATOMICRMW_FMAXIMUMNUM;
+ break;
+ case AtomicRMWInst::FMinimumNum:
+ Opcode = TargetOpcode::G_ATOMICRMW_FMINIMUMNUM;
+ break;
case AtomicRMWInst::UIncWrap:
Opcode = TargetOpcode::G_ATOMICRMW_UINC_WRAP;
break;
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index eb55a68eaba84..04b17b56b3d49 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -5251,6 +5251,12 @@ void SelectionDAGBuilder::visitAtomicRMW(const AtomicRMWInst &I) {
case AtomicRMWInst::FMinimum:
NT = ISD::ATOMIC_LOAD_FMINIMUM;
break;
+ case AtomicRMWInst::FMaximumNum:
+ NT = ISD::ATOMIC_LOAD_FMAXIMUMNUM;
+ break;
+ case AtomicRMWInst::FMinimumNum:
+ NT = ISD::ATOMIC_LOAD_FMINIMUMNUM;
+ break;
case AtomicRMWInst::UIncWrap:
NT = ISD::ATOMIC_LOAD_UINC_WRAP;
break;
diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
index 8148e113195cc..a1a25075f3703 100644
--- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -10445,6 +10445,8 @@ Value *OpenMPIRBuilder::emitRMWOpAsInstruction(Value *Src1, Value *Src2,
case AtomicRMWInst::FMin:
case AtomicRMWInst::FMaximum:
case AtomicRMWInst::FMinimum:
+ case AtomicRMWInst::FMaximumNum:
+ case AtomicRMWInst::FMinimumNum:
case AtomicRMWInst::UIncWrap:
case AtomicRMWInst::UDecWrap:
case AtomicRMWInst::USubCond:
diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
index f91439f410eaa..375fdc68d4e45 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -4102,6 +4102,10 @@ static AtomicRMWInst::BinOp mapFromLLVMRMWBinOp(LLVMAtomicRMWBinOp BinOp) {
return AtomicRMWInst::FMaximum;
case LLVMAtomicRMWBinOpFMinimum:
return AtomicRMWInst::FMinimum;
+ case LLVMAtomicRMWBinOpFMaximumNum:
+ return AtomicRMWInst::FMaximumNum;
+ case LLVMAtomicRMWBinOpFMinimumNum:
+ return AtomicRMWInst::FMinimumNum;
case LLVMAtomicRMWBinOpUIncWrap:
return AtomicRMWInst::UIncWrap;
case LLVMAtomicRMWBinOpUDecWrap:
@@ -4136,6 +4140,10 @@ static LLVMAtomicRMWBinOp mapToLLVMRMWBinOp(AtomicRMWInst::BinOp BinOp) {
return LLVMAtomicRMWBinOpFMaximum;
case AtomicRMWInst::FMinimum:
return LLVMAtomicRMWBinOpFMinimum;
+ case AtomicRMWInst::FMaximumNum:
+ return LLVMAtomicRMWBinOpFMaximumNum;
+ case AtomicRMWInst::FMinimumNum:
+ return LLVMAtomicRMWBinOpFMinimumNum;
case AtomicRMWInst::UIncWrap:
return LLVMAtomicRMWBinOpUIncWrap;
case AtomicRMWInst::UDecWrap:
diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp
index 0485af358e2c4..516bcee843b3b 100644
--- a/llvm/lib/IR/Instructions.cpp
+++ b/llvm/lib/IR/Instructions.cpp
@@ -1493,6 +1493,10 @@ StringRef AtomicRMWInst::getOperationName(BinOp Op) {
return "fmaximum";
case AtomicRMWInst::FMinimum:
return "fminimum";
+ case AtomicRMWInst::FMaximumNum:
+ return "fmaximumnum";
+ case AtomicRMWInst::FMinimumNum:
+ return "fminimumnum";
case AtomicRMWInst::UIncWrap:
return "uinc_wrap";
case AtomicRMWInst::UDecWrap:
diff --git a/llvm/lib/Target/AMDGPU/AMDGPULowerBufferFatPointers.cpp b/llvm/lib/Target/AMDGPU/AMDGPULowerBufferFatPointers.cpp
index 3ab23562ff1f9..4c1fd1ee660de 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPULowerBufferFatPointers.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPULowerBufferFatPointers.cpp
@@ -1774,6 +1774,18 @@ Value *SplitPtrStructs::handleMemoryInst(Instruction *I, Value *Arg, Value *Ptr,
"buffer resources and should've been expanded away");
break;
}
+ case AtomicRMWInst::FMaximumNum: {
+ reportFatalUsageError(
+ "atomic floating point fmaximumnum not supported for "
+ "buffer resources and should've been expanded away");
+ break;
+ }
+ case AtomicRMWInst::FMinimumNum: {
+ reportFatalUsageError(
+ "atomic floating point fminimumnum not supported for "
+ "buffer resources and should've been expanded away");
+ break;
+ }
case AtomicRMWInst::Nand:
reportFatalUsageError(
"atomic nand not supported for buffer resources and "
diff --git a/llvm/lib/Transforms/Utils/LowerAtomic.cpp b/llvm/lib/Transforms/Utils/LowerAtomic.cpp
index e8b06415d4062..d4c0602f6ce52 100644
--- a/llvm/lib/Transforms/Utils/LowerAtomic.cpp
+++ b/llvm/lib/Transforms/Utils/LowerAtomic.cpp
@@ -92,6 +92,10 @@ Value *llvm::buildAtomicRMWValue(AtomicRMWInst::BinOp Op,
return Builder.CreateMaximum(Loaded, Val);
case AtomicRMWInst::FMinimum:
return Builder.CreateMinimum(Loaded, Val);
+ case AtomicRMWInst::FMaximumNum:
+ return Builder.CreateMaximumNum(Loaded, Val);
+ case AtomicRMWInst::FMinimumNum:
+ return Builder.CreateMinimumNum(Loaded, Val);
case AtomicRMWInst::UIncWrap: {
Constant *One = ConstantInt::get(Loaded->getType(), 1);
Value *Inc = Builder.CreateAdd(Loaded, One);
diff --git a/llvm/test/Assembler/atomic.ll b/llvm/test/Assembler/atomic.ll
index 6609edc2953cc..0ed34f0ad98ef 100644
--- a/llvm/test/Assembler/atomic.ll
+++ b/llvm/test/Assembler/atomic.ll
@@ -111,6 +111,18 @@ define void @fp_atomics(ptr %x) {
; CHECK: atomicrmw volatile fminimum ptr %x, float 1.000000e+00 seq_cst
atomicrmw volatile fminimum ptr %x, float 1.0 seq_cst
+ ; CHECK: atomicrmw fmaximumnum ptr %x, float 1.000000e+00 seq_cst
+ atomicrmw fmaximumnum ptr %x, float 1.0 seq_cst
+
+ ; CHECK: atomicrmw volatile fmaximumnum ptr %x, float 1.000000e+00 seq_cst
+ atomicrmw volatile fmaximumnum ptr %x, float 1.0 seq_cst
+
+ ; CHECK: atomicrmw fminimumnum ptr %x, float 1.000000e+00 seq_cst
+ atomicrmw fminimumnum ptr %x, float 1.0 seq_cst
+
+ ; CHECK: atomicrmw volatile fminimumnum ptr %x, float 1.000000e+00 seq_cst
+ atomicrmw volatile fminimumnum ptr %x, float 1.0 seq_cst
+
ret void
}
@@ -133,5 +145,11 @@ define void @fp_vector_atomicrmw(ptr %x, <2 x half> %val) {
; CHECK: %atomic.fminimum = atomicrmw fminimum ptr %x, <2 x half> %val seq_cst
%atomic.fminimum = atomicrmw fminimum ptr %x, <2 x half> %val seq_cst
+ ; CHECK: %atomic.fmaximumnum = atomicrmw fmaximumnum ptr %x, <2 x half> %val seq_cst
+ %atomic.fmaximumnum = atomicrmw fmaximumnum ptr %x, <2 x half> %val seq_cst
+
+ ; CHECK: %atomic.fminimumnum = atomicrmw fminimumnum ptr %x, <2 x half> %val seq_cst
+ %atomic.fminimumnum = atomicrmw fminimumnum ptr %x, <2 x half> %val seq_cst
+
ret void
}
diff --git a/llvm/test/Bitcode/compatibility.ll b/llvm/test/Bitcode/compatibility.ll
index 06e7fc0096a53..c87159fe960f3 100644
--- a/llvm/test/Bitcode/compatibility.ll
+++ b/llvm/test/Bitcode/compatibility.ll
@@ -955,6 +955,12 @@ define void @fp_atomics(ptr %word) {
; CHECK: %atomicrmw.fminimum = atomicrmw fminimum ptr %word, float 1.000000e+00 monotonic
%atomicrmw.fminimum = atomicrmw fminimum ptr %word, float 1.0 monotonic
+; CHECK: %atomicrmw.fmaximumnum = atomicrmw fmaximumnum ptr %word, float 1.000000e+00 monotonic
+ %atomicrmw.fmaximumnum = atomicrmw fmaximumnum ptr %word, float 1.0 monotonic
+
+; CHECK: %atomicrmw.fminimumnum = atomicrmw fminimumnum ptr %word, float 1.000000e+00 monotonic
+ %atomicrmw.fminimumnum = atomicrmw fminimumnum ptr %word, float 1.0 monotonic
+
ret void
}
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
index 655e793f55c59..cbda65862d4c4 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
@@ -295,6 +295,12 @@
# DEBUG-NEXT: G_ATOMICRMW_FMINIMUM (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
+# DEBUG-NEXT: G_ATOMICRMW_FMAXIMUMNUM (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
+# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
+# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
+# DEBUG-NEXT: G_ATOMICRMW_FMINIMUMNUM (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
+# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
+# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
# DEBUG-NEXT: G_ATOMICRMW_UINC_WRAP (opcode {{[0-9]+}}): 2 type indices, 0 imm indices
# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
diff --git a/llvm/test/Transforms/AtomicExpand/AArch64/atomicrmw-fp.ll b/llvm/test/Transforms/AtomicExpand/AArch64/atomicrmw-fp.ll
index 3e7468a2c8f38..c8395738177ea 100644
--- a/llvm/test/Transforms/AtomicExpand/AArch64/atomicrmw-fp.ll
+++ b/llvm/test/Transforms/AtomicExpand/AArch64/atomicrmw-fp.ll
@@ -337,6 +337,90 @@ define <2 x half> @atomicrmw_fminimum_2_x_half(ptr %ptr, <2 x half> %val) {
ret <2 x half> %res
}
+define float @atomicrmw_fmaximumnum_float(ptr %ptr, float %value) {
+; CHECK-LABEL: @atomicrmw_fmaximumnum_float(
+; CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[PTR:%.*]], align 4
+; CHECK-NEXT: br label [[ATOMICRMW_START:%.*]]
+; CHECK: atomicrmw.start:
+; CHECK-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ]
+; CHECK-NEXT: [[TMP2:%.*]] = call float @llvm.maximumnum.f32(float [[LOADED]], float [[VALUE:%.*]])
+; CHECK-NEXT: [[TMP3:%.*]] = bitcast float [[TMP2]] to i32
+; CHECK-NEXT: [[TMP4:%.*]] = bitcast float [[LOADED]] to i32
+; CHECK-NEXT: [[TMP5:%.*]] = cmpxchg ptr [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4
+; CHECK-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1
+; CHECK-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0
+; CHECK-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to float
+; CHECK-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]]
+; CHECK: atomicrmw.end:
+; CHECK-NEXT: ret float [[TMP6]]
+;
+ %res = atomicrmw fmaximumnum ptr %ptr, float %value seq_cst
+ ret float %res
+}
+
+define float @atomicrmw_fminimumnum_float(ptr %ptr, float %value) {
+; CHECK-LABEL: @atomicrmw_fminimumnum_float(
+; CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[PTR:%.*]], align 4
+; CHECK-NEXT: br label [[ATOMICRMW_START:%.*]]
+; CHECK: atomicrmw.start:
+; CHECK-NEXT: [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ]
+; CHECK-NEXT: [[TMP2:%.*]] = call float @llvm.minimumnum.f32(float [[LOADED]], float [[VALUE:%.*]])
+; CHECK-NEXT: [[TMP3:%.*]] = bitcast float [[TMP2]] to i32
+; CHECK-NEXT: [[TMP4:%.*]] = bitcast float [[LOADED]] to i32
+; CHECK-NEXT: [[TMP5:%.*]] = cmpxchg ptr [[PTR]], i32 [[TMP4]], i32 [[TMP3]] seq_cst seq_cst, align 4
+; CHECK-NEXT: [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1
+; CHECK-NEXT: [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0
+; CHECK-NEXT: [[TMP6]] = bitcast i32 [[NEWLOADED]] to float
+; CHECK-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]]
+; CHECK: atomicrmw.end:
+; CHECK-NEXT: ret float [[TMP6]]
+;
+ %res = atomicrmw fminimumnum ptr %ptr, float %value seq_cst
+ ret float %res
+}
+
+define double @atomicrmw_fmaximumnum_double(ptr %ptr, double %value) {
+; CHECK-LABEL: @atomicrmw_fmaximumnum_double(
+; CHECK-NEXT: [[TMP1:%.*]] = load double, ptr [[PTR:%.*]], align 8
+; CHECK-NEXT: br label [[ATOMICRMW_START:%.*]]
+; CHECK: atomicrmw.start:
+; CHECK-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ]
+; CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.maximumnum.f64(double [[LOADED]], double [[VALUE:%.*]])
+; CHECK-NEXT: [[TMP3:%.*]] = bitcast double [[TMP2]] to i64
+; CHECK-NEXT: [[TMP4:%.*]] = bitcast double [[LOADED]] to i64
+; CHECK-NEXT: [[TMP5:%.*]] = cmpxchg ptr [[PTR]], i64 [[TMP4]], i64 [[TMP3]] seq_cst seq_cst, align 8
+; CHECK-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP5]], 1
+; CHECK-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP5]], 0
+; CHECK-NEXT: [[TMP6]] = bitcast i64 [[NEWLOADED]] to double
+; CHECK-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]]
+; CHECK: atomicrmw.end:
+; CHECK-NEXT: ret double [[TMP6]]
+;
+ %res = atomicrmw fmaximumnum ptr %ptr, double %value seq_cst
+ ret double %res
+}
+
+define double @atomicrmw_fminimumnum_double(ptr %ptr, double %value) {
+; CHECK-LABEL: @atomicrmw_fminimumnum_double(
+; CHECK-NEXT: [[TMP1:%.*]] = load double, ptr [[PTR:%.*]], align 8
+; CHECK-NEXT: br label [[ATOMICRMW_START:%.*]]
+; CHECK: atomicrmw.start:
+; CHECK-NEXT: [[LOADED:%.*]] = phi double [ [[TMP1]], [[TMP0:%.*]] ], [ [[TMP6:%.*]], [[ATOMICRMW_START]] ]
+; CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.minimumnum.f64(double [[LOADED]], double [[VALUE:%.*]])
+; CHECK-NEXT: [[TMP3:%.*]] = bitcast double [[TMP2]] to i64
+; CHECK-NEXT: [[TMP4:%.*]] = bitcast double [[LOADED]] to i64
+; CHECK-NEXT: [[TMP5:%.*]] = cmpxchg ptr [[PTR]], i64 [[TMP4]], i64 [[TMP3]] seq_cst seq_cst, align 8
+; CHECK-NEXT: [[SUCCESS:%.*]] = extractvalue { i64, i1 } [[TMP5]], 1
+; CHECK-NEXT: [[NEWLOADED:%.*]] = extractvalue { i64, i1 } [[TMP5]], 0
+; CHECK-NEXT: [[TMP6]] = bitcast i64 [[NEWLOADED]] to double
+; CHECK-NEXT: br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label [[ATOMICRMW_START]]
+; CHECK: atomicrmw.end:
+; CHECK-NEXT: ret double [[TMP6]]
+;
+ %res = atomicrmw fminimumnum ptr %ptr, double %value seq_cst
+ ret double %res
+}
+
!0 = !{!"function_entry_count", i64 1000}
;.
; CHECK: attributes #[[ATTR0:[0-9]+]] = { nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none) }
More information about the llvm-commits
mailing list