[llvm] SelectionDAG: Support nofpclass(nan/qnan/snan/nzero) in arguments (PR #130051)
YunQiang Su via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 16 03:27:16 PDT 2025
https://github.com/wzssyqa updated https://github.com/llvm/llvm-project/pull/130051
>From d9e047fdfd80a98dde018149b8c7a7b0c5824d63 Mon Sep 17 00:00:00 2001
From: YunQiang Su <yunqiang at isrc.iscas.ac.cn>
Date: Thu, 6 Mar 2025 18:09:56 +0800
Subject: [PATCH 1/2] SelectionDAG: Support nofpclass(nan/qnan/snan)
SelectionDAGISel::LowerArguments: Pass NoNaN Flags to InVals.
`nofpclass` support values nan, snan, qnan, where nan=snan|qnan.
So let's use NoSNaNs and NoQNaNs in SDNodeFlags.
Thus, we can use it in isKnownNeverNaN.
support ISD::AssertFPNoClass
Fix AssertFPNoClass
---
llvm/include/llvm/CodeGen/ISDOpcodes.h | 6 +
llvm/include/llvm/CodeGen/SelectionDAGNodes.h | 26 +-
.../include/llvm/Target/TargetSelectionDAG.td | 1 +
.../SelectionDAG/LegalizeFloatTypes.cpp | 3 +
.../SelectionDAG/LegalizeVectorTypes.cpp | 3 +
.../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 11 +-
.../SelectionDAG/SelectionDAGBuilder.cpp | 23 +-
.../SelectionDAG/SelectionDAGDumper.cpp | 1 +
.../CodeGen/SelectionDAG/SelectionDAGISel.cpp | 1 +
.../AArch64/fp-maximumnum-minimumnum.ll | 900 ++++++++++++++++++
.../LoongArch/fp-maximumnum-minimumnum.ll | 241 +++++
.../CodeGen/Mips/fp-maximumnum-minimumnum.ll | 73 ++
12 files changed, 1277 insertions(+), 12 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/ISDOpcodes.h b/llvm/include/llvm/CodeGen/ISDOpcodes.h
index ad8a95a353b56..7a9b716f652f3 100644
--- a/llvm/include/llvm/CodeGen/ISDOpcodes.h
+++ b/llvm/include/llvm/CodeGen/ISDOpcodes.h
@@ -67,6 +67,12 @@ enum NodeType {
/// poisoned the assertion will not be true for that value.
AssertAlign,
+ /// AssertNoFPClass - These nodes record if a register contains a float
+ /// value that is known to be not some type.
+ /// NOTE: In case of the source value (or any vector element value) is
+ /// poisoned the assertion will not be true for that value.
+ AssertNoFPClass,
+
/// Various leaf nodes.
BasicBlock,
VALUETYPE,
diff --git a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
index b62cf08693f63..6482b4673331d 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -397,7 +397,7 @@ struct SDNodeFlags {
Exact = 1 << 2,
Disjoint = 1 << 3,
NonNeg = 1 << 4,
- NoNaNs = 1 << 5,
+ // 1 << 5 was used as NoNaNs
NoInfs = 1 << 6,
NoSignedZeros = 1 << 7,
AllowReciprocal = 1 << 8,
@@ -416,13 +416,17 @@ struct SDNodeFlags {
// Compare instructions which may carry the samesign flag.
SameSign = 1 << 14,
+ NoSNaNs = 1 << 15,
+ NoQNaNs = 1 << 16,
+
// NOTE: Please update LargestValue in LLVM_DECLARE_ENUM_AS_BITMASK below
// the class definition when adding new flags.
PoisonGeneratingFlags = NoUnsignedWrap | NoSignedWrap | Exact | Disjoint |
- NonNeg | NoNaNs | NoInfs | SameSign,
- FastMathFlags = NoNaNs | NoInfs | NoSignedZeros | AllowReciprocal |
- AllowContract | ApproximateFuncs | AllowReassociation,
+ NonNeg | NoSNaNs | NoQNaNs | NoInfs | SameSign,
+ FastMathFlags = NoSNaNs | NoQNaNs | NoInfs | NoSignedZeros |
+ AllowReciprocal | AllowContract | ApproximateFuncs |
+ AllowReassociation,
};
/// Default constructor turns off all optimization flags.
@@ -430,7 +434,8 @@ struct SDNodeFlags {
/// Propagate the fast-math-flags from an IR FPMathOperator.
void copyFMF(const FPMathOperator &FPMO) {
- setNoNaNs(FPMO.hasNoNaNs());
+ setNoSNaNs(FPMO.hasNoNaNs());
+ setNoQNaNs(FPMO.hasNoNaNs());
setNoInfs(FPMO.hasNoInfs());
setNoSignedZeros(FPMO.hasNoSignedZeros());
setAllowReciprocal(FPMO.hasAllowReciprocal());
@@ -446,7 +451,12 @@ struct SDNodeFlags {
void setDisjoint(bool b) { setFlag<Disjoint>(b); }
void setSameSign(bool b) { setFlag<SameSign>(b); }
void setNonNeg(bool b) { setFlag<NonNeg>(b); }
- void setNoNaNs(bool b) { setFlag<NoNaNs>(b); }
+ void setNoNaNs(bool b) {
+ setFlag<NoSNaNs>(b);
+ setFlag<NoQNaNs>(b);
+ }
+ void setNoSNaNs(bool b) { setFlag<NoSNaNs>(b); }
+ void setNoQNaNs(bool b) { setFlag<NoQNaNs>(b); }
void setNoInfs(bool b) { setFlag<NoInfs>(b); }
void setNoSignedZeros(bool b) { setFlag<NoSignedZeros>(b); }
void setAllowReciprocal(bool b) { setFlag<AllowReciprocal>(b); }
@@ -463,7 +473,9 @@ struct SDNodeFlags {
bool hasDisjoint() const { return Flags & Disjoint; }
bool hasSameSign() const { return Flags & SameSign; }
bool hasNonNeg() const { return Flags & NonNeg; }
- bool hasNoNaNs() const { return Flags & NoNaNs; }
+ bool hasNoNaNs() const { return (Flags & NoSNaNs) && (Flags & NoQNaNs); }
+ bool hasNoSNaNs() const { return Flags & NoSNaNs; }
+ bool hasNoQNaNs() const { return Flags & NoQNaNs; }
bool hasNoInfs() const { return Flags & NoInfs; }
bool hasNoSignedZeros() const { return Flags & NoSignedZeros; }
bool hasAllowReciprocal() const { return Flags & AllowReciprocal; }
diff --git a/llvm/include/llvm/Target/TargetSelectionDAG.td b/llvm/include/llvm/Target/TargetSelectionDAG.td
index 9c241b6c4df0f..8453cf7f4e58a 100644
--- a/llvm/include/llvm/Target/TargetSelectionDAG.td
+++ b/llvm/include/llvm/Target/TargetSelectionDAG.td
@@ -859,6 +859,7 @@ def SDT_assert : SDTypeProfile<1, 1,
[SDTCisInt<0>, SDTCisInt<1>, SDTCisSameAs<1, 0>]>;
def assertsext : SDNode<"ISD::AssertSext", SDT_assert>;
def assertzext : SDNode<"ISD::AssertZext", SDT_assert>;
+def assernofpclass : SDNode<"ISD::AssertNoFPClass", SDTFPUnaryOp>;
def assertalign : SDNode<"ISD::AssertAlign", SDT_assert>;
def convergencectrl_anchor : SDNode<"ISD::CONVERGENCECTRL_ANCHOR",
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
index 432209e8ecb0a..d03eeaa01b697 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
@@ -168,6 +168,7 @@ void DAGTypeLegalizer::SoftenFloatResult(SDNode *N, unsigned ResNo) {
case ISD::POISON:
case ISD::UNDEF: R = SoftenFloatRes_UNDEF(N); break;
case ISD::VAARG: R = SoftenFloatRes_VAARG(N); break;
+ case ISD::AssertNoFPClass: R = GetSoftenedFloat(N->getOperand(0)); break;
case ISD::VECREDUCE_FADD:
case ISD::VECREDUCE_FMUL:
case ISD::VECREDUCE_FMIN:
@@ -2576,6 +2577,7 @@ bool DAGTypeLegalizer::PromoteFloatOperand(SDNode *N, unsigned OpNo) {
R = PromoteFloatOp_FAKE_USE(N, OpNo);
break;
case ISD::FCOPYSIGN: R = PromoteFloatOp_FCOPYSIGN(N, OpNo); break;
+ case ISD::AssertNoFPClass:
case ISD::FP_TO_SINT:
case ISD::FP_TO_UINT:
case ISD::LROUND:
@@ -2803,6 +2805,7 @@ void DAGTypeLegalizer::PromoteFloatResult(SDNode *N, unsigned ResNo) {
case ISD::FTRUNC:
case ISD::FTAN:
case ISD::FTANH:
+ case ISD::AssertNoFPClass:
case ISD::FCANONICALIZE: R = PromoteFloatRes_UnaryOp(N); break;
// Binary FP Operations
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
index f934d8b37561e..d98d76b24bd7a 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
@@ -129,6 +129,7 @@ void DAGTypeLegalizer::ScalarizeVectorResult(SDNode *N, unsigned ResNo) {
case ISD::UINT_TO_FP:
case ISD::ZERO_EXTEND:
case ISD::FCANONICALIZE:
+ case ISD::AssertNoFPClass:
R = ScalarizeVecRes_UnaryOp(N);
break;
case ISD::ADDRSPACECAST:
@@ -1278,6 +1279,7 @@ void DAGTypeLegalizer::SplitVectorResult(SDNode *N, unsigned ResNo) {
case ISD::UINT_TO_FP:
case ISD::VP_UINT_TO_FP:
case ISD::FCANONICALIZE:
+ case ISD::AssertNoFPClass:
SplitVecRes_UnaryOp(N, Lo, Hi);
break;
case ISD::ADDRSPACECAST:
@@ -4846,6 +4848,7 @@ void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) {
case ISD::FREEZE:
case ISD::ARITH_FENCE:
case ISD::FCANONICALIZE:
+ case ISD::AssertNoFPClass:
Res = WidenVecRes_Unary(N);
break;
case ISD::FMA: case ISD::VP_FMA:
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index d6dcb3f15ae7c..075b18879ff3f 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -5598,7 +5598,12 @@ bool SelectionDAG::isBaseWithConstantOffset(SDValue Op) const {
bool SelectionDAG::isKnownNeverNaN(SDValue Op, bool SNaN, unsigned Depth) const {
// If we're told that NaNs won't happen, assume they won't.
- if (getTarget().Options.NoNaNsFPMath || Op->getFlags().hasNoNaNs())
+ if (getTarget().Options.NoNaNsFPMath)
+ return true;
+ SDNodeFlags OpFlags = Op->getFlags();
+ if (SNaN && OpFlags.hasNoSNaNs())
+ return true;
+ if (OpFlags.hasNoSNaNs() && OpFlags.hasNoQNaNs())
return true;
if (Depth >= MaxRecursionDepth)
@@ -7365,6 +7370,10 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
N2.getOpcode() == ISD::TargetConstant && "Invalid FP_ROUND!");
if (N1.getValueType() == VT) return N1; // noop conversion.
break;
+ case ISD::AssertNoFPClass:
+ assert(N1.getValueType().isFloatingPoint() &&
+ "AssertNoFPClass is used for a non-floating type");
+ return N1;
case ISD::AssertSext:
case ISD::AssertZext: {
EVT EVT = cast<VTSDNode>(N2)->getVT();
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 8cae34d06c8ba..9dbbd759057b1 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -11827,10 +11827,25 @@ void SelectionDAGISel::LowerArguments(const Function &F) {
AssertOp = ISD::AssertSext;
else if (Arg.hasAttribute(Attribute::ZExt))
AssertOp = ISD::AssertZext;
-
- ArgValues.push_back(getCopyFromParts(DAG, dl, &InVals[i], NumParts,
- PartVT, VT, nullptr, NewRoot,
- F.getCallingConv(), AssertOp));
+ SDValue OutVal =
+ getCopyFromParts(DAG, dl, &InVals[i], NumParts, PartVT, VT, nullptr,
+ NewRoot, F.getCallingConv(), AssertOp);
+ if (Arg.hasAttribute(Attribute::NoFPClass) &&
+ OutVal.getValueType().isFloatingPoint()) {
+ SDNodeFlags OutValFlags = OutVal->getFlags();
+ bool NoSNaN = ((Arg.getNoFPClass() & llvm::fcSNan) == llvm::fcSNan);
+ bool NoQNaN = ((Arg.getNoFPClass() & llvm::fcQNan) == llvm::fcQNan);
+ bool NoInf = ((Arg.getNoFPClass() & llvm::fcInf) == llvm::fcInf);
+ bool NoNegZero =
+ ((Arg.getNoFPClass() & llvm::fcInf) == llvm::fcNegZero);
+ OutValFlags.setNoSNaNs(NoSNaN);
+ OutValFlags.setNoQNaNs(NoQNaN);
+ OutValFlags.setNoInfs(NoInf);
+ OutValFlags.setNoSignedZeros(NoNegZero);
+ OutVal =
+ DAG.getNode(ISD::AssertNoFPClass, dl, VT, OutVal, OutValFlags);
+ }
+ ArgValues.push_back(OutVal);
}
i += NumParts;
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
index 8fcec6c6cd7c6..240115ac739f0 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
@@ -122,6 +122,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
case ISD::TokenFactor: return "TokenFactor";
case ISD::AssertSext: return "AssertSext";
case ISD::AssertZext: return "AssertZext";
+ case ISD::AssertNoFPClass: return "AssertNoFPClass";
case ISD::AssertAlign: return "AssertAlign";
case ISD::BasicBlock: return "BasicBlock";
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 598de6b207754..62d911fed2a3f 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -3265,6 +3265,7 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
return;
case ISD::AssertSext:
case ISD::AssertZext:
+ case ISD::AssertNoFPClass:
case ISD::AssertAlign:
ReplaceUses(SDValue(NodeToMatch, 0), NodeToMatch->getOperand(0));
CurDAG->RemoveDeadNode(NodeToMatch);
diff --git a/llvm/test/CodeGen/AArch64/fp-maximumnum-minimumnum.ll b/llvm/test/CodeGen/AArch64/fp-maximumnum-minimumnum.ll
index bb3f9a3e52a16..6bf6f32b6565b 100644
--- a/llvm/test/CodeGen/AArch64/fp-maximumnum-minimumnum.ll
+++ b/llvm/test/CodeGen/AArch64/fp-maximumnum-minimumnum.ll
@@ -1032,3 +1032,903 @@ entry:
%c = call <16 x half> @llvm.minimumnum.v16f16(<16 x half> %a, <16 x half> %b)
ret <16 x half> %c
}
+;;;;;;;;;;;;;;;; max_f64
+define double @max_nofpclass_f64(double nofpclass(nan) %a, double nofpclass(nan) %b) {
+; AARCH64-LABEL: max_nofpclass_f64:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fmaxnm d0, d0, d1
+; AARCH64-NEXT: ret
+entry:
+ %c = call double @llvm.maximumnum.f64(double %a, double %b)
+ ret double %c
+}
+
+define <2 x double> @max_nofpclass_v2f64(<2 x double> nofpclass(nan) %a, <2 x double> nofpclass(nan) %b) {
+; AARCH64-LABEL: max_nofpclass_v2f64:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fmaxnm v0.2d, v0.2d, v1.2d
+; AARCH64-NEXT: ret
+entry:
+ %c = call <2 x double> @llvm.maximumnum.v2f64(<2 x double> %a, <2 x double> %b)
+ ret <2 x double> %c
+}
+
+define <3 x double> @max_nofpclass_v3f64(<3 x double> nofpclass(nan) %a, <3 x double> nofpclass(nan) %b) {
+; AARCH64-LABEL: max_nofpclass_v3f64:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: // kill: def $d3 killed $d3 def $q3
+; AARCH64-NEXT: // kill: def $d0 killed $d0 def $q0
+; AARCH64-NEXT: // kill: def $d4 killed $d4 def $q4
+; AARCH64-NEXT: // kill: def $d1 killed $d1 def $q1
+; AARCH64-NEXT: // kill: def $d2 killed $d2 def $q2
+; AARCH64-NEXT: // kill: def $d5 killed $d5 def $q5
+; AARCH64-NEXT: mov v3.d[1], v4.d[0]
+; AARCH64-NEXT: mov v0.d[1], v1.d[0]
+; AARCH64-NEXT: fmaxnm v2.2d, v2.2d, v5.2d
+; AARCH64-NEXT: // kill: def $d2 killed $d2 killed $q2
+; AARCH64-NEXT: fmaxnm v0.2d, v0.2d, v3.2d
+; AARCH64-NEXT: ext v1.16b, v0.16b, v0.16b, #8
+; AARCH64-NEXT: // kill: def $d0 killed $d0 killed $q0
+; AARCH64-NEXT: // kill: def $d1 killed $d1 killed $q1
+; AARCH64-NEXT: ret
+entry:
+ %c = call <3 x double> @llvm.maximumnum.v3f64(<3 x double> %a, <3 x double> %b)
+ ret <3 x double> %c
+}
+
+define <4 x double> @max_nofpclass_v4f64(<4 x double> nofpclass(nan) %a, <4 x double> nofpclass(nan) %b) {
+; AARCH64-LABEL: max_nofpclass_v4f64:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fmaxnm v1.2d, v1.2d, v3.2d
+; AARCH64-NEXT: fmaxnm v0.2d, v0.2d, v2.2d
+; AARCH64-NEXT: ret
+entry:
+ %c = call <4 x double> @llvm.maximumnum.v4f64(<4 x double> %a, <4 x double> %b)
+ ret <4 x double> %c
+}
+
+;;;;;;;;;;;;;;;;;; max_f32
+define float @max_nofpclass_f32(float nofpclass(nan) %a, float nofpclass(nan) %b) {
+; AARCH64-LABEL: max_nofpclass_f32:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fmaxnm s0, s0, s1
+; AARCH64-NEXT: ret
+entry:
+ %c = call float @llvm.maximumnum.f32(float %a, float %b)
+ ret float %c
+}
+
+define <2 x float> @max_nofpclass_v2f32(<2 x float> nofpclass(nan) %a, <2 x float> nofpclass(nan) %b) {
+; AARCH64-LABEL: max_nofpclass_v2f32:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fmaxnm v0.2s, v0.2s, v1.2s
+; AARCH64-NEXT: ret
+entry:
+ %c = call <2 x float> @llvm.maximumnum.v2f32(<2 x float> %a, <2 x float> %b)
+ ret <2 x float> %c
+}
+
+define <3 x float> @max_nofpclass_v3f32(<3 x float> nofpclass(nan) %a, <3 x float> nofpclass(nan) %b) {
+; AARCH64-LABEL: max_nofpclass_v3f32:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fmaxnm v0.4s, v0.4s, v1.4s
+; AARCH64-NEXT: ret
+entry:
+ %c = call <3 x float> @llvm.maximumnum.v3f32(<3 x float> %a, <3 x float> %b)
+ ret <3 x float> %c
+}
+
+define <4 x float> @max_nofpclass_v4f32(<4 x float> nofpclass(nan) %a, <4 x float> nofpclass(nan) %b) {
+; AARCH64-LABEL: max_nofpclass_v4f32:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fmaxnm v0.4s, v0.4s, v1.4s
+; AARCH64-NEXT: ret
+entry:
+ %c = call <4 x float> @llvm.maximumnum.v4f32(<4 x float> %a, <4 x float> %b)
+ ret <4 x float> %c
+}
+
+define <5 x float> @max_nofpclass_v5f32(<5 x float> nofpclass(nan) %a, <5 x float> nofpclass(nan) %b) {
+; AARCH64-LABEL: max_nofpclass_v5f32:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: // kill: def $s0 killed $s0 def $q0
+; AARCH64-NEXT: // kill: def $s5 killed $s5 def $q5
+; AARCH64-NEXT: // kill: def $s1 killed $s1 def $q1
+; AARCH64-NEXT: // kill: def $s6 killed $s6 def $q6
+; AARCH64-NEXT: // kill: def $s2 killed $s2 def $q2
+; AARCH64-NEXT: // kill: def $s7 killed $s7 def $q7
+; AARCH64-NEXT: // kill: def $s3 killed $s3 def $q3
+; AARCH64-NEXT: mov x8, sp
+; AARCH64-NEXT: // kill: def $s4 killed $s4 def $q4
+; AARCH64-NEXT: mov v0.s[1], v1.s[0]
+; AARCH64-NEXT: mov v5.s[1], v6.s[0]
+; AARCH64-NEXT: mov v0.s[2], v2.s[0]
+; AARCH64-NEXT: mov v5.s[2], v7.s[0]
+; AARCH64-NEXT: ldr s2, [sp, #8]
+; AARCH64-NEXT: fmaxnm v4.4s, v4.4s, v2.4s
+; AARCH64-NEXT: // kill: def $s4 killed $s4 killed $q4
+; AARCH64-NEXT: mov v0.s[3], v3.s[0]
+; AARCH64-NEXT: ld1 { v5.s }[3], [x8]
+; AARCH64-NEXT: fmaxnm v0.4s, v0.4s, v5.4s
+; AARCH64-NEXT: mov s1, v0.s[1]
+; AARCH64-NEXT: mov s2, v0.s[2]
+; AARCH64-NEXT: mov s3, v0.s[3]
+; AARCH64-NEXT: // kill: def $s0 killed $s0 killed $q0
+; AARCH64-NEXT: ret
+entry:
+ %c = call <5 x float> @llvm.maximumnum.v5f32(<5 x float> %a, <5 x float> %b)
+ ret <5 x float> %c
+}
+
+define <8 x float> @max_nofpclass_v8f32(<8 x float> nofpclass(nan) %a, <8 x float> nofpclass(nan) %b) {
+; AARCH64-LABEL: max_nofpclass_v8f32:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fmaxnm v1.4s, v1.4s, v3.4s
+; AARCH64-NEXT: fmaxnm v0.4s, v0.4s, v2.4s
+; AARCH64-NEXT: ret
+entry:
+ %c = call <8 x float> @llvm.maximumnum.v8f32(<8 x float> %a, <8 x float> %b)
+ ret <8 x float> %c
+}
+
+define <2 x half> @max_nofpclass_v2f16(<2 x half> nofpclass(nan) %a, <2 x half> nofpclass(nan) %b) {
+; AARCH64-LABEL: max_nofpclass_v2f16:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fmaxnm v0.4h, v0.4h, v1.4h
+; AARCH64-NEXT: ret
+entry:
+ %c = call <2 x half> @llvm.maximumnum.v2f16(<2 x half> %a, <2 x half> %b)
+ ret <2 x half> %c
+}
+
+define <4 x half> @max_nofpclass_v4f16(<4 x half> nofpclass(nan) %a, <4 x half> nofpclass(nan) %b) {
+; AARCH64-LABEL: max_nofpclass_v4f16:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fmaxnm v0.4h, v0.4h, v1.4h
+; AARCH64-NEXT: ret
+entry:
+ %c = call <4 x half> @llvm.maximumnum.v4f16(<4 x half> %a, <4 x half> %b)
+ ret <4 x half> %c
+}
+
+define <8 x half> @max_nofpclass_v8f16(<8 x half> nofpclass(nan) %a, <8 x half> nofpclass(nan) %b) {
+; AARCH64-LABEL: max_nofpclass_v8f16:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fmaxnm v0.8h, v0.8h, v1.8h
+; AARCH64-NEXT: ret
+entry:
+ %c = call <8 x half> @llvm.maximumnum.v8f16(<8 x half> %a, <8 x half> %b)
+ ret <8 x half> %c
+}
+
+define <9 x half> @max_nofpclass_v9f16(<9 x half> nofpclass(nan) %a, <9 x half> nofpclass(nan) %b) {
+; AARCH64-LABEL: max_nofpclass_v9f16:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: // kill: def $h0 killed $h0 def $q0
+; AARCH64-NEXT: // kill: def $h1 killed $h1 def $q1
+; AARCH64-NEXT: // kill: def $h2 killed $h2 def $q2
+; AARCH64-NEXT: add x9, sp, #16
+; AARCH64-NEXT: // kill: def $h3 killed $h3 def $q3
+; AARCH64-NEXT: // kill: def $h4 killed $h4 def $q4
+; AARCH64-NEXT: // kill: def $h5 killed $h5 def $q5
+; AARCH64-NEXT: // kill: def $h6 killed $h6 def $q6
+; AARCH64-NEXT: // kill: def $h7 killed $h7 def $q7
+; AARCH64-NEXT: mov v0.h[1], v1.h[0]
+; AARCH64-NEXT: ldr h1, [sp, #8]
+; AARCH64-NEXT: ld1 { v1.h }[1], [x9]
+; AARCH64-NEXT: add x9, sp, #24
+; AARCH64-NEXT: mov v0.h[2], v2.h[0]
+; AARCH64-NEXT: ldr h2, [sp, #72]
+; AARCH64-NEXT: ld1 { v1.h }[2], [x9]
+; AARCH64-NEXT: add x9, sp, #32
+; AARCH64-NEXT: mov v0.h[3], v3.h[0]
+; AARCH64-NEXT: ld1 { v1.h }[3], [x9]
+; AARCH64-NEXT: add x9, sp, #40
+; AARCH64-NEXT: ldr h3, [sp]
+; AARCH64-NEXT: ld1 { v1.h }[4], [x9]
+; AARCH64-NEXT: add x9, sp, #48
+; AARCH64-NEXT: fmaxnm v2.8h, v3.8h, v2.8h
+; AARCH64-NEXT: mov v0.h[4], v4.h[0]
+; AARCH64-NEXT: ld1 { v1.h }[5], [x9]
+; AARCH64-NEXT: add x9, sp, #56
+; AARCH64-NEXT: str h2, [x8, #16]
+; AARCH64-NEXT: mov v0.h[5], v5.h[0]
+; AARCH64-NEXT: ld1 { v1.h }[6], [x9]
+; AARCH64-NEXT: add x9, sp, #64
+; AARCH64-NEXT: mov v0.h[6], v6.h[0]
+; AARCH64-NEXT: ld1 { v1.h }[7], [x9]
+; AARCH64-NEXT: mov v0.h[7], v7.h[0]
+; AARCH64-NEXT: fmaxnm v0.8h, v0.8h, v1.8h
+; AARCH64-NEXT: str q0, [x8]
+; AARCH64-NEXT: ret
+entry:
+ %c = call <9 x half> @llvm.maximumnum.v9f16(<9 x half> %a, <9 x half> %b)
+ ret <9 x half> %c
+}
+
+define <16 x half> @max_nofpclass_v16f16(<16 x half> nofpclass(nan) %a, <16 x half> nofpclass(nan) %b) {
+; AARCH64-LABEL: max_nofpclass_v16f16:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fmaxnm v1.8h, v1.8h, v3.8h
+; AARCH64-NEXT: fmaxnm v0.8h, v0.8h, v2.8h
+; AARCH64-NEXT: ret
+entry:
+ %c = call <16 x half> @llvm.maximumnum.v16f16(<16 x half> %a, <16 x half> %b)
+ ret <16 x half> %c
+}
+
+;;;;;;;;;;;;;;;; min_f64
+define double @min_nofpclass_f64(double nofpclass(nan) %a, double nofpclass(nan) %b) {
+; AARCH64-LABEL: min_nofpclass_f64:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fminnm d0, d0, d1
+; AARCH64-NEXT: ret
+entry:
+ %c = call double @llvm.minimumnum.f64(double %a, double %b)
+ ret double %c
+}
+
+define <2 x double> @min_nofpclass_v2f64(<2 x double> nofpclass(nan) %a, <2 x double> nofpclass(nan) %b) {
+; AARCH64-LABEL: min_nofpclass_v2f64:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fminnm v0.2d, v0.2d, v1.2d
+; AARCH64-NEXT: ret
+entry:
+ %c = call <2 x double> @llvm.minimumnum.v2f64(<2 x double> %a, <2 x double> %b)
+ ret <2 x double> %c
+}
+
+define <3 x double> @min_nofpclass_v3f64(<3 x double> nofpclass(nan) %a, <3 x double> nofpclass(nan) %b) {
+; AARCH64-LABEL: min_nofpclass_v3f64:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: // kill: def $d3 killed $d3 def $q3
+; AARCH64-NEXT: // kill: def $d0 killed $d0 def $q0
+; AARCH64-NEXT: // kill: def $d4 killed $d4 def $q4
+; AARCH64-NEXT: // kill: def $d1 killed $d1 def $q1
+; AARCH64-NEXT: // kill: def $d2 killed $d2 def $q2
+; AARCH64-NEXT: // kill: def $d5 killed $d5 def $q5
+; AARCH64-NEXT: mov v3.d[1], v4.d[0]
+; AARCH64-NEXT: mov v0.d[1], v1.d[0]
+; AARCH64-NEXT: fminnm v2.2d, v2.2d, v5.2d
+; AARCH64-NEXT: // kill: def $d2 killed $d2 killed $q2
+; AARCH64-NEXT: fminnm v0.2d, v0.2d, v3.2d
+; AARCH64-NEXT: ext v1.16b, v0.16b, v0.16b, #8
+; AARCH64-NEXT: // kill: def $d0 killed $d0 killed $q0
+; AARCH64-NEXT: // kill: def $d1 killed $d1 killed $q1
+; AARCH64-NEXT: ret
+entry:
+ %c = call <3 x double> @llvm.minimumnum.v3f64(<3 x double> %a, <3 x double> %b)
+ ret <3 x double> %c
+}
+
+define <4 x double> @min_nofpclass_v4f64(<4 x double> nofpclass(nan) %a, <4 x double> nofpclass(nan) %b) {
+; AARCH64-LABEL: min_nofpclass_v4f64:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fminnm v1.2d, v1.2d, v3.2d
+; AARCH64-NEXT: fminnm v0.2d, v0.2d, v2.2d
+; AARCH64-NEXT: ret
+entry:
+ %c = call <4 x double> @llvm.minimumnum.v4f64(<4 x double> %a, <4 x double> %b)
+ ret <4 x double> %c
+}
+
+define <2 x float> @min_nofpclass_v2f32(<2 x float> nofpclass(nan) %a, <2 x float> nofpclass(nan) %b) {
+; AARCH64-LABEL: min_nofpclass_v2f32:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fminnm v0.2s, v0.2s, v1.2s
+; AARCH64-NEXT: ret
+entry:
+ %c = call <2 x float> @llvm.minimumnum.v2f32(<2 x float> %a, <2 x float> %b)
+ ret <2 x float> %c
+}
+
+define <3 x float> @min_nofpclass_v3f32(<3 x float> nofpclass(nan) %a, <3 x float> nofpclass(nan) %b) {
+; AARCH64-LABEL: min_nofpclass_v3f32:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fminnm v0.4s, v0.4s, v1.4s
+; AARCH64-NEXT: ret
+entry:
+ %c = call <3 x float> @llvm.minimumnum.v3f32(<3 x float> %a, <3 x float> %b)
+ ret <3 x float> %c
+}
+
+define <4 x float> @min_nofpclass_v4f32(<4 x float> nofpclass(nan) %a, <4 x float> nofpclass(nan) %b) {
+; AARCH64-LABEL: min_nofpclass_v4f32:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fminnm v0.4s, v0.4s, v1.4s
+; AARCH64-NEXT: ret
+entry:
+ %c = call <4 x float> @llvm.minimumnum.v4f32(<4 x float> %a, <4 x float> %b)
+ ret <4 x float> %c
+}
+
+define <5 x float> @min_nofpclass_v5f32(<5 x float> nofpclass(nan) %a, <5 x float> nofpclass(nan) %b) {
+; AARCH64-LABEL: min_nofpclass_v5f32:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: // kill: def $s0 killed $s0 def $q0
+; AARCH64-NEXT: // kill: def $s5 killed $s5 def $q5
+; AARCH64-NEXT: // kill: def $s1 killed $s1 def $q1
+; AARCH64-NEXT: // kill: def $s6 killed $s6 def $q6
+; AARCH64-NEXT: // kill: def $s2 killed $s2 def $q2
+; AARCH64-NEXT: // kill: def $s7 killed $s7 def $q7
+; AARCH64-NEXT: // kill: def $s3 killed $s3 def $q3
+; AARCH64-NEXT: mov x8, sp
+; AARCH64-NEXT: // kill: def $s4 killed $s4 def $q4
+; AARCH64-NEXT: mov v0.s[1], v1.s[0]
+; AARCH64-NEXT: mov v5.s[1], v6.s[0]
+; AARCH64-NEXT: mov v0.s[2], v2.s[0]
+; AARCH64-NEXT: mov v5.s[2], v7.s[0]
+; AARCH64-NEXT: ldr s2, [sp, #8]
+; AARCH64-NEXT: fminnm v4.4s, v4.4s, v2.4s
+; AARCH64-NEXT: // kill: def $s4 killed $s4 killed $q4
+; AARCH64-NEXT: mov v0.s[3], v3.s[0]
+; AARCH64-NEXT: ld1 { v5.s }[3], [x8]
+; AARCH64-NEXT: fminnm v0.4s, v0.4s, v5.4s
+; AARCH64-NEXT: mov s1, v0.s[1]
+; AARCH64-NEXT: mov s2, v0.s[2]
+; AARCH64-NEXT: mov s3, v0.s[3]
+; AARCH64-NEXT: // kill: def $s0 killed $s0 killed $q0
+; AARCH64-NEXT: ret
+entry:
+ %c = call <5 x float> @llvm.minimumnum.v5f32(<5 x float> %a, <5 x float> %b)
+ ret <5 x float> %c
+}
+
+define <8 x float> @min_nofpclass_v8f32(<8 x float> nofpclass(nan) %a, <8 x float> nofpclass(nan) %b) {
+; AARCH64-LABEL: min_nofpclass_v8f32:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fminnm v1.4s, v1.4s, v3.4s
+; AARCH64-NEXT: fminnm v0.4s, v0.4s, v2.4s
+; AARCH64-NEXT: ret
+entry:
+ %c = call <8 x float> @llvm.minimumnum.v8f32(<8 x float> %a, <8 x float> %b)
+ ret <8 x float> %c
+}
+
+;;;;;;;;;;;;;;;;;; min_f16
+define half @min_nofpclass_f16(half nofpclass(nan) %a, half nofpclass(nan) %b) {
+; AARCH64-LABEL: min_nofpclass_f16:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fminnm h0, h0, h1
+; AARCH64-NEXT: ret
+entry:
+ %c = call half @llvm.minimumnum.f16(half %a, half %b)
+ ret half %c
+}
+
+define <2 x half> @min_nofpclass_v2f16(<2 x half> nofpclass(nan) %a, <2 x half> nofpclass(nan) %b) {
+; AARCH64-LABEL: min_nofpclass_v2f16:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fminnm v0.4h, v0.4h, v1.4h
+; AARCH64-NEXT: ret
+entry:
+ %c = call <2 x half> @llvm.minimumnum.v2f16(<2 x half> %a, <2 x half> %b)
+ ret <2 x half> %c
+}
+
+define <4 x half> @min_nofpclass_v4f16(<4 x half> nofpclass(nan) %a, <4 x half> nofpclass(nan) %b) {
+; AARCH64-LABEL: min_nofpclass_v4f16:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fminnm v0.4h, v0.4h, v1.4h
+; AARCH64-NEXT: ret
+entry:
+ %c = call <4 x half> @llvm.minimumnum.v4f16(<4 x half> %a, <4 x half> %b)
+ ret <4 x half> %c
+}
+
+define <8 x half> @min_nofpclass_v8f16(<8 x half> nofpclass(nan) %a, <8 x half> nofpclass(nan) %b) {
+; AARCH64-LABEL: min_nofpclass_v8f16:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fminnm v0.8h, v0.8h, v1.8h
+; AARCH64-NEXT: ret
+entry:
+ %c = call <8 x half> @llvm.minimumnum.v8f16(<8 x half> %a, <8 x half> %b)
+ ret <8 x half> %c
+}
+
+define <9 x half> @min_nofpclass_v9f16(<9 x half> nofpclass(nan) %a, <9 x half> nofpclass(nan) %b) {
+; AARCH64-LABEL: min_nofpclass_v9f16:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: // kill: def $h0 killed $h0 def $q0
+; AARCH64-NEXT: // kill: def $h1 killed $h1 def $q1
+; AARCH64-NEXT: // kill: def $h2 killed $h2 def $q2
+; AARCH64-NEXT: add x9, sp, #16
+; AARCH64-NEXT: // kill: def $h3 killed $h3 def $q3
+; AARCH64-NEXT: // kill: def $h4 killed $h4 def $q4
+; AARCH64-NEXT: // kill: def $h5 killed $h5 def $q5
+; AARCH64-NEXT: // kill: def $h6 killed $h6 def $q6
+; AARCH64-NEXT: // kill: def $h7 killed $h7 def $q7
+; AARCH64-NEXT: mov v0.h[1], v1.h[0]
+; AARCH64-NEXT: ldr h1, [sp, #8]
+; AARCH64-NEXT: ld1 { v1.h }[1], [x9]
+; AARCH64-NEXT: add x9, sp, #24
+; AARCH64-NEXT: mov v0.h[2], v2.h[0]
+; AARCH64-NEXT: ldr h2, [sp, #72]
+; AARCH64-NEXT: ld1 { v1.h }[2], [x9]
+; AARCH64-NEXT: add x9, sp, #32
+; AARCH64-NEXT: mov v0.h[3], v3.h[0]
+; AARCH64-NEXT: ld1 { v1.h }[3], [x9]
+; AARCH64-NEXT: add x9, sp, #40
+; AARCH64-NEXT: ldr h3, [sp]
+; AARCH64-NEXT: ld1 { v1.h }[4], [x9]
+; AARCH64-NEXT: add x9, sp, #48
+; AARCH64-NEXT: fminnm v2.8h, v3.8h, v2.8h
+; AARCH64-NEXT: mov v0.h[4], v4.h[0]
+; AARCH64-NEXT: ld1 { v1.h }[5], [x9]
+; AARCH64-NEXT: add x9, sp, #56
+; AARCH64-NEXT: str h2, [x8, #16]
+; AARCH64-NEXT: mov v0.h[5], v5.h[0]
+; AARCH64-NEXT: ld1 { v1.h }[6], [x9]
+; AARCH64-NEXT: add x9, sp, #64
+; AARCH64-NEXT: mov v0.h[6], v6.h[0]
+; AARCH64-NEXT: ld1 { v1.h }[7], [x9]
+; AARCH64-NEXT: mov v0.h[7], v7.h[0]
+; AARCH64-NEXT: fminnm v0.8h, v0.8h, v1.8h
+; AARCH64-NEXT: str q0, [x8]
+; AARCH64-NEXT: ret
+entry:
+ %c = call <9 x half> @llvm.minimumnum.v9f16(<9 x half> %a, <9 x half> %b)
+ ret <9 x half> %c
+}
+
+define <16 x half> @min_nofpclass_v16f16(<16 x half> nofpclass(nan) %a, <16 x half> nofpclass(nan) %b) {
+; AARCH64-LABEL: min_nofpclass_v16f16:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fminnm v1.8h, v1.8h, v3.8h
+; AARCH64-NEXT: fminnm v0.8h, v0.8h, v2.8h
+; AARCH64-NEXT: ret
+entry:
+ %c = call <16 x half> @llvm.minimumnum.v16f16(<16 x half> %a, <16 x half> %b)
+ ret <16 x half> %c
+}
+
+
+;;;;;;;;;;;;;;;; max_f64
+define double @max_nofpclass_s_f64(double nofpclass(snan) %a, double nofpclass(snan) %b) {
+; AARCH64-LABEL: max_nofpclass_s_f64:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fmaxnm d0, d0, d1
+; AARCH64-NEXT: ret
+entry:
+ %c = call double @llvm.maximumnum.f64(double %a, double %b)
+ ret double %c
+}
+
+define <2 x double> @max_nofpclass_s_v2f64(<2 x double> nofpclass(snan) %a, <2 x double> nofpclass(snan) %b) {
+; AARCH64-LABEL: max_nofpclass_s_v2f64:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fmaxnm v0.2d, v0.2d, v1.2d
+; AARCH64-NEXT: ret
+entry:
+ %c = call <2 x double> @llvm.maximumnum.v2f64(<2 x double> %a, <2 x double> %b)
+ ret <2 x double> %c
+}
+
+define <3 x double> @max_nofpclass_s_v3f64(<3 x double> nofpclass(snan) %a, <3 x double> nofpclass(snan) %b) {
+; AARCH64-LABEL: max_nofpclass_s_v3f64:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: // kill: def $d3 killed $d3 def $q3
+; AARCH64-NEXT: // kill: def $d0 killed $d0 def $q0
+; AARCH64-NEXT: // kill: def $d4 killed $d4 def $q4
+; AARCH64-NEXT: // kill: def $d1 killed $d1 def $q1
+; AARCH64-NEXT: // kill: def $d2 killed $d2 def $q2
+; AARCH64-NEXT: // kill: def $d5 killed $d5 def $q5
+; AARCH64-NEXT: mov v3.d[1], v4.d[0]
+; AARCH64-NEXT: mov v0.d[1], v1.d[0]
+; AARCH64-NEXT: fmaxnm v2.2d, v2.2d, v5.2d
+; AARCH64-NEXT: // kill: def $d2 killed $d2 killed $q2
+; AARCH64-NEXT: fmaxnm v0.2d, v0.2d, v3.2d
+; AARCH64-NEXT: ext v1.16b, v0.16b, v0.16b, #8
+; AARCH64-NEXT: // kill: def $d0 killed $d0 killed $q0
+; AARCH64-NEXT: // kill: def $d1 killed $d1 killed $q1
+; AARCH64-NEXT: ret
+entry:
+ %c = call <3 x double> @llvm.maximumnum.v3f64(<3 x double> %a, <3 x double> %b)
+ ret <3 x double> %c
+}
+
+define <4 x double> @max_nofpclass_s_v4f64(<4 x double> nofpclass(snan) %a, <4 x double> nofpclass(snan) %b) {
+; AARCH64-LABEL: max_nofpclass_s_v4f64:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fmaxnm v1.2d, v1.2d, v3.2d
+; AARCH64-NEXT: fmaxnm v0.2d, v0.2d, v2.2d
+; AARCH64-NEXT: ret
+entry:
+ %c = call <4 x double> @llvm.maximumnum.v4f64(<4 x double> %a, <4 x double> %b)
+ ret <4 x double> %c
+}
+
+;;;;;;;;;;;;;;;;;; max_f32
+define float @max_nofpclass_s_f32(float nofpclass(snan) %a, float nofpclass(snan) %b) {
+; AARCH64-LABEL: max_nofpclass_s_f32:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fmaxnm s0, s0, s1
+; AARCH64-NEXT: ret
+entry:
+ %c = call float @llvm.maximumnum.f32(float %a, float %b)
+ ret float %c
+}
+
+define <2 x float> @max_nofpclass_s_v2f32(<2 x float> nofpclass(snan) %a, <2 x float> nofpclass(snan) %b) {
+; AARCH64-LABEL: max_nofpclass_s_v2f32:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fmaxnm v0.2s, v0.2s, v1.2s
+; AARCH64-NEXT: ret
+entry:
+ %c = call <2 x float> @llvm.maximumnum.v2f32(<2 x float> %a, <2 x float> %b)
+ ret <2 x float> %c
+}
+
+define <3 x float> @max_nofpclass_s_v3f32(<3 x float> nofpclass(snan) %a, <3 x float> nofpclass(snan) %b) {
+; AARCH64-LABEL: max_nofpclass_s_v3f32:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fmaxnm v0.4s, v0.4s, v1.4s
+; AARCH64-NEXT: ret
+entry:
+ %c = call <3 x float> @llvm.maximumnum.v3f32(<3 x float> %a, <3 x float> %b)
+ ret <3 x float> %c
+}
+
+define <4 x float> @max_nofpclass_s_v4f32(<4 x float> nofpclass(snan) %a, <4 x float> nofpclass(snan) %b) {
+; AARCH64-LABEL: max_nofpclass_s_v4f32:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fmaxnm v0.4s, v0.4s, v1.4s
+; AARCH64-NEXT: ret
+entry:
+ %c = call <4 x float> @llvm.maximumnum.v4f32(<4 x float> %a, <4 x float> %b)
+ ret <4 x float> %c
+}
+
+define <5 x float> @max_nofpclass_s_v5f32(<5 x float> nofpclass(snan) %a, <5 x float> nofpclass(snan) %b) {
+; AARCH64-LABEL: max_nofpclass_s_v5f32:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: // kill: def $s0 killed $s0 def $q0
+; AARCH64-NEXT: // kill: def $s5 killed $s5 def $q5
+; AARCH64-NEXT: // kill: def $s1 killed $s1 def $q1
+; AARCH64-NEXT: // kill: def $s6 killed $s6 def $q6
+; AARCH64-NEXT: // kill: def $s2 killed $s2 def $q2
+; AARCH64-NEXT: // kill: def $s7 killed $s7 def $q7
+; AARCH64-NEXT: // kill: def $s3 killed $s3 def $q3
+; AARCH64-NEXT: mov x8, sp
+; AARCH64-NEXT: // kill: def $s4 killed $s4 def $q4
+; AARCH64-NEXT: mov v0.s[1], v1.s[0]
+; AARCH64-NEXT: mov v5.s[1], v6.s[0]
+; AARCH64-NEXT: mov v0.s[2], v2.s[0]
+; AARCH64-NEXT: mov v5.s[2], v7.s[0]
+; AARCH64-NEXT: ldr s2, [sp, #8]
+; AARCH64-NEXT: fmaxnm v4.4s, v4.4s, v2.4s
+; AARCH64-NEXT: // kill: def $s4 killed $s4 killed $q4
+; AARCH64-NEXT: mov v0.s[3], v3.s[0]
+; AARCH64-NEXT: ld1 { v5.s }[3], [x8]
+; AARCH64-NEXT: fmaxnm v0.4s, v0.4s, v5.4s
+; AARCH64-NEXT: mov s1, v0.s[1]
+; AARCH64-NEXT: mov s2, v0.s[2]
+; AARCH64-NEXT: mov s3, v0.s[3]
+; AARCH64-NEXT: // kill: def $s0 killed $s0 killed $q0
+; AARCH64-NEXT: ret
+entry:
+ %c = call <5 x float> @llvm.maximumnum.v5f32(<5 x float> %a, <5 x float> %b)
+ ret <5 x float> %c
+}
+
+define <8 x float> @max_nofpclass_s_v8f32(<8 x float> nofpclass(snan) %a, <8 x float> nofpclass(snan) %b) {
+; AARCH64-LABEL: max_nofpclass_s_v8f32:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fmaxnm v1.4s, v1.4s, v3.4s
+; AARCH64-NEXT: fmaxnm v0.4s, v0.4s, v2.4s
+; AARCH64-NEXT: ret
+entry:
+ %c = call <8 x float> @llvm.maximumnum.v8f32(<8 x float> %a, <8 x float> %b)
+ ret <8 x float> %c
+}
+
+define <2 x half> @max_nofpclass_s_v2f16(<2 x half> nofpclass(snan) %a, <2 x half> nofpclass(snan) %b) {
+; AARCH64-LABEL: max_nofpclass_s_v2f16:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fmaxnm v0.4h, v0.4h, v1.4h
+; AARCH64-NEXT: ret
+entry:
+ %c = call <2 x half> @llvm.maximumnum.v2f16(<2 x half> %a, <2 x half> %b)
+ ret <2 x half> %c
+}
+
+define <4 x half> @max_nofpclass_s_v4f16(<4 x half> nofpclass(snan) %a, <4 x half> nofpclass(snan) %b) {
+; AARCH64-LABEL: max_nofpclass_s_v4f16:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fmaxnm v0.4h, v0.4h, v1.4h
+; AARCH64-NEXT: ret
+entry:
+ %c = call <4 x half> @llvm.maximumnum.v4f16(<4 x half> %a, <4 x half> %b)
+ ret <4 x half> %c
+}
+
+define <8 x half> @max_nofpclass_s_v8f16(<8 x half> nofpclass(snan) %a, <8 x half> nofpclass(snan) %b) {
+; AARCH64-LABEL: max_nofpclass_s_v8f16:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fmaxnm v0.8h, v0.8h, v1.8h
+; AARCH64-NEXT: ret
+entry:
+ %c = call <8 x half> @llvm.maximumnum.v8f16(<8 x half> %a, <8 x half> %b)
+ ret <8 x half> %c
+}
+
+define <9 x half> @max_nofpclass_s_v9f16(<9 x half> nofpclass(snan) %a, <9 x half> nofpclass(snan) %b) {
+; AARCH64-LABEL: max_nofpclass_s_v9f16:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: // kill: def $h0 killed $h0 def $q0
+; AARCH64-NEXT: // kill: def $h1 killed $h1 def $q1
+; AARCH64-NEXT: // kill: def $h2 killed $h2 def $q2
+; AARCH64-NEXT: add x9, sp, #16
+; AARCH64-NEXT: // kill: def $h3 killed $h3 def $q3
+; AARCH64-NEXT: // kill: def $h4 killed $h4 def $q4
+; AARCH64-NEXT: // kill: def $h5 killed $h5 def $q5
+; AARCH64-NEXT: // kill: def $h6 killed $h6 def $q6
+; AARCH64-NEXT: // kill: def $h7 killed $h7 def $q7
+; AARCH64-NEXT: mov v0.h[1], v1.h[0]
+; AARCH64-NEXT: ldr h1, [sp, #8]
+; AARCH64-NEXT: ld1 { v1.h }[1], [x9]
+; AARCH64-NEXT: add x9, sp, #24
+; AARCH64-NEXT: mov v0.h[2], v2.h[0]
+; AARCH64-NEXT: ldr h2, [sp, #72]
+; AARCH64-NEXT: ld1 { v1.h }[2], [x9]
+; AARCH64-NEXT: add x9, sp, #32
+; AARCH64-NEXT: mov v0.h[3], v3.h[0]
+; AARCH64-NEXT: ld1 { v1.h }[3], [x9]
+; AARCH64-NEXT: add x9, sp, #40
+; AARCH64-NEXT: ldr h3, [sp]
+; AARCH64-NEXT: ld1 { v1.h }[4], [x9]
+; AARCH64-NEXT: add x9, sp, #48
+; AARCH64-NEXT: fmaxnm v2.8h, v3.8h, v2.8h
+; AARCH64-NEXT: mov v0.h[4], v4.h[0]
+; AARCH64-NEXT: ld1 { v1.h }[5], [x9]
+; AARCH64-NEXT: add x9, sp, #56
+; AARCH64-NEXT: str h2, [x8, #16]
+; AARCH64-NEXT: mov v0.h[5], v5.h[0]
+; AARCH64-NEXT: ld1 { v1.h }[6], [x9]
+; AARCH64-NEXT: add x9, sp, #64
+; AARCH64-NEXT: mov v0.h[6], v6.h[0]
+; AARCH64-NEXT: ld1 { v1.h }[7], [x9]
+; AARCH64-NEXT: mov v0.h[7], v7.h[0]
+; AARCH64-NEXT: fmaxnm v0.8h, v0.8h, v1.8h
+; AARCH64-NEXT: str q0, [x8]
+; AARCH64-NEXT: ret
+entry:
+ %c = call <9 x half> @llvm.maximumnum.v9f16(<9 x half> %a, <9 x half> %b)
+ ret <9 x half> %c
+}
+
+define <16 x half> @max_nofpclass_s_v16f16(<16 x half> nofpclass(snan) %a, <16 x half> nofpclass(snan) %b) {
+; AARCH64-LABEL: max_nofpclass_s_v16f16:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fmaxnm v1.8h, v1.8h, v3.8h
+; AARCH64-NEXT: fmaxnm v0.8h, v0.8h, v2.8h
+; AARCH64-NEXT: ret
+entry:
+ %c = call <16 x half> @llvm.maximumnum.v16f16(<16 x half> %a, <16 x half> %b)
+ ret <16 x half> %c
+}
+
+;;;;;;;;;;;;;;;; min_f64
+define double @min_nofpclass_s_f64(double nofpclass(snan) %a, double nofpclass(snan) %b) {
+; AARCH64-LABEL: min_nofpclass_s_f64:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fminnm d0, d0, d1
+; AARCH64-NEXT: ret
+entry:
+ %c = call double @llvm.minimumnum.f64(double %a, double %b)
+ ret double %c
+}
+
+define <2 x double> @min_nofpclass_s_v2f64(<2 x double> nofpclass(snan) %a, <2 x double> nofpclass(snan) %b) {
+; AARCH64-LABEL: min_nofpclass_s_v2f64:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fminnm v0.2d, v0.2d, v1.2d
+; AARCH64-NEXT: ret
+entry:
+ %c = call <2 x double> @llvm.minimumnum.v2f64(<2 x double> %a, <2 x double> %b)
+ ret <2 x double> %c
+}
+
+define <3 x double> @min_nofpclass_s_v3f64(<3 x double> nofpclass(snan) %a, <3 x double> nofpclass(snan) %b) {
+; AARCH64-LABEL: min_nofpclass_s_v3f64:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: // kill: def $d3 killed $d3 def $q3
+; AARCH64-NEXT: // kill: def $d0 killed $d0 def $q0
+; AARCH64-NEXT: // kill: def $d4 killed $d4 def $q4
+; AARCH64-NEXT: // kill: def $d1 killed $d1 def $q1
+; AARCH64-NEXT: // kill: def $d2 killed $d2 def $q2
+; AARCH64-NEXT: // kill: def $d5 killed $d5 def $q5
+; AARCH64-NEXT: mov v3.d[1], v4.d[0]
+; AARCH64-NEXT: mov v0.d[1], v1.d[0]
+; AARCH64-NEXT: fminnm v2.2d, v2.2d, v5.2d
+; AARCH64-NEXT: // kill: def $d2 killed $d2 killed $q2
+; AARCH64-NEXT: fminnm v0.2d, v0.2d, v3.2d
+; AARCH64-NEXT: ext v1.16b, v0.16b, v0.16b, #8
+; AARCH64-NEXT: // kill: def $d0 killed $d0 killed $q0
+; AARCH64-NEXT: // kill: def $d1 killed $d1 killed $q1
+; AARCH64-NEXT: ret
+entry:
+ %c = call <3 x double> @llvm.minimumnum.v3f64(<3 x double> %a, <3 x double> %b)
+ ret <3 x double> %c
+}
+
+define <4 x double> @min_nofpclass_s_v4f64(<4 x double> nofpclass(snan) %a, <4 x double> nofpclass(snan) %b) {
+; AARCH64-LABEL: min_nofpclass_s_v4f64:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fminnm v1.2d, v1.2d, v3.2d
+; AARCH64-NEXT: fminnm v0.2d, v0.2d, v2.2d
+; AARCH64-NEXT: ret
+entry:
+ %c = call <4 x double> @llvm.minimumnum.v4f64(<4 x double> %a, <4 x double> %b)
+ ret <4 x double> %c
+}
+
+define <2 x float> @min_nofpclass_s_v2f32(<2 x float> nofpclass(snan) %a, <2 x float> nofpclass(snan) %b) {
+; AARCH64-LABEL: min_nofpclass_s_v2f32:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fminnm v0.2s, v0.2s, v1.2s
+; AARCH64-NEXT: ret
+entry:
+ %c = call <2 x float> @llvm.minimumnum.v2f32(<2 x float> %a, <2 x float> %b)
+ ret <2 x float> %c
+}
+
+define <3 x float> @min_nofpclass_s_v3f32(<3 x float> nofpclass(snan) %a, <3 x float> nofpclass(snan) %b) {
+; AARCH64-LABEL: min_nofpclass_s_v3f32:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fminnm v0.4s, v0.4s, v1.4s
+; AARCH64-NEXT: ret
+entry:
+ %c = call <3 x float> @llvm.minimumnum.v3f32(<3 x float> %a, <3 x float> %b)
+ ret <3 x float> %c
+}
+
+define <4 x float> @min_nofpclass_s_v4f32(<4 x float> nofpclass(snan) %a, <4 x float> nofpclass(snan) %b) {
+; AARCH64-LABEL: min_nofpclass_s_v4f32:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fminnm v0.4s, v0.4s, v1.4s
+; AARCH64-NEXT: ret
+entry:
+ %c = call <4 x float> @llvm.minimumnum.v4f32(<4 x float> %a, <4 x float> %b)
+ ret <4 x float> %c
+}
+
+define <5 x float> @min_nofpclass_s_v5f32(<5 x float> nofpclass(snan) %a, <5 x float> nofpclass(snan) %b) {
+; AARCH64-LABEL: min_nofpclass_s_v5f32:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: // kill: def $s0 killed $s0 def $q0
+; AARCH64-NEXT: // kill: def $s5 killed $s5 def $q5
+; AARCH64-NEXT: // kill: def $s1 killed $s1 def $q1
+; AARCH64-NEXT: // kill: def $s6 killed $s6 def $q6
+; AARCH64-NEXT: // kill: def $s2 killed $s2 def $q2
+; AARCH64-NEXT: // kill: def $s7 killed $s7 def $q7
+; AARCH64-NEXT: // kill: def $s3 killed $s3 def $q3
+; AARCH64-NEXT: mov x8, sp
+; AARCH64-NEXT: // kill: def $s4 killed $s4 def $q4
+; AARCH64-NEXT: mov v0.s[1], v1.s[0]
+; AARCH64-NEXT: mov v5.s[1], v6.s[0]
+; AARCH64-NEXT: mov v0.s[2], v2.s[0]
+; AARCH64-NEXT: mov v5.s[2], v7.s[0]
+; AARCH64-NEXT: ldr s2, [sp, #8]
+; AARCH64-NEXT: fminnm v4.4s, v4.4s, v2.4s
+; AARCH64-NEXT: // kill: def $s4 killed $s4 killed $q4
+; AARCH64-NEXT: mov v0.s[3], v3.s[0]
+; AARCH64-NEXT: ld1 { v5.s }[3], [x8]
+; AARCH64-NEXT: fminnm v0.4s, v0.4s, v5.4s
+; AARCH64-NEXT: mov s1, v0.s[1]
+; AARCH64-NEXT: mov s2, v0.s[2]
+; AARCH64-NEXT: mov s3, v0.s[3]
+; AARCH64-NEXT: // kill: def $s0 killed $s0 killed $q0
+; AARCH64-NEXT: ret
+entry:
+ %c = call <5 x float> @llvm.minimumnum.v5f32(<5 x float> %a, <5 x float> %b)
+ ret <5 x float> %c
+}
+
+define <8 x float> @min_nofpclass_s_v8f32(<8 x float> nofpclass(snan) %a, <8 x float> nofpclass(snan) %b) {
+; AARCH64-LABEL: min_nofpclass_s_v8f32:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fminnm v1.4s, v1.4s, v3.4s
+; AARCH64-NEXT: fminnm v0.4s, v0.4s, v2.4s
+; AARCH64-NEXT: ret
+entry:
+ %c = call <8 x float> @llvm.minimumnum.v8f32(<8 x float> %a, <8 x float> %b)
+ ret <8 x float> %c
+}
+
+;;;;;;;;;;;;;;;;;; min_f16
+define half @min_nofpclass_s_f16(half nofpclass(snan) %a, half nofpclass(snan) %b) {
+; AARCH64-LABEL: min_nofpclass_s_f16:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fminnm h0, h0, h1
+; AARCH64-NEXT: ret
+entry:
+ %c = call half @llvm.minimumnum.f16(half %a, half %b)
+ ret half %c
+}
+
+define <2 x half> @min_nofpclass_s_v2f16(<2 x half> nofpclass(snan) %a, <2 x half> nofpclass(snan) %b) {
+; AARCH64-LABEL: min_nofpclass_s_v2f16:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fminnm v0.4h, v0.4h, v1.4h
+; AARCH64-NEXT: ret
+entry:
+ %c = call <2 x half> @llvm.minimumnum.v2f16(<2 x half> %a, <2 x half> %b)
+ ret <2 x half> %c
+}
+
+define <4 x half> @min_nofpclass_s_v4f16(<4 x half> nofpclass(snan) %a, <4 x half> nofpclass(snan) %b) {
+; AARCH64-LABEL: min_nofpclass_s_v4f16:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fminnm v0.4h, v0.4h, v1.4h
+; AARCH64-NEXT: ret
+entry:
+ %c = call <4 x half> @llvm.minimumnum.v4f16(<4 x half> %a, <4 x half> %b)
+ ret <4 x half> %c
+}
+
+define <8 x half> @min_nofpclass_s_v8f16(<8 x half> nofpclass(snan) %a, <8 x half> nofpclass(snan) %b) {
+; AARCH64-LABEL: min_nofpclass_s_v8f16:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fminnm v0.8h, v0.8h, v1.8h
+; AARCH64-NEXT: ret
+entry:
+ %c = call <8 x half> @llvm.minimumnum.v8f16(<8 x half> %a, <8 x half> %b)
+ ret <8 x half> %c
+}
+
+define <9 x half> @min_nofpclass_s_v9f16(<9 x half> nofpclass(snan) %a, <9 x half> nofpclass(snan) %b) {
+; AARCH64-LABEL: min_nofpclass_s_v9f16:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: // kill: def $h0 killed $h0 def $q0
+; AARCH64-NEXT: // kill: def $h1 killed $h1 def $q1
+; AARCH64-NEXT: // kill: def $h2 killed $h2 def $q2
+; AARCH64-NEXT: add x9, sp, #16
+; AARCH64-NEXT: // kill: def $h3 killed $h3 def $q3
+; AARCH64-NEXT: // kill: def $h4 killed $h4 def $q4
+; AARCH64-NEXT: // kill: def $h5 killed $h5 def $q5
+; AARCH64-NEXT: // kill: def $h6 killed $h6 def $q6
+; AARCH64-NEXT: // kill: def $h7 killed $h7 def $q7
+; AARCH64-NEXT: mov v0.h[1], v1.h[0]
+; AARCH64-NEXT: ldr h1, [sp, #8]
+; AARCH64-NEXT: ld1 { v1.h }[1], [x9]
+; AARCH64-NEXT: add x9, sp, #24
+; AARCH64-NEXT: mov v0.h[2], v2.h[0]
+; AARCH64-NEXT: ldr h2, [sp, #72]
+; AARCH64-NEXT: ld1 { v1.h }[2], [x9]
+; AARCH64-NEXT: add x9, sp, #32
+; AARCH64-NEXT: mov v0.h[3], v3.h[0]
+; AARCH64-NEXT: ld1 { v1.h }[3], [x9]
+; AARCH64-NEXT: add x9, sp, #40
+; AARCH64-NEXT: ldr h3, [sp]
+; AARCH64-NEXT: ld1 { v1.h }[4], [x9]
+; AARCH64-NEXT: add x9, sp, #48
+; AARCH64-NEXT: fminnm v2.8h, v3.8h, v2.8h
+; AARCH64-NEXT: mov v0.h[4], v4.h[0]
+; AARCH64-NEXT: ld1 { v1.h }[5], [x9]
+; AARCH64-NEXT: add x9, sp, #56
+; AARCH64-NEXT: str h2, [x8, #16]
+; AARCH64-NEXT: mov v0.h[5], v5.h[0]
+; AARCH64-NEXT: ld1 { v1.h }[6], [x9]
+; AARCH64-NEXT: add x9, sp, #64
+; AARCH64-NEXT: mov v0.h[6], v6.h[0]
+; AARCH64-NEXT: ld1 { v1.h }[7], [x9]
+; AARCH64-NEXT: mov v0.h[7], v7.h[0]
+; AARCH64-NEXT: fminnm v0.8h, v0.8h, v1.8h
+; AARCH64-NEXT: str q0, [x8]
+; AARCH64-NEXT: ret
+entry:
+ %c = call <9 x half> @llvm.minimumnum.v9f16(<9 x half> %a, <9 x half> %b)
+ ret <9 x half> %c
+}
+
+define <16 x half> @min_nofpclass_s_v16f16(<16 x half> nofpclass(snan) %a, <16 x half> nofpclass(snan) %b) {
+; AARCH64-LABEL: min_nofpclass_s_v16f16:
+; AARCH64: // %bb.0: // %entry
+; AARCH64-NEXT: fminnm v1.8h, v1.8h, v3.8h
+; AARCH64-NEXT: fminnm v0.8h, v0.8h, v2.8h
+; AARCH64-NEXT: ret
+entry:
+ %c = call <16 x half> @llvm.minimumnum.v16f16(<16 x half> %a, <16 x half> %b)
+ ret <16 x half> %c
+}
diff --git a/llvm/test/CodeGen/LoongArch/fp-maximumnum-minimumnum.ll b/llvm/test/CodeGen/LoongArch/fp-maximumnum-minimumnum.ll
index 607e50cb5a6c6..16319e74510d5 100644
--- a/llvm/test/CodeGen/LoongArch/fp-maximumnum-minimumnum.ll
+++ b/llvm/test/CodeGen/LoongArch/fp-maximumnum-minimumnum.ll
@@ -100,6 +100,54 @@ define float @maximumnum_float_nnan(float %x, float %y) {
ret float %z
}
+define float @maximumnum_float_nofpclass(float nofpclass(nan) %x, float nofpclass(nan) %y) {
+; LA32F-LABEL: maximumnum_float_nofpclass:
+; LA32F: # %bb.0:
+; LA32F-NEXT: fmax.s $fa0, $fa0, $fa1
+; LA32F-NEXT: ret
+;
+; LA32D-LABEL: maximumnum_float_nofpclass:
+; LA32D: # %bb.0:
+; LA32D-NEXT: fmax.s $fa0, $fa0, $fa1
+; LA32D-NEXT: ret
+;
+; LA64F-LABEL: maximumnum_float_nofpclass:
+; LA64F: # %bb.0:
+; LA64F-NEXT: fmax.s $fa0, $fa0, $fa1
+; LA64F-NEXT: ret
+;
+; LA64D-LABEL: maximumnum_float_nofpclass:
+; LA64D: # %bb.0:
+; LA64D-NEXT: fmax.s $fa0, $fa0, $fa1
+; LA64D-NEXT: ret
+ %z = call float @llvm.maximumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+define float @maximumnum_float_nofpclass_s(float nofpclass(snan) %x, float nofpclass(snan) %y) {
+; LA32F-LABEL: maximumnum_float_nofpclass_s:
+; LA32F: # %bb.0:
+; LA32F-NEXT: fmax.s $fa0, $fa0, $fa1
+; LA32F-NEXT: ret
+;
+; LA32D-LABEL: maximumnum_float_nofpclass_s:
+; LA32D: # %bb.0:
+; LA32D-NEXT: fmax.s $fa0, $fa0, $fa1
+; LA32D-NEXT: ret
+;
+; LA64F-LABEL: maximumnum_float_nofpclass_s:
+; LA64F: # %bb.0:
+; LA64F-NEXT: fmax.s $fa0, $fa0, $fa1
+; LA64F-NEXT: ret
+;
+; LA64D-LABEL: maximumnum_float_nofpclass_s:
+; LA64D: # %bb.0:
+; LA64D-NEXT: fmax.s $fa0, $fa0, $fa1
+; LA64D-NEXT: ret
+ %z = call float @llvm.maximumnum.f32(float %x, float %y)
+ ret float %z
+}
+
define double @maximumnum_double(double %x, double %y) {
;
@@ -223,6 +271,79 @@ define double @maximumnum_double_nnan(double %x, double %y) {
ret double %z
}
+define double @maximumnum_double_nofpclass(double nofpclass(nan) %x, double nofpclass(nan) %y) {
+; LA32F-LABEL: maximumnum_double_nofpclass:
+; LA32F: # %bb.0:
+; LA32F-NEXT: addi.w $sp, $sp, -16
+; LA32F-NEXT: .cfi_def_cfa_offset 16
+; LA32F-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill
+; LA32F-NEXT: .cfi_offset 1, -4
+; LA32F-NEXT: bl %plt(fmaximum_num)
+; LA32F-NEXT: ld.w $ra, $sp, 12 # 4-byte Folded Reload
+; LA32F-NEXT: addi.w $sp, $sp, 16
+; LA32F-NEXT: ret
+;
+; LA32D-LABEL: maximumnum_double_nofpclass:
+; LA32D: # %bb.0:
+; LA32D-NEXT: fmax.d $fa0, $fa0, $fa1
+; LA32D-NEXT: ret
+;
+; LA64F-LABEL: maximumnum_double_nofpclass:
+; LA64F: # %bb.0:
+; LA64F-NEXT: addi.d $sp, $sp, -16
+; LA64F-NEXT: .cfi_def_cfa_offset 16
+; LA64F-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
+; LA64F-NEXT: .cfi_offset 1, -8
+; LA64F-NEXT: bl %plt(fmaximum_num)
+; LA64F-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
+; LA64F-NEXT: addi.d $sp, $sp, 16
+; LA64F-NEXT: ret
+;
+; LA64D-LABEL: maximumnum_double_nofpclass:
+; LA64D: # %bb.0:
+; LA64D-NEXT: fmax.d $fa0, $fa0, $fa1
+; LA64D-NEXT: ret
+ %z = call double @llvm.maximumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define double @maximumnum_double_nofpclass_s(double nofpclass(snan) %x, double nofpclass(snan) %y) {
+; LA32F-LABEL: maximumnum_double_nofpclass_s:
+; LA32F: # %bb.0:
+; LA32F-NEXT: addi.w $sp, $sp, -16
+; LA32F-NEXT: .cfi_def_cfa_offset 16
+; LA32F-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill
+; LA32F-NEXT: .cfi_offset 1, -4
+; LA32F-NEXT: bl %plt(fmaximum_num)
+; LA32F-NEXT: ld.w $ra, $sp, 12 # 4-byte Folded Reload
+; LA32F-NEXT: addi.w $sp, $sp, 16
+; LA32F-NEXT: ret
+;
+; LA32D-LABEL: maximumnum_double_nofpclass_s:
+; LA32D: # %bb.0:
+; LA32D-NEXT: fmax.d $fa0, $fa0, $fa1
+; LA32D-NEXT: ret
+;
+; LA64F-LABEL: maximumnum_double_nofpclass_s:
+; LA64F: # %bb.0:
+; LA64F-NEXT: addi.d $sp, $sp, -16
+; LA64F-NEXT: .cfi_def_cfa_offset 16
+; LA64F-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
+; LA64F-NEXT: .cfi_offset 1, -8
+; LA64F-NEXT: bl %plt(fmaximum_num)
+; LA64F-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
+; LA64F-NEXT: addi.d $sp, $sp, 16
+; LA64F-NEXT: ret
+;
+; LA64D-LABEL: maximumnum_double_nofpclass_s:
+; LA64D: # %bb.0:
+; LA64D-NEXT: fmax.d $fa0, $fa0, $fa1
+; LA64D-NEXT: ret
+ %z = call double @llvm.maximumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+
define float @minimumnum_float(float %x, float %y) {
;
; LA32F-LABEL: minimumnum_float:
@@ -314,6 +435,54 @@ define float @minimumnum_float_nnan(float %x, float %y) {
ret float %z
}
+define float @minimumnum_float_nofpclass(float nofpclass(nan) %x, float nofpclass(nan) %y) {
+; LA32F-LABEL: minimumnum_float_nofpclass:
+; LA32F: # %bb.0:
+; LA32F-NEXT: fmin.s $fa0, $fa0, $fa1
+; LA32F-NEXT: ret
+;
+; LA32D-LABEL: minimumnum_float_nofpclass:
+; LA32D: # %bb.0:
+; LA32D-NEXT: fmin.s $fa0, $fa0, $fa1
+; LA32D-NEXT: ret
+;
+; LA64F-LABEL: minimumnum_float_nofpclass:
+; LA64F: # %bb.0:
+; LA64F-NEXT: fmin.s $fa0, $fa0, $fa1
+; LA64F-NEXT: ret
+;
+; LA64D-LABEL: minimumnum_float_nofpclass:
+; LA64D: # %bb.0:
+; LA64D-NEXT: fmin.s $fa0, $fa0, $fa1
+; LA64D-NEXT: ret
+ %z = call float @llvm.minimumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+define float @minimumnum_float_nofpclass_s(float nofpclass(snan) %x, float nofpclass(snan) %y) {
+; LA32F-LABEL: minimumnum_float_nofpclass_s:
+; LA32F: # %bb.0:
+; LA32F-NEXT: fmin.s $fa0, $fa0, $fa1
+; LA32F-NEXT: ret
+;
+; LA32D-LABEL: minimumnum_float_nofpclass_s:
+; LA32D: # %bb.0:
+; LA32D-NEXT: fmin.s $fa0, $fa0, $fa1
+; LA32D-NEXT: ret
+;
+; LA64F-LABEL: minimumnum_float_nofpclass_s:
+; LA64F: # %bb.0:
+; LA64F-NEXT: fmin.s $fa0, $fa0, $fa1
+; LA64F-NEXT: ret
+;
+; LA64D-LABEL: minimumnum_float_nofpclass_s:
+; LA64D: # %bb.0:
+; LA64D-NEXT: fmin.s $fa0, $fa0, $fa1
+; LA64D-NEXT: ret
+ %z = call float @llvm.minimumnum.f32(float %x, float %y)
+ ret float %z
+}
+
define double @minimumnum_double(double %x, double %y) {
;
; LA32F-LABEL: minimumnum_double:
@@ -435,3 +604,75 @@ define double @minimumnum_double_nnan(double %x, double %y) {
%z = call nnan double @llvm.minimumnum.f64(double %x, double %y)
ret double %z
}
+
+define double @minimumnum_double_nofpclass(double nofpclass(nan) %x, double nofpclass(nan) %y) {
+; LA32F-LABEL: minimumnum_double_nofpclass:
+; LA32F: # %bb.0:
+; LA32F-NEXT: addi.w $sp, $sp, -16
+; LA32F-NEXT: .cfi_def_cfa_offset 16
+; LA32F-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill
+; LA32F-NEXT: .cfi_offset 1, -4
+; LA32F-NEXT: bl %plt(fminimum_num)
+; LA32F-NEXT: ld.w $ra, $sp, 12 # 4-byte Folded Reload
+; LA32F-NEXT: addi.w $sp, $sp, 16
+; LA32F-NEXT: ret
+;
+; LA32D-LABEL: minimumnum_double_nofpclass:
+; LA32D: # %bb.0:
+; LA32D-NEXT: fmin.d $fa0, $fa0, $fa1
+; LA32D-NEXT: ret
+;
+; LA64F-LABEL: minimumnum_double_nofpclass:
+; LA64F: # %bb.0:
+; LA64F-NEXT: addi.d $sp, $sp, -16
+; LA64F-NEXT: .cfi_def_cfa_offset 16
+; LA64F-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
+; LA64F-NEXT: .cfi_offset 1, -8
+; LA64F-NEXT: bl %plt(fminimum_num)
+; LA64F-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
+; LA64F-NEXT: addi.d $sp, $sp, 16
+; LA64F-NEXT: ret
+;
+; LA64D-LABEL: minimumnum_double_nofpclass:
+; LA64D: # %bb.0:
+; LA64D-NEXT: fmin.d $fa0, $fa0, $fa1
+; LA64D-NEXT: ret
+ %z = call double @llvm.minimumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define double @minimumnum_double_nofpclass_s(double nofpclass(snan) %x, double nofpclass(snan) %y) {
+; LA32F-LABEL: minimumnum_double_nofpclass_s:
+; LA32F: # %bb.0:
+; LA32F-NEXT: addi.w $sp, $sp, -16
+; LA32F-NEXT: .cfi_def_cfa_offset 16
+; LA32F-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill
+; LA32F-NEXT: .cfi_offset 1, -4
+; LA32F-NEXT: bl %plt(fminimum_num)
+; LA32F-NEXT: ld.w $ra, $sp, 12 # 4-byte Folded Reload
+; LA32F-NEXT: addi.w $sp, $sp, 16
+; LA32F-NEXT: ret
+;
+; LA32D-LABEL: minimumnum_double_nofpclass_s:
+; LA32D: # %bb.0:
+; LA32D-NEXT: fmin.d $fa0, $fa0, $fa1
+; LA32D-NEXT: ret
+;
+; LA64F-LABEL: minimumnum_double_nofpclass_s:
+; LA64F: # %bb.0:
+; LA64F-NEXT: addi.d $sp, $sp, -16
+; LA64F-NEXT: .cfi_def_cfa_offset 16
+; LA64F-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
+; LA64F-NEXT: .cfi_offset 1, -8
+; LA64F-NEXT: bl %plt(fminimum_num)
+; LA64F-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
+; LA64F-NEXT: addi.d $sp, $sp, 16
+; LA64F-NEXT: ret
+;
+; LA64D-LABEL: minimumnum_double_nofpclass_s:
+; LA64D: # %bb.0:
+; LA64D-NEXT: fmin.d $fa0, $fa0, $fa1
+; LA64D-NEXT: ret
+ %z = call double @llvm.minimumnum.f64(double %x, double %y)
+ ret double %z
+}
diff --git a/llvm/test/CodeGen/Mips/fp-maximumnum-minimumnum.ll b/llvm/test/CodeGen/Mips/fp-maximumnum-minimumnum.ll
index bc81966ca0f5c..4e79cd5a635bd 100644
--- a/llvm/test/CodeGen/Mips/fp-maximumnum-minimumnum.ll
+++ b/llvm/test/CodeGen/Mips/fp-maximumnum-minimumnum.ll
@@ -37,6 +37,24 @@ define float @maximumnum_float_nnan(float %x, float %y) {
ret float %z
}
+define float @maximumnum_float_nofpclass(float nofpclass(nan) %x, float nofpclass(nan) %y) {
+; MIPS32R6-LABEL: maximumnum_float_nofpclass:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: max.s $f0, $f12, $f14
+ %z = call float @llvm.maximumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+define float @maximumnum_float_nofpclass_s(float nofpclass(snan) %x, float nofpclass(snan) %y) {
+; MIPS32R6-LABEL: maximumnum_float_nofpclass_s:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: max.s $f0, $f12, $f14
+ %z = call float @llvm.maximumnum.f32(float %x, float %y)
+ ret float %z
+}
+
define double @maximumnum_double(double %x, double %y) {
; MIPS32R6-LABEL: maximumnum_double:
@@ -69,6 +87,25 @@ define double @maximumnum_double_nnan(double %x, double %y) {
ret double %z
}
+define double @maximumnum_double_nofpclass(double nofpclass(nan) %x, double nofpclass(nan) %y) {
+; MIPS32R6-LABEL: maximumnum_double_nofpclass:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: max.d $f0, $f12, $f14
+ %z = call double @llvm.maximumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define double @maximumnum_double_nofpclass_s(double nofpclass(snan) %x, double nofpclass(snan) %y) {
+; MIPS32R6-LABEL: maximumnum_double_nofpclass_s:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: max.d $f0, $f12, $f14
+ %z = call double @llvm.maximumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+
define float @minimumnum_float(float %x, float %y) {
; MIPS32R6-LABEL: minimumnum_float:
; MIPS32R6: # %bb.0:
@@ -100,6 +137,24 @@ define float @minimumnum_float_nnan(float %x, float %y) {
ret float %z
}
+define float @minimumnum_float_nofpclass(float nofpclass(nan) %x, float nofpclass(nan) %y) {
+; MIPS32R6-LABEL: minimumnum_float_nofpclass:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: min.s $f0, $f12, $f14
+ %z = call float @llvm.minimumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+define float @minimumnum_float_nofpclass_s(float nofpclass(snan) %x, float nofpclass(snan) %y) {
+; MIPS32R6-LABEL: minimumnum_float_nofpclass_s:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: min.s $f0, $f12, $f14
+ %z = call float @llvm.minimumnum.f32(float %x, float %y)
+ ret float %z
+}
+
define double @minimumnum_double(double %x, double %y) {
; MIPS32R6-LABEL: minimumnum_double:
; MIPS32R6: # %bb.0:
@@ -130,3 +185,21 @@ define double @minimumnum_double_nnan(double %x, double %y) {
%z = call nnan double @llvm.minimumnum.f64(double %x, double %y)
ret double %z
}
+
+define double @minimumnum_double_nofpclass(double nofpclass(nan) %x, double nofpclass(nan) %y) {
+; MIPS32R6-LABEL: minimumnum_double_nofpclass:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: min.d $f0, $f12, $f14
+ %z = call double @llvm.minimumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define double @minimumnum_double_nofpclass_s(double nofpclass(snan) %x, double nofpclass(snan) %y) {
+; MIPS32R6-LABEL: minimumnum_double_nofpclass_s:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: min.d $f0, $f12, $f14
+ %z = call double @llvm.minimumnum.f64(double %x, double %y)
+ ret double %z
+}
>From 7b368a2888c6d2634e8cad937b5df02f84fff898 Mon Sep 17 00:00:00 2001
From: YunQiang Su <yunqiang at isrc.iscas.ac.cn>
Date: Wed, 16 Apr 2025 18:26:58 +0800
Subject: [PATCH 2/2] Update LoongArch test
---
.../CodeGen/LoongArch/fp-maximumnum-minimumnum.ll | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/llvm/test/CodeGen/LoongArch/fp-maximumnum-minimumnum.ll b/llvm/test/CodeGen/LoongArch/fp-maximumnum-minimumnum.ll
index 16319e74510d5..704ff592996fc 100644
--- a/llvm/test/CodeGen/LoongArch/fp-maximumnum-minimumnum.ll
+++ b/llvm/test/CodeGen/LoongArch/fp-maximumnum-minimumnum.ll
@@ -294,7 +294,8 @@ define double @maximumnum_double_nofpclass(double nofpclass(nan) %x, double nofp
; LA64F-NEXT: .cfi_def_cfa_offset 16
; LA64F-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
; LA64F-NEXT: .cfi_offset 1, -8
-; LA64F-NEXT: bl %plt(fmaximum_num)
+; LA64F-NEXT: pcaddu18i $ra, %call36(fmaximum_num)
+; LA64F-NEXT: jirl $ra, $ra, 0
; LA64F-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
; LA64F-NEXT: addi.d $sp, $sp, 16
; LA64F-NEXT: ret
@@ -330,7 +331,8 @@ define double @maximumnum_double_nofpclass_s(double nofpclass(snan) %x, double n
; LA64F-NEXT: .cfi_def_cfa_offset 16
; LA64F-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
; LA64F-NEXT: .cfi_offset 1, -8
-; LA64F-NEXT: bl %plt(fmaximum_num)
+; LA64F-NEXT: pcaddu18i $ra, %call36(fmaximum_num)
+; LA64F-NEXT: jirl $ra, $ra, 0
; LA64F-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
; LA64F-NEXT: addi.d $sp, $sp, 16
; LA64F-NEXT: ret
@@ -628,7 +630,8 @@ define double @minimumnum_double_nofpclass(double nofpclass(nan) %x, double nofp
; LA64F-NEXT: .cfi_def_cfa_offset 16
; LA64F-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
; LA64F-NEXT: .cfi_offset 1, -8
-; LA64F-NEXT: bl %plt(fminimum_num)
+; LA64F-NEXT: pcaddu18i $ra, %call36(fminimum_num)
+; LA64F-NEXT: jirl $ra, $ra, 0
; LA64F-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
; LA64F-NEXT: addi.d $sp, $sp, 16
; LA64F-NEXT: ret
@@ -664,7 +667,8 @@ define double @minimumnum_double_nofpclass_s(double nofpclass(snan) %x, double n
; LA64F-NEXT: .cfi_def_cfa_offset 16
; LA64F-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
; LA64F-NEXT: .cfi_offset 1, -8
-; LA64F-NEXT: bl %plt(fminimum_num)
+; LA64F-NEXT: pcaddu18i $ra, %call36(fminimum_num)
+; LA64F-NEXT: jirl $ra, $ra, 0
; LA64F-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
; LA64F-NEXT: addi.d $sp, $sp, 16
; LA64F-NEXT: ret
More information about the llvm-commits
mailing list