[llvm] Intrinsic: introduce minimumnum and maximumnum for IR and SelectionDAG (PR #96649)
YunQiang Su via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 13 19:28:01 PDT 2024
https://github.com/wzssyqa updated https://github.com/llvm/llvm-project/pull/96649
>From 76e4aec38e897b96485c9b397b515d46a3baa281 Mon Sep 17 00:00:00 2001
From: YunQiang Su <syq at gcc.gnu.org>
Date: Tue, 25 Jun 2024 22:23:41 +0800
Subject: [PATCH 01/17] Intrinsic: introduce minimumnum and maximumnum for IR
and SelectionDAG
C23 introduced new functions fminimum_num and fmaximum_num,
and they follow the minimumNumber and maximumNumber of IEEE754-2019.
Let's introduce new intrinsics to support them.
This patch introduces support only support for scalar values.
The support of
vector (vp, vp.reduce, vector.reduce),
experimental.constrained
will be added in future patches.
With this patch, MIPSr6 and LoongArch can work out of box.
Other architectures will fallback to libc call. The support of them
will be added in future patches.
Background
Currently we have fminnum/fmaxnum, which have different
behavior on different platform for NUM vs sNaN:
1) Fallback to fmin(3)/fmax(3): return qNaN.
2) ARM64/ARM32+Neon: same as libc.
3) MIPSr6/LoongArch/RISC-V: return NUM.
And the fix of fminnum/fmaxnum to follow minNUM/maxNUM of IEEE754-2008
will submit as separated patches.
---
llvm/docs/LangRef.rst | 186 ++++++++++++++++++
.../llvm/Analysis/TargetLibraryInfo.def | 33 ++++
llvm/include/llvm/CodeGen/BasicTTIImpl.h | 6 +
llvm/include/llvm/CodeGen/ISDOpcodes.h | 5 +
llvm/include/llvm/CodeGen/TargetLowering.h | 7 +
llvm/include/llvm/IR/IRBuilder.h | 12 ++
llvm/include/llvm/IR/IntrinsicInst.h | 2 +
llvm/include/llvm/IR/Intrinsics.td | 8 +
llvm/include/llvm/IR/RuntimeLibcalls.def | 10 +
.../include/llvm/Target/TargetSelectionDAG.td | 4 +
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 5 +-
llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 18 ++
.../SelectionDAG/LegalizeFloatTypes.cpp | 46 +++++
llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h | 4 +
.../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 8 +-
.../SelectionDAG/SelectionDAGBuilder.cpp | 24 +++
.../SelectionDAG/SelectionDAGDumper.cpp | 2 +
.../CodeGen/SelectionDAG/TargetLowering.cpp | 87 ++++++++
llvm/lib/CodeGen/TargetLoweringBase.cpp | 1 +
.../LoongArch/fp-maximumnum-minimumnum.ll | 154 +++++++++++++++
.../CodeGen/Mips/fp-maximumnum-minimumnum.ll | 100 ++++++++++
.../tools/llvm-tli-checker/ps4-tli-check.yaml | 16 +-
.../Analysis/TargetLibraryInfoTest.cpp | 6 +
23 files changed, 737 insertions(+), 7 deletions(-)
create mode 100644 llvm/test/CodeGen/LoongArch/fp-maximumnum-minimumnum.ll
create mode 100644 llvm/test/CodeGen/Mips/fp-maximumnum-minimumnum.ll
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 0ee4d7b444cfcf..903eaa3db12332 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -16131,6 +16131,100 @@ The returned value is completely identical to the input except for the sign bit;
in particular, if the input is a NaN, then the quiet/signaling bit and payload
are perfectly preserved.
+.. _i_fminmax_family:
+
+'``llvm.min.*``' Intrinsics Comparation
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Standard:
+"""""""""
+
+IEEE754 and ISO C define some min/max operations, and they have some differences
+on working with qNaN/sNaN and +0.0/-0.0. Here is the list:
+
+.. list-table::
+ :header-rows: 2
+
+ * - ``ISO C``
+ - fmin/fmax
+ - fmininum/fmaximum
+ - fminimum_num/fmaximum_num
+
+ * - ``IEEE754``
+ - minNum/maxNum (2008)
+ - minimum/maximum (2019)
+ - minimumNumber/maximumNumber (2019)
+
+ * - ``+0.0 vs -0.0``
+ - either one
+ - +0.0 > -0.0
+ - +0.0 > -0.0
+
+ * - ``NUM vs sNaN``
+ - qNaN, invalid exception
+ - qNaN, invalid exception
+ - NUM, invalid exception
+
+ * - ``qNaN vs sNaN``
+ - qNaN, invalid exception
+ - qNaN, invalid exception
+ - qNaN, invalid exception
+
+ * - ``NUM vs qNaN``
+ - NUM, no exception
+ - qNaN, no exception
+ - NUM, no exception
+
+LLVM Implementation:
+""""""""""""""""""""
+
+LLVM implements all ISO C flavors as listed in this table.
+Only basic intrinsics list here. The constrained version
+ones may have different behaivor on exception.
+
+Since some architectures implement minNum/maxNum with +0.0>-0.0,
+so we define internal ISD::MINNUM_IEEE and ISD::MAXNUM_IEEE.
+They will be helpful to implement minimumnum/maximumnum.
+
+.. list-table::
+ :header-rows: 1
+ :widths: 16 28 28 28
+
+ * - Operation
+ - minnum/maxnum
+ - minimum/maximum
+ - minimumnum/maximumnum
+
+ * - ``NUM vs qNaN``
+ - NUM, no exception
+ - qNaN, no exception
+ - NUM, no exception
+
+ * - ``NUM vs sNaN``
+ - qNaN, invalid exception
+ - qNaN, invalid exception
+ - NUM, invalid exception
+
+ * - ``qNaN vs sNaN``
+ - qNaN, invalid exception
+ - qNaN, invalid exception
+ - qNaN, invalid exception
+
+ * - ``sNaN vs sNaN``
+ - qNaN, invalid exception
+ - qNaN, invalid exception
+ - qNaN, invalid exception
+
+ * - ``+0.0 vs -0.0``
+ - either one
+ - +0.0(max)/-0.0(min)
+ - +0.0(max)/-0.0(min)
+
+ * - ``NUM vs NUM``
+ - larger(max)/smaller(min)
+ - larger(max)/smaller(min)
+ - larger(max)/smaller(min)
+
.. _i_minnum:
'``llvm.minnum.*``' Intrinsic
@@ -16312,6 +16406,98 @@ of the two arguments. -0.0 is considered to be less than +0.0 for this
intrinsic. Note that these are the semantics specified in the draft of
IEEE 754-2019.
+.. _i_minimumnum:
+
+'``llvm.minimumnum.*``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+This is an overloaded intrinsic. You can use ``llvm.minimumnum`` on any
+floating-point or vector of floating-point type. Not all targets support
+all types however.
+
+::
+
+ declare float @llvm.minimumnum.f32(float %Val0, float %Val1)
+ declare double @llvm.minimumnum.f64(double %Val0, double %Val1)
+ declare x86_fp80 @llvm.minimumnum.f80(x86_fp80 %Val0, x86_fp80 %Val1)
+ declare fp128 @llvm.minimumnum.f128(fp128 %Val0, fp128 %Val1)
+ declare ppc_fp128 @llvm.minimumnum.ppcf128(ppc_fp128 %Val0, ppc_fp128 %Val1)
+
+Overview:
+"""""""""
+
+The '``llvm.minimumnum.*``' intrinsics return the minimum of the two
+arguments, not propagating NaNs and treating -0.0 as less than +0.0.
+
+
+Arguments:
+""""""""""
+
+The arguments and return value are floating-point numbers of the same
+type.
+
+Semantics:
+""""""""""
+If both operands are NaNs (including sNaN), returns qNaN. If one operand
+is NaN (including sNaN) and another operand is a number, return the number.
+Otherwise returns the lesser of the two arguments. -0.0 is considered to
+be less than +0.0 for this intrinsic.
+
+Note that these are the semantics of minimumNumber specified in IEEE 754-2019.
+
+It has some different with '``llvm.minnum.*``':
+1)'``llvm.minnum.*``' will return qNaN if either operand is sNaN.
+2)'``llvm.minnum*``' may return either one if we compare +0.0 vs -0.0.
+
+.. _i_maximumnum:
+
+'``llvm.maximumnum.*``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+This is an overloaded intrinsic. You can use ``llvm.maximumnum`` on any
+floating-point or vector of floating-point type. Not all targets support
+all types however.
+
+::
+
+ declare float @llvm.maximumnum.f32(float %Val0, float %Val1)
+ declare double @llvm.maximumnum.f64(double %Val0, double %Val1)
+ declare x86_fp80 @llvm.maximumnum.f80(x86_fp80 %Val0, x86_fp80 %Val1)
+ declare fp128 @llvm.maximumnum.f128(fp128 %Val0, fp128 %Val1)
+ declare ppc_fp128 @llvm.maximumnum.ppcf128(ppc_fp128 %Val0, ppc_fp128 %Val1)
+
+Overview:
+"""""""""
+
+The '``llvm.maximumnum.*``' intrinsics return the maximum of the two
+arguments, not propagating NaNs and treating -0.0 as less than +0.0.
+
+
+Arguments:
+""""""""""
+
+The arguments and return value are floating-point numbers of the same
+type.
+
+Semantics:
+""""""""""
+If both operands are NaNs (including sNaN), returns qNaN. If one operand
+is NaN (including sNaN) and another operand is a number, return the number.
+Otherwise returns the greater of the two arguments. -0.0 is considered to
+be less than +0.0 for this intrinsic.
+
+Note that these are the semantics of maximumNumber specified in IEEE 754-2019.
+
+It has some different with '``llvm.maxnum.*``':
+1)'``llvm.maxnum.*``' will return qNaN if either operand is sNaN.
+2)'``llvm.maxnum*``' may return either one if we compare +0.0 vs -0.0.
+
.. _int_copysign:
'``llvm.copysign.*``' Intrinsic
diff --git a/llvm/include/llvm/Analysis/TargetLibraryInfo.def b/llvm/include/llvm/Analysis/TargetLibraryInfo.def
index 23c910b56434e8..5b5833e50b984b 100644
--- a/llvm/include/llvm/Analysis/TargetLibraryInfo.def
+++ b/llvm/include/llvm/Analysis/TargetLibraryInfo.def
@@ -1388,6 +1388,39 @@ TLI_DEFINE_ENUM_INTERNAL(fminl)
TLI_DEFINE_STRING_INTERNAL("fminl")
TLI_DEFINE_SIG_INTERNAL(Floating, Same, Same)
+// Calls to fmaximum_num and fminimum_num library functions expand to the llvm.maximumnum and
+// llvm.minimumnum intrinsics with the correct parameter types for the arguments
+// (all types must match).
+/// double fmaximum_num(double x, double y);
+TLI_DEFINE_ENUM_INTERNAL(fmaximum_num)
+TLI_DEFINE_STRING_INTERNAL("fmaximum_num")
+TLI_DEFINE_SIG_INTERNAL(Floating, Same, Same)
+
+/// float fmaximum_numf(float x, float y);
+TLI_DEFINE_ENUM_INTERNAL(fmaximum_numf)
+TLI_DEFINE_STRING_INTERNAL("fmaximum_numf")
+TLI_DEFINE_SIG_INTERNAL(Floating, Same, Same)
+
+/// long double fmaximum_numl(long double x, long double y);
+TLI_DEFINE_ENUM_INTERNAL(fmaximum_numl)
+TLI_DEFINE_STRING_INTERNAL("fmaximum_numl")
+TLI_DEFINE_SIG_INTERNAL(Floating, Same, Same)
+
+/// double fminimum_num(double x, double y);
+TLI_DEFINE_ENUM_INTERNAL(fminimum_num)
+TLI_DEFINE_STRING_INTERNAL("fminimum_num")
+TLI_DEFINE_SIG_INTERNAL(Floating, Same, Same)
+
+/// float fminimum_numf(float x, float y);
+TLI_DEFINE_ENUM_INTERNAL(fminimum_numf)
+TLI_DEFINE_STRING_INTERNAL("fminimum_numf")
+TLI_DEFINE_SIG_INTERNAL(Floating, Same, Same)
+
+/// long double fminimum_numl(long double x, long double y);
+TLI_DEFINE_ENUM_INTERNAL(fminimum_numl)
+TLI_DEFINE_STRING_INTERNAL("fminimum_numl")
+TLI_DEFINE_SIG_INTERNAL(Floating, Same, Same)
+
/// double fmod(double x, double y);
TLI_DEFINE_ENUM_INTERNAL(fmod)
TLI_DEFINE_STRING_INTERNAL("fmod")
diff --git a/llvm/include/llvm/CodeGen/BasicTTIImpl.h b/llvm/include/llvm/CodeGen/BasicTTIImpl.h
index c2bc1353ee8838..468a9856e5bf2a 100644
--- a/llvm/include/llvm/CodeGen/BasicTTIImpl.h
+++ b/llvm/include/llvm/CodeGen/BasicTTIImpl.h
@@ -2037,6 +2037,12 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
case Intrinsic::maximum:
ISD = ISD::FMAXIMUM;
break;
+ case Intrinsic::minimumnum:
+ ISD = ISD::FMINIMUMNUM;
+ break;
+ case Intrinsic::maximumnum:
+ ISD = ISD::FMAXIMUMNUM;
+ break;
case Intrinsic::copysign:
ISD = ISD::FCOPYSIGN;
break;
diff --git a/llvm/include/llvm/CodeGen/ISDOpcodes.h b/llvm/include/llvm/CodeGen/ISDOpcodes.h
index 5b657fb1712968..be2c3e8a0249a1 100644
--- a/llvm/include/llvm/CodeGen/ISDOpcodes.h
+++ b/llvm/include/llvm/CodeGen/ISDOpcodes.h
@@ -1027,6 +1027,11 @@ enum NodeType {
FMINIMUM,
FMAXIMUM,
+ /// FMINIMUMNUM/FMAXIMUMNUM - minimumnum/maximumnum that is same with
+ /// FMINNUM_IEEE and FMAXNUM_IEEE besides if either operand is sNaN.
+ FMINIMUMNUM,
+ FMAXIMUMNUM,
+
/// FSINCOS - Compute both fsin and fcos as a single operation.
FSINCOS,
diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index 5b2214fa66c40b..b6fe99346bec86 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -2908,6 +2908,8 @@ class TargetLoweringBase {
case ISD::FMAXNUM_IEEE:
case ISD::FMINIMUM:
case ISD::FMAXIMUM:
+ case ISD::FMINIMUMNUM:
+ case ISD::FMAXIMUMNUM:
case ISD::AVGFLOORS:
case ISD::AVGFLOORU:
case ISD::AVGCEILS:
@@ -5144,6 +5146,8 @@ class TargetLowering : public TargetLoweringBase {
/// through to the default expansion/soften to libcall, we might introduce a
/// link-time dependency on libm into a file that originally did not have one.
SDValue createSelectForFMINNUM_FMAXNUM(SDNode *Node, SelectionDAG &DAG) const;
+ SDValue createSelectForFMINIMUMNUM_FMAXIMUMNUM(SDNode *Node,
+ SelectionDAG &DAG) const;
/// Return a reciprocal estimate value for the input operand.
/// \p Enabled is a ReciprocalEstimate enum with value either 'Unspecified' or
@@ -5275,6 +5279,9 @@ class TargetLowering : public TargetLoweringBase {
/// Expand fminimum/fmaximum into multiple comparison with selects.
SDValue expandFMINIMUM_FMAXIMUM(SDNode *N, SelectionDAG &DAG) const;
+ /// Expand fminimumnum/fmaximumnum into multiple comparison with selects.
+ SDValue expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *N, SelectionDAG &DAG) const;
+
/// Expand FP_TO_[US]INT_SAT into FP_TO_[US]INT and selects or min/max.
/// \param N Node to expand
/// \returns The expansion result
diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h
index 3f3d75012c6945..0dbcbc0b2cb76f 100644
--- a/llvm/include/llvm/IR/IRBuilder.h
+++ b/llvm/include/llvm/IR/IRBuilder.h
@@ -1015,6 +1015,18 @@ class IRBuilderBase {
return CreateBinaryIntrinsic(Intrinsic::maximum, LHS, RHS, nullptr, Name);
}
+ /// Create call to the minimumnum intrinsic.
+ Value *CreateMinimumNum(Value *LHS, Value *RHS, const Twine &Name = "") {
+ return CreateBinaryIntrinsic(Intrinsic::minimumnum, LHS, RHS, nullptr,
+ Name);
+ }
+
+ /// Create call to the maximum intrinsic.
+ Value *CreateMaximumNum(Value *LHS, Value *RHS, const Twine &Name = "") {
+ return CreateBinaryIntrinsic(Intrinsic::maximumnum, LHS, RHS, nullptr,
+ Name);
+ }
+
/// Create call to the copysign intrinsic.
Value *CreateCopySign(Value *LHS, Value *RHS,
Instruction *FMFSource = nullptr,
diff --git a/llvm/include/llvm/IR/IntrinsicInst.h b/llvm/include/llvm/IR/IntrinsicInst.h
index 94c8fa092f45e6..2f1e2c08c3ecec 100644
--- a/llvm/include/llvm/IR/IntrinsicInst.h
+++ b/llvm/include/llvm/IR/IntrinsicInst.h
@@ -76,6 +76,8 @@ class IntrinsicInst : public CallInst {
case Intrinsic::minnum:
case Intrinsic::maximum:
case Intrinsic::minimum:
+ case Intrinsic::maximumnum:
+ case Intrinsic::minimumnum:
case Intrinsic::smax:
case Intrinsic::smin:
case Intrinsic::umax:
diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td
index b4e758136b39fb..0841273fd2e1e5 100644
--- a/llvm/include/llvm/IR/Intrinsics.td
+++ b/llvm/include/llvm/IR/Intrinsics.td
@@ -1085,6 +1085,14 @@ def int_maximum : DefaultAttrsIntrinsic<[llvm_anyfloat_ty],
[LLVMMatchType<0>, LLVMMatchType<0>],
[IntrNoMem, IntrSpeculatable, IntrWillReturn, Commutative]
>;
+def int_minimumnum : DefaultAttrsIntrinsic<[llvm_anyfloat_ty],
+ [LLVMMatchType<0>, LLVMMatchType<0>],
+ [IntrNoMem, IntrSpeculatable, IntrWillReturn, Commutative]
+>;
+def int_maximumnum : DefaultAttrsIntrinsic<[llvm_anyfloat_ty],
+ [LLVMMatchType<0>, LLVMMatchType<0>],
+ [IntrNoMem, IntrSpeculatable, IntrWillReturn, Commutative]
+>;
// Internal interface for object size checking
def int_objectsize : DefaultAttrsIntrinsic<[llvm_anyint_ty],
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.def b/llvm/include/llvm/IR/RuntimeLibcalls.def
index 89aaf6d1ad83f8..c3d5ef9f4e4f82 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.def
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.def
@@ -299,6 +299,16 @@ HANDLE_LIBCALL(FMAX_F64, "fmax")
HANDLE_LIBCALL(FMAX_F80, "fmaxl")
HANDLE_LIBCALL(FMAX_F128, "fmaxl")
HANDLE_LIBCALL(FMAX_PPCF128, "fmaxl")
+HANDLE_LIBCALL(FMINIMUMNUM_F32, "fminimum_numf")
+HANDLE_LIBCALL(FMINIMUMNUM_F64, "fminimum_num")
+HANDLE_LIBCALL(FMINIMUMNUM_F80, "fminimum_numl")
+HANDLE_LIBCALL(FMINIMUMNUM_F128, "fminmum_numl")
+HANDLE_LIBCALL(FMINIMUMNUM_PPCF128, "fminimum_numl")
+HANDLE_LIBCALL(FMAXIMUMNUM_F32, "fmaximum_numf")
+HANDLE_LIBCALL(FMAXIMUMNUM_F64, "fmaximum_num")
+HANDLE_LIBCALL(FMAXIMUMNUM_F80, "fmaximum_numl")
+HANDLE_LIBCALL(FMAXIMUMNUM_F128, "fmaxmum_numl")
+HANDLE_LIBCALL(FMAXIMUMNUM_PPCF128, "fmaximum_numl")
HANDLE_LIBCALL(LROUND_F32, "lroundf")
HANDLE_LIBCALL(LROUND_F64, "lround")
HANDLE_LIBCALL(LROUND_F80, "lroundl")
diff --git a/llvm/include/llvm/Target/TargetSelectionDAG.td b/llvm/include/llvm/Target/TargetSelectionDAG.td
index fd47ddda6ca3a5..1759f94dfb83fa 100644
--- a/llvm/include/llvm/Target/TargetSelectionDAG.td
+++ b/llvm/include/llvm/Target/TargetSelectionDAG.td
@@ -514,6 +514,10 @@ def fminimum : SDNode<"ISD::FMINIMUM" , SDTFPBinOp,
[SDNPCommutative, SDNPAssociative]>;
def fmaximum : SDNode<"ISD::FMAXIMUM" , SDTFPBinOp,
[SDNPCommutative, SDNPAssociative]>;
+def fminimumnum : SDNode<"ISD::FMINIMUMNUM" , SDTFPBinOp,
+ [SDNPCommutative, SDNPAssociative]>;
+def fmaximumnum : SDNode<"ISD::FMAXIMUMNUM" , SDTFPBinOp,
+ [SDNPCommutative, SDNPAssociative]>;
def fgetsign : SDNode<"ISD::FGETSIGN" , SDTFPToIntOp>;
def fcanonicalize : SDNode<"ISD::FCANONICALIZE", SDTFPUnaryOp>;
def fneg : SDNode<"ISD::FNEG" , SDTFPUnaryOp>;
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index f0c459d61a4d74..8ded0509cbc234 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -1937,7 +1937,9 @@ SDValue DAGCombiner::visit(SDNode *N) {
case ISD::FMINNUM:
case ISD::FMAXNUM:
case ISD::FMINIMUM:
- case ISD::FMAXIMUM: return visitFMinMax(N);
+ case ISD::FMAXIMUM:
+ case ISD::FMINIMUMNUM:
+ case ISD::FMAXIMUMNUM: return visitFMinMax(N);
case ISD::FCEIL: return visitFCEIL(N);
case ISD::FTRUNC: return visitFTRUNC(N);
case ISD::FFREXP: return visitFFREXP(N);
@@ -6068,6 +6070,7 @@ static bool arebothOperandsNotNan(SDValue Operand1, SDValue Operand2,
return DAG.isKnownNeverNaN(Operand2) && DAG.isKnownNeverNaN(Operand1);
}
+// FIXME: use FMINIMUMNUM if possible, such as for RISC-V.
static unsigned getMinMaxOpcodeForFP(SDValue Operand1, SDValue Operand2,
ISD::CondCode CC, unsigned OrAndOpcode,
SelectionDAG &DAG,
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index f4b3d1a41c681b..72d1c38497b5c5 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -3660,6 +3660,12 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
Results.push_back(Expanded);
break;
}
+ case ISD::FMINIMUMNUM:
+ case ISD::FMAXIMUMNUM: {
+ if (SDValue Expanded = TLI.expandFMINIMUMNUM_FMAXIMUMNUM(Node, DAG))
+ Results.push_back(Expanded);
+ break;
+ }
case ISD::FSIN:
case ISD::FCOS: {
EVT VT = Node->getValueType(0);
@@ -4539,6 +4545,16 @@ void SelectionDAGLegalize::ConvertNodeToLibcall(SDNode *Node) {
RTLIB::FMAX_F80, RTLIB::FMAX_F128,
RTLIB::FMAX_PPCF128, Results);
break;
+ case ISD::FMINIMUMNUM:
+ ExpandFPLibCall(Node, RTLIB::FMINIMUMNUM_F32, RTLIB::FMINIMUMNUM_F64,
+ RTLIB::FMINIMUMNUM_F80, RTLIB::FMINIMUMNUM_F128,
+ RTLIB::FMINIMUMNUM_PPCF128, Results);
+ break;
+ case ISD::FMAXIMUMNUM:
+ ExpandFPLibCall(Node, RTLIB::FMAXIMUMNUM_F32, RTLIB::FMAXIMUMNUM_F64,
+ RTLIB::FMAXIMUMNUM_F80, RTLIB::FMAXIMUMNUM_F128,
+ RTLIB::FMAXIMUMNUM_PPCF128, Results);
+ break;
case ISD::FSQRT:
case ISD::STRICT_FSQRT:
ExpandFPLibCall(Node, RTLIB::SQRT_F32, RTLIB::SQRT_F64,
@@ -5464,6 +5480,8 @@ void SelectionDAGLegalize::PromoteNode(SDNode *Node) {
case ISD::FMAXNUM:
case ISD::FMINIMUM:
case ISD::FMAXIMUM:
+ case ISD::FMINIMUMNUM:
+ case ISD::FMAXIMUMNUM:
case ISD::FPOW:
Tmp1 = DAG.getNode(ISD::FP_EXTEND, dl, NVT, Node->getOperand(0));
Tmp2 = DAG.getNode(ISD::FP_EXTEND, dl, NVT, Node->getOperand(1));
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
index edebb5ee87001b..068f610451de80 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
@@ -74,6 +74,8 @@ void DAGTypeLegalizer::SoftenFloatResult(SDNode *N, unsigned ResNo) {
case ISD::FMINNUM: R = SoftenFloatRes_FMINNUM(N); break;
case ISD::STRICT_FMAXNUM:
case ISD::FMAXNUM: R = SoftenFloatRes_FMAXNUM(N); break;
+ case ISD::FMINIMUMNUM: R = SoftenFloatRes_FMINIMUMNUM(N); break;
+ case ISD::FMAXIMUMNUM: R = SoftenFloatRes_FMAXIMUMNUM(N); break;
case ISD::STRICT_FADD:
case ISD::FADD: R = SoftenFloatRes_FADD(N); break;
case ISD::STRICT_FACOS:
@@ -323,6 +325,24 @@ SDValue DAGTypeLegalizer::SoftenFloatRes_FMAXNUM(SDNode *N) {
RTLIB::FMAX_PPCF128));
}
+SDValue DAGTypeLegalizer::SoftenFloatRes_FMINIMUMNUM(SDNode *N) {
+ if (SDValue SelCC = TLI.createSelectForFMINIMUMNUM_FMAXIMUMNUM(N, DAG))
+ return SoftenFloatRes_SELECT_CC(SelCC.getNode());
+ return SoftenFloatRes_Binary(
+ N, GetFPLibCall(N->getValueType(0), RTLIB::FMINIMUMNUM_F32,
+ RTLIB::FMINIMUMNUM_F64, RTLIB::FMINIMUMNUM_F80,
+ RTLIB::FMINIMUMNUM_F128, RTLIB::FMINIMUMNUM_PPCF128));
+}
+
+SDValue DAGTypeLegalizer::SoftenFloatRes_FMAXIMUMNUM(SDNode *N) {
+ if (SDValue SelCC = TLI.createSelectForFMINIMUMNUM_FMAXIMUMNUM(N, DAG))
+ return SoftenFloatRes_SELECT_CC(SelCC.getNode());
+ return SoftenFloatRes_Binary(
+ N, GetFPLibCall(N->getValueType(0), RTLIB::FMAXIMUMNUM_F32,
+ RTLIB::FMAXIMUMNUM_F64, RTLIB::FMAXIMUMNUM_F80,
+ RTLIB::FMAXIMUMNUM_F128, RTLIB::FMAXIMUMNUM_PPCF128));
+}
+
SDValue DAGTypeLegalizer::SoftenFloatRes_FADD(SDNode *N) {
return SoftenFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
RTLIB::ADD_F32,
@@ -1404,6 +1424,8 @@ void DAGTypeLegalizer::ExpandFloatResult(SDNode *N, unsigned ResNo) {
case ISD::FMINNUM: ExpandFloatRes_FMINNUM(N, Lo, Hi); break;
case ISD::STRICT_FMAXNUM:
case ISD::FMAXNUM: ExpandFloatRes_FMAXNUM(N, Lo, Hi); break;
+ case ISD::FMINIMUMNUM: ExpandFloatRes_FMINIMUMNUM(N, Lo, Hi); break;
+ case ISD::FMAXIMUMNUM: ExpandFloatRes_FMAXIMUMNUM(N, Lo, Hi); break;
case ISD::STRICT_FADD:
case ISD::FADD: ExpandFloatRes_FADD(N, Lo, Hi); break;
case ISD::STRICT_FACOS:
@@ -1561,6 +1583,26 @@ void DAGTypeLegalizer::ExpandFloatRes_FMAXNUM(SDNode *N, SDValue &Lo,
RTLIB::FMAX_PPCF128), Lo, Hi);
}
+void DAGTypeLegalizer::ExpandFloatRes_FMINIMUMNUM(SDNode *N, SDValue &Lo,
+ SDValue &Hi) {
+ ExpandFloatRes_Binary(
+ N,
+ GetFPLibCall(N->getValueType(0), RTLIB::FMINIMUMNUM_F32,
+ RTLIB::FMINIMUMNUM_F64, RTLIB::FMINIMUMNUM_F80,
+ RTLIB::FMINIMUMNUM_F128, RTLIB::FMINIMUMNUM_PPCF128),
+ Lo, Hi);
+}
+
+void DAGTypeLegalizer::ExpandFloatRes_FMAXIMUMNUM(SDNode *N, SDValue &Lo,
+ SDValue &Hi) {
+ ExpandFloatRes_Binary(
+ N,
+ GetFPLibCall(N->getValueType(0), RTLIB::FMAXIMUMNUM_F32,
+ RTLIB::FMAXIMUMNUM_F64, RTLIB::FMAXIMUMNUM_F80,
+ RTLIB::FMAXIMUMNUM_F128, RTLIB::FMAXIMUMNUM_PPCF128),
+ Lo, Hi);
+}
+
void DAGTypeLegalizer::ExpandFloatRes_FADD(SDNode *N, SDValue &Lo,
SDValue &Hi) {
ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0),
@@ -2627,6 +2669,8 @@ void DAGTypeLegalizer::PromoteFloatResult(SDNode *N, unsigned ResNo) {
case ISD::FDIV:
case ISD::FMAXIMUM:
case ISD::FMINIMUM:
+ case ISD::FMAXIMUMNUM:
+ case ISD::FMINIMUMNUM:
case ISD::FMAXNUM:
case ISD::FMINNUM:
case ISD::FMAXNUM_IEEE:
@@ -3069,6 +3113,8 @@ void DAGTypeLegalizer::SoftPromoteHalfResult(SDNode *N, unsigned ResNo) {
case ISD::FDIV:
case ISD::FMAXIMUM:
case ISD::FMINIMUM:
+ case ISD::FMAXIMUMNUM:
+ case ISD::FMINIMUMNUM:
case ISD::FMAXNUM:
case ISD::FMINNUM:
case ISD::FMUL:
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h
index 3a49a8ff10860a..6de1e3eca7feda 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h
@@ -567,6 +567,8 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
SDValue SoftenFloatRes_FATAN(SDNode *N);
SDValue SoftenFloatRes_FMINNUM(SDNode *N);
SDValue SoftenFloatRes_FMAXNUM(SDNode *N);
+ SDValue SoftenFloatRes_FMINIMUMNUM(SDNode *N);
+ SDValue SoftenFloatRes_FMAXIMUMNUM(SDNode *N);
SDValue SoftenFloatRes_FADD(SDNode *N);
SDValue SoftenFloatRes_FCBRT(SDNode *N);
SDValue SoftenFloatRes_FCEIL(SDNode *N);
@@ -659,6 +661,8 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
void ExpandFloatRes_FATAN (SDNode *N, SDValue &Lo, SDValue &Hi);
void ExpandFloatRes_FMINNUM (SDNode *N, SDValue &Lo, SDValue &Hi);
void ExpandFloatRes_FMAXNUM (SDNode *N, SDValue &Lo, SDValue &Hi);
+ void ExpandFloatRes_FMINIMUMNUM(SDNode *N, SDValue &Lo, SDValue &Hi);
+ void ExpandFloatRes_FMAXIMUMNUM(SDNode *N, SDValue &Lo, SDValue &Hi);
void ExpandFloatRes_FADD (SDNode *N, SDValue &Lo, SDValue &Hi);
void ExpandFloatRes_FCBRT (SDNode *N, SDValue &Lo, SDValue &Hi);
void ExpandFloatRes_FCEIL (SDNode *N, SDValue &Lo, SDValue &Hi);
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index c3a7df5361cd45..4e9a3c13d07646 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -5468,7 +5468,9 @@ bool SelectionDAG::isKnownNeverNaN(SDValue Op, bool SNaN, unsigned Depth) const
return false;
}
case ISD::FMINNUM:
- case ISD::FMAXNUM: {
+ case ISD::FMAXNUM:
+ case ISD::FMINIMUMNUM:
+ case ISD::FMAXIMUMNUM: {
// Only one needs to be known not-nan, since it will be returned if the
// other ends up being one.
return isKnownNeverNaN(Op.getOperand(0), SNaN, Depth + 1) ||
@@ -6808,6 +6810,10 @@ SDValue SelectionDAG::foldConstantFPMath(unsigned Opcode, const SDLoc &DL,
return getConstantFP(minimum(C1, C2), DL, VT);
case ISD::FMAXIMUM:
return getConstantFP(maximum(C1, C2), DL, VT);
+ case ISD::FMINIMUMNUM:
+ return getConstantFP(minimumnum(C1, C2), DL, VT);
+ case ISD::FMAXIMUMNUM:
+ return getConstantFP(maximumnum(C1, C2), DL, VT);
default: break;
}
}
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 37ba62911ec70b..7cdd3d47b641d7 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -6882,6 +6882,18 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
getValue(I.getArgOperand(0)),
getValue(I.getArgOperand(1)), Flags));
return;
+ case Intrinsic::minimumnum:
+ setValue(&I, DAG.getNode(ISD::FMINIMUMNUM, sdl,
+ getValue(I.getArgOperand(0)).getValueType(),
+ getValue(I.getArgOperand(0)),
+ getValue(I.getArgOperand(1)), Flags));
+ return;
+ case Intrinsic::maximumnum:
+ setValue(&I, DAG.getNode(ISD::FMAXIMUMNUM, sdl,
+ getValue(I.getArgOperand(0)).getValueType(),
+ getValue(I.getArgOperand(0)),
+ getValue(I.getArgOperand(1)), Flags));
+ return;
case Intrinsic::copysign:
setValue(&I, DAG.getNode(ISD::FCOPYSIGN, sdl,
getValue(I.getArgOperand(0)).getValueType(),
@@ -9257,6 +9269,18 @@ void SelectionDAGBuilder::visitCall(const CallInst &I) {
if (visitBinaryFloatCall(I, ISD::FMAXNUM))
return;
break;
+ case LibFunc_fminimum_num:
+ case LibFunc_fminimum_numf:
+ case LibFunc_fminimum_numl:
+ if (visitBinaryFloatCall(I, ISD::FMINIMUMNUM))
+ return;
+ break;
+ case LibFunc_fmaximum_num:
+ case LibFunc_fmaximum_numf:
+ case LibFunc_fmaximum_numl:
+ if (visitBinaryFloatCall(I, ISD::FMAXIMUMNUM))
+ return;
+ break;
case LibFunc_sin:
case LibFunc_sinf:
case LibFunc_sinl:
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
index 16fc52caebb757..209c23eab1dda2 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
@@ -203,6 +203,8 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
case ISD::STRICT_FMINIMUM: return "strict_fminimum";
case ISD::FMAXIMUM: return "fmaximum";
case ISD::STRICT_FMAXIMUM: return "strict_fmaximum";
+ case ISD::FMINIMUMNUM: return "fminimumnum";
+ case ISD::FMAXIMUMNUM: return "fmaximumnum";
case ISD::FNEG: return "fneg";
case ISD::FSQRT: return "fsqrt";
case ISD::STRICT_FSQRT: return "strict_fsqrt";
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index b16bf3a8ec7784..1c6910e020fcd4 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -8531,6 +8531,93 @@ SDValue TargetLowering::expandFMINIMUM_FMAXIMUM(SDNode *N,
return MinMax;
}
+SDValue TargetLowering::createSelectForFMINIMUMNUM_FMAXIMUMNUM(
+ SDNode *Node, SelectionDAG &DAG) const {
+ unsigned Opcode = Node->getOpcode();
+ assert((Opcode == ISD::FMINIMUMNUM || Opcode == ISD::FMAXIMUMNUM) &&
+ "Wrong opcode");
+
+ if (Node->getFlags().hasNoNaNs()) {
+ ISD::CondCode Pred = Opcode == ISD::FMINIMUMNUM ? ISD::SETLT : ISD::SETGT;
+ SDValue Op1 = Node->getOperand(0);
+ SDValue Op2 = Node->getOperand(1);
+ SDValue SelCC = DAG.getSelectCC(SDLoc(Node), Op1, Op2, Op1, Op2, Pred);
+ // Copy FMF flags, but always set the no-signed-zeros flag
+ // as this is implied by the FMINNUM/FMAXNUM semantics.
+ SDNodeFlags Flags = Node->getFlags();
+ Flags.setNoSignedZeros(true);
+ SelCC->setFlags(Flags);
+ return SelCC;
+ }
+
+ return SDValue();
+}
+
+SDValue TargetLowering::expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *Node,
+ SelectionDAG &DAG) const {
+ SDLoc dl(Node);
+ unsigned NewOp = Node->getOpcode() == ISD::FMINIMUMNUM ? ISD::FMINNUM_IEEE
+ : ISD::FMAXNUM_IEEE;
+ EVT VT = Node->getValueType(0);
+
+ if (VT.isScalableVector())
+ report_fatal_error(
+ "Expanding fminimumnum/fmaximumnum for scalable vectors is undefined.");
+
+ if (isOperationLegalOrCustom(NewOp, VT)) {
+ SDValue Quiet0 = Node->getOperand(0);
+ SDValue Quiet1 = Node->getOperand(1);
+
+ if (!Node->getFlags().hasNoNaNs()) {
+ // Insert canonicalizes if it's possible we need to quiet to get correct
+ // sNaN behavior.
+ if (!DAG.isKnownNeverSNaN(Quiet0)) {
+ Quiet0 =
+ DAG.getNode(ISD::FCANONICALIZE, dl, VT, Quiet0, Node->getFlags());
+ }
+ if (!DAG.isKnownNeverSNaN(Quiet1)) {
+ Quiet1 =
+ DAG.getNode(ISD::FCANONICALIZE, dl, VT, Quiet1, Node->getFlags());
+ }
+ }
+
+ return DAG.getNode(NewOp, dl, VT, Quiet0, Quiet1, Node->getFlags());
+ }
+
+ // FMINIMUM/FMAXIMUM always return NaN if either operand is NaN.
+ // It has same behavior about +0.0 vs -0.0.
+ if (Node->getFlags().hasNoNaNs() ||
+ (DAG.isKnownNeverNaN(Node->getOperand(0)) &&
+ DAG.isKnownNeverNaN(Node->getOperand(1)))) {
+ unsigned IEEE2019Op =
+ Node->getOpcode() == ISD::FMINIMUMNUM ? ISD::FMINIMUM : ISD::FMAXIMUM;
+ if (isOperationLegalOrCustom(IEEE2019Op, VT))
+ return DAG.getNode(IEEE2019Op, dl, VT, Node->getOperand(0),
+ Node->getOperand(1), Node->getFlags());
+ }
+
+ // FMINNUM/FMAXIMUM returns qNaN if either operand is sNaN, and it may return
+ // either one for +0.0 vs -0.0.
+ // FIXME: maybe we need hasNoSNaNs().
+ if ((Node->getFlags().hasNoNaNs() ||
+ (DAG.isKnownNeverSNaN(Node->getOperand(0)) &&
+ DAG.isKnownNeverSNaN(Node->getOperand(1)))) &&
+ (Node->getFlags().hasNoSignedZeros() ||
+ DAG.isKnownNeverZeroFloat(Node->getOperand(0)) ||
+ DAG.isKnownNeverZeroFloat(Node->getOperand(1)))) {
+ unsigned IEEE2008Op =
+ Node->getOpcode() == ISD::FMINIMUMNUM ? ISD::FMINNUM : ISD::FMAXNUM;
+ if (isOperationLegalOrCustom(IEEE2008Op, VT))
+ return DAG.getNode(IEEE2008Op, dl, VT, Node->getOperand(0),
+ Node->getOperand(1), Node->getFlags());
+ }
+
+ if (SDValue SelCC = createSelectForFMINIMUMNUM_FMAXIMUMNUM(Node, DAG))
+ return SelCC;
+
+ return SDValue();
+}
+
/// Returns a true value if if this FPClassTest can be performed with an ordered
/// fcmp to 0, and a false value if it's an unordered fcmp to 0. Returns
/// std::nullopt if it cannot be performed as a compare with 0.
diff --git a/llvm/lib/CodeGen/TargetLoweringBase.cpp b/llvm/lib/CodeGen/TargetLoweringBase.cpp
index 6ca9955993d242..bc2b144b5001f3 100644
--- a/llvm/lib/CodeGen/TargetLoweringBase.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp
@@ -713,6 +713,7 @@ void TargetLoweringBase::initActions() {
ISD::FMINNUM, ISD::FMAXNUM,
ISD::FMINNUM_IEEE, ISD::FMAXNUM_IEEE,
ISD::FMINIMUM, ISD::FMAXIMUM,
+ ISD::FMINIMUMNUM, ISD::FMAXIMUMNUM,
ISD::FMAD, ISD::SMIN,
ISD::SMAX, ISD::UMIN,
ISD::UMAX, ISD::ABS,
diff --git a/llvm/test/CodeGen/LoongArch/fp-maximumnum-minimumnum.ll b/llvm/test/CodeGen/LoongArch/fp-maximumnum-minimumnum.ll
new file mode 100644
index 00000000000000..5f86efaa45e995
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/fp-maximumnum-minimumnum.ll
@@ -0,0 +1,154 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc --mtriple=loongarch32 --mattr=+f,-d < %s | FileCheck %s --check-prefix=LA32F
+; RUN: llc --mtriple=loongarch32 --mattr=+d < %s | FileCheck %s --check-prefix=LA32D
+; RUN: llc --mtriple=loongarch64 --mattr=+f,-d < %s | FileCheck %s --check-prefix=LA64F
+; RUN: llc --mtriple=loongarch64 --mattr=+d < %s | FileCheck %s --check-prefix=LA64D
+
+declare float @llvm.maximumnum.f32(float, float)
+declare double @llvm.maximumnum.f64(double, double)
+declare float @llvm.minimumnum.f32(float, float)
+declare double @llvm.minimumnum.f64(double, double)
+
+define float @maximumnum_float(float %x, float %y) {
+; LA32F-LABEL: maximumnum_float:
+; LA32F: # %bb.0:
+; LA32F-NEXT: fmax.s $fa1, $fa1, $fa1
+; LA32F-NEXT: fmax.s $fa0, $fa0, $fa0
+; LA32F-NEXT: fmax.s $fa0, $fa0, $fa1
+; LA32F-NEXT: ret
+;
+; LA32D-LABEL: maximumnum_float:
+; LA32D: # %bb.0:
+; LA32D-NEXT: fmax.s $fa1, $fa1, $fa1
+; LA32D-NEXT: fmax.s $fa0, $fa0, $fa0
+; LA32D-NEXT: fmax.s $fa0, $fa0, $fa1
+; LA32D-NEXT: ret
+;
+; LA64F-LABEL: maximumnum_float:
+; LA64F: # %bb.0:
+; LA64F-NEXT: fmax.s $fa1, $fa1, $fa1
+; LA64F-NEXT: fmax.s $fa0, $fa0, $fa0
+; LA64F-NEXT: fmax.s $fa0, $fa0, $fa1
+; LA64F-NEXT: ret
+;
+; LA64D-LABEL: maximumnum_float:
+; LA64D: # %bb.0:
+; LA64D-NEXT: fmax.s $fa1, $fa1, $fa1
+; LA64D-NEXT: fmax.s $fa0, $fa0, $fa0
+; 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) {
+; LA32F-LABEL: maximumnum_double:
+; 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:
+; LA32D: # %bb.0:
+; LA32D-NEXT: fmax.d $fa1, $fa1, $fa1
+; LA32D-NEXT: fmax.d $fa0, $fa0, $fa0
+; LA32D-NEXT: fmax.d $fa0, $fa0, $fa1
+; LA32D-NEXT: ret
+;
+; LA64F-LABEL: maximumnum_double:
+; 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:
+; LA64D: # %bb.0:
+; LA64D-NEXT: fmax.d $fa1, $fa1, $fa1
+; LA64D-NEXT: fmax.d $fa0, $fa0, $fa0
+; 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:
+; LA32F: # %bb.0:
+; LA32F-NEXT: fmax.s $fa1, $fa1, $fa1
+; LA32F-NEXT: fmax.s $fa0, $fa0, $fa0
+; LA32F-NEXT: fmin.s $fa0, $fa0, $fa1
+; LA32F-NEXT: ret
+;
+; LA32D-LABEL: minimumnum_float:
+; LA32D: # %bb.0:
+; LA32D-NEXT: fmax.s $fa1, $fa1, $fa1
+; LA32D-NEXT: fmax.s $fa0, $fa0, $fa0
+; LA32D-NEXT: fmin.s $fa0, $fa0, $fa1
+; LA32D-NEXT: ret
+;
+; LA64F-LABEL: minimumnum_float:
+; LA64F: # %bb.0:
+; LA64F-NEXT: fmax.s $fa1, $fa1, $fa1
+; LA64F-NEXT: fmax.s $fa0, $fa0, $fa0
+; LA64F-NEXT: fmin.s $fa0, $fa0, $fa1
+; LA64F-NEXT: ret
+;
+; LA64D-LABEL: minimumnum_float:
+; LA64D: # %bb.0:
+; LA64D-NEXT: fmax.s $fa1, $fa1, $fa1
+; LA64D-NEXT: fmax.s $fa0, $fa0, $fa0
+; 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:
+; 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:
+; LA32D: # %bb.0:
+; LA32D-NEXT: fmax.d $fa1, $fa1, $fa1
+; LA32D-NEXT: fmax.d $fa0, $fa0, $fa0
+; LA32D-NEXT: fmin.d $fa0, $fa0, $fa1
+; LA32D-NEXT: ret
+;
+; LA64F-LABEL: minimumnum_double:
+; 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:
+; LA64D: # %bb.0:
+; LA64D-NEXT: fmax.d $fa1, $fa1, $fa1
+; LA64D-NEXT: fmax.d $fa0, $fa0, $fa0
+; 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
new file mode 100644
index 00000000000000..8ee4070e534348
--- /dev/null
+++ b/llvm/test/CodeGen/Mips/fp-maximumnum-minimumnum.ll
@@ -0,0 +1,100 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc --mtriple=mipsisa32r6 < %s | FileCheck %s --check-prefix=MIPS32R6
+; RUN: llc --mtriple=mips < %s | FileCheck %s --check-prefix=MIPS32
+
+declare float @llvm.maximumnum.f32(float, float)
+declare double @llvm.maximumnum.f64(double, double)
+declare float @llvm.minimumnum.f32(float, float)
+declare double @llvm.minimumnum.f64(double, double)
+
+define float @maximumnum_float(float %x, float %y) {
+; MIPS32R6-LABEL: maximumnum_float:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: min.s $f0, $f14, $f14
+; MIPS32R6-NEXT: min.s $f1, $f12, $f12
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: max.s $f0, $f1, $f0
+;
+; MIPS32-LABEL: maximumnum_float:
+; MIPS32: # %bb.0:
+; MIPS32-NEXT: addiu $sp, $sp, -24
+; MIPS32-NEXT: .cfi_def_cfa_offset 24
+; MIPS32-NEXT: sw $ra, 20($sp) # 4-byte Folded Spill
+; MIPS32-NEXT: .cfi_offset 31, -4
+; MIPS32-NEXT: jal fmaximum_numf
+; MIPS32-NEXT: nop
+; MIPS32-NEXT: lw $ra, 20($sp) # 4-byte Folded Reload
+; MIPS32-NEXT: jr $ra
+; MIPS32-NEXT: addiu $sp, $sp, 24
+ %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:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: min.d $f0, $f14, $f14
+; MIPS32R6-NEXT: min.d $f1, $f12, $f12
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: max.d $f0, $f1, $f0
+;
+; MIPS32-LABEL: maximumnum_double:
+; MIPS32: # %bb.0:
+; MIPS32-NEXT: addiu $sp, $sp, -24
+; MIPS32-NEXT: .cfi_def_cfa_offset 24
+; MIPS32-NEXT: sw $ra, 20($sp) # 4-byte Folded Spill
+; MIPS32-NEXT: .cfi_offset 31, -4
+; MIPS32-NEXT: jal fmaximum_num
+; MIPS32-NEXT: nop
+; MIPS32-NEXT: lw $ra, 20($sp) # 4-byte Folded Reload
+; MIPS32-NEXT: jr $ra
+; MIPS32-NEXT: addiu $sp, $sp, 24
+ %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:
+; MIPS32R6-NEXT: min.s $f0, $f14, $f14
+; MIPS32R6-NEXT: min.s $f1, $f12, $f12
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: min.s $f0, $f1, $f0
+;
+; MIPS32-LABEL: minimumnum_float:
+; MIPS32: # %bb.0:
+; MIPS32-NEXT: addiu $sp, $sp, -24
+; MIPS32-NEXT: .cfi_def_cfa_offset 24
+; MIPS32-NEXT: sw $ra, 20($sp) # 4-byte Folded Spill
+; MIPS32-NEXT: .cfi_offset 31, -4
+; MIPS32-NEXT: jal fminimum_numf
+; MIPS32-NEXT: nop
+; MIPS32-NEXT: lw $ra, 20($sp) # 4-byte Folded Reload
+; MIPS32-NEXT: jr $ra
+; MIPS32-NEXT: addiu $sp, $sp, 24
+ %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:
+; MIPS32R6-NEXT: min.d $f0, $f14, $f14
+; MIPS32R6-NEXT: min.d $f1, $f12, $f12
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: min.d $f0, $f1, $f0
+;
+; MIPS32-LABEL: minimumnum_double:
+; MIPS32: # %bb.0:
+; MIPS32-NEXT: addiu $sp, $sp, -24
+; MIPS32-NEXT: .cfi_def_cfa_offset 24
+; MIPS32-NEXT: sw $ra, 20($sp) # 4-byte Folded Spill
+; MIPS32-NEXT: .cfi_offset 31, -4
+; MIPS32-NEXT: jal fminimum_num
+; MIPS32-NEXT: nop
+; MIPS32-NEXT: lw $ra, 20($sp) # 4-byte Folded Reload
+; MIPS32-NEXT: jr $ra
+; MIPS32-NEXT: addiu $sp, $sp, 24
+ %z = call double @llvm.minimumnum.f64(double %x, double %y)
+ ret double %z
+}
diff --git a/llvm/test/tools/llvm-tli-checker/ps4-tli-check.yaml b/llvm/test/tools/llvm-tli-checker/ps4-tli-check.yaml
index 9b37b49b3d49d2..cff5019f8e6ee4 100644
--- a/llvm/test/tools/llvm-tli-checker/ps4-tli-check.yaml
+++ b/llvm/test/tools/llvm-tli-checker/ps4-tli-check.yaml
@@ -32,15 +32,21 @@
# RUN: FileCheck %s --check-prefix=AVAIL --input-file %t3.txt
# RUN: FileCheck %s --check-prefix=UNAVAIL --input-file %t3.txt
#
-# CHECK: << Total TLI yes SDK no: 12
+# CHECK: << Total TLI yes SDK no: 18
# CHECK: >> Total TLI no SDK yes: 0
# CHECK: == Total TLI yes SDK yes: 248
#
# WRONG_DETAIL: << TLI yes SDK no : '_ZdaPv' aka operator delete[](void*)
# WRONG_DETAIL: >> TLI no SDK yes: '_ZdaPvj' aka operator delete[](void*, unsigned int)
-# WRONG_DETAIL-COUNT-8: << TLI yes SDK no : '_Zn{{.*}}__hot_cold_t
+# WRONG_DETAIL-COUNT-8: << TLI yes SDK no : {{.*}}__hot_cold_t
# WRONG_DETAIL-COUNT-4: << TLI yes SDK no : '__size_returning_new{{.*}}
-# WRONG_SUMMARY: << Total TLI yes SDK no: 13{{$}}
+# WRONG_DETAIL: << TLI yes SDK no : 'fmaximum_num'
+# WRONG_DETAIL: << TLI yes SDK no : 'fmaximum_numf'
+# WRONG_DETAIL: << TLI yes SDK no : 'fmaximum_numl'
+# WRONG_DETAIL: << TLI yes SDK no : 'fminimum_num'
+# WRONG_DETAIL: << TLI yes SDK no : 'fminimum_numf'
+# WRONG_DETAIL: << TLI yes SDK no : 'fminimum_numl'
+# WRONG_SUMMARY: << Total TLI yes SDK no: 19{{$}}
# WRONG_SUMMARY: >> Total TLI no SDK yes: 1{{$}}
# WRONG_SUMMARY: == Total TLI yes SDK yes: 247
#
@@ -48,8 +54,8 @@
## the exact count first; the two directives should add up to that.
## Yes, this means additions to TLI will fail this test, but the argument
## to -COUNT can't be an expression.
-# AVAIL: TLI knows 493 symbols, 260 available
-# AVAIL-COUNT-260: {{^}} available
+# AVAIL: TLI knows 499 symbols, 266 available
+# AVAIL-COUNT-266: {{^}} available
# AVAIL-NOT: {{^}} available
# UNAVAIL-COUNT-233: not available
# UNAVAIL-NOT: not available
diff --git a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
index d200956f741020..6c5d63e82b4f29 100644
--- a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
+++ b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
@@ -188,6 +188,12 @@ TEST_F(TargetLibraryInfoTest, ValidProto) {
"declare double @fmin(double, double)\n"
"declare float @fminf(float, float)\n"
"declare x86_fp80 @fminl(x86_fp80, x86_fp80)\n"
+ "declare double @fmaximum_num(double, double)\n"
+ "declare float @fmaximum_numf(float, float)\n"
+ "declare x86_fp80 @fmaximum_numl(x86_fp80, x86_fp80)\n"
+ "declare double @fminimum_num(double, double)\n"
+ "declare float @fminimum_numf(float, float)\n"
+ "declare x86_fp80 @fminimum_numl(x86_fp80, x86_fp80)\n"
"declare double @fmod(double, double)\n"
"declare float @fmodf(float, float)\n"
"declare x86_fp80 @fmodl(x86_fp80, x86_fp80)\n"
>From 6c49e1634052e6df4042619033d138956cd8ed79 Mon Sep 17 00:00:00 2001
From: YunQiang Su <syq at gcc.gnu.org>
Date: Thu, 4 Jul 2024 10:44:23 +0800
Subject: [PATCH 02/17] Remove MINNUM_IEEE in LangRef
---
llvm/docs/LangRef.rst | 4 ----
1 file changed, 4 deletions(-)
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 903eaa3db12332..76c79e8cf31a92 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -16182,10 +16182,6 @@ LLVM implements all ISO C flavors as listed in this table.
Only basic intrinsics list here. The constrained version
ones may have different behaivor on exception.
-Since some architectures implement minNum/maxNum with +0.0>-0.0,
-so we define internal ISD::MINNUM_IEEE and ISD::MAXNUM_IEEE.
-They will be helpful to implement minimumnum/maximumnum.
-
.. list-table::
:header-rows: 1
:widths: 16 28 28 28
>From 9a374e3725612a04ccda6d2e88e6dcae3780a51e Mon Sep 17 00:00:00 2001
From: YunQiang Su <syq at gcc.gnu.org>
Date: Thu, 4 Jul 2024 10:44:43 +0800
Subject: [PATCH 03/17] fix code style
---
llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
index 209c23eab1dda2..8bcdfa39fc82c3 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
@@ -203,8 +203,8 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
case ISD::STRICT_FMINIMUM: return "strict_fminimum";
case ISD::FMAXIMUM: return "fmaximum";
case ISD::STRICT_FMAXIMUM: return "strict_fmaximum";
- case ISD::FMINIMUMNUM: return "fminimumnum";
- case ISD::FMAXIMUMNUM: return "fmaximumnum";
+ case ISD::FMINIMUMNUM: return "fminimumnum";
+ case ISD::FMAXIMUMNUM: return "fmaximumnum";
case ISD::FNEG: return "fneg";
case ISD::FSQRT: return "fsqrt";
case ISD::STRICT_FSQRT: return "strict_fsqrt";
>From 473a8830ae1f8828fb3cbc973dd1e2b441f644cb Mon Sep 17 00:00:00 2001
From: YunQiang Su <syq at gcc.gnu.org>
Date: Thu, 4 Jul 2024 15:00:57 +0800
Subject: [PATCH 04/17] remove createSelectForFMINIMUMNUM_FMAXIMUMNUM
---
llvm/include/llvm/CodeGen/TargetLowering.h | 2 --
.../SelectionDAG/LegalizeFloatTypes.cpp | 4 ---
.../CodeGen/SelectionDAG/TargetLowering.cpp | 28 ++-----------------
3 files changed, 2 insertions(+), 32 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index b6fe99346bec86..fc3804a5894005 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -5146,8 +5146,6 @@ class TargetLowering : public TargetLoweringBase {
/// through to the default expansion/soften to libcall, we might introduce a
/// link-time dependency on libm into a file that originally did not have one.
SDValue createSelectForFMINNUM_FMAXNUM(SDNode *Node, SelectionDAG &DAG) const;
- SDValue createSelectForFMINIMUMNUM_FMAXIMUMNUM(SDNode *Node,
- SelectionDAG &DAG) const;
/// Return a reciprocal estimate value for the input operand.
/// \p Enabled is a ReciprocalEstimate enum with value either 'Unspecified' or
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
index 068f610451de80..02947275f64720 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
@@ -326,8 +326,6 @@ SDValue DAGTypeLegalizer::SoftenFloatRes_FMAXNUM(SDNode *N) {
}
SDValue DAGTypeLegalizer::SoftenFloatRes_FMINIMUMNUM(SDNode *N) {
- if (SDValue SelCC = TLI.createSelectForFMINIMUMNUM_FMAXIMUMNUM(N, DAG))
- return SoftenFloatRes_SELECT_CC(SelCC.getNode());
return SoftenFloatRes_Binary(
N, GetFPLibCall(N->getValueType(0), RTLIB::FMINIMUMNUM_F32,
RTLIB::FMINIMUMNUM_F64, RTLIB::FMINIMUMNUM_F80,
@@ -335,8 +333,6 @@ SDValue DAGTypeLegalizer::SoftenFloatRes_FMINIMUMNUM(SDNode *N) {
}
SDValue DAGTypeLegalizer::SoftenFloatRes_FMAXIMUMNUM(SDNode *N) {
- if (SDValue SelCC = TLI.createSelectForFMINIMUMNUM_FMAXIMUMNUM(N, DAG))
- return SoftenFloatRes_SELECT_CC(SelCC.getNode());
return SoftenFloatRes_Binary(
N, GetFPLibCall(N->getValueType(0), RTLIB::FMAXIMUMNUM_F32,
RTLIB::FMAXIMUMNUM_F64, RTLIB::FMAXIMUMNUM_F80,
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 1c6910e020fcd4..210aed38416c9a 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -8531,28 +8531,6 @@ SDValue TargetLowering::expandFMINIMUM_FMAXIMUM(SDNode *N,
return MinMax;
}
-SDValue TargetLowering::createSelectForFMINIMUMNUM_FMAXIMUMNUM(
- SDNode *Node, SelectionDAG &DAG) const {
- unsigned Opcode = Node->getOpcode();
- assert((Opcode == ISD::FMINIMUMNUM || Opcode == ISD::FMAXIMUMNUM) &&
- "Wrong opcode");
-
- if (Node->getFlags().hasNoNaNs()) {
- ISD::CondCode Pred = Opcode == ISD::FMINIMUMNUM ? ISD::SETLT : ISD::SETGT;
- SDValue Op1 = Node->getOperand(0);
- SDValue Op2 = Node->getOperand(1);
- SDValue SelCC = DAG.getSelectCC(SDLoc(Node), Op1, Op2, Op1, Op2, Pred);
- // Copy FMF flags, but always set the no-signed-zeros flag
- // as this is implied by the FMINNUM/FMAXNUM semantics.
- SDNodeFlags Flags = Node->getFlags();
- Flags.setNoSignedZeros(true);
- SelCC->setFlags(Flags);
- return SelCC;
- }
-
- return SDValue();
-}
-
SDValue TargetLowering::expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *Node,
SelectionDAG &DAG) const {
SDLoc dl(Node);
@@ -8596,7 +8574,7 @@ SDValue TargetLowering::expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *Node,
Node->getOperand(1), Node->getFlags());
}
- // FMINNUM/FMAXIMUM returns qNaN if either operand is sNaN, and it may return
+ // FMINNUM/FMAXMUM returns qNaN if either operand is sNaN, and it may return
// either one for +0.0 vs -0.0.
// FIXME: maybe we need hasNoSNaNs().
if ((Node->getFlags().hasNoNaNs() ||
@@ -8612,9 +8590,7 @@ SDValue TargetLowering::expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *Node,
Node->getOperand(1), Node->getFlags());
}
- if (SDValue SelCC = createSelectForFMINIMUMNUM_FMAXIMUMNUM(Node, DAG))
- return SelCC;
-
+ // FIXME: we may use setCC/getSELECT to optimize it instead of fallback to libcall.
return SDValue();
}
>From 64681ae61ae14a0e047127ccbb1f556dc8bbeed4 Mon Sep 17 00:00:00 2001
From: YunQiang Su <syq at gcc.gnu.org>
Date: Thu, 4 Jul 2024 16:49:20 +0800
Subject: [PATCH 05/17] fix code style
---
llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 210aed38416c9a..5c471da594a419 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -8590,7 +8590,8 @@ SDValue TargetLowering::expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *Node,
Node->getOperand(1), Node->getFlags());
}
- // FIXME: we may use setCC/getSELECT to optimize it instead of fallback to libcall.
+ // FIXME: we may use setCC/getSELECT to optimize it instead of fallback to
+ // libcall.
return SDValue();
}
>From 0a16db50af85dd0a6ed7e994e83a1628d3e15b04 Mon Sep 17 00:00:00 2001
From: YunQiang Su <syq at gcc.gnu.org>
Date: Thu, 25 Jul 2024 08:49:15 +0800
Subject: [PATCH 06/17] improve LangRef.rst
---
llvm/docs/LangRef.rst | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 76c79e8cf31a92..5e5e9b9e8a93b1 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -16178,9 +16178,9 @@ on working with qNaN/sNaN and +0.0/-0.0. Here is the list:
LLVM Implementation:
""""""""""""""""""""
-LLVM implements all ISO C flavors as listed in this table.
-Only basic intrinsics list here. The constrained version
-ones may have different behaivor on exception.
+LLVM implements all ISO C flavors as listed in this table, except in the
+default floating-point environment exceptions are ignored. The constrained
+versions of the intrinsics respect the exception behavior.
.. list-table::
:header-rows: 1
@@ -16444,7 +16444,7 @@ be less than +0.0 for this intrinsic.
Note that these are the semantics of minimumNumber specified in IEEE 754-2019.
-It has some different with '``llvm.minnum.*``':
+It has some differences with '``llvm.minnum.*``':
1)'``llvm.minnum.*``' will return qNaN if either operand is sNaN.
2)'``llvm.minnum*``' may return either one if we compare +0.0 vs -0.0.
@@ -16490,7 +16490,7 @@ be less than +0.0 for this intrinsic.
Note that these are the semantics of maximumNumber specified in IEEE 754-2019.
-It has some different with '``llvm.maxnum.*``':
+It has some differences with '``llvm.maxnum.*``':
1)'``llvm.maxnum.*``' will return qNaN if either operand is sNaN.
2)'``llvm.maxnum*``' may return either one if we compare +0.0 vs -0.0.
>From cefc739f4337d1fb16bb07f956cf377ccdcb7a76 Mon Sep 17 00:00:00 2001
From: YunQiang Su <syq at gcc.gnu.org>
Date: Thu, 25 Jul 2024 15:15:35 +0800
Subject: [PATCH 07/17] Use SetCC/SelectCC as final fallback
It seems exposing a bug of RISC-V backend:
```
define dso_local float @f(float noundef %a, float noundef %b) local_unnamed_addr #0 {
entry:
%0 = tail call float @llvm.minimumnum.f32(float %a, float %b)
ret float %0
}
```
```
./bin/clang --target=riscv64-linux-gnu -S yy.ll -O2 -o -
li a0, 1
bnez a0, .LBB0_2
```
---
.../CodeGen/SelectionDAG/TargetLowering.cpp | 96 ++++++++++++-------
1 file changed, 60 insertions(+), 36 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 5c471da594a419..efa88ff90aa170 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -8533,66 +8533,90 @@ SDValue TargetLowering::expandFMINIMUM_FMAXIMUM(SDNode *N,
SDValue TargetLowering::expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *Node,
SelectionDAG &DAG) const {
- SDLoc dl(Node);
- unsigned NewOp = Node->getOpcode() == ISD::FMINIMUMNUM ? ISD::FMINNUM_IEEE
- : ISD::FMAXNUM_IEEE;
+ SDLoc DL(Node);
+ SDValue LHS = Node->getOperand(0);
+ SDValue RHS = Node->getOperand(1);
+ unsigned Opc = Node->getOpcode();
EVT VT = Node->getValueType(0);
+ EVT CCVT = getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);
+ bool IsMax = Opc == ISD::FMAXIMUMNUM;
+ SDNodeFlags Flags = Node->getFlags();
- if (VT.isScalableVector())
- report_fatal_error(
- "Expanding fminimumnum/fmaximumnum for scalable vectors is undefined.");
+ unsigned NewOp =
+ Opc == ISD::FMINIMUMNUM ? ISD::FMINNUM_IEEE : ISD::FMAXNUM_IEEE;
if (isOperationLegalOrCustom(NewOp, VT)) {
- SDValue Quiet0 = Node->getOperand(0);
- SDValue Quiet1 = Node->getOperand(1);
-
- if (!Node->getFlags().hasNoNaNs()) {
+ if (!Flags.hasNoNaNs()) {
// Insert canonicalizes if it's possible we need to quiet to get correct
// sNaN behavior.
- if (!DAG.isKnownNeverSNaN(Quiet0)) {
- Quiet0 =
- DAG.getNode(ISD::FCANONICALIZE, dl, VT, Quiet0, Node->getFlags());
+ if (!DAG.isKnownNeverSNaN(LHS)) {
+ LHS = DAG.getNode(ISD::FCANONICALIZE, DL, VT, LHS, Node->getFlags());
}
- if (!DAG.isKnownNeverSNaN(Quiet1)) {
- Quiet1 =
- DAG.getNode(ISD::FCANONICALIZE, dl, VT, Quiet1, Node->getFlags());
+ if (!DAG.isKnownNeverSNaN(RHS)) {
+ RHS = DAG.getNode(ISD::FCANONICALIZE, DL, VT, RHS, Node->getFlags());
}
}
- return DAG.getNode(NewOp, dl, VT, Quiet0, Quiet1, Node->getFlags());
+ return DAG.getNode(NewOp, DL, VT, LHS, RHS, Flags);
}
// FMINIMUM/FMAXIMUM always return NaN if either operand is NaN.
// It has same behavior about +0.0 vs -0.0.
- if (Node->getFlags().hasNoNaNs() ||
- (DAG.isKnownNeverNaN(Node->getOperand(0)) &&
- DAG.isKnownNeverNaN(Node->getOperand(1)))) {
+ if (Flags.hasNoNaNs() ||
+ (DAG.isKnownNeverNaN(LHS) && DAG.isKnownNeverNaN(RHS))) {
unsigned IEEE2019Op =
- Node->getOpcode() == ISD::FMINIMUMNUM ? ISD::FMINIMUM : ISD::FMAXIMUM;
+ Opc == ISD::FMINIMUMNUM ? ISD::FMINIMUM : ISD::FMAXIMUM;
if (isOperationLegalOrCustom(IEEE2019Op, VT))
- return DAG.getNode(IEEE2019Op, dl, VT, Node->getOperand(0),
- Node->getOperand(1), Node->getFlags());
+ return DAG.getNode(IEEE2019Op, DL, VT, LHS, RHS, Flags);
}
// FMINNUM/FMAXMUM returns qNaN if either operand is sNaN, and it may return
// either one for +0.0 vs -0.0.
// FIXME: maybe we need hasNoSNaNs().
- if ((Node->getFlags().hasNoNaNs() ||
- (DAG.isKnownNeverSNaN(Node->getOperand(0)) &&
- DAG.isKnownNeverSNaN(Node->getOperand(1)))) &&
- (Node->getFlags().hasNoSignedZeros() ||
- DAG.isKnownNeverZeroFloat(Node->getOperand(0)) ||
- DAG.isKnownNeverZeroFloat(Node->getOperand(1)))) {
- unsigned IEEE2008Op =
- Node->getOpcode() == ISD::FMINIMUMNUM ? ISD::FMINNUM : ISD::FMAXNUM;
+ if ((Flags.hasNoNaNs() ||
+ (DAG.isKnownNeverSNaN(LHS) && DAG.isKnownNeverSNaN(RHS))) &&
+ (Flags.hasNoSignedZeros() || DAG.isKnownNeverZeroFloat(LHS) ||
+ DAG.isKnownNeverZeroFloat(RHS))) {
+ unsigned IEEE2008Op = Opc == ISD::FMINIMUMNUM ? ISD::FMINNUM : ISD::FMAXNUM;
if (isOperationLegalOrCustom(IEEE2008Op, VT))
- return DAG.getNode(IEEE2008Op, dl, VT, Node->getOperand(0),
- Node->getOperand(1), Node->getFlags());
+ return DAG.getNode(IEEE2008Op, DL, VT, LHS, RHS, Flags);
}
- // FIXME: we may use setCC/getSELECT to optimize it instead of fallback to
- // libcall.
- return SDValue();
+ SDValue MinMax;
+ // If one operand is NaN, let's move another value to it.
+ // So that if only one operand is NaN, we can have both two operands are
+ // non-NaN now.
+ SDValue LHSCompareLHS = DAG.getSetCC(DL, CCVT, LHS, LHS, ISD::SETEQ);
+ LHS = DAG.getSelect(DL, VT, LHSCompareLHS, LHS, RHS, Flags);
+ SDValue RHSCompareRHS = DAG.getSetCC(DL, CCVT, RHS, RHS, ISD::SETEQ);
+ RHS = DAG.getSelect(DL, VT, RHSCompareRHS, RHS, LHS, Flags);
+
+ SDValue Compare =
+ DAG.getSetCC(DL, CCVT, LHS, RHS, IsMax ? ISD::SETGT : ISD::SETLT);
+ MinMax = DAG.getSelect(DL, VT, Compare, LHS, RHS, Flags);
+
+ // If MinMax is NaN, let's quiet it with MinMax = MinMax + 0.
+ SDValue MinMaxCompareMinMax =
+ DAG.getSetCC(DL, CCVT, MinMax, MinMax, ISD::SETEQ);
+ SDValue MinMaxQuiet = DAG.getNode(ISD::FADD, DL, VT, MinMax,
+ DAG.getConstantFP(0.0, DL, VT), Flags);
+ MinMax =
+ DAG.getSelect(DL, VT, MinMaxCompareMinMax, MinMax, MinMaxQuiet, Flags);
+
+ // Let's process +0.0 vs -0.0.
+ SDValue TestZero =
+ DAG.getTargetConstant(IsMax ? fcPosZero : fcNegZero, DL, MVT::i32);
+ SDValue IsZero = DAG.getSetCC(DL, CCVT, MinMax,
+ DAG.getConstantFP(0.0, DL, VT), ISD::SETEQ);
+ SDValue LCmp = DAG.getSelect(
+ DL, VT, DAG.getNode(ISD::IS_FPCLASS, DL, CCVT, LHS, TestZero), LHS,
+ MinMax, Flags);
+ SDValue RCmp = DAG.getSelect(
+ DL, VT, DAG.getNode(ISD::IS_FPCLASS, DL, CCVT, RHS, TestZero), RHS, LCmp,
+ Flags);
+ MinMax = DAG.getSelect(DL, VT, IsZero, RCmp, MinMax, Flags);
+
+ return MinMax;
}
/// Returns a true value if if this FPClassTest can be performed with an ordered
>From dcee25d95261384a66a11aeb40cf4856b38c3245 Mon Sep 17 00:00:00 2001
From: YunQiang Su <syq at gcc.gnu.org>
Date: Sun, 28 Jul 2024 23:09:34 +0800
Subject: [PATCH 08/17] Remove the check in LegalizeDAG.cpp: not needed
---
llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index 72d1c38497b5c5..3a28e3301328cd 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -3662,8 +3662,7 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
}
case ISD::FMINIMUMNUM:
case ISD::FMAXIMUMNUM: {
- if (SDValue Expanded = TLI.expandFMINIMUMNUM_FMAXIMUMNUM(Node, DAG))
- Results.push_back(Expanded);
+ Results.push_back(TLI.expandFMINIMUMNUM_FMAXIMUMNUM(Node, DAG));
break;
}
case ISD::FSIN:
>From e8390134e99521b0fde832599c05053c5802021d Mon Sep 17 00:00:00 2001
From: YunQiang Su <syq at gcc.gnu.org>
Date: Sun, 28 Jul 2024 23:17:26 +0800
Subject: [PATCH 09/17] Some improve to expand
1. No need to emit move if we know one operand is not NaN.
2. No need to emit quiet if we know the result of MinMax is not NaN.
3. No need to fixup signed zero behavior if we know either operand
is not zero or Options.NoSignedZerosFPMath.
---
.../CodeGen/SelectionDAG/TargetLowering.cpp | 80 ++++++++++---------
1 file changed, 41 insertions(+), 39 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index efa88ff90aa170..e7b3366a5e3075 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -8540,6 +8540,7 @@ SDValue TargetLowering::expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *Node,
EVT VT = Node->getValueType(0);
EVT CCVT = getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);
bool IsMax = Opc == ISD::FMAXIMUMNUM;
+ const TargetOptions &Options = DAG.getTarget().Options;
SDNodeFlags Flags = Node->getFlags();
unsigned NewOp =
@@ -8550,18 +8551,18 @@ SDValue TargetLowering::expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *Node,
// Insert canonicalizes if it's possible we need to quiet to get correct
// sNaN behavior.
if (!DAG.isKnownNeverSNaN(LHS)) {
- LHS = DAG.getNode(ISD::FCANONICALIZE, DL, VT, LHS, Node->getFlags());
+ LHS = DAG.getNode(ISD::FCANONICALIZE, DL, VT, LHS, Flags);
}
if (!DAG.isKnownNeverSNaN(RHS)) {
- RHS = DAG.getNode(ISD::FCANONICALIZE, DL, VT, RHS, Node->getFlags());
+ RHS = DAG.getNode(ISD::FCANONICALIZE, DL, VT, RHS, Flags);
}
}
return DAG.getNode(NewOp, DL, VT, LHS, RHS, Flags);
}
- // FMINIMUM/FMAXIMUM always return NaN if either operand is NaN.
- // It has same behavior about +0.0 vs -0.0.
+ // We can use FMINIMUM/FMAXIMUM if there is no NaN, since it has
+ // same behaviors for all of other cases: +0.0 vs -0.0 included.
if (Flags.hasNoNaNs() ||
(DAG.isKnownNeverNaN(LHS) && DAG.isKnownNeverNaN(RHS))) {
unsigned IEEE2019Op =
@@ -8572,7 +8573,6 @@ SDValue TargetLowering::expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *Node,
// FMINNUM/FMAXMUM returns qNaN if either operand is sNaN, and it may return
// either one for +0.0 vs -0.0.
- // FIXME: maybe we need hasNoSNaNs().
if ((Flags.hasNoNaNs() ||
(DAG.isKnownNeverSNaN(LHS) && DAG.isKnownNeverSNaN(RHS))) &&
(Flags.hasNoSignedZeros() || DAG.isKnownNeverZeroFloat(LHS) ||
@@ -8582,41 +8582,43 @@ SDValue TargetLowering::expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *Node,
return DAG.getNode(IEEE2008Op, DL, VT, LHS, RHS, Flags);
}
- SDValue MinMax;
- // If one operand is NaN, let's move another value to it.
- // So that if only one operand is NaN, we can have both two operands are
- // non-NaN now.
- SDValue LHSCompareLHS = DAG.getSetCC(DL, CCVT, LHS, LHS, ISD::SETEQ);
- LHS = DAG.getSelect(DL, VT, LHSCompareLHS, LHS, RHS, Flags);
- SDValue RHSCompareRHS = DAG.getSetCC(DL, CCVT, RHS, RHS, ISD::SETEQ);
- RHS = DAG.getSelect(DL, VT, RHSCompareRHS, RHS, LHS, Flags);
-
- SDValue Compare =
- DAG.getSetCC(DL, CCVT, LHS, RHS, IsMax ? ISD::SETGT : ISD::SETLT);
- MinMax = DAG.getSelect(DL, VT, Compare, LHS, RHS, Flags);
-
- // If MinMax is NaN, let's quiet it with MinMax = MinMax + 0.
- SDValue MinMaxCompareMinMax =
- DAG.getSetCC(DL, CCVT, MinMax, MinMax, ISD::SETEQ);
- SDValue MinMaxQuiet = DAG.getNode(ISD::FADD, DL, VT, MinMax,
- DAG.getConstantFP(0.0, DL, VT), Flags);
- MinMax =
- DAG.getSelect(DL, VT, MinMaxCompareMinMax, MinMax, MinMaxQuiet, Flags);
-
- // Let's process +0.0 vs -0.0.
- SDValue TestZero =
- DAG.getTargetConstant(IsMax ? fcPosZero : fcNegZero, DL, MVT::i32);
- SDValue IsZero = DAG.getSetCC(DL, CCVT, MinMax,
- DAG.getConstantFP(0.0, DL, VT), ISD::SETEQ);
- SDValue LCmp = DAG.getSelect(
- DL, VT, DAG.getNode(ISD::IS_FPCLASS, DL, CCVT, LHS, TestZero), LHS,
- MinMax, Flags);
- SDValue RCmp = DAG.getSelect(
- DL, VT, DAG.getNode(ISD::IS_FPCLASS, DL, CCVT, RHS, TestZero), RHS, LCmp,
- Flags);
- MinMax = DAG.getSelect(DL, VT, IsZero, RCmp, MinMax, Flags);
+ // If only one operand is NaN, override it with another operand.
+ if (!Flags.hasNoNaNs() && !DAG.isKnownNeverNaN(LHS)) {
+ LHS = DAG.getSelectCC(DL, LHS, LHS, RHS, LHS, ISD::SETUO);
+ }
+ if (!Flags.hasNoNaNs() && !DAG.isKnownNeverNaN(RHS)) {
+ RHS = DAG.getSelectCC(DL, RHS, RHS, LHS, RHS, ISD::SETUO);
+ }
- return MinMax;
+ SDValue MinMax =
+ DAG.getSelectCC(DL, LHS, RHS, LHS, RHS, IsMax ? ISD::SETGT : ISD::SETLT);
+ // If MinMax is NaN, let's quiet it.
+ if (!Flags.hasNoNaNs() && !DAG.isKnownNeverNaN(LHS) &&
+ !DAG.isKnownNeverNaN(RHS)) {
+ // Only use FADD to quiet it if it is NaN, because -0.0+0.0->+0.0.
+ SDValue MinMaxQuiet = DAG.getNode(ISD::FADD, DL, VT, MinMax, MinMax, Flags);
+ MinMax =
+ DAG.getSelectCC(DL, MinMax, MinMax, MinMaxQuiet, MinMax, ISD::SETUO);
+ //}
+ }
+
+ // Fixup signed zero behavior.
+ if (Options.NoSignedZerosFPMath || Flags.hasNoSignedZeros() ||
+ DAG.isKnownNeverZeroFloat(LHS) || DAG.isKnownNeverZeroFloat(RHS)) {
+ return MinMax;
+ } else {
+ SDValue TestZero =
+ DAG.getTargetConstant(IsMax ? fcPosZero : fcNegZero, DL, MVT::i32);
+ SDValue IsZero = DAG.getSetCC(DL, CCVT, MinMax,
+ DAG.getConstantFP(0.0, DL, VT), ISD::SETEQ);
+ SDValue LCmp = DAG.getSelect(
+ DL, VT, DAG.getNode(ISD::IS_FPCLASS, DL, CCVT, LHS, TestZero), LHS,
+ MinMax, Flags);
+ SDValue RCmp = DAG.getSelect(
+ DL, VT, DAG.getNode(ISD::IS_FPCLASS, DL, CCVT, RHS, TestZero), RHS,
+ LCmp, Flags);
+ return DAG.getSelect(DL, VT, IsZero, RCmp, MinMax, Flags);
+ }
}
/// Returns a true value if if this FPClassTest can be performed with an ordered
>From 35d1ece2b58fb13f769a14af08b2ee57a93ef832 Mon Sep 17 00:00:00 2001
From: YunQiang Su <syq at gcc.gnu.org>
Date: Mon, 29 Jul 2024 15:11:47 +0800
Subject: [PATCH 10/17] Round RHS/LHS if IS_FPCLASS cannot process them
---
.../lib/CodeGen/SelectionDAG/TargetLowering.cpp | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index e7b3366a5e3075..432c0ea7e18aa7 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -8542,6 +8542,7 @@ SDValue TargetLowering::expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *Node,
bool IsMax = Opc == ISD::FMAXIMUMNUM;
const TargetOptions &Options = DAG.getTarget().Options;
SDNodeFlags Flags = Node->getFlags();
+ const Triple &TT = DAG.getTarget().getTargetTriple();
unsigned NewOp =
Opc == ISD::FMINIMUMNUM ? ISD::FMINNUM_IEEE : ISD::FMAXNUM_IEEE;
@@ -8599,7 +8600,6 @@ SDValue TargetLowering::expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *Node,
SDValue MinMaxQuiet = DAG.getNode(ISD::FADD, DL, VT, MinMax, MinMax, Flags);
MinMax =
DAG.getSelectCC(DL, MinMax, MinMax, MinMaxQuiet, MinMax, ISD::SETUO);
- //}
}
// Fixup signed zero behavior.
@@ -8607,15 +8607,26 @@ SDValue TargetLowering::expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *Node,
DAG.isKnownNeverZeroFloat(LHS) || DAG.isKnownNeverZeroFloat(RHS)) {
return MinMax;
} else {
+ SDValue LRound = LHS;
+ SDValue RRound = RHS;
+ EVT RCCVT = CCVT;
+ // expandIS_FPCLASS is buggy for GPR32+FPR64. Let's round them to single for this case.
+ if (TT.isArch32Bit() && !isOperationLegalOrCustom(ISD::IS_FPCLASS, VT) && VT.getSizeInBits() > TT.getArchPointerBitWidth() && !TT.isX32()) {
+ LRound = DAG.getNode(ISD::FP_ROUND, DL, MVT::f32, LHS,
+ DAG.getIntPtrConstant(0, DL, /*isTarget=*/true));
+ RRound = DAG.getNode(ISD::FP_ROUND, DL, MVT::f32, RHS,
+ DAG.getIntPtrConstant(0, DL, /*isTarget=*/true));
+ RCCVT = getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), MVT::f32);
+ }
SDValue TestZero =
DAG.getTargetConstant(IsMax ? fcPosZero : fcNegZero, DL, MVT::i32);
SDValue IsZero = DAG.getSetCC(DL, CCVT, MinMax,
DAG.getConstantFP(0.0, DL, VT), ISD::SETEQ);
SDValue LCmp = DAG.getSelect(
- DL, VT, DAG.getNode(ISD::IS_FPCLASS, DL, CCVT, LHS, TestZero), LHS,
+ DL, VT, DAG.getNode(ISD::IS_FPCLASS, DL, RCCVT, LRound, TestZero), LHS,
MinMax, Flags);
SDValue RCmp = DAG.getSelect(
- DL, VT, DAG.getNode(ISD::IS_FPCLASS, DL, CCVT, RHS, TestZero), RHS,
+ DL, VT, DAG.getNode(ISD::IS_FPCLASS, DL, RCCVT, RRound, TestZero), RHS,
LCmp, Flags);
return DAG.getSelect(DL, VT, IsZero, RCmp, MinMax, Flags);
}
>From 43aa8138930fbe80ed958cd99c7aecc8fc7e3a0d Mon Sep 17 00:00:00 2001
From: YunQiang Su <syq at gcc.gnu.org>
Date: Mon, 29 Jul 2024 19:21:27 +0800
Subject: [PATCH 11/17] Fix testcases
Add test for Sparc, SystemZ, X86.
ARM64: we can use fmin if we add FMINNUM_IEEE.
RISCV: fmin is good for FMINIMUMNUM.
PowerPC: Need some updates of FCANONICAL.
These architectures will be fixed in the future PRs.
---
.../LoongArch/fp-maximumnum-minimumnum.ll | 277 +++
.../CodeGen/Mips/fp-maximumnum-minimumnum.ll | 325 ++-
.../CodeGen/SPARC/fp-maximumnum-minimumnum.ll | 1355 +++++++++++
.../SystemZ/fp-maximumnum-minimumnum.ll | 500 ++++
.../CodeGen/X86/fp-maximumnum-minimumnum.ll | 2121 +++++++++++++++++
5 files changed, 4546 insertions(+), 32 deletions(-)
create mode 100644 llvm/test/CodeGen/SPARC/fp-maximumnum-minimumnum.ll
create mode 100644 llvm/test/CodeGen/SystemZ/fp-maximumnum-minimumnum.ll
create mode 100644 llvm/test/CodeGen/X86/fp-maximumnum-minimumnum.ll
diff --git a/llvm/test/CodeGen/LoongArch/fp-maximumnum-minimumnum.ll b/llvm/test/CodeGen/LoongArch/fp-maximumnum-minimumnum.ll
index 5f86efaa45e995..b4fdd954b856c8 100644
--- a/llvm/test/CodeGen/LoongArch/fp-maximumnum-minimumnum.ll
+++ b/llvm/test/CodeGen/LoongArch/fp-maximumnum-minimumnum.ll
@@ -10,6 +10,7 @@ declare float @llvm.minimumnum.f32(float, float)
declare double @llvm.minimumnum.f64(double, double)
define float @maximumnum_float(float %x, float %y) {
+;
; LA32F-LABEL: maximumnum_float:
; LA32F: # %bb.0:
; LA32F-NEXT: fmax.s $fa1, $fa1, $fa1
@@ -41,7 +42,67 @@ define float @maximumnum_float(float %x, float %y) {
ret float %z
}
+define float @maximumnum_float_nsz(float %x, float %y) {
+;
+; LA32F-LABEL: maximumnum_float_nsz:
+; LA32F: # %bb.0:
+; LA32F-NEXT: fmax.s $fa1, $fa1, $fa1
+; LA32F-NEXT: fmax.s $fa0, $fa0, $fa0
+; LA32F-NEXT: fmax.s $fa0, $fa0, $fa1
+; LA32F-NEXT: ret
+;
+; LA32D-LABEL: maximumnum_float_nsz:
+; LA32D: # %bb.0:
+; LA32D-NEXT: fmax.s $fa1, $fa1, $fa1
+; LA32D-NEXT: fmax.s $fa0, $fa0, $fa0
+; LA32D-NEXT: fmax.s $fa0, $fa0, $fa1
+; LA32D-NEXT: ret
+;
+; LA64F-LABEL: maximumnum_float_nsz:
+; LA64F: # %bb.0:
+; LA64F-NEXT: fmax.s $fa1, $fa1, $fa1
+; LA64F-NEXT: fmax.s $fa0, $fa0, $fa0
+; LA64F-NEXT: fmax.s $fa0, $fa0, $fa1
+; LA64F-NEXT: ret
+;
+; LA64D-LABEL: maximumnum_float_nsz:
+; LA64D: # %bb.0:
+; LA64D-NEXT: fmax.s $fa1, $fa1, $fa1
+; LA64D-NEXT: fmax.s $fa0, $fa0, $fa0
+; LA64D-NEXT: fmax.s $fa0, $fa0, $fa1
+; LA64D-NEXT: ret
+ %z = call nsz float @llvm.maximumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+define float @maximumnum_float_nnan(float %x, float %y) {
+;
+; LA32F-LABEL: maximumnum_float_nnan:
+; LA32F: # %bb.0:
+; LA32F-NEXT: fmax.s $fa0, $fa0, $fa1
+; LA32F-NEXT: ret
+;
+; LA32D-LABEL: maximumnum_float_nnan:
+; LA32D: # %bb.0:
+; LA32D-NEXT: fmax.s $fa0, $fa0, $fa1
+; LA32D-NEXT: ret
+;
+; LA64F-LABEL: maximumnum_float_nnan:
+; LA64F: # %bb.0:
+; LA64F-NEXT: fmax.s $fa0, $fa0, $fa1
+; LA64F-NEXT: ret
+;
+; LA64D-LABEL: maximumnum_float_nnan:
+; LA64D: # %bb.0:
+; LA64D-NEXT: fmax.s $fa0, $fa0, $fa1
+; LA64D-NEXT: ret
+ %z = call nnan float @llvm.maximumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+
define double @maximumnum_double(double %x, double %y) {
+;
; LA32F-LABEL: maximumnum_double:
; LA32F: # %bb.0:
; LA32F-NEXT: addi.w $sp, $sp, -16
@@ -81,7 +142,86 @@ define double @maximumnum_double(double %x, double %y) {
ret double %z
}
+define double @maximumnum_double_nsz(double %x, double %y) {
+;
+; LA32F-LABEL: maximumnum_double_nsz:
+; 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_nsz:
+; LA32D: # %bb.0:
+; LA32D-NEXT: fmax.d $fa1, $fa1, $fa1
+; LA32D-NEXT: fmax.d $fa0, $fa0, $fa0
+; LA32D-NEXT: fmax.d $fa0, $fa0, $fa1
+; LA32D-NEXT: ret
+;
+; LA64F-LABEL: maximumnum_double_nsz:
+; 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_nsz:
+; LA64D: # %bb.0:
+; LA64D-NEXT: fmax.d $fa1, $fa1, $fa1
+; LA64D-NEXT: fmax.d $fa0, $fa0, $fa0
+; LA64D-NEXT: fmax.d $fa0, $fa0, $fa1
+; LA64D-NEXT: ret
+ %z = call nsz double @llvm.maximumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define double @maximumnum_double_nnan(double %x, double %y) {
+;
+; LA32F-LABEL: maximumnum_double_nnan:
+; 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_nnan:
+; LA32D: # %bb.0:
+; LA32D-NEXT: fmax.d $fa0, $fa0, $fa1
+; LA32D-NEXT: ret
+;
+; LA64F-LABEL: maximumnum_double_nnan:
+; 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_nnan:
+; LA64D: # %bb.0:
+; LA64D-NEXT: fmax.d $fa0, $fa0, $fa1
+; LA64D-NEXT: ret
+ %z = call nnan double @llvm.maximumnum.f64(double %x, double %y)
+ ret double %z
+}
+
define float @minimumnum_float(float %x, float %y) {
+;
; LA32F-LABEL: minimumnum_float:
; LA32F: # %bb.0:
; LA32F-NEXT: fmax.s $fa1, $fa1, $fa1
@@ -113,7 +253,66 @@ define float @minimumnum_float(float %x, float %y) {
ret float %z
}
+define float @minimumnum_float_nsz(float %x, float %y) {
+;
+; LA32F-LABEL: minimumnum_float_nsz:
+; LA32F: # %bb.0:
+; LA32F-NEXT: fmax.s $fa1, $fa1, $fa1
+; LA32F-NEXT: fmax.s $fa0, $fa0, $fa0
+; LA32F-NEXT: fmin.s $fa0, $fa0, $fa1
+; LA32F-NEXT: ret
+;
+; LA32D-LABEL: minimumnum_float_nsz:
+; LA32D: # %bb.0:
+; LA32D-NEXT: fmax.s $fa1, $fa1, $fa1
+; LA32D-NEXT: fmax.s $fa0, $fa0, $fa0
+; LA32D-NEXT: fmin.s $fa0, $fa0, $fa1
+; LA32D-NEXT: ret
+;
+; LA64F-LABEL: minimumnum_float_nsz:
+; LA64F: # %bb.0:
+; LA64F-NEXT: fmax.s $fa1, $fa1, $fa1
+; LA64F-NEXT: fmax.s $fa0, $fa0, $fa0
+; LA64F-NEXT: fmin.s $fa0, $fa0, $fa1
+; LA64F-NEXT: ret
+;
+; LA64D-LABEL: minimumnum_float_nsz:
+; LA64D: # %bb.0:
+; LA64D-NEXT: fmax.s $fa1, $fa1, $fa1
+; LA64D-NEXT: fmax.s $fa0, $fa0, $fa0
+; LA64D-NEXT: fmin.s $fa0, $fa0, $fa1
+; LA64D-NEXT: ret
+ %z = call nsz float @llvm.minimumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+define float @minimumnum_float_nnan(float %x, float %y) {
+;
+; LA32F-LABEL: minimumnum_float_nnan:
+; LA32F: # %bb.0:
+; LA32F-NEXT: fmin.s $fa0, $fa0, $fa1
+; LA32F-NEXT: ret
+;
+; LA32D-LABEL: minimumnum_float_nnan:
+; LA32D: # %bb.0:
+; LA32D-NEXT: fmin.s $fa0, $fa0, $fa1
+; LA32D-NEXT: ret
+;
+; LA64F-LABEL: minimumnum_float_nnan:
+; LA64F: # %bb.0:
+; LA64F-NEXT: fmin.s $fa0, $fa0, $fa1
+; LA64F-NEXT: ret
+;
+; LA64D-LABEL: minimumnum_float_nnan:
+; LA64D: # %bb.0:
+; LA64D-NEXT: fmin.s $fa0, $fa0, $fa1
+; LA64D-NEXT: ret
+ %z = call nnan float @llvm.minimumnum.f32(float %x, float %y)
+ ret float %z
+}
+
define double @minimumnum_double(double %x, double %y) {
+;
; LA32F-LABEL: minimumnum_double:
; LA32F: # %bb.0:
; LA32F-NEXT: addi.w $sp, $sp, -16
@@ -152,3 +351,81 @@ define double @minimumnum_double(double %x, double %y) {
%z = call double @llvm.minimumnum.f64(double %x, double %y)
ret double %z
}
+
+define double @minimumnum_double_nsz(double %x, double %y) {
+;
+; LA32F-LABEL: minimumnum_double_nsz:
+; 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_nsz:
+; LA32D: # %bb.0:
+; LA32D-NEXT: fmax.d $fa1, $fa1, $fa1
+; LA32D-NEXT: fmax.d $fa0, $fa0, $fa0
+; LA32D-NEXT: fmin.d $fa0, $fa0, $fa1
+; LA32D-NEXT: ret
+;
+; LA64F-LABEL: minimumnum_double_nsz:
+; 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_nsz:
+; LA64D: # %bb.0:
+; LA64D-NEXT: fmax.d $fa1, $fa1, $fa1
+; LA64D-NEXT: fmax.d $fa0, $fa0, $fa0
+; LA64D-NEXT: fmin.d $fa0, $fa0, $fa1
+; LA64D-NEXT: ret
+ %z = call nsz double @llvm.minimumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define double @minimumnum_double_nnan(double %x, double %y) {
+;
+; LA32F-LABEL: minimumnum_double_nnan:
+; 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_nnan:
+; LA32D: # %bb.0:
+; LA32D-NEXT: fmin.d $fa0, $fa0, $fa1
+; LA32D-NEXT: ret
+;
+; LA64F-LABEL: minimumnum_double_nnan:
+; 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_nnan:
+; LA64D: # %bb.0:
+; LA64D-NEXT: fmin.d $fa0, $fa0, $fa1
+; LA64D-NEXT: ret
+ %z = call nnan 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 8ee4070e534348..160c1ed243c396 100644
--- a/llvm/test/CodeGen/Mips/fp-maximumnum-minimumnum.ll
+++ b/llvm/test/CodeGen/Mips/fp-maximumnum-minimumnum.ll
@@ -17,19 +17,79 @@ define float @maximumnum_float(float %x, float %y) {
;
; MIPS32-LABEL: maximumnum_float:
; MIPS32: # %bb.0:
-; MIPS32-NEXT: addiu $sp, $sp, -24
-; MIPS32-NEXT: .cfi_def_cfa_offset 24
-; MIPS32-NEXT: sw $ra, 20($sp) # 4-byte Folded Spill
-; MIPS32-NEXT: .cfi_offset 31, -4
-; MIPS32-NEXT: jal fmaximum_numf
-; MIPS32-NEXT: nop
-; MIPS32-NEXT: lw $ra, 20($sp) # 4-byte Folded Reload
+; MIPS32-NEXT: c.un.s $f12, $f12
+; MIPS32-NEXT: movt.s $f12, $f14, $fcc0
+; MIPS32-NEXT: c.un.s $f14, $f14
+; MIPS32-NEXT: movt.s $f14, $f12, $fcc0
+; MIPS32-NEXT: c.ule.s $f12, $f14
+; MIPS32-NEXT: mov.s $f0, $f14
+; MIPS32-NEXT: movf.s $f0, $f12, $fcc0
+; MIPS32-NEXT: add.s $f1, $f0, $f0
+; MIPS32-NEXT: c.un.s $f0, $f0
+; MIPS32-NEXT: movt.s $f0, $f1, $fcc0
+; MIPS32-NEXT: mfc1 $1, $f12
+; MIPS32-NEXT: mov.s $f1, $f0
+; MIPS32-NEXT: movz.s $f1, $f12, $1
+; MIPS32-NEXT: mfc1 $1, $f14
+; MIPS32-NEXT: mtc1 $zero, $f2
+; MIPS32-NEXT: movz.s $f1, $f14, $1
+; MIPS32-NEXT: c.eq.s $f0, $f2
; MIPS32-NEXT: jr $ra
-; MIPS32-NEXT: addiu $sp, $sp, 24
+; MIPS32-NEXT: movt.s $f0, $f1, $fcc0
%z = call float @llvm.maximumnum.f32(float %x, float %y)
ret float %z
}
+define float @maximumnum_float_nsz(float %x, float %y) {
+; MIPS32R6-LABEL: maximumnum_float_nsz:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: min.s $f0, $f14, $f14
+; MIPS32R6-NEXT: min.s $f1, $f12, $f12
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: max.s $f0, $f1, $f0
+;
+; MIPS32-LABEL: maximumnum_float_nsz:
+; MIPS32: # %bb.0:
+; MIPS32-NEXT: mov.s $f0, $f14
+; MIPS32-NEXT: c.un.s $f12, $f12
+; MIPS32-NEXT: movt.s $f12, $f14, $fcc0
+; MIPS32-NEXT: c.un.s $f14, $f14
+; MIPS32-NEXT: movt.s $f0, $f12, $fcc0
+; MIPS32-NEXT: c.ule.s $f12, $f0
+; MIPS32-NEXT: movf.s $f0, $f12, $fcc0
+; MIPS32-NEXT: add.s $f1, $f0, $f0
+; MIPS32-NEXT: c.un.s $f0, $f0
+; MIPS32-NEXT: jr $ra
+; MIPS32-NEXT: movt.s $f0, $f1, $fcc0
+ %z = call nsz float @llvm.maximumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+define float @maximumnum_float_nnan(float %x, float %y) {
+; MIPS32R6-LABEL: maximumnum_float_nnan:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: max.s $f0, $f12, $f14
+;
+; MIPS32-LABEL: maximumnum_float_nnan:
+; MIPS32: # %bb.0:
+; MIPS32-NEXT: c.ule.s $f12, $f14
+; MIPS32-NEXT: mov.s $f0, $f14
+; MIPS32-NEXT: movf.s $f0, $f12, $fcc0
+; MIPS32-NEXT: mfc1 $1, $f12
+; MIPS32-NEXT: mov.s $f1, $f0
+; MIPS32-NEXT: movz.s $f1, $f12, $1
+; MIPS32-NEXT: mfc1 $1, $f14
+; MIPS32-NEXT: movz.s $f1, $f14, $1
+; MIPS32-NEXT: mtc1 $zero, $f2
+; MIPS32-NEXT: c.eq.s $f0, $f2
+; MIPS32-NEXT: jr $ra
+; MIPS32-NEXT: movt.s $f0, $f1, $fcc0
+ %z = call nnan float @llvm.maximumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+
define double @maximumnum_double(double %x, double %y) {
; MIPS32R6-LABEL: maximumnum_double:
; MIPS32R6: # %bb.0:
@@ -40,19 +100,84 @@ define double @maximumnum_double(double %x, double %y) {
;
; MIPS32-LABEL: maximumnum_double:
; MIPS32: # %bb.0:
-; MIPS32-NEXT: addiu $sp, $sp, -24
-; MIPS32-NEXT: .cfi_def_cfa_offset 24
-; MIPS32-NEXT: sw $ra, 20($sp) # 4-byte Folded Spill
-; MIPS32-NEXT: .cfi_offset 31, -4
-; MIPS32-NEXT: jal fmaximum_num
-; MIPS32-NEXT: nop
-; MIPS32-NEXT: lw $ra, 20($sp) # 4-byte Folded Reload
+; MIPS32-NEXT: c.un.d $f12, $f12
+; MIPS32-NEXT: movt.d $f12, $f14, $fcc0
+; MIPS32-NEXT: c.un.d $f14, $f14
+; MIPS32-NEXT: movt.d $f14, $f12, $fcc0
+; MIPS32-NEXT: c.ule.d $f12, $f14
+; MIPS32-NEXT: mov.d $f0, $f14
+; MIPS32-NEXT: movf.d $f0, $f12, $fcc0
+; MIPS32-NEXT: add.d $f2, $f0, $f0
+; MIPS32-NEXT: c.un.d $f0, $f0
+; MIPS32-NEXT: movt.d $f0, $f2, $fcc0
+; MIPS32-NEXT: cvt.s.d $f2, $f12
+; MIPS32-NEXT: mfc1 $1, $f2
+; MIPS32-NEXT: mov.d $f2, $f0
+; MIPS32-NEXT: movz.d $f2, $f12, $1
+; MIPS32-NEXT: cvt.s.d $f4, $f14
+; MIPS32-NEXT: mfc1 $1, $f4
+; MIPS32-NEXT: movz.d $f2, $f14, $1
+; MIPS32-NEXT: mtc1 $zero, $f4
+; MIPS32-NEXT: mtc1 $zero, $f5
+; MIPS32-NEXT: c.eq.d $f0, $f4
; MIPS32-NEXT: jr $ra
-; MIPS32-NEXT: addiu $sp, $sp, 24
+; MIPS32-NEXT: movt.d $f0, $f2, $fcc0
%z = call double @llvm.maximumnum.f64(double %x, double %y)
ret double %z
}
+define double @maximumnum_double_nsz(double %x, double %y) {
+; MIPS32R6-LABEL: maximumnum_double_nsz:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: min.d $f0, $f14, $f14
+; MIPS32R6-NEXT: min.d $f1, $f12, $f12
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: max.d $f0, $f1, $f0
+;
+; MIPS32-LABEL: maximumnum_double_nsz:
+; MIPS32: # %bb.0:
+; MIPS32-NEXT: mov.d $f0, $f14
+; MIPS32-NEXT: c.un.d $f12, $f12
+; MIPS32-NEXT: movt.d $f12, $f14, $fcc0
+; MIPS32-NEXT: c.un.d $f14, $f14
+; MIPS32-NEXT: movt.d $f0, $f12, $fcc0
+; MIPS32-NEXT: c.ule.d $f12, $f0
+; MIPS32-NEXT: movf.d $f0, $f12, $fcc0
+; MIPS32-NEXT: add.d $f2, $f0, $f0
+; MIPS32-NEXT: c.un.d $f0, $f0
+; MIPS32-NEXT: jr $ra
+; MIPS32-NEXT: movt.d $f0, $f2, $fcc0
+ %z = call nsz double @llvm.maximumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define double @maximumnum_double_nnan(double %x, double %y) {
+; MIPS32R6-LABEL: maximumnum_double_nnan:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: max.d $f0, $f12, $f14
+;
+; MIPS32-LABEL: maximumnum_double_nnan:
+; MIPS32: # %bb.0:
+; MIPS32-NEXT: c.ule.d $f12, $f14
+; MIPS32-NEXT: mov.d $f0, $f14
+; MIPS32-NEXT: movf.d $f0, $f12, $fcc0
+; MIPS32-NEXT: cvt.s.d $f2, $f12
+; MIPS32-NEXT: mfc1 $1, $f2
+; MIPS32-NEXT: mov.d $f2, $f0
+; MIPS32-NEXT: movz.d $f2, $f12, $1
+; MIPS32-NEXT: cvt.s.d $f4, $f14
+; MIPS32-NEXT: mfc1 $1, $f4
+; MIPS32-NEXT: movz.d $f2, $f14, $1
+; MIPS32-NEXT: mtc1 $zero, $f4
+; MIPS32-NEXT: mtc1 $zero, $f5
+; MIPS32-NEXT: c.eq.d $f0, $f4
+; MIPS32-NEXT: jr $ra
+; MIPS32-NEXT: movt.d $f0, $f2, $fcc0
+ %z = call nnan 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:
@@ -63,19 +188,84 @@ define float @minimumnum_float(float %x, float %y) {
;
; MIPS32-LABEL: minimumnum_float:
; MIPS32: # %bb.0:
-; MIPS32-NEXT: addiu $sp, $sp, -24
-; MIPS32-NEXT: .cfi_def_cfa_offset 24
-; MIPS32-NEXT: sw $ra, 20($sp) # 4-byte Folded Spill
-; MIPS32-NEXT: .cfi_offset 31, -4
-; MIPS32-NEXT: jal fminimum_numf
-; MIPS32-NEXT: nop
-; MIPS32-NEXT: lw $ra, 20($sp) # 4-byte Folded Reload
+; MIPS32-NEXT: c.un.s $f12, $f12
+; MIPS32-NEXT: movt.s $f12, $f14, $fcc0
+; MIPS32-NEXT: c.un.s $f14, $f14
+; MIPS32-NEXT: movt.s $f14, $f12, $fcc0
+; MIPS32-NEXT: c.olt.s $f12, $f14
+; MIPS32-NEXT: mov.s $f0, $f14
+; MIPS32-NEXT: movt.s $f0, $f12, $fcc0
+; MIPS32-NEXT: add.s $f1, $f0, $f0
+; MIPS32-NEXT: c.un.s $f0, $f0
+; MIPS32-NEXT: movt.s $f0, $f1, $fcc0
+; MIPS32-NEXT: mfc1 $1, $f12
+; MIPS32-NEXT: lui $2, 32768
+; MIPS32-NEXT: xor $1, $1, $2
+; MIPS32-NEXT: mov.s $f1, $f0
+; MIPS32-NEXT: movz.s $f1, $f12, $1
+; MIPS32-NEXT: mfc1 $1, $f14
+; MIPS32-NEXT: xor $1, $1, $2
+; MIPS32-NEXT: mtc1 $zero, $f2
+; MIPS32-NEXT: movz.s $f1, $f14, $1
+; MIPS32-NEXT: c.eq.s $f0, $f2
; MIPS32-NEXT: jr $ra
-; MIPS32-NEXT: addiu $sp, $sp, 24
+; MIPS32-NEXT: movt.s $f0, $f1, $fcc0
%z = call float @llvm.minimumnum.f32(float %x, float %y)
ret float %z
}
+define float @minimumnum_float_nsz(float %x, float %y) {
+; MIPS32R6-LABEL: minimumnum_float_nsz:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: min.s $f0, $f14, $f14
+; MIPS32R6-NEXT: min.s $f1, $f12, $f12
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: min.s $f0, $f1, $f0
+;
+; MIPS32-LABEL: minimumnum_float_nsz:
+; MIPS32: # %bb.0:
+; MIPS32-NEXT: mov.s $f0, $f14
+; MIPS32-NEXT: c.un.s $f12, $f12
+; MIPS32-NEXT: movt.s $f12, $f14, $fcc0
+; MIPS32-NEXT: c.un.s $f14, $f14
+; MIPS32-NEXT: movt.s $f0, $f12, $fcc0
+; MIPS32-NEXT: c.olt.s $f12, $f0
+; MIPS32-NEXT: movt.s $f0, $f12, $fcc0
+; MIPS32-NEXT: add.s $f1, $f0, $f0
+; MIPS32-NEXT: c.un.s $f0, $f0
+; MIPS32-NEXT: jr $ra
+; MIPS32-NEXT: movt.s $f0, $f1, $fcc0
+ %z = call nsz float @llvm.minimumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+define float @minimumnum_float_nnan(float %x, float %y) {
+; MIPS32R6-LABEL: minimumnum_float_nnan:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: min.s $f0, $f12, $f14
+;
+; MIPS32-LABEL: minimumnum_float_nnan:
+; MIPS32: # %bb.0:
+; MIPS32-NEXT: c.olt.s $f12, $f14
+; MIPS32-NEXT: mov.s $f0, $f14
+; MIPS32-NEXT: movt.s $f0, $f12, $fcc0
+; MIPS32-NEXT: mfc1 $1, $f12
+; MIPS32-NEXT: lui $2, 32768
+; MIPS32-NEXT: xor $1, $1, $2
+; MIPS32-NEXT: mov.s $f1, $f0
+; MIPS32-NEXT: movz.s $f1, $f12, $1
+; MIPS32-NEXT: mfc1 $1, $f14
+; MIPS32-NEXT: xor $1, $1, $2
+; MIPS32-NEXT: movz.s $f1, $f14, $1
+; MIPS32-NEXT: mtc1 $zero, $f2
+; MIPS32-NEXT: c.eq.s $f0, $f2
+; MIPS32-NEXT: jr $ra
+; MIPS32-NEXT: movt.s $f0, $f1, $fcc0
+ %z = call nnan 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:
@@ -86,15 +276,86 @@ define double @minimumnum_double(double %x, double %y) {
;
; MIPS32-LABEL: minimumnum_double:
; MIPS32: # %bb.0:
-; MIPS32-NEXT: addiu $sp, $sp, -24
-; MIPS32-NEXT: .cfi_def_cfa_offset 24
-; MIPS32-NEXT: sw $ra, 20($sp) # 4-byte Folded Spill
-; MIPS32-NEXT: .cfi_offset 31, -4
-; MIPS32-NEXT: jal fminimum_num
-; MIPS32-NEXT: nop
-; MIPS32-NEXT: lw $ra, 20($sp) # 4-byte Folded Reload
+; MIPS32-NEXT: c.un.d $f12, $f12
+; MIPS32-NEXT: movt.d $f12, $f14, $fcc0
+; MIPS32-NEXT: c.un.d $f14, $f14
+; MIPS32-NEXT: movt.d $f14, $f12, $fcc0
+; MIPS32-NEXT: c.olt.d $f12, $f14
+; MIPS32-NEXT: mov.d $f0, $f14
+; MIPS32-NEXT: movt.d $f0, $f12, $fcc0
+; MIPS32-NEXT: add.d $f2, $f0, $f0
+; MIPS32-NEXT: c.un.d $f0, $f0
+; MIPS32-NEXT: movt.d $f0, $f2, $fcc0
+; MIPS32-NEXT: cvt.s.d $f2, $f12
+; MIPS32-NEXT: mfc1 $1, $f2
+; MIPS32-NEXT: lui $2, 32768
+; MIPS32-NEXT: xor $1, $1, $2
+; MIPS32-NEXT: mov.d $f2, $f0
+; MIPS32-NEXT: movz.d $f2, $f12, $1
+; MIPS32-NEXT: cvt.s.d $f4, $f14
+; MIPS32-NEXT: mfc1 $1, $f4
+; MIPS32-NEXT: xor $1, $1, $2
+; MIPS32-NEXT: movz.d $f2, $f14, $1
+; MIPS32-NEXT: mtc1 $zero, $f4
+; MIPS32-NEXT: mtc1 $zero, $f5
+; MIPS32-NEXT: c.eq.d $f0, $f4
; MIPS32-NEXT: jr $ra
-; MIPS32-NEXT: addiu $sp, $sp, 24
+; MIPS32-NEXT: movt.d $f0, $f2, $fcc0
%z = call double @llvm.minimumnum.f64(double %x, double %y)
ret double %z
}
+
+define double @minimumnum_double_nsz(double %x, double %y) {
+; MIPS32R6-LABEL: minimumnum_double_nsz:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: min.d $f0, $f14, $f14
+; MIPS32R6-NEXT: min.d $f1, $f12, $f12
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: min.d $f0, $f1, $f0
+;
+; MIPS32-LABEL: minimumnum_double_nsz:
+; MIPS32: # %bb.0:
+; MIPS32-NEXT: mov.d $f0, $f14
+; MIPS32-NEXT: c.un.d $f12, $f12
+; MIPS32-NEXT: movt.d $f12, $f14, $fcc0
+; MIPS32-NEXT: c.un.d $f14, $f14
+; MIPS32-NEXT: movt.d $f0, $f12, $fcc0
+; MIPS32-NEXT: c.olt.d $f12, $f0
+; MIPS32-NEXT: movt.d $f0, $f12, $fcc0
+; MIPS32-NEXT: add.d $f2, $f0, $f0
+; MIPS32-NEXT: c.un.d $f0, $f0
+; MIPS32-NEXT: jr $ra
+; MIPS32-NEXT: movt.d $f0, $f2, $fcc0
+ %z = call nsz double @llvm.minimumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define double @minimumnum_double_nnan(double %x, double %y) {
+; MIPS32R6-LABEL: minimumnum_double_nnan:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: min.d $f0, $f12, $f14
+;
+; MIPS32-LABEL: minimumnum_double_nnan:
+; MIPS32: # %bb.0:
+; MIPS32-NEXT: c.olt.d $f12, $f14
+; MIPS32-NEXT: mov.d $f0, $f14
+; MIPS32-NEXT: movt.d $f0, $f12, $fcc0
+; MIPS32-NEXT: cvt.s.d $f2, $f12
+; MIPS32-NEXT: mfc1 $1, $f2
+; MIPS32-NEXT: lui $2, 32768
+; MIPS32-NEXT: xor $1, $1, $2
+; MIPS32-NEXT: mov.d $f2, $f0
+; MIPS32-NEXT: movz.d $f2, $f12, $1
+; MIPS32-NEXT: cvt.s.d $f4, $f14
+; MIPS32-NEXT: mfc1 $1, $f4
+; MIPS32-NEXT: xor $1, $1, $2
+; MIPS32-NEXT: movz.d $f2, $f14, $1
+; MIPS32-NEXT: mtc1 $zero, $f4
+; MIPS32-NEXT: mtc1 $zero, $f5
+; MIPS32-NEXT: c.eq.d $f0, $f4
+; MIPS32-NEXT: jr $ra
+; MIPS32-NEXT: movt.d $f0, $f2, $fcc0
+ %z = call nnan double @llvm.minimumnum.f64(double %x, double %y)
+ ret double %z
+}
diff --git a/llvm/test/CodeGen/SPARC/fp-maximumnum-minimumnum.ll b/llvm/test/CodeGen/SPARC/fp-maximumnum-minimumnum.ll
new file mode 100644
index 00000000000000..6d3766fafe7324
--- /dev/null
+++ b/llvm/test/CodeGen/SPARC/fp-maximumnum-minimumnum.ll
@@ -0,0 +1,1355 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc --mtriple=sparc64 < %s | FileCheck %s --check-prefix=SPARC64
+; RUN: llc --mtriple=sparc < %s | FileCheck %s --check-prefix=SPARC
+
+declare float @llvm.maximumnum.f32(float, float)
+declare double @llvm.maximumnum.f64(double, double)
+declare float @llvm.minimumnum.f32(float, float)
+declare double @llvm.minimumnum.f64(double, double)
+
+define float @maximumnum_float(float %x, float %y) {
+;
+; SPARC64-LABEL: maximumnum_float:
+; SPARC64: .cfi_startproc
+; SPARC64-NEXT: ! %bb.0:
+; SPARC64-NEXT: add %sp, -144, %sp
+; SPARC64-NEXT: .cfi_def_cfa_register %fp
+; SPARC64-NEXT: .cfi_window_save
+; SPARC64-NEXT: .cfi_register %o7, %i7
+; SPARC64-NEXT: mov %g0, %o0
+; SPARC64-NEXT: mov %g0, %o1
+; SPARC64-NEXT: fcmps %fcc0, %f1, %f1
+; SPARC64-NEXT: fmovsu %fcc0, %f3, %f1
+; SPARC64-NEXT: st %f1, [%sp+2187]
+; SPARC64-NEXT: fcmps %fcc0, %f3, %f3
+; SPARC64-NEXT: fmovsu %fcc0, %f1, %f3
+; SPARC64-NEXT: st %f3, [%sp+2183]
+; SPARC64-NEXT: fcmps %fcc0, %f1, %f3
+; SPARC64-NEXT: fmovs %f3, %f0
+; SPARC64-NEXT: fmovsg %fcc0, %f1, %f0
+; SPARC64-NEXT: ld [%sp+2187], %o2
+; SPARC64-NEXT: fadds %f0, %f0, %f2
+; SPARC64-NEXT: fcmps %fcc0, %f0, %f0
+; SPARC64-NEXT: fmovsu %fcc0, %f2, %f0
+; SPARC64-NEXT: cmp %o2, 0
+; SPARC64-NEXT: ld [%sp+2183], %o2
+; SPARC64-NEXT: move %icc, 1, %o0
+; SPARC64-NEXT: cmp %o0, 0
+; SPARC64-NEXT: fmovs %f0, %f2
+; SPARC64-NEXT: fmovsne %icc, %f1, %f2
+; SPARC64-NEXT: cmp %o2, 0
+; SPARC64-NEXT: sethi %h44(.LCPI0_0), %o0
+; SPARC64-NEXT: add %o0, %m44(.LCPI0_0), %o0
+; SPARC64-NEXT: sllx %o0, 12, %o0
+; SPARC64-NEXT: ld [%o0+%l44(.LCPI0_0)], %f1
+; SPARC64-NEXT: move %icc, 1, %o1
+; SPARC64-NEXT: cmp %o1, 0
+; SPARC64-NEXT: fmovsne %icc, %f3, %f2
+; SPARC64-NEXT: fcmps %fcc0, %f0, %f1
+; SPARC64-NEXT: fmovse %fcc0, %f2, %f0
+; SPARC64-NEXT: retl
+; SPARC64-NEXT: add %sp, 144, %sp
+;
+; SPARC-LABEL: maximumnum_float:
+; SPARC: .cfi_startproc
+; SPARC-NEXT: ! %bb.0:
+; SPARC-NEXT: add %sp, -112, %sp
+; SPARC-NEXT: .cfi_def_cfa_register %fp
+; SPARC-NEXT: .cfi_window_save
+; SPARC-NEXT: .cfi_register %o7, %i7
+; SPARC-NEXT: st %o0, [%sp+104]
+; SPARC-NEXT: st %o1, [%sp+108]
+; SPARC-NEXT: ld [%sp+104], %f0
+; SPARC-NEXT: ld [%sp+108], %f2
+; SPARC-NEXT: fcmps %f0, %f0
+; SPARC-NEXT: nop
+; SPARC-NEXT: fmovs %f2, %f1
+; SPARC-NEXT: fbu .LBB0_2
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.1:
+; SPARC-NEXT: fmovs %f0, %f1
+; SPARC-NEXT: .LBB0_2:
+; SPARC-NEXT: fcmps %f2, %f2
+; SPARC-NEXT: nop
+; SPARC-NEXT: st %f1, [%sp+100]
+; SPARC-NEXT: fmovs %f1, %f0
+; SPARC-NEXT: fbu .LBB0_4
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.3:
+; SPARC-NEXT: fmovs %f2, %f0
+; SPARC-NEXT: .LBB0_4:
+; SPARC-NEXT: fcmps %f1, %f0
+; SPARC-NEXT: nop
+; SPARC-NEXT: st %f0, [%sp+96]
+; SPARC-NEXT: fmovs %f1, %f2
+; SPARC-NEXT: fbg .LBB0_6
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.5:
+; SPARC-NEXT: fmovs %f0, %f2
+; SPARC-NEXT: .LBB0_6:
+; SPARC-NEXT: fcmps %f2, %f2
+; SPARC-NEXT: nop
+; SPARC-NEXT: fbo .LBB0_8
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.7:
+; SPARC-NEXT: fadds %f2, %f2, %f2
+; SPARC-NEXT: .LBB0_8:
+; SPARC-NEXT: ld [%sp+100], %o1
+; SPARC-NEXT: mov 1, %o0
+; SPARC-NEXT: cmp %o1, 0
+; SPARC-NEXT: be .LBB0_10
+; SPARC-NEXT: mov %o0, %o1
+; SPARC-NEXT: ! %bb.9:
+; SPARC-NEXT: mov %g0, %o1
+; SPARC-NEXT: .LBB0_10:
+; SPARC-NEXT: cmp %o1, 0
+; SPARC-NEXT: bne .LBB0_12
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.11:
+; SPARC-NEXT: fmovs %f2, %f1
+; SPARC-NEXT: .LBB0_12:
+; SPARC-NEXT: ld [%sp+96], %o1
+; SPARC-NEXT: cmp %o1, 0
+; SPARC-NEXT: be .LBB0_14
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.13:
+; SPARC-NEXT: mov %g0, %o0
+; SPARC-NEXT: .LBB0_14:
+; SPARC-NEXT: cmp %o0, 0
+; SPARC-NEXT: bne .LBB0_16
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.15:
+; SPARC-NEXT: fmovs %f1, %f0
+; SPARC-NEXT: .LBB0_16:
+; SPARC-NEXT: sethi %hi(.LCPI0_0), %o0
+; SPARC-NEXT: ld [%o0+%lo(.LCPI0_0)], %f1
+; SPARC-NEXT: fcmps %f2, %f1
+; SPARC-NEXT: nop
+; SPARC-NEXT: fbe .LBB0_18
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.17:
+; SPARC-NEXT: fmovs %f2, %f0
+; SPARC-NEXT: .LBB0_18:
+; SPARC-NEXT: retl
+; SPARC-NEXT: add %sp, 112, %sp
+ %z = call float @llvm.maximumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+define float @maximumnum_float_nsz(float %x, float %y) {
+;
+; SPARC64-LABEL: maximumnum_float_nsz:
+; SPARC64: .cfi_startproc
+; SPARC64-NEXT: ! %bb.0:
+; SPARC64-NEXT: fmovs %f3, %f0
+; SPARC64-NEXT: fcmps %fcc0, %f1, %f1
+; SPARC64-NEXT: fmovsu %fcc0, %f3, %f1
+; SPARC64-NEXT: fcmps %fcc0, %f3, %f3
+; SPARC64-NEXT: fmovsu %fcc0, %f1, %f0
+; SPARC64-NEXT: fcmps %fcc0, %f1, %f0
+; SPARC64-NEXT: fmovsg %fcc0, %f1, %f0
+; SPARC64-NEXT: fadds %f0, %f0, %f1
+; SPARC64-NEXT: fcmps %fcc0, %f0, %f0
+; SPARC64-NEXT: retl
+; SPARC64-NEXT: fmovsu %fcc0, %f1, %f0
+;
+; SPARC-LABEL: maximumnum_float_nsz:
+; SPARC: .cfi_startproc
+; SPARC-NEXT: ! %bb.0:
+; SPARC-NEXT: add %sp, -104, %sp
+; SPARC-NEXT: .cfi_def_cfa_register %fp
+; SPARC-NEXT: .cfi_window_save
+; SPARC-NEXT: .cfi_register %o7, %i7
+; SPARC-NEXT: st %o0, [%sp+96]
+; SPARC-NEXT: st %o1, [%sp+100]
+; SPARC-NEXT: ld [%sp+96], %f2
+; SPARC-NEXT: ld [%sp+100], %f1
+; SPARC-NEXT: fcmps %f2, %f2
+; SPARC-NEXT: nop
+; SPARC-NEXT: fmovs %f1, %f0
+; SPARC-NEXT: fbu .LBB1_2
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.1:
+; SPARC-NEXT: fmovs %f2, %f0
+; SPARC-NEXT: .LBB1_2:
+; SPARC-NEXT: fcmps %f1, %f1
+; SPARC-NEXT: nop
+; SPARC-NEXT: fmovs %f0, %f2
+; SPARC-NEXT: fbo .LBB1_6
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.3:
+; SPARC-NEXT: fcmps %f0, %f2
+; SPARC-NEXT: nop
+; SPARC-NEXT: fbule .LBB1_7
+; SPARC-NEXT: nop
+; SPARC-NEXT: .LBB1_4:
+; SPARC-NEXT: fcmps %f0, %f0
+; SPARC-NEXT: nop
+; SPARC-NEXT: fbu .LBB1_8
+; SPARC-NEXT: nop
+; SPARC-NEXT: .LBB1_5:
+; SPARC-NEXT: retl
+; SPARC-NEXT: add %sp, 104, %sp
+; SPARC-NEXT: .LBB1_6:
+; SPARC-NEXT: fmovs %f1, %f2
+; SPARC-NEXT: fcmps %f0, %f2
+; SPARC-NEXT: nop
+; SPARC-NEXT: fbg .LBB1_4
+; SPARC-NEXT: nop
+; SPARC-NEXT: .LBB1_7:
+; SPARC-NEXT: fmovs %f2, %f0
+; SPARC-NEXT: fcmps %f0, %f0
+; SPARC-NEXT: nop
+; SPARC-NEXT: fbo .LBB1_5
+; SPARC-NEXT: nop
+; SPARC-NEXT: .LBB1_8:
+; SPARC-NEXT: fadds %f0, %f0, %f0
+; SPARC-NEXT: retl
+; SPARC-NEXT: add %sp, 104, %sp
+ %z = call nsz float @llvm.maximumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+define float @maximumnum_float_nnan(float %x, float %y) {
+;
+; SPARC64-LABEL: maximumnum_float_nnan:
+; SPARC64: .cfi_startproc
+; SPARC64-NEXT: ! %bb.0:
+; SPARC64-NEXT: add %sp, -144, %sp
+; SPARC64-NEXT: .cfi_def_cfa_register %fp
+; SPARC64-NEXT: .cfi_window_save
+; SPARC64-NEXT: .cfi_register %o7, %i7
+; SPARC64-NEXT: st %f3, [%sp+2183]
+; SPARC64-NEXT: st %f1, [%sp+2187]
+; SPARC64-NEXT: ld [%sp+2187], %o0
+; SPARC64-NEXT: mov %g0, %o1
+; SPARC64-NEXT: mov %g0, %o2
+; SPARC64-NEXT: cmp %o0, 0
+; SPARC64-NEXT: ld [%sp+2183], %o0
+; SPARC64-NEXT: fcmps %fcc0, %f1, %f3
+; SPARC64-NEXT: fmovs %f3, %f0
+; SPARC64-NEXT: fmovsg %fcc0, %f1, %f0
+; SPARC64-NEXT: move %icc, 1, %o1
+; SPARC64-NEXT: cmp %o1, 0
+; SPARC64-NEXT: fmovs %f0, %f2
+; SPARC64-NEXT: fmovsne %icc, %f1, %f2
+; SPARC64-NEXT: cmp %o0, 0
+; SPARC64-NEXT: sethi %h44(.LCPI2_0), %o0
+; SPARC64-NEXT: add %o0, %m44(.LCPI2_0), %o0
+; SPARC64-NEXT: sllx %o0, 12, %o0
+; SPARC64-NEXT: ld [%o0+%l44(.LCPI2_0)], %f1
+; SPARC64-NEXT: move %icc, 1, %o2
+; SPARC64-NEXT: cmp %o2, 0
+; SPARC64-NEXT: fmovsne %icc, %f3, %f2
+; SPARC64-NEXT: fcmps %fcc0, %f0, %f1
+; SPARC64-NEXT: fmovse %fcc0, %f2, %f0
+; SPARC64-NEXT: retl
+; SPARC64-NEXT: add %sp, 144, %sp
+;
+; SPARC-LABEL: maximumnum_float_nnan:
+; SPARC: .cfi_startproc
+; SPARC-NEXT: ! %bb.0:
+; SPARC-NEXT: add %sp, -112, %sp
+; SPARC-NEXT: .cfi_def_cfa_register %fp
+; SPARC-NEXT: .cfi_window_save
+; SPARC-NEXT: .cfi_register %o7, %i7
+; SPARC-NEXT: st %o0, [%sp+104]
+; SPARC-NEXT: st %o1, [%sp+108]
+; SPARC-NEXT: ld [%sp+104], %f1
+; SPARC-NEXT: st %f1, [%sp+100]
+; SPARC-NEXT: ld [%sp+108], %f0
+; SPARC-NEXT: st %f0, [%sp+96]
+; SPARC-NEXT: ld [%sp+96], %o0
+; SPARC-NEXT: ld [%sp+100], %o2
+; SPARC-NEXT: mov 1, %o1
+; SPARC-NEXT: cmp %o0, 0
+; SPARC-NEXT: be .LBB2_2
+; SPARC-NEXT: mov %o1, %o0
+; SPARC-NEXT: ! %bb.1:
+; SPARC-NEXT: mov %g0, %o0
+; SPARC-NEXT: .LBB2_2:
+; SPARC-NEXT: cmp %o2, 0
+; SPARC-NEXT: be .LBB2_4
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.3:
+; SPARC-NEXT: mov %g0, %o1
+; SPARC-NEXT: .LBB2_4:
+; SPARC-NEXT: fcmps %f1, %f0
+; SPARC-NEXT: nop
+; SPARC-NEXT: fmovs %f1, %f2
+; SPARC-NEXT: fbule .LBB2_11
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.5:
+; SPARC-NEXT: cmp %o1, 0
+; SPARC-NEXT: be .LBB2_12
+; SPARC-NEXT: nop
+; SPARC-NEXT: .LBB2_6:
+; SPARC-NEXT: cmp %o0, 0
+; SPARC-NEXT: bne .LBB2_8
+; SPARC-NEXT: nop
+; SPARC-NEXT: .LBB2_7:
+; SPARC-NEXT: fmovs %f1, %f0
+; SPARC-NEXT: .LBB2_8:
+; SPARC-NEXT: sethi %hi(.LCPI2_0), %o0
+; SPARC-NEXT: ld [%o0+%lo(.LCPI2_0)], %f1
+; SPARC-NEXT: fcmps %f2, %f1
+; SPARC-NEXT: nop
+; SPARC-NEXT: fbe .LBB2_10
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.9:
+; SPARC-NEXT: fmovs %f2, %f0
+; SPARC-NEXT: .LBB2_10:
+; SPARC-NEXT: retl
+; SPARC-NEXT: add %sp, 112, %sp
+; SPARC-NEXT: .LBB2_11:
+; SPARC-NEXT: fmovs %f0, %f2
+; SPARC-NEXT: cmp %o1, 0
+; SPARC-NEXT: bne .LBB2_6
+; SPARC-NEXT: nop
+; SPARC-NEXT: .LBB2_12:
+; SPARC-NEXT: fmovs %f2, %f1
+; SPARC-NEXT: cmp %o0, 0
+; SPARC-NEXT: be .LBB2_7
+; SPARC-NEXT: nop
+; SPARC-NEXT: ba .LBB2_8
+; SPARC-NEXT: nop
+ %z = call nnan float @llvm.maximumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+
+define double @maximumnum_double(double %x, double %y) {
+;
+; SPARC64-LABEL: maximumnum_double:
+; SPARC64: .cfi_startproc
+; SPARC64-NEXT: ! %bb.0:
+; SPARC64-NEXT: add %sp, -144, %sp
+; SPARC64-NEXT: .cfi_def_cfa_register %fp
+; SPARC64-NEXT: .cfi_window_save
+; SPARC64-NEXT: .cfi_register %o7, %i7
+; SPARC64-NEXT: mov %g0, %o0
+; SPARC64-NEXT: mov %g0, %o1
+; SPARC64-NEXT: fcmpd %fcc0, %f0, %f0
+; SPARC64-NEXT: fmovdu %fcc0, %f2, %f0
+; SPARC64-NEXT: std %f0, [%sp+2183]
+; SPARC64-NEXT: fcmpd %fcc0, %f2, %f2
+; SPARC64-NEXT: fmovdu %fcc0, %f0, %f2
+; SPARC64-NEXT: std %f2, [%sp+2175]
+; SPARC64-NEXT: fcmpd %fcc0, %f0, %f2
+; SPARC64-NEXT: fmovd %f2, %f4
+; SPARC64-NEXT: fmovdg %fcc0, %f0, %f4
+; SPARC64-NEXT: ldx [%sp+2183], %o2
+; SPARC64-NEXT: faddd %f4, %f4, %f6
+; SPARC64-NEXT: fcmpd %fcc0, %f4, %f4
+; SPARC64-NEXT: fmovdu %fcc0, %f6, %f4
+; SPARC64-NEXT: movrz %o2, 1, %o0
+; SPARC64-NEXT: cmp %o0, 0
+; SPARC64-NEXT: ldx [%sp+2175], %o0
+; SPARC64-NEXT: sethi %h44(.LCPI3_0), %o2
+; SPARC64-NEXT: add %o2, %m44(.LCPI3_0), %o2
+; SPARC64-NEXT: sllx %o2, 12, %o2
+; SPARC64-NEXT: ldd [%o2+%l44(.LCPI3_0)], %f6
+; SPARC64-NEXT: fmovd %f4, %f8
+; SPARC64-NEXT: fmovdne %icc, %f0, %f8
+; SPARC64-NEXT: movrz %o0, 1, %o1
+; SPARC64-NEXT: cmp %o1, 0
+; SPARC64-NEXT: fmovdne %icc, %f2, %f8
+; SPARC64-NEXT: fcmpd %fcc0, %f4, %f6
+; SPARC64-NEXT: fmovde %fcc0, %f8, %f4
+; SPARC64-NEXT: fmovd %f4, %f0
+; SPARC64-NEXT: retl
+; SPARC64-NEXT: add %sp, 144, %sp
+;
+; SPARC-LABEL: maximumnum_double:
+; SPARC: .cfi_startproc
+; SPARC-NEXT: ! %bb.0:
+; SPARC-NEXT: add %sp, -120, %sp
+; SPARC-NEXT: .cfi_def_cfa_register %fp
+; SPARC-NEXT: .cfi_window_save
+; SPARC-NEXT: .cfi_register %o7, %i7
+; SPARC-NEXT: ! kill: def $o1 killed $o1 killed $o0_o1 def $o0_o1
+; SPARC-NEXT: ! kill: def $o3 killed $o3 killed $o2_o3 def $o2_o3
+; SPARC-NEXT: ! kill: def $o0 killed $o0 killed $o0_o1 def $o0_o1
+; SPARC-NEXT: std %o0, [%sp+112]
+; SPARC-NEXT: ! kill: def $o2 killed $o2 killed $o2_o3 def $o2_o3
+; SPARC-NEXT: std %o2, [%sp+104]
+; SPARC-NEXT: ldd [%sp+112], %f0
+; SPARC-NEXT: ldd [%sp+104], %f4
+; SPARC-NEXT: fcmpd %f0, %f0
+; SPARC-NEXT: nop
+; SPARC-NEXT: fmovs %f4, %f2
+; SPARC-NEXT: fmovs %f5, %f3
+; SPARC-NEXT: fbu .LBB3_2
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.1:
+; SPARC-NEXT: fmovs %f0, %f2
+; SPARC-NEXT: fmovs %f1, %f3
+; SPARC-NEXT: .LBB3_2:
+; SPARC-NEXT: fdtos %f2, %f0
+; SPARC-NEXT: fcmpd %f4, %f4
+; SPARC-NEXT: nop
+; SPARC-NEXT: st %f0, [%sp+100]
+; SPARC-NEXT: fmovs %f2, %f0
+; SPARC-NEXT: fmovs %f3, %f1
+; SPARC-NEXT: fbu .LBB3_4
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.3:
+; SPARC-NEXT: fmovs %f4, %f0
+; SPARC-NEXT: fmovs %f5, %f1
+; SPARC-NEXT: .LBB3_4:
+; SPARC-NEXT: fdtos %f0, %f4
+; SPARC-NEXT: fcmpd %f2, %f0
+; SPARC-NEXT: nop
+; SPARC-NEXT: st %f4, [%sp+96]
+; SPARC-NEXT: fmovs %f2, %f4
+; SPARC-NEXT: fmovs %f3, %f5
+; SPARC-NEXT: fbg .LBB3_6
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.5:
+; SPARC-NEXT: fmovs %f0, %f4
+; SPARC-NEXT: fmovs %f1, %f5
+; SPARC-NEXT: .LBB3_6:
+; SPARC-NEXT: fcmpd %f4, %f4
+; SPARC-NEXT: nop
+; SPARC-NEXT: fbo .LBB3_8
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.7:
+; SPARC-NEXT: faddd %f4, %f4, %f4
+; SPARC-NEXT: .LBB3_8:
+; SPARC-NEXT: ld [%sp+100], %o1
+; SPARC-NEXT: mov 1, %o0
+; SPARC-NEXT: cmp %o1, 0
+; SPARC-NEXT: be .LBB3_10
+; SPARC-NEXT: mov %o0, %o1
+; SPARC-NEXT: ! %bb.9:
+; SPARC-NEXT: mov %g0, %o1
+; SPARC-NEXT: .LBB3_10:
+; SPARC-NEXT: cmp %o1, 0
+; SPARC-NEXT: bne .LBB3_12
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.11:
+; SPARC-NEXT: fmovs %f4, %f2
+; SPARC-NEXT: fmovs %f5, %f3
+; SPARC-NEXT: .LBB3_12:
+; SPARC-NEXT: ld [%sp+96], %o1
+; SPARC-NEXT: cmp %o1, 0
+; SPARC-NEXT: be .LBB3_14
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.13:
+; SPARC-NEXT: mov %g0, %o0
+; SPARC-NEXT: .LBB3_14:
+; SPARC-NEXT: cmp %o0, 0
+; SPARC-NEXT: bne .LBB3_16
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.15:
+; SPARC-NEXT: fmovs %f2, %f0
+; SPARC-NEXT: fmovs %f3, %f1
+; SPARC-NEXT: .LBB3_16:
+; SPARC-NEXT: sethi %hi(.LCPI3_0), %o0
+; SPARC-NEXT: ldd [%o0+%lo(.LCPI3_0)], %f2
+; SPARC-NEXT: fcmpd %f4, %f2
+; SPARC-NEXT: nop
+; SPARC-NEXT: fbe .LBB3_18
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.17:
+; SPARC-NEXT: fmovs %f4, %f0
+; SPARC-NEXT: fmovs %f5, %f1
+; SPARC-NEXT: .LBB3_18:
+; SPARC-NEXT: retl
+; SPARC-NEXT: add %sp, 120, %sp
+ %z = call double @llvm.maximumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define double @maximumnum_double_nsz(double %x, double %y) {
+;
+; SPARC64-LABEL: maximumnum_double_nsz:
+; SPARC64: .cfi_startproc
+; SPARC64-NEXT: ! %bb.0:
+; SPARC64-NEXT: fcmpd %fcc0, %f0, %f0
+; SPARC64-NEXT: fmovdu %fcc0, %f2, %f0
+; SPARC64-NEXT: fcmpd %fcc0, %f2, %f2
+; SPARC64-NEXT: fmovdu %fcc0, %f0, %f2
+; SPARC64-NEXT: fcmpd %fcc0, %f0, %f2
+; SPARC64-NEXT: fmovdg %fcc0, %f0, %f2
+; SPARC64-NEXT: faddd %f2, %f2, %f0
+; SPARC64-NEXT: fcmpd %fcc0, %f2, %f2
+; SPARC64-NEXT: fmovdu %fcc0, %f0, %f2
+; SPARC64-NEXT: fmovd %f2, %f0
+; SPARC64-NEXT: retl
+; SPARC64-NEXT: nop
+;
+; SPARC-LABEL: maximumnum_double_nsz:
+; SPARC: .cfi_startproc
+; SPARC-NEXT: ! %bb.0:
+; SPARC-NEXT: add %sp, -112, %sp
+; SPARC-NEXT: .cfi_def_cfa_register %fp
+; SPARC-NEXT: .cfi_window_save
+; SPARC-NEXT: .cfi_register %o7, %i7
+; SPARC-NEXT: ! kill: def $o1 killed $o1 killed $o0_o1 def $o0_o1
+; SPARC-NEXT: ! kill: def $o3 killed $o3 killed $o2_o3 def $o2_o3
+; SPARC-NEXT: ! kill: def $o0 killed $o0 killed $o0_o1 def $o0_o1
+; SPARC-NEXT: std %o0, [%sp+104]
+; SPARC-NEXT: ! kill: def $o2 killed $o2 killed $o2_o3 def $o2_o3
+; SPARC-NEXT: std %o2, [%sp+96]
+; SPARC-NEXT: ldd [%sp+104], %f4
+; SPARC-NEXT: ldd [%sp+96], %f2
+; SPARC-NEXT: fcmpd %f4, %f4
+; SPARC-NEXT: nop
+; SPARC-NEXT: fmovs %f2, %f0
+; SPARC-NEXT: fmovs %f3, %f1
+; SPARC-NEXT: fbu .LBB4_2
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.1:
+; SPARC-NEXT: fmovs %f4, %f0
+; SPARC-NEXT: fmovs %f5, %f1
+; SPARC-NEXT: .LBB4_2:
+; SPARC-NEXT: fcmpd %f2, %f2
+; SPARC-NEXT: nop
+; SPARC-NEXT: fmovs %f0, %f4
+; SPARC-NEXT: fmovs %f1, %f5
+; SPARC-NEXT: fbo .LBB4_6
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.3:
+; SPARC-NEXT: fcmpd %f0, %f4
+; SPARC-NEXT: nop
+; SPARC-NEXT: fbule .LBB4_7
+; SPARC-NEXT: nop
+; SPARC-NEXT: .LBB4_4:
+; SPARC-NEXT: fcmpd %f0, %f0
+; SPARC-NEXT: nop
+; SPARC-NEXT: fbu .LBB4_8
+; SPARC-NEXT: nop
+; SPARC-NEXT: .LBB4_5:
+; SPARC-NEXT: retl
+; SPARC-NEXT: add %sp, 112, %sp
+; SPARC-NEXT: .LBB4_6:
+; SPARC-NEXT: fmovs %f2, %f4
+; SPARC-NEXT: fmovs %f3, %f5
+; SPARC-NEXT: fcmpd %f0, %f4
+; SPARC-NEXT: nop
+; SPARC-NEXT: fbg .LBB4_4
+; SPARC-NEXT: nop
+; SPARC-NEXT: .LBB4_7:
+; SPARC-NEXT: fmovs %f4, %f0
+; SPARC-NEXT: fmovs %f5, %f1
+; SPARC-NEXT: fcmpd %f0, %f0
+; SPARC-NEXT: nop
+; SPARC-NEXT: fbo .LBB4_5
+; SPARC-NEXT: nop
+; SPARC-NEXT: .LBB4_8:
+; SPARC-NEXT: faddd %f0, %f0, %f0
+; SPARC-NEXT: retl
+; SPARC-NEXT: add %sp, 112, %sp
+ %z = call nsz double @llvm.maximumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define double @maximumnum_double_nnan(double %x, double %y) {
+;
+; SPARC64-LABEL: maximumnum_double_nnan:
+; SPARC64: .cfi_startproc
+; SPARC64-NEXT: ! %bb.0:
+; SPARC64-NEXT: add %sp, -144, %sp
+; SPARC64-NEXT: .cfi_def_cfa_register %fp
+; SPARC64-NEXT: .cfi_window_save
+; SPARC64-NEXT: .cfi_register %o7, %i7
+; SPARC64-NEXT: std %f2, [%sp+2175]
+; SPARC64-NEXT: std %f0, [%sp+2183]
+; SPARC64-NEXT: ldx [%sp+2183], %o0
+; SPARC64-NEXT: mov %g0, %o1
+; SPARC64-NEXT: mov %g0, %o2
+; SPARC64-NEXT: movrz %o0, 1, %o1
+; SPARC64-NEXT: ldx [%sp+2175], %o0
+; SPARC64-NEXT: fcmpd %fcc0, %f0, %f2
+; SPARC64-NEXT: fmovd %f2, %f4
+; SPARC64-NEXT: fmovdg %fcc0, %f0, %f4
+; SPARC64-NEXT: cmp %o1, 0
+; SPARC64-NEXT: fmovd %f4, %f6
+; SPARC64-NEXT: fmovdne %icc, %f0, %f6
+; SPARC64-NEXT: sethi %h44(.LCPI5_0), %o1
+; SPARC64-NEXT: add %o1, %m44(.LCPI5_0), %o1
+; SPARC64-NEXT: sllx %o1, 12, %o1
+; SPARC64-NEXT: ldd [%o1+%l44(.LCPI5_0)], %f0
+; SPARC64-NEXT: movrz %o0, 1, %o2
+; SPARC64-NEXT: cmp %o2, 0
+; SPARC64-NEXT: fmovdne %icc, %f2, %f6
+; SPARC64-NEXT: fcmpd %fcc0, %f4, %f0
+; SPARC64-NEXT: fmovde %fcc0, %f6, %f4
+; SPARC64-NEXT: fmovd %f4, %f0
+; SPARC64-NEXT: retl
+; SPARC64-NEXT: add %sp, 144, %sp
+;
+; SPARC-LABEL: maximumnum_double_nnan:
+; SPARC: .cfi_startproc
+; SPARC-NEXT: ! %bb.0:
+; SPARC-NEXT: add %sp, -120, %sp
+; SPARC-NEXT: .cfi_def_cfa_register %fp
+; SPARC-NEXT: .cfi_window_save
+; SPARC-NEXT: .cfi_register %o7, %i7
+; SPARC-NEXT: ! kill: def $o1 killed $o1 killed $o0_o1 def $o0_o1
+; SPARC-NEXT: ! kill: def $o3 killed $o3 killed $o2_o3 def $o2_o3
+; SPARC-NEXT: ! kill: def $o0 killed $o0 killed $o0_o1 def $o0_o1
+; SPARC-NEXT: std %o0, [%sp+112]
+; SPARC-NEXT: ! kill: def $o2 killed $o2 killed $o2_o3 def $o2_o3
+; SPARC-NEXT: std %o2, [%sp+104]
+; SPARC-NEXT: ldd [%sp+104], %f0
+; SPARC-NEXT: ldd [%sp+112], %f2
+; SPARC-NEXT: fdtos %f0, %f4
+; SPARC-NEXT: st %f4, [%sp+96]
+; SPARC-NEXT: fdtos %f2, %f4
+; SPARC-NEXT: st %f4, [%sp+100]
+; SPARC-NEXT: ld [%sp+96], %o0
+; SPARC-NEXT: mov 1, %o1
+; SPARC-NEXT: cmp %o0, 0
+; SPARC-NEXT: be .LBB5_2
+; SPARC-NEXT: mov %o1, %o0
+; SPARC-NEXT: ! %bb.1:
+; SPARC-NEXT: mov %g0, %o0
+; SPARC-NEXT: .LBB5_2:
+; SPARC-NEXT: ld [%sp+100], %o2
+; SPARC-NEXT: cmp %o2, 0
+; SPARC-NEXT: be .LBB5_4
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.3:
+; SPARC-NEXT: mov %g0, %o1
+; SPARC-NEXT: .LBB5_4:
+; SPARC-NEXT: fcmpd %f2, %f0
+; SPARC-NEXT: nop
+; SPARC-NEXT: fmovs %f2, %f4
+; SPARC-NEXT: fmovs %f3, %f5
+; SPARC-NEXT: fbule .LBB5_11
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.5:
+; SPARC-NEXT: cmp %o1, 0
+; SPARC-NEXT: be .LBB5_12
+; SPARC-NEXT: nop
+; SPARC-NEXT: .LBB5_6:
+; SPARC-NEXT: cmp %o0, 0
+; SPARC-NEXT: bne .LBB5_8
+; SPARC-NEXT: nop
+; SPARC-NEXT: .LBB5_7:
+; SPARC-NEXT: fmovs %f2, %f0
+; SPARC-NEXT: fmovs %f3, %f1
+; SPARC-NEXT: .LBB5_8:
+; SPARC-NEXT: sethi %hi(.LCPI5_0), %o0
+; SPARC-NEXT: ldd [%o0+%lo(.LCPI5_0)], %f2
+; SPARC-NEXT: fcmpd %f4, %f2
+; SPARC-NEXT: nop
+; SPARC-NEXT: fbe .LBB5_10
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.9:
+; SPARC-NEXT: fmovs %f4, %f0
+; SPARC-NEXT: fmovs %f5, %f1
+; SPARC-NEXT: .LBB5_10:
+; SPARC-NEXT: retl
+; SPARC-NEXT: add %sp, 120, %sp
+; SPARC-NEXT: .LBB5_11:
+; SPARC-NEXT: fmovs %f0, %f4
+; SPARC-NEXT: fmovs %f1, %f5
+; SPARC-NEXT: cmp %o1, 0
+; SPARC-NEXT: bne .LBB5_6
+; SPARC-NEXT: nop
+; SPARC-NEXT: .LBB5_12:
+; SPARC-NEXT: fmovs %f4, %f2
+; SPARC-NEXT: fmovs %f5, %f3
+; SPARC-NEXT: cmp %o0, 0
+; SPARC-NEXT: be .LBB5_7
+; SPARC-NEXT: nop
+; SPARC-NEXT: ba .LBB5_8
+; SPARC-NEXT: nop
+ %z = call nnan double @llvm.maximumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define float @minimumnum_float(float %x, float %y) {
+;
+; SPARC64-LABEL: minimumnum_float:
+; SPARC64: .cfi_startproc
+; SPARC64-NEXT: ! %bb.0:
+; SPARC64-NEXT: add %sp, -144, %sp
+; SPARC64-NEXT: .cfi_def_cfa_register %fp
+; SPARC64-NEXT: .cfi_window_save
+; SPARC64-NEXT: .cfi_register %o7, %i7
+; SPARC64-NEXT: mov %g0, %o0
+; SPARC64-NEXT: mov %g0, %o1
+; SPARC64-NEXT: fcmps %fcc0, %f1, %f1
+; SPARC64-NEXT: fmovsu %fcc0, %f3, %f1
+; SPARC64-NEXT: st %f1, [%sp+2187]
+; SPARC64-NEXT: fcmps %fcc0, %f3, %f3
+; SPARC64-NEXT: fmovsu %fcc0, %f1, %f3
+; SPARC64-NEXT: st %f3, [%sp+2183]
+; SPARC64-NEXT: fcmps %fcc0, %f1, %f3
+; SPARC64-NEXT: fmovs %f3, %f0
+; SPARC64-NEXT: fmovsl %fcc0, %f1, %f0
+; SPARC64-NEXT: fadds %f0, %f0, %f2
+; SPARC64-NEXT: ld [%sp+2187], %o2
+; SPARC64-NEXT: fcmps %fcc0, %f0, %f0
+; SPARC64-NEXT: fmovsu %fcc0, %f2, %f0
+; SPARC64-NEXT: sethi 2097152, %o3
+; SPARC64-NEXT: cmp %o2, %o3
+; SPARC64-NEXT: ld [%sp+2183], %o2
+; SPARC64-NEXT: move %icc, 1, %o0
+; SPARC64-NEXT: cmp %o0, 0
+; SPARC64-NEXT: fmovs %f0, %f2
+; SPARC64-NEXT: fmovsne %icc, %f1, %f2
+; SPARC64-NEXT: cmp %o2, %o3
+; SPARC64-NEXT: sethi %h44(.LCPI6_0), %o0
+; SPARC64-NEXT: add %o0, %m44(.LCPI6_0), %o0
+; SPARC64-NEXT: sllx %o0, 12, %o0
+; SPARC64-NEXT: ld [%o0+%l44(.LCPI6_0)], %f1
+; SPARC64-NEXT: move %icc, 1, %o1
+; SPARC64-NEXT: cmp %o1, 0
+; SPARC64-NEXT: fmovsne %icc, %f3, %f2
+; SPARC64-NEXT: fcmps %fcc0, %f0, %f1
+; SPARC64-NEXT: fmovse %fcc0, %f2, %f0
+; SPARC64-NEXT: retl
+; SPARC64-NEXT: add %sp, 144, %sp
+;
+; SPARC-LABEL: minimumnum_float:
+; SPARC: .cfi_startproc
+; SPARC-NEXT: ! %bb.0:
+; SPARC-NEXT: add %sp, -112, %sp
+; SPARC-NEXT: .cfi_def_cfa_register %fp
+; SPARC-NEXT: .cfi_window_save
+; SPARC-NEXT: .cfi_register %o7, %i7
+; SPARC-NEXT: st %o0, [%sp+104]
+; SPARC-NEXT: st %o1, [%sp+108]
+; SPARC-NEXT: ld [%sp+104], %f0
+; SPARC-NEXT: ld [%sp+108], %f2
+; SPARC-NEXT: fcmps %f0, %f0
+; SPARC-NEXT: nop
+; SPARC-NEXT: fmovs %f2, %f1
+; SPARC-NEXT: fbu .LBB6_2
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.1:
+; SPARC-NEXT: fmovs %f0, %f1
+; SPARC-NEXT: .LBB6_2:
+; SPARC-NEXT: fcmps %f2, %f2
+; SPARC-NEXT: nop
+; SPARC-NEXT: st %f1, [%sp+100]
+; SPARC-NEXT: fmovs %f1, %f0
+; SPARC-NEXT: fbu .LBB6_4
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.3:
+; SPARC-NEXT: fmovs %f2, %f0
+; SPARC-NEXT: .LBB6_4:
+; SPARC-NEXT: st %f0, [%sp+96]
+; SPARC-NEXT: ld [%sp+100], %o2
+; SPARC-NEXT: sethi 2097152, %o1
+; SPARC-NEXT: mov 1, %o0
+; SPARC-NEXT: cmp %o2, %o1
+; SPARC-NEXT: be .LBB6_6
+; SPARC-NEXT: mov %o0, %o2
+; SPARC-NEXT: ! %bb.5:
+; SPARC-NEXT: mov %g0, %o2
+; SPARC-NEXT: .LBB6_6:
+; SPARC-NEXT: fcmps %f1, %f0
+; SPARC-NEXT: nop
+; SPARC-NEXT: fmovs %f1, %f2
+; SPARC-NEXT: fbuge .LBB6_17
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.7:
+; SPARC-NEXT: fcmps %f2, %f2
+; SPARC-NEXT: nop
+; SPARC-NEXT: fbu .LBB6_18
+; SPARC-NEXT: nop
+; SPARC-NEXT: .LBB6_8:
+; SPARC-NEXT: cmp %o2, 0
+; SPARC-NEXT: bne .LBB6_10
+; SPARC-NEXT: nop
+; SPARC-NEXT: .LBB6_9:
+; SPARC-NEXT: fmovs %f2, %f1
+; SPARC-NEXT: .LBB6_10:
+; SPARC-NEXT: ld [%sp+96], %o2
+; SPARC-NEXT: cmp %o2, %o1
+; SPARC-NEXT: be .LBB6_12
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.11:
+; SPARC-NEXT: mov %g0, %o0
+; SPARC-NEXT: .LBB6_12:
+; SPARC-NEXT: cmp %o0, 0
+; SPARC-NEXT: bne .LBB6_14
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.13:
+; SPARC-NEXT: fmovs %f1, %f0
+; SPARC-NEXT: .LBB6_14:
+; SPARC-NEXT: sethi %hi(.LCPI6_0), %o0
+; SPARC-NEXT: ld [%o0+%lo(.LCPI6_0)], %f1
+; SPARC-NEXT: fcmps %f2, %f1
+; SPARC-NEXT: nop
+; SPARC-NEXT: fbe .LBB6_16
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.15:
+; SPARC-NEXT: fmovs %f2, %f0
+; SPARC-NEXT: .LBB6_16:
+; SPARC-NEXT: retl
+; SPARC-NEXT: add %sp, 112, %sp
+; SPARC-NEXT: .LBB6_17:
+; SPARC-NEXT: fmovs %f0, %f2
+; SPARC-NEXT: fcmps %f2, %f2
+; SPARC-NEXT: nop
+; SPARC-NEXT: fbo .LBB6_8
+; SPARC-NEXT: nop
+; SPARC-NEXT: .LBB6_18:
+; SPARC-NEXT: cmp %o2, 0
+; SPARC-NEXT: be .LBB6_9
+; SPARC-NEXT: fadds %f2, %f2, %f2
+; SPARC-NEXT: ba .LBB6_10
+; SPARC-NEXT: nop
+ %z = call float @llvm.minimumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+define float @minimumnum_float_nsz(float %x, float %y) {
+;
+; SPARC64-LABEL: minimumnum_float_nsz:
+; SPARC64: .cfi_startproc
+; SPARC64-NEXT: ! %bb.0:
+; SPARC64-NEXT: fmovs %f3, %f0
+; SPARC64-NEXT: fcmps %fcc0, %f1, %f1
+; SPARC64-NEXT: fmovsu %fcc0, %f3, %f1
+; SPARC64-NEXT: fcmps %fcc0, %f3, %f3
+; SPARC64-NEXT: fmovsu %fcc0, %f1, %f0
+; SPARC64-NEXT: fcmps %fcc0, %f1, %f0
+; SPARC64-NEXT: fmovsl %fcc0, %f1, %f0
+; SPARC64-NEXT: fadds %f0, %f0, %f1
+; SPARC64-NEXT: fcmps %fcc0, %f0, %f0
+; SPARC64-NEXT: retl
+; SPARC64-NEXT: fmovsu %fcc0, %f1, %f0
+;
+; SPARC-LABEL: minimumnum_float_nsz:
+; SPARC: .cfi_startproc
+; SPARC-NEXT: ! %bb.0:
+; SPARC-NEXT: add %sp, -104, %sp
+; SPARC-NEXT: .cfi_def_cfa_register %fp
+; SPARC-NEXT: .cfi_window_save
+; SPARC-NEXT: .cfi_register %o7, %i7
+; SPARC-NEXT: st %o0, [%sp+96]
+; SPARC-NEXT: st %o1, [%sp+100]
+; SPARC-NEXT: ld [%sp+96], %f2
+; SPARC-NEXT: ld [%sp+100], %f1
+; SPARC-NEXT: fcmps %f2, %f2
+; SPARC-NEXT: nop
+; SPARC-NEXT: fmovs %f1, %f0
+; SPARC-NEXT: fbu .LBB7_2
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.1:
+; SPARC-NEXT: fmovs %f2, %f0
+; SPARC-NEXT: .LBB7_2:
+; SPARC-NEXT: fcmps %f1, %f1
+; SPARC-NEXT: nop
+; SPARC-NEXT: fmovs %f0, %f2
+; SPARC-NEXT: fbo .LBB7_6
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.3:
+; SPARC-NEXT: fcmps %f0, %f2
+; SPARC-NEXT: nop
+; SPARC-NEXT: fbuge .LBB7_7
+; SPARC-NEXT: nop
+; SPARC-NEXT: .LBB7_4:
+; SPARC-NEXT: fcmps %f0, %f0
+; SPARC-NEXT: nop
+; SPARC-NEXT: fbu .LBB7_8
+; SPARC-NEXT: nop
+; SPARC-NEXT: .LBB7_5:
+; SPARC-NEXT: retl
+; SPARC-NEXT: add %sp, 104, %sp
+; SPARC-NEXT: .LBB7_6:
+; SPARC-NEXT: fmovs %f1, %f2
+; SPARC-NEXT: fcmps %f0, %f2
+; SPARC-NEXT: nop
+; SPARC-NEXT: fbl .LBB7_4
+; SPARC-NEXT: nop
+; SPARC-NEXT: .LBB7_7:
+; SPARC-NEXT: fmovs %f2, %f0
+; SPARC-NEXT: fcmps %f0, %f0
+; SPARC-NEXT: nop
+; SPARC-NEXT: fbo .LBB7_5
+; SPARC-NEXT: nop
+; SPARC-NEXT: .LBB7_8:
+; SPARC-NEXT: fadds %f0, %f0, %f0
+; SPARC-NEXT: retl
+; SPARC-NEXT: add %sp, 104, %sp
+ %z = call nsz float @llvm.minimumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+define float @minimumnum_float_nnan(float %x, float %y) {
+;
+; SPARC64-LABEL: minimumnum_float_nnan:
+; SPARC64: .cfi_startproc
+; SPARC64-NEXT: ! %bb.0:
+; SPARC64-NEXT: add %sp, -144, %sp
+; SPARC64-NEXT: .cfi_def_cfa_register %fp
+; SPARC64-NEXT: .cfi_window_save
+; SPARC64-NEXT: .cfi_register %o7, %i7
+; SPARC64-NEXT: st %f1, [%sp+2187]
+; SPARC64-NEXT: st %f3, [%sp+2183]
+; SPARC64-NEXT: ld [%sp+2183], %o0
+; SPARC64-NEXT: mov %g0, %o1
+; SPARC64-NEXT: mov %g0, %o2
+; SPARC64-NEXT: ld [%sp+2187], %o3
+; SPARC64-NEXT: sethi 2097152, %o4
+; SPARC64-NEXT: cmp %o0, %o4
+; SPARC64-NEXT: move %icc, 1, %o1
+; SPARC64-NEXT: cmp %o3, %o4
+; SPARC64-NEXT: move %icc, 1, %o2
+; SPARC64-NEXT: fcmps %fcc0, %f1, %f3
+; SPARC64-NEXT: fmovs %f3, %f0
+; SPARC64-NEXT: fmovsl %fcc0, %f1, %f0
+; SPARC64-NEXT: cmp %o2, 0
+; SPARC64-NEXT: fmovs %f0, %f2
+; SPARC64-NEXT: sethi %h44(.LCPI8_0), %o0
+; SPARC64-NEXT: add %o0, %m44(.LCPI8_0), %o0
+; SPARC64-NEXT: sllx %o0, 12, %o0
+; SPARC64-NEXT: ld [%o0+%l44(.LCPI8_0)], %f4
+; SPARC64-NEXT: fmovsne %icc, %f1, %f2
+; SPARC64-NEXT: cmp %o1, 0
+; SPARC64-NEXT: fmovsne %icc, %f3, %f2
+; SPARC64-NEXT: fcmps %fcc0, %f0, %f4
+; SPARC64-NEXT: fmovse %fcc0, %f2, %f0
+; SPARC64-NEXT: retl
+; SPARC64-NEXT: add %sp, 144, %sp
+;
+; SPARC-LABEL: minimumnum_float_nnan:
+; SPARC: .cfi_startproc
+; SPARC-NEXT: ! %bb.0:
+; SPARC-NEXT: add %sp, -112, %sp
+; SPARC-NEXT: .cfi_def_cfa_register %fp
+; SPARC-NEXT: .cfi_window_save
+; SPARC-NEXT: .cfi_register %o7, %i7
+; SPARC-NEXT: st %o0, [%sp+104]
+; SPARC-NEXT: st %o1, [%sp+108]
+; SPARC-NEXT: ld [%sp+104], %f1
+; SPARC-NEXT: st %f1, [%sp+100]
+; SPARC-NEXT: ld [%sp+108], %f0
+; SPARC-NEXT: st %f0, [%sp+96]
+; SPARC-NEXT: ld [%sp+96], %o0
+; SPARC-NEXT: ld [%sp+100], %o2
+; SPARC-NEXT: sethi 2097152, %o3
+; SPARC-NEXT: mov 1, %o1
+; SPARC-NEXT: cmp %o0, %o3
+; SPARC-NEXT: be .LBB8_2
+; SPARC-NEXT: mov %o1, %o0
+; SPARC-NEXT: ! %bb.1:
+; SPARC-NEXT: mov %g0, %o0
+; SPARC-NEXT: .LBB8_2:
+; SPARC-NEXT: cmp %o2, %o3
+; SPARC-NEXT: be .LBB8_4
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.3:
+; SPARC-NEXT: mov %g0, %o1
+; SPARC-NEXT: .LBB8_4:
+; SPARC-NEXT: fcmps %f1, %f0
+; SPARC-NEXT: nop
+; SPARC-NEXT: fmovs %f1, %f2
+; SPARC-NEXT: fbuge .LBB8_11
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.5:
+; SPARC-NEXT: cmp %o1, 0
+; SPARC-NEXT: be .LBB8_12
+; SPARC-NEXT: nop
+; SPARC-NEXT: .LBB8_6:
+; SPARC-NEXT: cmp %o0, 0
+; SPARC-NEXT: bne .LBB8_8
+; SPARC-NEXT: nop
+; SPARC-NEXT: .LBB8_7:
+; SPARC-NEXT: fmovs %f1, %f0
+; SPARC-NEXT: .LBB8_8:
+; SPARC-NEXT: sethi %hi(.LCPI8_0), %o0
+; SPARC-NEXT: ld [%o0+%lo(.LCPI8_0)], %f1
+; SPARC-NEXT: fcmps %f2, %f1
+; SPARC-NEXT: nop
+; SPARC-NEXT: fbe .LBB8_10
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.9:
+; SPARC-NEXT: fmovs %f2, %f0
+; SPARC-NEXT: .LBB8_10:
+; SPARC-NEXT: retl
+; SPARC-NEXT: add %sp, 112, %sp
+; SPARC-NEXT: .LBB8_11:
+; SPARC-NEXT: fmovs %f0, %f2
+; SPARC-NEXT: cmp %o1, 0
+; SPARC-NEXT: bne .LBB8_6
+; SPARC-NEXT: nop
+; SPARC-NEXT: .LBB8_12:
+; SPARC-NEXT: fmovs %f2, %f1
+; SPARC-NEXT: cmp %o0, 0
+; SPARC-NEXT: be .LBB8_7
+; SPARC-NEXT: nop
+; SPARC-NEXT: ba .LBB8_8
+; SPARC-NEXT: nop
+ %z = call nnan float @llvm.minimumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+define double @minimumnum_double(double %x, double %y) {
+;
+; SPARC64-LABEL: minimumnum_double:
+; SPARC64: .cfi_startproc
+; SPARC64-NEXT: ! %bb.0:
+; SPARC64-NEXT: add %sp, -144, %sp
+; SPARC64-NEXT: .cfi_def_cfa_register %fp
+; SPARC64-NEXT: .cfi_window_save
+; SPARC64-NEXT: .cfi_register %o7, %i7
+; SPARC64-NEXT: mov %g0, %o0
+; SPARC64-NEXT: mov %g0, %o1
+; SPARC64-NEXT: fcmpd %fcc0, %f0, %f0
+; SPARC64-NEXT: fmovdu %fcc0, %f2, %f0
+; SPARC64-NEXT: std %f0, [%sp+2183]
+; SPARC64-NEXT: fcmpd %fcc0, %f2, %f2
+; SPARC64-NEXT: fmovdu %fcc0, %f0, %f2
+; SPARC64-NEXT: std %f2, [%sp+2175]
+; SPARC64-NEXT: fcmpd %fcc0, %f0, %f2
+; SPARC64-NEXT: fmovd %f2, %f4
+; SPARC64-NEXT: fmovdl %fcc0, %f0, %f4
+; SPARC64-NEXT: sethi 0, %o2
+; SPARC64-NEXT: or %o2, 0, %o2
+; SPARC64-NEXT: sethi 2097152, %o3
+; SPARC64-NEXT: or %o3, 0, %o3
+; SPARC64-NEXT: sllx %o3, 32, %o3
+; SPARC64-NEXT: or %o3, %o2, %o2
+; SPARC64-NEXT: ldx [%sp+2183], %o3
+; SPARC64-NEXT: faddd %f4, %f4, %f6
+; SPARC64-NEXT: fcmpd %fcc0, %f4, %f4
+; SPARC64-NEXT: fmovdu %fcc0, %f6, %f4
+; SPARC64-NEXT: cmp %o3, %o2
+; SPARC64-NEXT: ldx [%sp+2175], %o3
+; SPARC64-NEXT: move %xcc, 1, %o0
+; SPARC64-NEXT: cmp %o0, 0
+; SPARC64-NEXT: fmovd %f4, %f6
+; SPARC64-NEXT: fmovdne %icc, %f0, %f6
+; SPARC64-NEXT: cmp %o3, %o2
+; SPARC64-NEXT: sethi %h44(.LCPI9_0), %o0
+; SPARC64-NEXT: add %o0, %m44(.LCPI9_0), %o0
+; SPARC64-NEXT: sllx %o0, 12, %o0
+; SPARC64-NEXT: ldd [%o0+%l44(.LCPI9_0)], %f0
+; SPARC64-NEXT: move %xcc, 1, %o1
+; SPARC64-NEXT: cmp %o1, 0
+; SPARC64-NEXT: fmovdne %icc, %f2, %f6
+; SPARC64-NEXT: fcmpd %fcc0, %f4, %f0
+; SPARC64-NEXT: fmovde %fcc0, %f6, %f4
+; SPARC64-NEXT: fmovd %f4, %f0
+; SPARC64-NEXT: retl
+; SPARC64-NEXT: add %sp, 144, %sp
+;
+; SPARC-LABEL: minimumnum_double:
+; SPARC: .cfi_startproc
+; SPARC-NEXT: ! %bb.0:
+; SPARC-NEXT: add %sp, -120, %sp
+; SPARC-NEXT: .cfi_def_cfa_register %fp
+; SPARC-NEXT: .cfi_window_save
+; SPARC-NEXT: .cfi_register %o7, %i7
+; SPARC-NEXT: ! kill: def $o1 killed $o1 killed $o0_o1 def $o0_o1
+; SPARC-NEXT: ! kill: def $o3 killed $o3 killed $o2_o3 def $o2_o3
+; SPARC-NEXT: ! kill: def $o0 killed $o0 killed $o0_o1 def $o0_o1
+; SPARC-NEXT: std %o0, [%sp+112]
+; SPARC-NEXT: ! kill: def $o2 killed $o2 killed $o2_o3 def $o2_o3
+; SPARC-NEXT: std %o2, [%sp+104]
+; SPARC-NEXT: ldd [%sp+112], %f0
+; SPARC-NEXT: ldd [%sp+104], %f4
+; SPARC-NEXT: fcmpd %f0, %f0
+; SPARC-NEXT: nop
+; SPARC-NEXT: fmovs %f4, %f2
+; SPARC-NEXT: fmovs %f5, %f3
+; SPARC-NEXT: fbu .LBB9_2
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.1:
+; SPARC-NEXT: fmovs %f0, %f2
+; SPARC-NEXT: fmovs %f1, %f3
+; SPARC-NEXT: .LBB9_2:
+; SPARC-NEXT: fdtos %f2, %f0
+; SPARC-NEXT: fcmpd %f4, %f4
+; SPARC-NEXT: nop
+; SPARC-NEXT: st %f0, [%sp+100]
+; SPARC-NEXT: fmovs %f2, %f0
+; SPARC-NEXT: fmovs %f3, %f1
+; SPARC-NEXT: fbu .LBB9_4
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.3:
+; SPARC-NEXT: fmovs %f4, %f0
+; SPARC-NEXT: fmovs %f5, %f1
+; SPARC-NEXT: .LBB9_4:
+; SPARC-NEXT: fdtos %f0, %f4
+; SPARC-NEXT: st %f4, [%sp+96]
+; SPARC-NEXT: ld [%sp+100], %o2
+; SPARC-NEXT: sethi 2097152, %o1
+; SPARC-NEXT: mov 1, %o0
+; SPARC-NEXT: cmp %o2, %o1
+; SPARC-NEXT: be .LBB9_6
+; SPARC-NEXT: mov %o0, %o2
+; SPARC-NEXT: ! %bb.5:
+; SPARC-NEXT: mov %g0, %o2
+; SPARC-NEXT: .LBB9_6:
+; SPARC-NEXT: fcmpd %f2, %f0
+; SPARC-NEXT: nop
+; SPARC-NEXT: fmovs %f2, %f4
+; SPARC-NEXT: fmovs %f3, %f5
+; SPARC-NEXT: fbuge .LBB9_17
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.7:
+; SPARC-NEXT: fcmpd %f4, %f4
+; SPARC-NEXT: nop
+; SPARC-NEXT: fbu .LBB9_18
+; SPARC-NEXT: nop
+; SPARC-NEXT: .LBB9_8:
+; SPARC-NEXT: cmp %o2, 0
+; SPARC-NEXT: bne .LBB9_10
+; SPARC-NEXT: nop
+; SPARC-NEXT: .LBB9_9:
+; SPARC-NEXT: fmovs %f4, %f2
+; SPARC-NEXT: fmovs %f5, %f3
+; SPARC-NEXT: .LBB9_10:
+; SPARC-NEXT: ld [%sp+96], %o2
+; SPARC-NEXT: cmp %o2, %o1
+; SPARC-NEXT: be .LBB9_12
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.11:
+; SPARC-NEXT: mov %g0, %o0
+; SPARC-NEXT: .LBB9_12:
+; SPARC-NEXT: cmp %o0, 0
+; SPARC-NEXT: bne .LBB9_14
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.13:
+; SPARC-NEXT: fmovs %f2, %f0
+; SPARC-NEXT: fmovs %f3, %f1
+; SPARC-NEXT: .LBB9_14:
+; SPARC-NEXT: sethi %hi(.LCPI9_0), %o0
+; SPARC-NEXT: ldd [%o0+%lo(.LCPI9_0)], %f2
+; SPARC-NEXT: fcmpd %f4, %f2
+; SPARC-NEXT: nop
+; SPARC-NEXT: fbe .LBB9_16
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.15:
+; SPARC-NEXT: fmovs %f4, %f0
+; SPARC-NEXT: fmovs %f5, %f1
+; SPARC-NEXT: .LBB9_16:
+; SPARC-NEXT: retl
+; SPARC-NEXT: add %sp, 120, %sp
+; SPARC-NEXT: .LBB9_17:
+; SPARC-NEXT: fmovs %f0, %f4
+; SPARC-NEXT: fmovs %f1, %f5
+; SPARC-NEXT: fcmpd %f4, %f4
+; SPARC-NEXT: nop
+; SPARC-NEXT: fbo .LBB9_8
+; SPARC-NEXT: nop
+; SPARC-NEXT: .LBB9_18:
+; SPARC-NEXT: cmp %o2, 0
+; SPARC-NEXT: be .LBB9_9
+; SPARC-NEXT: faddd %f4, %f4, %f4
+; SPARC-NEXT: ba .LBB9_10
+; SPARC-NEXT: nop
+ %z = call double @llvm.minimumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define double @minimumnum_double_nsz(double %x, double %y) {
+;
+; SPARC64-LABEL: minimumnum_double_nsz:
+; SPARC64: .cfi_startproc
+; SPARC64-NEXT: ! %bb.0:
+; SPARC64-NEXT: fcmpd %fcc0, %f0, %f0
+; SPARC64-NEXT: fmovdu %fcc0, %f2, %f0
+; SPARC64-NEXT: fcmpd %fcc0, %f2, %f2
+; SPARC64-NEXT: fmovdu %fcc0, %f0, %f2
+; SPARC64-NEXT: fcmpd %fcc0, %f0, %f2
+; SPARC64-NEXT: fmovdl %fcc0, %f0, %f2
+; SPARC64-NEXT: faddd %f2, %f2, %f0
+; SPARC64-NEXT: fcmpd %fcc0, %f2, %f2
+; SPARC64-NEXT: fmovdu %fcc0, %f0, %f2
+; SPARC64-NEXT: fmovd %f2, %f0
+; SPARC64-NEXT: retl
+; SPARC64-NEXT: nop
+;
+; SPARC-LABEL: minimumnum_double_nsz:
+; SPARC: .cfi_startproc
+; SPARC-NEXT: ! %bb.0:
+; SPARC-NEXT: add %sp, -112, %sp
+; SPARC-NEXT: .cfi_def_cfa_register %fp
+; SPARC-NEXT: .cfi_window_save
+; SPARC-NEXT: .cfi_register %o7, %i7
+; SPARC-NEXT: ! kill: def $o1 killed $o1 killed $o0_o1 def $o0_o1
+; SPARC-NEXT: ! kill: def $o3 killed $o3 killed $o2_o3 def $o2_o3
+; SPARC-NEXT: ! kill: def $o0 killed $o0 killed $o0_o1 def $o0_o1
+; SPARC-NEXT: std %o0, [%sp+104]
+; SPARC-NEXT: ! kill: def $o2 killed $o2 killed $o2_o3 def $o2_o3
+; SPARC-NEXT: std %o2, [%sp+96]
+; SPARC-NEXT: ldd [%sp+104], %f4
+; SPARC-NEXT: ldd [%sp+96], %f2
+; SPARC-NEXT: fcmpd %f4, %f4
+; SPARC-NEXT: nop
+; SPARC-NEXT: fmovs %f2, %f0
+; SPARC-NEXT: fmovs %f3, %f1
+; SPARC-NEXT: fbu .LBB10_2
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.1:
+; SPARC-NEXT: fmovs %f4, %f0
+; SPARC-NEXT: fmovs %f5, %f1
+; SPARC-NEXT: .LBB10_2:
+; SPARC-NEXT: fcmpd %f2, %f2
+; SPARC-NEXT: nop
+; SPARC-NEXT: fmovs %f0, %f4
+; SPARC-NEXT: fmovs %f1, %f5
+; SPARC-NEXT: fbo .LBB10_6
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.3:
+; SPARC-NEXT: fcmpd %f0, %f4
+; SPARC-NEXT: nop
+; SPARC-NEXT: fbuge .LBB10_7
+; SPARC-NEXT: nop
+; SPARC-NEXT: .LBB10_4:
+; SPARC-NEXT: fcmpd %f0, %f0
+; SPARC-NEXT: nop
+; SPARC-NEXT: fbu .LBB10_8
+; SPARC-NEXT: nop
+; SPARC-NEXT: .LBB10_5:
+; SPARC-NEXT: retl
+; SPARC-NEXT: add %sp, 112, %sp
+; SPARC-NEXT: .LBB10_6:
+; SPARC-NEXT: fmovs %f2, %f4
+; SPARC-NEXT: fmovs %f3, %f5
+; SPARC-NEXT: fcmpd %f0, %f4
+; SPARC-NEXT: nop
+; SPARC-NEXT: fbl .LBB10_4
+; SPARC-NEXT: nop
+; SPARC-NEXT: .LBB10_7:
+; SPARC-NEXT: fmovs %f4, %f0
+; SPARC-NEXT: fmovs %f5, %f1
+; SPARC-NEXT: fcmpd %f0, %f0
+; SPARC-NEXT: nop
+; SPARC-NEXT: fbo .LBB10_5
+; SPARC-NEXT: nop
+; SPARC-NEXT: .LBB10_8:
+; SPARC-NEXT: faddd %f0, %f0, %f0
+; SPARC-NEXT: retl
+; SPARC-NEXT: add %sp, 112, %sp
+ %z = call nsz double @llvm.minimumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define double @minimumnum_double_nnan(double %x, double %y) {
+;
+; SPARC64-LABEL: minimumnum_double_nnan:
+; SPARC64: .cfi_startproc
+; SPARC64-NEXT: ! %bb.0:
+; SPARC64-NEXT: add %sp, -144, %sp
+; SPARC64-NEXT: .cfi_def_cfa_register %fp
+; SPARC64-NEXT: .cfi_window_save
+; SPARC64-NEXT: .cfi_register %o7, %i7
+; SPARC64-NEXT: mov %g0, %o0
+; SPARC64-NEXT: mov %g0, %o1
+; SPARC64-NEXT: std %f2, [%sp+2175]
+; SPARC64-NEXT: std %f0, [%sp+2183]
+; SPARC64-NEXT: ldx [%sp+2183], %o2
+; SPARC64-NEXT: sethi 0, %o3
+; SPARC64-NEXT: or %o3, 0, %o3
+; SPARC64-NEXT: sethi 2097152, %o4
+; SPARC64-NEXT: or %o4, 0, %o4
+; SPARC64-NEXT: sllx %o4, 32, %o4
+; SPARC64-NEXT: or %o4, %o3, %o3
+; SPARC64-NEXT: cmp %o2, %o3
+; SPARC64-NEXT: ldx [%sp+2175], %o2
+; SPARC64-NEXT: move %xcc, 1, %o0
+; SPARC64-NEXT: fcmpd %fcc0, %f0, %f2
+; SPARC64-NEXT: fmovd %f2, %f4
+; SPARC64-NEXT: fmovdl %fcc0, %f0, %f4
+; SPARC64-NEXT: cmp %o0, 0
+; SPARC64-NEXT: fmovd %f4, %f6
+; SPARC64-NEXT: fmovdne %icc, %f0, %f6
+; SPARC64-NEXT: cmp %o2, %o3
+; SPARC64-NEXT: sethi %h44(.LCPI11_0), %o0
+; SPARC64-NEXT: add %o0, %m44(.LCPI11_0), %o0
+; SPARC64-NEXT: sllx %o0, 12, %o0
+; SPARC64-NEXT: ldd [%o0+%l44(.LCPI11_0)], %f0
+; SPARC64-NEXT: move %xcc, 1, %o1
+; SPARC64-NEXT: cmp %o1, 0
+; SPARC64-NEXT: fmovdne %icc, %f2, %f6
+; SPARC64-NEXT: fcmpd %fcc0, %f4, %f0
+; SPARC64-NEXT: fmovde %fcc0, %f6, %f4
+; SPARC64-NEXT: fmovd %f4, %f0
+; SPARC64-NEXT: retl
+; SPARC64-NEXT: add %sp, 144, %sp
+;
+; SPARC-LABEL: minimumnum_double_nnan:
+; SPARC: .cfi_startproc
+; SPARC-NEXT: ! %bb.0:
+; SPARC-NEXT: add %sp, -120, %sp
+; SPARC-NEXT: .cfi_def_cfa_register %fp
+; SPARC-NEXT: .cfi_window_save
+; SPARC-NEXT: .cfi_register %o7, %i7
+; SPARC-NEXT: ! kill: def $o1 killed $o1 killed $o0_o1 def $o0_o1
+; SPARC-NEXT: ! kill: def $o3 killed $o3 killed $o2_o3 def $o2_o3
+; SPARC-NEXT: ! kill: def $o0 killed $o0 killed $o0_o1 def $o0_o1
+; SPARC-NEXT: std %o0, [%sp+112]
+; SPARC-NEXT: ! kill: def $o2 killed $o2 killed $o2_o3 def $o2_o3
+; SPARC-NEXT: std %o2, [%sp+104]
+; SPARC-NEXT: ldd [%sp+104], %f0
+; SPARC-NEXT: ldd [%sp+112], %f2
+; SPARC-NEXT: fdtos %f0, %f4
+; SPARC-NEXT: st %f4, [%sp+96]
+; SPARC-NEXT: fdtos %f2, %f4
+; SPARC-NEXT: st %f4, [%sp+100]
+; SPARC-NEXT: ld [%sp+96], %o0
+; SPARC-NEXT: sethi 2097152, %o2
+; SPARC-NEXT: mov 1, %o1
+; SPARC-NEXT: cmp %o0, %o2
+; SPARC-NEXT: be .LBB11_2
+; SPARC-NEXT: mov %o1, %o0
+; SPARC-NEXT: ! %bb.1:
+; SPARC-NEXT: mov %g0, %o0
+; SPARC-NEXT: .LBB11_2:
+; SPARC-NEXT: ld [%sp+100], %o3
+; SPARC-NEXT: cmp %o3, %o2
+; SPARC-NEXT: be .LBB11_4
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.3:
+; SPARC-NEXT: mov %g0, %o1
+; SPARC-NEXT: .LBB11_4:
+; SPARC-NEXT: fcmpd %f2, %f0
+; SPARC-NEXT: nop
+; SPARC-NEXT: fmovs %f2, %f4
+; SPARC-NEXT: fmovs %f3, %f5
+; SPARC-NEXT: fbuge .LBB11_11
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.5:
+; SPARC-NEXT: cmp %o1, 0
+; SPARC-NEXT: be .LBB11_12
+; SPARC-NEXT: nop
+; SPARC-NEXT: .LBB11_6:
+; SPARC-NEXT: cmp %o0, 0
+; SPARC-NEXT: bne .LBB11_8
+; SPARC-NEXT: nop
+; SPARC-NEXT: .LBB11_7:
+; SPARC-NEXT: fmovs %f2, %f0
+; SPARC-NEXT: fmovs %f3, %f1
+; SPARC-NEXT: .LBB11_8:
+; SPARC-NEXT: sethi %hi(.LCPI11_0), %o0
+; SPARC-NEXT: ldd [%o0+%lo(.LCPI11_0)], %f2
+; SPARC-NEXT: fcmpd %f4, %f2
+; SPARC-NEXT: nop
+; SPARC-NEXT: fbe .LBB11_10
+; SPARC-NEXT: nop
+; SPARC-NEXT: ! %bb.9:
+; SPARC-NEXT: fmovs %f4, %f0
+; SPARC-NEXT: fmovs %f5, %f1
+; SPARC-NEXT: .LBB11_10:
+; SPARC-NEXT: retl
+; SPARC-NEXT: add %sp, 120, %sp
+; SPARC-NEXT: .LBB11_11:
+; SPARC-NEXT: fmovs %f0, %f4
+; SPARC-NEXT: fmovs %f1, %f5
+; SPARC-NEXT: cmp %o1, 0
+; SPARC-NEXT: bne .LBB11_6
+; SPARC-NEXT: nop
+; SPARC-NEXT: .LBB11_12:
+; SPARC-NEXT: fmovs %f4, %f2
+; SPARC-NEXT: fmovs %f5, %f3
+; SPARC-NEXT: cmp %o0, 0
+; SPARC-NEXT: be .LBB11_7
+; SPARC-NEXT: nop
+; SPARC-NEXT: ba .LBB11_8
+; SPARC-NEXT: nop
+ %z = call nnan double @llvm.minimumnum.f64(double %x, double %y)
+ ret double %z
+}
diff --git a/llvm/test/CodeGen/SystemZ/fp-maximumnum-minimumnum.ll b/llvm/test/CodeGen/SystemZ/fp-maximumnum-minimumnum.ll
new file mode 100644
index 00000000000000..41fc01fcfbd586
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/fp-maximumnum-minimumnum.ll
@@ -0,0 +1,500 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc --mtriple=s390x < %s | FileCheck %s --check-prefix=S390X
+
+declare float @llvm.maximumnum.f32(float, float)
+declare double @llvm.maximumnum.f64(double, double)
+declare float @llvm.minimumnum.f32(float, float)
+declare double @llvm.minimumnum.f64(double, double)
+
+define float @maximumnum_float(float %x, float %y) {
+;
+;
+; S390X-LABEL: maximumnum_float:
+; S390X: # %bb.0:
+; S390X-NEXT: cebr %f0, %f0
+; S390X-NEXT: ler %f1, %f2
+; S390X-NEXT: jo .LBB0_2
+; S390X-NEXT: # %bb.1:
+; S390X-NEXT: ler %f1, %f0
+; S390X-NEXT: .LBB0_2:
+; S390X-NEXT: cebr %f2, %f2
+; S390X-NEXT: ler %f0, %f1
+; S390X-NEXT: jo .LBB0_4
+; S390X-NEXT: # %bb.3:
+; S390X-NEXT: ler %f0, %f2
+; S390X-NEXT: .LBB0_4:
+; S390X-NEXT: cebr %f1, %f0
+; S390X-NEXT: ler %f2, %f1
+; S390X-NEXT: jh .LBB0_6
+; S390X-NEXT: # %bb.5:
+; S390X-NEXT: ler %f2, %f0
+; S390X-NEXT: .LBB0_6:
+; S390X-NEXT: cebr %f2, %f2
+; S390X-NEXT: jno .LBB0_8
+; S390X-NEXT: # %bb.7:
+; S390X-NEXT: aebr %f2, %f2
+; S390X-NEXT: .LBB0_8:
+; S390X-NEXT: tceb %f1, 2048
+; S390X-NEXT: ipm %r0
+; S390X-NEXT: srl %r0, 28
+; S390X-NEXT: cijlh %r0, 0, .LBB0_10
+; S390X-NEXT: # %bb.9:
+; S390X-NEXT: ler %f1, %f2
+; S390X-NEXT: .LBB0_10:
+; S390X-NEXT: tceb %f0, 2048
+; S390X-NEXT: ipm %r0
+; S390X-NEXT: srl %r0, 28
+; S390X-NEXT: cijlh %r0, 0, .LBB0_12
+; S390X-NEXT: # %bb.11:
+; S390X-NEXT: ler %f0, %f1
+; S390X-NEXT: .LBB0_12:
+; S390X-NEXT: ltebr %f1, %f2
+; S390X-NEXT: ber %r14
+; S390X-NEXT: .LBB0_13:
+; S390X-NEXT: ler %f0, %f2
+; S390X-NEXT: br %r14
+ %z = call float @llvm.maximumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+define float @maximumnum_float_nsz(float %x, float %y) {
+;
+;
+; S390X-LABEL: maximumnum_float_nsz:
+; S390X: # %bb.0:
+; S390X-NEXT: ler %f1, %f0
+; S390X-NEXT: cebr %f0, %f0
+; S390X-NEXT: ler %f0, %f2
+; S390X-NEXT: jo .LBB1_2
+; S390X-NEXT: # %bb.1:
+; S390X-NEXT: ler %f0, %f1
+; S390X-NEXT: .LBB1_2:
+; S390X-NEXT: cebr %f2, %f2
+; S390X-NEXT: ler %f1, %f0
+; S390X-NEXT: jo .LBB1_4
+; S390X-NEXT: # %bb.3:
+; S390X-NEXT: ler %f1, %f2
+; S390X-NEXT: .LBB1_4:
+; S390X-NEXT: cebr %f0, %f1
+; S390X-NEXT: jh .LBB1_6
+; S390X-NEXT: # %bb.5:
+; S390X-NEXT: ler %f0, %f1
+; S390X-NEXT: .LBB1_6:
+; S390X-NEXT: cebr %f0, %f0
+; S390X-NEXT: bnor %r14
+; S390X-NEXT: .LBB1_7:
+; S390X-NEXT: aebr %f0, %f0
+; S390X-NEXT: br %r14
+ %z = call nsz float @llvm.maximumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+define float @maximumnum_float_nnan(float %x, float %y) {
+;
+;
+; S390X-LABEL: maximumnum_float_nnan:
+; S390X: # %bb.0:
+; S390X-NEXT: cebr %f0, %f2
+; S390X-NEXT: ler %f1, %f0
+; S390X-NEXT: jh .LBB2_2
+; S390X-NEXT: # %bb.1:
+; S390X-NEXT: ler %f1, %f2
+; S390X-NEXT: .LBB2_2:
+; S390X-NEXT: tceb %f0, 2048
+; S390X-NEXT: ipm %r0
+; S390X-NEXT: srl %r0, 28
+; S390X-NEXT: cijlh %r0, 0, .LBB2_4
+; S390X-NEXT: # %bb.3:
+; S390X-NEXT: ler %f0, %f1
+; S390X-NEXT: .LBB2_4:
+; S390X-NEXT: tceb %f2, 2048
+; S390X-NEXT: ipm %r0
+; S390X-NEXT: srl %r0, 28
+; S390X-NEXT: cije %r0, 0, .LBB2_7
+; S390X-NEXT: # %bb.5:
+; S390X-NEXT: ltebr %f0, %f1
+; S390X-NEXT: jne .LBB2_8
+; S390X-NEXT: .LBB2_6:
+; S390X-NEXT: ler %f0, %f2
+; S390X-NEXT: br %r14
+; S390X-NEXT: .LBB2_7:
+; S390X-NEXT: ler %f2, %f0
+; S390X-NEXT: ltebr %f0, %f1
+; S390X-NEXT: je .LBB2_6
+; S390X-NEXT: .LBB2_8:
+; S390X-NEXT: ler %f2, %f1
+; S390X-NEXT: ler %f0, %f2
+; S390X-NEXT: br %r14
+ %z = call nnan float @llvm.maximumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+
+define double @maximumnum_double(double %x, double %y) {
+;
+;
+; S390X-LABEL: maximumnum_double:
+; S390X: # %bb.0:
+; S390X-NEXT: cdbr %f0, %f0
+; S390X-NEXT: ldr %f1, %f2
+; S390X-NEXT: jo .LBB3_2
+; S390X-NEXT: # %bb.1:
+; S390X-NEXT: ldr %f1, %f0
+; S390X-NEXT: .LBB3_2:
+; S390X-NEXT: cdbr %f2, %f2
+; S390X-NEXT: ldr %f0, %f1
+; S390X-NEXT: jo .LBB3_4
+; S390X-NEXT: # %bb.3:
+; S390X-NEXT: ldr %f0, %f2
+; S390X-NEXT: .LBB3_4:
+; S390X-NEXT: cdbr %f1, %f0
+; S390X-NEXT: ldr %f2, %f1
+; S390X-NEXT: jh .LBB3_6
+; S390X-NEXT: # %bb.5:
+; S390X-NEXT: ldr %f2, %f0
+; S390X-NEXT: .LBB3_6:
+; S390X-NEXT: cdbr %f2, %f2
+; S390X-NEXT: jno .LBB3_8
+; S390X-NEXT: # %bb.7:
+; S390X-NEXT: adbr %f2, %f2
+; S390X-NEXT: .LBB3_8:
+; S390X-NEXT: tcdb %f1, 2048
+; S390X-NEXT: ipm %r0
+; S390X-NEXT: srl %r0, 28
+; S390X-NEXT: cijlh %r0, 0, .LBB3_10
+; S390X-NEXT: # %bb.9:
+; S390X-NEXT: ldr %f1, %f2
+; S390X-NEXT: .LBB3_10:
+; S390X-NEXT: tcdb %f0, 2048
+; S390X-NEXT: ipm %r0
+; S390X-NEXT: srl %r0, 28
+; S390X-NEXT: cijlh %r0, 0, .LBB3_12
+; S390X-NEXT: # %bb.11:
+; S390X-NEXT: ldr %f0, %f1
+; S390X-NEXT: .LBB3_12:
+; S390X-NEXT: ltdbr %f1, %f2
+; S390X-NEXT: ber %r14
+; S390X-NEXT: .LBB3_13:
+; S390X-NEXT: ldr %f0, %f2
+; S390X-NEXT: br %r14
+ %z = call double @llvm.maximumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define double @maximumnum_double_nsz(double %x, double %y) {
+;
+;
+; S390X-LABEL: maximumnum_double_nsz:
+; S390X: # %bb.0:
+; S390X-NEXT: ldr %f1, %f0
+; S390X-NEXT: cdbr %f0, %f0
+; S390X-NEXT: ldr %f0, %f2
+; S390X-NEXT: jo .LBB4_2
+; S390X-NEXT: # %bb.1:
+; S390X-NEXT: ldr %f0, %f1
+; S390X-NEXT: .LBB4_2:
+; S390X-NEXT: cdbr %f2, %f2
+; S390X-NEXT: ldr %f1, %f0
+; S390X-NEXT: jo .LBB4_4
+; S390X-NEXT: # %bb.3:
+; S390X-NEXT: ldr %f1, %f2
+; S390X-NEXT: .LBB4_4:
+; S390X-NEXT: cdbr %f0, %f1
+; S390X-NEXT: jh .LBB4_6
+; S390X-NEXT: # %bb.5:
+; S390X-NEXT: ldr %f0, %f1
+; S390X-NEXT: .LBB4_6:
+; S390X-NEXT: cdbr %f0, %f0
+; S390X-NEXT: bnor %r14
+; S390X-NEXT: .LBB4_7:
+; S390X-NEXT: adbr %f0, %f0
+; S390X-NEXT: br %r14
+ %z = call nsz double @llvm.maximumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define double @maximumnum_double_nnan(double %x, double %y) {
+;
+;
+; S390X-LABEL: maximumnum_double_nnan:
+; S390X: # %bb.0:
+; S390X-NEXT: cdbr %f0, %f2
+; S390X-NEXT: ldr %f1, %f0
+; S390X-NEXT: jh .LBB5_2
+; S390X-NEXT: # %bb.1:
+; S390X-NEXT: ldr %f1, %f2
+; S390X-NEXT: .LBB5_2:
+; S390X-NEXT: tcdb %f0, 2048
+; S390X-NEXT: ipm %r0
+; S390X-NEXT: srl %r0, 28
+; S390X-NEXT: cijlh %r0, 0, .LBB5_4
+; S390X-NEXT: # %bb.3:
+; S390X-NEXT: ldr %f0, %f1
+; S390X-NEXT: .LBB5_4:
+; S390X-NEXT: tcdb %f2, 2048
+; S390X-NEXT: ipm %r0
+; S390X-NEXT: srl %r0, 28
+; S390X-NEXT: cije %r0, 0, .LBB5_7
+; S390X-NEXT: # %bb.5:
+; S390X-NEXT: ltdbr %f0, %f1
+; S390X-NEXT: jne .LBB5_8
+; S390X-NEXT: .LBB5_6:
+; S390X-NEXT: ldr %f0, %f2
+; S390X-NEXT: br %r14
+; S390X-NEXT: .LBB5_7:
+; S390X-NEXT: ldr %f2, %f0
+; S390X-NEXT: ltdbr %f0, %f1
+; S390X-NEXT: je .LBB5_6
+; S390X-NEXT: .LBB5_8:
+; S390X-NEXT: ldr %f2, %f1
+; S390X-NEXT: ldr %f0, %f2
+; S390X-NEXT: br %r14
+ %z = call nnan double @llvm.maximumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define float @minimumnum_float(float %x, float %y) {
+;
+;
+; S390X-LABEL: minimumnum_float:
+; S390X: # %bb.0:
+; S390X-NEXT: cebr %f0, %f0
+; S390X-NEXT: ler %f1, %f2
+; S390X-NEXT: jo .LBB6_2
+; S390X-NEXT: # %bb.1:
+; S390X-NEXT: ler %f1, %f0
+; S390X-NEXT: .LBB6_2:
+; S390X-NEXT: cebr %f2, %f2
+; S390X-NEXT: ler %f0, %f1
+; S390X-NEXT: jo .LBB6_4
+; S390X-NEXT: # %bb.3:
+; S390X-NEXT: ler %f0, %f2
+; S390X-NEXT: .LBB6_4:
+; S390X-NEXT: cebr %f1, %f0
+; S390X-NEXT: ler %f2, %f1
+; S390X-NEXT: jl .LBB6_6
+; S390X-NEXT: # %bb.5:
+; S390X-NEXT: ler %f2, %f0
+; S390X-NEXT: .LBB6_6:
+; S390X-NEXT: cebr %f2, %f2
+; S390X-NEXT: jno .LBB6_8
+; S390X-NEXT: # %bb.7:
+; S390X-NEXT: aebr %f2, %f2
+; S390X-NEXT: .LBB6_8:
+; S390X-NEXT: tceb %f1, 1024
+; S390X-NEXT: ipm %r0
+; S390X-NEXT: srl %r0, 28
+; S390X-NEXT: cijlh %r0, 0, .LBB6_10
+; S390X-NEXT: # %bb.9:
+; S390X-NEXT: ler %f1, %f2
+; S390X-NEXT: .LBB6_10:
+; S390X-NEXT: tceb %f0, 1024
+; S390X-NEXT: ipm %r0
+; S390X-NEXT: srl %r0, 28
+; S390X-NEXT: cijlh %r0, 0, .LBB6_12
+; S390X-NEXT: # %bb.11:
+; S390X-NEXT: ler %f0, %f1
+; S390X-NEXT: .LBB6_12:
+; S390X-NEXT: ltebr %f1, %f2
+; S390X-NEXT: ber %r14
+; S390X-NEXT: .LBB6_13:
+; S390X-NEXT: ler %f0, %f2
+; S390X-NEXT: br %r14
+ %z = call float @llvm.minimumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+define float @minimumnum_float_nsz(float %x, float %y) {
+;
+;
+; S390X-LABEL: minimumnum_float_nsz:
+; S390X: # %bb.0:
+; S390X-NEXT: ler %f1, %f0
+; S390X-NEXT: cebr %f0, %f0
+; S390X-NEXT: ler %f0, %f2
+; S390X-NEXT: jo .LBB7_2
+; S390X-NEXT: # %bb.1:
+; S390X-NEXT: ler %f0, %f1
+; S390X-NEXT: .LBB7_2:
+; S390X-NEXT: cebr %f2, %f2
+; S390X-NEXT: ler %f1, %f0
+; S390X-NEXT: jo .LBB7_4
+; S390X-NEXT: # %bb.3:
+; S390X-NEXT: ler %f1, %f2
+; S390X-NEXT: .LBB7_4:
+; S390X-NEXT: cebr %f0, %f1
+; S390X-NEXT: jl .LBB7_6
+; S390X-NEXT: # %bb.5:
+; S390X-NEXT: ler %f0, %f1
+; S390X-NEXT: .LBB7_6:
+; S390X-NEXT: cebr %f0, %f0
+; S390X-NEXT: bnor %r14
+; S390X-NEXT: .LBB7_7:
+; S390X-NEXT: aebr %f0, %f0
+; S390X-NEXT: br %r14
+ %z = call nsz float @llvm.minimumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+define float @minimumnum_float_nnan(float %x, float %y) {
+;
+;
+; S390X-LABEL: minimumnum_float_nnan:
+; S390X: # %bb.0:
+; S390X-NEXT: cebr %f0, %f2
+; S390X-NEXT: ler %f1, %f0
+; S390X-NEXT: jl .LBB8_2
+; S390X-NEXT: # %bb.1:
+; S390X-NEXT: ler %f1, %f2
+; S390X-NEXT: .LBB8_2:
+; S390X-NEXT: tceb %f0, 1024
+; S390X-NEXT: ipm %r0
+; S390X-NEXT: srl %r0, 28
+; S390X-NEXT: cijlh %r0, 0, .LBB8_4
+; S390X-NEXT: # %bb.3:
+; S390X-NEXT: ler %f0, %f1
+; S390X-NEXT: .LBB8_4:
+; S390X-NEXT: tceb %f2, 1024
+; S390X-NEXT: ipm %r0
+; S390X-NEXT: srl %r0, 28
+; S390X-NEXT: cije %r0, 0, .LBB8_7
+; S390X-NEXT: # %bb.5:
+; S390X-NEXT: ltebr %f0, %f1
+; S390X-NEXT: jne .LBB8_8
+; S390X-NEXT: .LBB8_6:
+; S390X-NEXT: ler %f0, %f2
+; S390X-NEXT: br %r14
+; S390X-NEXT: .LBB8_7:
+; S390X-NEXT: ler %f2, %f0
+; S390X-NEXT: ltebr %f0, %f1
+; S390X-NEXT: je .LBB8_6
+; S390X-NEXT: .LBB8_8:
+; S390X-NEXT: ler %f2, %f1
+; S390X-NEXT: ler %f0, %f2
+; S390X-NEXT: br %r14
+ %z = call nnan float @llvm.minimumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+define double @minimumnum_double(double %x, double %y) {
+;
+;
+; S390X-LABEL: minimumnum_double:
+; S390X: # %bb.0:
+; S390X-NEXT: cdbr %f0, %f0
+; S390X-NEXT: ldr %f1, %f2
+; S390X-NEXT: jo .LBB9_2
+; S390X-NEXT: # %bb.1:
+; S390X-NEXT: ldr %f1, %f0
+; S390X-NEXT: .LBB9_2:
+; S390X-NEXT: cdbr %f2, %f2
+; S390X-NEXT: ldr %f0, %f1
+; S390X-NEXT: jo .LBB9_4
+; S390X-NEXT: # %bb.3:
+; S390X-NEXT: ldr %f0, %f2
+; S390X-NEXT: .LBB9_4:
+; S390X-NEXT: cdbr %f1, %f0
+; S390X-NEXT: ldr %f2, %f1
+; S390X-NEXT: jl .LBB9_6
+; S390X-NEXT: # %bb.5:
+; S390X-NEXT: ldr %f2, %f0
+; S390X-NEXT: .LBB9_6:
+; S390X-NEXT: cdbr %f2, %f2
+; S390X-NEXT: jno .LBB9_8
+; S390X-NEXT: # %bb.7:
+; S390X-NEXT: adbr %f2, %f2
+; S390X-NEXT: .LBB9_8:
+; S390X-NEXT: tcdb %f1, 1024
+; S390X-NEXT: ipm %r0
+; S390X-NEXT: srl %r0, 28
+; S390X-NEXT: cijlh %r0, 0, .LBB9_10
+; S390X-NEXT: # %bb.9:
+; S390X-NEXT: ldr %f1, %f2
+; S390X-NEXT: .LBB9_10:
+; S390X-NEXT: tcdb %f0, 1024
+; S390X-NEXT: ipm %r0
+; S390X-NEXT: srl %r0, 28
+; S390X-NEXT: cijlh %r0, 0, .LBB9_12
+; S390X-NEXT: # %bb.11:
+; S390X-NEXT: ldr %f0, %f1
+; S390X-NEXT: .LBB9_12:
+; S390X-NEXT: ltdbr %f1, %f2
+; S390X-NEXT: ber %r14
+; S390X-NEXT: .LBB9_13:
+; S390X-NEXT: ldr %f0, %f2
+; S390X-NEXT: br %r14
+ %z = call double @llvm.minimumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define double @minimumnum_double_nsz(double %x, double %y) {
+;
+;
+; S390X-LABEL: minimumnum_double_nsz:
+; S390X: # %bb.0:
+; S390X-NEXT: ldr %f1, %f0
+; S390X-NEXT: cdbr %f0, %f0
+; S390X-NEXT: ldr %f0, %f2
+; S390X-NEXT: jo .LBB10_2
+; S390X-NEXT: # %bb.1:
+; S390X-NEXT: ldr %f0, %f1
+; S390X-NEXT: .LBB10_2:
+; S390X-NEXT: cdbr %f2, %f2
+; S390X-NEXT: ldr %f1, %f0
+; S390X-NEXT: jo .LBB10_4
+; S390X-NEXT: # %bb.3:
+; S390X-NEXT: ldr %f1, %f2
+; S390X-NEXT: .LBB10_4:
+; S390X-NEXT: cdbr %f0, %f1
+; S390X-NEXT: jl .LBB10_6
+; S390X-NEXT: # %bb.5:
+; S390X-NEXT: ldr %f0, %f1
+; S390X-NEXT: .LBB10_6:
+; S390X-NEXT: cdbr %f0, %f0
+; S390X-NEXT: bnor %r14
+; S390X-NEXT: .LBB10_7:
+; S390X-NEXT: adbr %f0, %f0
+; S390X-NEXT: br %r14
+ %z = call nsz double @llvm.minimumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define double @minimumnum_double_nnan(double %x, double %y) {
+;
+;
+; S390X-LABEL: minimumnum_double_nnan:
+; S390X: # %bb.0:
+; S390X-NEXT: cdbr %f0, %f2
+; S390X-NEXT: ldr %f1, %f0
+; S390X-NEXT: jl .LBB11_2
+; S390X-NEXT: # %bb.1:
+; S390X-NEXT: ldr %f1, %f2
+; S390X-NEXT: .LBB11_2:
+; S390X-NEXT: tcdb %f0, 1024
+; S390X-NEXT: ipm %r0
+; S390X-NEXT: srl %r0, 28
+; S390X-NEXT: cijlh %r0, 0, .LBB11_4
+; S390X-NEXT: # %bb.3:
+; S390X-NEXT: ldr %f0, %f1
+; S390X-NEXT: .LBB11_4:
+; S390X-NEXT: tcdb %f2, 1024
+; S390X-NEXT: ipm %r0
+; S390X-NEXT: srl %r0, 28
+; S390X-NEXT: cije %r0, 0, .LBB11_7
+; S390X-NEXT: # %bb.5:
+; S390X-NEXT: ltdbr %f0, %f1
+; S390X-NEXT: jne .LBB11_8
+; S390X-NEXT: .LBB11_6:
+; S390X-NEXT: ldr %f0, %f2
+; S390X-NEXT: br %r14
+; S390X-NEXT: .LBB11_7:
+; S390X-NEXT: ldr %f2, %f0
+; S390X-NEXT: ltdbr %f0, %f1
+; S390X-NEXT: je .LBB11_6
+; S390X-NEXT: .LBB11_8:
+; S390X-NEXT: ldr %f2, %f1
+; S390X-NEXT: ldr %f0, %f2
+; S390X-NEXT: br %r14
+ %z = call nnan double @llvm.minimumnum.f64(double %x, double %y)
+ ret double %z
+}
diff --git a/llvm/test/CodeGen/X86/fp-maximumnum-minimumnum.ll b/llvm/test/CodeGen/X86/fp-maximumnum-minimumnum.ll
new file mode 100644
index 00000000000000..099fe9918c60f5
--- /dev/null
+++ b/llvm/test/CodeGen/X86/fp-maximumnum-minimumnum.ll
@@ -0,0 +1,2121 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc --mtriple=x86_64 < %s | FileCheck %s --check-prefix=X86-64
+; RUN: llc --mtriple=i386 < %s | FileCheck %s --check-prefix=I386
+; RUN: llc --mtriple=i386 -mattr=+sse2 < %s | FileCheck %s --check-prefix=SSE2
+; RUN: llc --mtriple=i386 -mattr=+avx < %s | FileCheck %s --check-prefix=AVX
+
+declare float @llvm.maximumnum.f32(float, float)
+declare double @llvm.maximumnum.f64(double, double)
+declare float @llvm.minimumnum.f32(float, float)
+declare double @llvm.minimumnum.f64(double, double)
+
+define float @maximumnum_float(float %x, float %y) {
+;
+; X86-64-LABEL: maximumnum_float:
+; X86-64: # %bb.0:
+; X86-64-NEXT: movaps %xmm0, %xmm2
+; X86-64-NEXT: cmpunordss %xmm0, %xmm2
+; X86-64-NEXT: movaps %xmm2, %xmm3
+; X86-64-NEXT: andps %xmm1, %xmm3
+; X86-64-NEXT: andnps %xmm0, %xmm2
+; X86-64-NEXT: orps %xmm3, %xmm2
+; X86-64-NEXT: movaps %xmm1, %xmm3
+; X86-64-NEXT: cmpunordss %xmm1, %xmm3
+; X86-64-NEXT: movaps %xmm3, %xmm0
+; X86-64-NEXT: andps %xmm2, %xmm0
+; X86-64-NEXT: andnps %xmm1, %xmm3
+; X86-64-NEXT: orps %xmm0, %xmm3
+; X86-64-NEXT: movaps %xmm3, %xmm0
+; X86-64-NEXT: cmpltss %xmm2, %xmm0
+; X86-64-NEXT: movaps %xmm0, %xmm1
+; X86-64-NEXT: andps %xmm2, %xmm1
+; X86-64-NEXT: andnps %xmm3, %xmm0
+; X86-64-NEXT: orps %xmm1, %xmm0
+; X86-64-NEXT: movaps %xmm0, %xmm1
+; X86-64-NEXT: addss %xmm0, %xmm1
+; X86-64-NEXT: movaps %xmm0, %xmm4
+; X86-64-NEXT: cmpunordss %xmm0, %xmm4
+; X86-64-NEXT: andps %xmm4, %xmm1
+; X86-64-NEXT: andnps %xmm0, %xmm4
+; X86-64-NEXT: orps %xmm1, %xmm4
+; X86-64-NEXT: xorps %xmm1, %xmm1
+; X86-64-NEXT: cmpeqss %xmm4, %xmm1
+; X86-64-NEXT: movd %xmm2, %eax
+; X86-64-NEXT: testl %eax, %eax
+; X86-64-NEXT: je .LBB0_2
+; X86-64-NEXT: # %bb.1:
+; X86-64-NEXT: movaps %xmm4, %xmm2
+; X86-64-NEXT: .LBB0_2:
+; X86-64-NEXT: movaps %xmm1, %xmm0
+; X86-64-NEXT: andnps %xmm4, %xmm0
+; X86-64-NEXT: movd %xmm3, %eax
+; X86-64-NEXT: testl %eax, %eax
+; X86-64-NEXT: je .LBB0_4
+; X86-64-NEXT: # %bb.3:
+; X86-64-NEXT: movaps %xmm2, %xmm3
+; X86-64-NEXT: .LBB0_4:
+; X86-64-NEXT: andps %xmm3, %xmm1
+; X86-64-NEXT: orps %xmm1, %xmm0
+; X86-64-NEXT: retq
+;
+; I386-LABEL: maximumnum_float:
+; I386: # %bb.0:
+; I386-NEXT: subl $8, %esp
+; I386-NEXT: .cfi_def_cfa_offset 12
+; I386-NEXT: flds {{[0-9]+}}(%esp)
+; I386-NEXT: flds {{[0-9]+}}(%esp)
+; I386-NEXT: fucom %st(0)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: fld %st(1)
+; I386-NEXT: jp .LBB0_2
+; I386-NEXT: # %bb.1:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: .LBB0_2:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fsts {{[0-9]+}}(%esp)
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(0)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: fld %st(1)
+; I386-NEXT: jp .LBB0_4
+; I386-NEXT: # %bb.3:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: .LBB0_4:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fsts (%esp)
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(1)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: fld %st(0)
+; I386-NEXT: ja .LBB0_6
+; I386-NEXT: # %bb.5:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: fld %st(1)
+; I386-NEXT: .LBB0_6:
+; I386-NEXT: fld %st(0)
+; I386-NEXT: fadd %st(1), %st
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(0)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: jp .LBB0_8
+; I386-NEXT: # %bb.7:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fldz
+; I386-NEXT: .LBB0_8:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: cmpl $0, {{[0-9]+}}(%esp)
+; I386-NEXT: je .LBB0_10
+; I386-NEXT: # %bb.9:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fld %st(0)
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: .LBB0_10:
+; I386-NEXT: cmpl $0, (%esp)
+; I386-NEXT: je .LBB0_12
+; I386-NEXT: # %bb.11:
+; I386-NEXT: fstp %st(2)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fxch %st(2)
+; I386-NEXT: .LBB0_12:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(1)
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: je .LBB0_14
+; I386-NEXT: # %bb.13:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fldz
+; I386-NEXT: .LBB0_14:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: addl $8, %esp
+; I386-NEXT: .cfi_def_cfa_offset 4
+; I386-NEXT: retl
+;
+; SSE2-LABEL: maximumnum_float:
+; SSE2: # %bb.0:
+; SSE2-NEXT: pushl %eax
+; SSE2-NEXT: .cfi_def_cfa_offset 8
+; SSE2-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
+; SSE2-NEXT: movss {{.*#+}} xmm2 = mem[0],zero,zero,zero
+; SSE2-NEXT: movaps %xmm1, %xmm0
+; SSE2-NEXT: cmpunordss %xmm1, %xmm0
+; SSE2-NEXT: movaps %xmm0, %xmm3
+; SSE2-NEXT: andps %xmm2, %xmm3
+; SSE2-NEXT: andnps %xmm1, %xmm0
+; SSE2-NEXT: orps %xmm3, %xmm0
+; SSE2-NEXT: movaps %xmm2, %xmm1
+; SSE2-NEXT: cmpunordss %xmm2, %xmm1
+; SSE2-NEXT: movaps %xmm1, %xmm3
+; SSE2-NEXT: andps %xmm0, %xmm3
+; SSE2-NEXT: andnps %xmm2, %xmm1
+; SSE2-NEXT: orps %xmm3, %xmm1
+; SSE2-NEXT: movaps %xmm1, %xmm2
+; SSE2-NEXT: cmpltss %xmm0, %xmm2
+; SSE2-NEXT: movaps %xmm2, %xmm3
+; SSE2-NEXT: andps %xmm0, %xmm3
+; SSE2-NEXT: andnps %xmm1, %xmm2
+; SSE2-NEXT: orps %xmm3, %xmm2
+; SSE2-NEXT: movaps %xmm2, %xmm4
+; SSE2-NEXT: addss %xmm2, %xmm4
+; SSE2-NEXT: movaps %xmm2, %xmm3
+; SSE2-NEXT: cmpunordss %xmm2, %xmm3
+; SSE2-NEXT: andps %xmm3, %xmm4
+; SSE2-NEXT: andnps %xmm2, %xmm3
+; SSE2-NEXT: orps %xmm4, %xmm3
+; SSE2-NEXT: xorps %xmm2, %xmm2
+; SSE2-NEXT: cmpeqss %xmm3, %xmm2
+; SSE2-NEXT: movd %xmm0, %eax
+; SSE2-NEXT: testl %eax, %eax
+; SSE2-NEXT: je .LBB0_2
+; SSE2-NEXT: # %bb.1:
+; SSE2-NEXT: movaps %xmm3, %xmm0
+; SSE2-NEXT: .LBB0_2:
+; SSE2-NEXT: movaps %xmm2, %xmm4
+; SSE2-NEXT: andnps %xmm3, %xmm4
+; SSE2-NEXT: movd %xmm1, %eax
+; SSE2-NEXT: testl %eax, %eax
+; SSE2-NEXT: je .LBB0_4
+; SSE2-NEXT: # %bb.3:
+; SSE2-NEXT: movaps %xmm0, %xmm1
+; SSE2-NEXT: .LBB0_4:
+; SSE2-NEXT: andps %xmm1, %xmm2
+; SSE2-NEXT: orps %xmm2, %xmm4
+; SSE2-NEXT: movss %xmm4, (%esp)
+; SSE2-NEXT: flds (%esp)
+; SSE2-NEXT: popl %eax
+; SSE2-NEXT: .cfi_def_cfa_offset 4
+; SSE2-NEXT: retl
+;
+; AVX-LABEL: maximumnum_float:
+; AVX: # %bb.0:
+; AVX-NEXT: pushl %eax
+; AVX-NEXT: .cfi_def_cfa_offset 8
+; AVX-NEXT: vmovss {{.*#+}} xmm0 = mem[0],zero,zero,zero
+; AVX-NEXT: vmovss {{.*#+}} xmm2 = mem[0],zero,zero,zero
+; AVX-NEXT: vcmpunordss %xmm0, %xmm0, %xmm1
+; AVX-NEXT: vblendvps %xmm1, %xmm2, %xmm0, %xmm1
+; AVX-NEXT: vcmpunordss %xmm2, %xmm2, %xmm0
+; AVX-NEXT: vblendvps %xmm0, %xmm1, %xmm2, %xmm0
+; AVX-NEXT: vcmpltss %xmm1, %xmm0, %xmm2
+; AVX-NEXT: vblendvps %xmm2, %xmm1, %xmm0, %xmm2
+; AVX-NEXT: vcmpunordss %xmm2, %xmm2, %xmm3
+; AVX-NEXT: vaddss %xmm2, %xmm2, %xmm4
+; AVX-NEXT: vblendvps %xmm3, %xmm4, %xmm2, %xmm2
+; AVX-NEXT: vxorps %xmm3, %xmm3, %xmm3
+; AVX-NEXT: vmovd %xmm1, %eax
+; AVX-NEXT: testl %eax, %eax
+; AVX-NEXT: je .LBB0_2
+; AVX-NEXT: # %bb.1:
+; AVX-NEXT: vmovaps %xmm2, %xmm1
+; AVX-NEXT: .LBB0_2:
+; AVX-NEXT: vcmpeqss %xmm3, %xmm2, %xmm3
+; AVX-NEXT: vmovd %xmm0, %eax
+; AVX-NEXT: testl %eax, %eax
+; AVX-NEXT: je .LBB0_4
+; AVX-NEXT: # %bb.3:
+; AVX-NEXT: vmovaps %xmm1, %xmm0
+; AVX-NEXT: .LBB0_4:
+; AVX-NEXT: vblendvps %xmm3, %xmm0, %xmm2, %xmm0
+; AVX-NEXT: vmovss %xmm0, (%esp)
+; AVX-NEXT: flds (%esp)
+; AVX-NEXT: popl %eax
+; AVX-NEXT: .cfi_def_cfa_offset 4
+; AVX-NEXT: retl
+ %z = call float @llvm.maximumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+define float @maximumnum_float_nsz(float %x, float %y) {
+;
+; X86-64-LABEL: maximumnum_float_nsz:
+; X86-64: # %bb.0:
+; X86-64-NEXT: movaps %xmm0, %xmm2
+; X86-64-NEXT: cmpunordss %xmm0, %xmm2
+; X86-64-NEXT: movaps %xmm2, %xmm3
+; X86-64-NEXT: andps %xmm1, %xmm3
+; X86-64-NEXT: andnps %xmm0, %xmm2
+; X86-64-NEXT: orps %xmm3, %xmm2
+; X86-64-NEXT: movaps %xmm1, %xmm0
+; X86-64-NEXT: cmpunordss %xmm1, %xmm0
+; X86-64-NEXT: movaps %xmm0, %xmm3
+; X86-64-NEXT: andps %xmm2, %xmm3
+; X86-64-NEXT: andnps %xmm1, %xmm0
+; X86-64-NEXT: orps %xmm3, %xmm0
+; X86-64-NEXT: movaps %xmm0, %xmm1
+; X86-64-NEXT: cmpltss %xmm2, %xmm1
+; X86-64-NEXT: andps %xmm1, %xmm2
+; X86-64-NEXT: andnps %xmm0, %xmm1
+; X86-64-NEXT: orps %xmm2, %xmm1
+; X86-64-NEXT: movaps %xmm1, %xmm2
+; X86-64-NEXT: addss %xmm1, %xmm2
+; X86-64-NEXT: movaps %xmm1, %xmm0
+; X86-64-NEXT: cmpunordss %xmm1, %xmm0
+; X86-64-NEXT: andps %xmm0, %xmm2
+; X86-64-NEXT: andnps %xmm1, %xmm0
+; X86-64-NEXT: orps %xmm2, %xmm0
+; X86-64-NEXT: retq
+;
+; I386-LABEL: maximumnum_float_nsz:
+; I386: # %bb.0:
+; I386-NEXT: flds {{[0-9]+}}(%esp)
+; I386-NEXT: flds {{[0-9]+}}(%esp)
+; I386-NEXT: fucom %st(0)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: fld %st(1)
+; I386-NEXT: jp .LBB1_2
+; I386-NEXT: # %bb.1:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: .LBB1_2:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(0)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: fld %st(1)
+; I386-NEXT: jp .LBB1_4
+; I386-NEXT: # %bb.3:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: .LBB1_4:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(1)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: ja .LBB1_6
+; I386-NEXT: # %bb.5:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: .LBB1_6:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fld %st(0)
+; I386-NEXT: fadd %st(1), %st
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(0)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: jp .LBB1_8
+; I386-NEXT: # %bb.7:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fldz
+; I386-NEXT: .LBB1_8:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: retl
+;
+; SSE2-LABEL: maximumnum_float_nsz:
+; SSE2: # %bb.0:
+; SSE2-NEXT: pushl %eax
+; SSE2-NEXT: .cfi_def_cfa_offset 8
+; SSE2-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
+; SSE2-NEXT: movss {{.*#+}} xmm2 = mem[0],zero,zero,zero
+; SSE2-NEXT: movaps %xmm1, %xmm0
+; SSE2-NEXT: cmpunordss %xmm1, %xmm0
+; SSE2-NEXT: movaps %xmm0, %xmm3
+; SSE2-NEXT: andps %xmm2, %xmm3
+; SSE2-NEXT: andnps %xmm1, %xmm0
+; SSE2-NEXT: orps %xmm3, %xmm0
+; SSE2-NEXT: movaps %xmm2, %xmm1
+; SSE2-NEXT: cmpunordss %xmm2, %xmm1
+; SSE2-NEXT: movaps %xmm1, %xmm3
+; SSE2-NEXT: andps %xmm0, %xmm3
+; SSE2-NEXT: andnps %xmm2, %xmm1
+; SSE2-NEXT: orps %xmm3, %xmm1
+; SSE2-NEXT: movaps %xmm1, %xmm2
+; SSE2-NEXT: cmpltss %xmm0, %xmm2
+; SSE2-NEXT: andps %xmm2, %xmm0
+; SSE2-NEXT: andnps %xmm1, %xmm2
+; SSE2-NEXT: orps %xmm0, %xmm2
+; SSE2-NEXT: movaps %xmm2, %xmm0
+; SSE2-NEXT: addss %xmm2, %xmm0
+; SSE2-NEXT: movaps %xmm2, %xmm1
+; SSE2-NEXT: cmpunordss %xmm2, %xmm1
+; SSE2-NEXT: andps %xmm1, %xmm0
+; SSE2-NEXT: andnps %xmm2, %xmm1
+; SSE2-NEXT: orps %xmm0, %xmm1
+; SSE2-NEXT: movss %xmm1, (%esp)
+; SSE2-NEXT: flds (%esp)
+; SSE2-NEXT: popl %eax
+; SSE2-NEXT: .cfi_def_cfa_offset 4
+; SSE2-NEXT: retl
+;
+; AVX-LABEL: maximumnum_float_nsz:
+; AVX: # %bb.0:
+; AVX-NEXT: pushl %eax
+; AVX-NEXT: .cfi_def_cfa_offset 8
+; AVX-NEXT: vmovss {{.*#+}} xmm0 = mem[0],zero,zero,zero
+; AVX-NEXT: vmovss {{.*#+}} xmm1 = mem[0],zero,zero,zero
+; AVX-NEXT: vcmpunordss %xmm0, %xmm0, %xmm2
+; AVX-NEXT: vblendvps %xmm2, %xmm1, %xmm0, %xmm0
+; AVX-NEXT: vcmpunordss %xmm1, %xmm1, %xmm2
+; AVX-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm1
+; AVX-NEXT: vcmpltss %xmm0, %xmm1, %xmm2
+; AVX-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm0
+; AVX-NEXT: vcmpunordss %xmm0, %xmm0, %xmm1
+; AVX-NEXT: vaddss %xmm0, %xmm0, %xmm2
+; AVX-NEXT: vblendvps %xmm1, %xmm2, %xmm0, %xmm0
+; AVX-NEXT: vmovss %xmm0, (%esp)
+; AVX-NEXT: flds (%esp)
+; AVX-NEXT: popl %eax
+; AVX-NEXT: .cfi_def_cfa_offset 4
+; AVX-NEXT: retl
+ %z = call nsz float @llvm.maximumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+define float @maximumnum_float_nnan(float %x, float %y) {
+;
+; X86-64-LABEL: maximumnum_float_nnan:
+; X86-64: # %bb.0:
+; X86-64-NEXT: movd %xmm0, %eax
+; X86-64-NEXT: testl %eax, %eax
+; X86-64-NEXT: js .LBB2_1
+; X86-64-NEXT: # %bb.2:
+; X86-64-NEXT: movdqa %xmm0, %xmm2
+; X86-64-NEXT: jmp .LBB2_3
+; X86-64-NEXT: .LBB2_1:
+; X86-64-NEXT: movdqa %xmm1, %xmm2
+; X86-64-NEXT: movdqa %xmm0, %xmm1
+; X86-64-NEXT: .LBB2_3:
+; X86-64-NEXT: maxss %xmm2, %xmm1
+; X86-64-NEXT: movaps %xmm1, %xmm0
+; X86-64-NEXT: retq
+;
+; I386-LABEL: maximumnum_float_nnan:
+; I386: # %bb.0:
+; I386-NEXT: subl $8, %esp
+; I386-NEXT: .cfi_def_cfa_offset 12
+; I386-NEXT: flds {{[0-9]+}}(%esp)
+; I386-NEXT: fsts {{[0-9]+}}(%esp)
+; I386-NEXT: flds {{[0-9]+}}(%esp)
+; I386-NEXT: fsts (%esp)
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(1)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: fld %st(0)
+; I386-NEXT: jbe .LBB2_1
+; I386-NEXT: # %bb.2:
+; I386-NEXT: cmpl $0, {{[0-9]+}}(%esp)
+; I386-NEXT: jne .LBB2_3
+; I386-NEXT: .LBB2_4:
+; I386-NEXT: cmpl $0, (%esp)
+; I386-NEXT: je .LBB2_6
+; I386-NEXT: .LBB2_5:
+; I386-NEXT: fstp %st(2)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fxch %st(2)
+; I386-NEXT: .LBB2_6:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(1)
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: je .LBB2_8
+; I386-NEXT: # %bb.7:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fldz
+; I386-NEXT: .LBB2_8:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: addl $8, %esp
+; I386-NEXT: .cfi_def_cfa_offset 4
+; I386-NEXT: retl
+; I386-NEXT: .LBB2_1:
+; I386-NEXT: .cfi_def_cfa_offset 12
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: fld %st(1)
+; I386-NEXT: cmpl $0, {{[0-9]+}}(%esp)
+; I386-NEXT: je .LBB2_4
+; I386-NEXT: .LBB2_3:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fld %st(0)
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: cmpl $0, (%esp)
+; I386-NEXT: jne .LBB2_5
+; I386-NEXT: jmp .LBB2_6
+;
+; SSE2-LABEL: maximumnum_float_nnan:
+; SSE2: # %bb.0:
+; SSE2-NEXT: pushl %eax
+; SSE2-NEXT: .cfi_def_cfa_offset 8
+; SSE2-NEXT: movd {{.*#+}} xmm0 = mem[0],zero,zero,zero
+; SSE2-NEXT: movd {{.*#+}} xmm2 = mem[0],zero,zero,zero
+; SSE2-NEXT: movd %xmm2, %eax
+; SSE2-NEXT: testl %eax, %eax
+; SSE2-NEXT: js .LBB2_1
+; SSE2-NEXT: # %bb.2:
+; SSE2-NEXT: movdqa %xmm2, %xmm1
+; SSE2-NEXT: jmp .LBB2_3
+; SSE2-NEXT: .LBB2_1:
+; SSE2-NEXT: movdqa %xmm0, %xmm1
+; SSE2-NEXT: movdqa %xmm2, %xmm0
+; SSE2-NEXT: .LBB2_3:
+; SSE2-NEXT: maxss %xmm1, %xmm0
+; SSE2-NEXT: movss %xmm0, (%esp)
+; SSE2-NEXT: flds (%esp)
+; SSE2-NEXT: popl %eax
+; SSE2-NEXT: .cfi_def_cfa_offset 4
+; SSE2-NEXT: retl
+;
+; AVX-LABEL: maximumnum_float_nnan:
+; AVX: # %bb.0:
+; AVX-NEXT: pushl %eax
+; AVX-NEXT: .cfi_def_cfa_offset 8
+; AVX-NEXT: vmovd {{.*#+}} xmm0 = mem[0],zero,zero,zero
+; AVX-NEXT: vmovd {{.*#+}} xmm2 = mem[0],zero,zero,zero
+; AVX-NEXT: vmovd %xmm2, %eax
+; AVX-NEXT: testl %eax, %eax
+; AVX-NEXT: js .LBB2_1
+; AVX-NEXT: # %bb.2:
+; AVX-NEXT: vmovdqa %xmm2, %xmm1
+; AVX-NEXT: jmp .LBB2_3
+; AVX-NEXT: .LBB2_1:
+; AVX-NEXT: vmovdqa %xmm0, %xmm1
+; AVX-NEXT: vmovdqa %xmm2, %xmm0
+; AVX-NEXT: .LBB2_3:
+; AVX-NEXT: vmaxss %xmm1, %xmm0, %xmm0
+; AVX-NEXT: vmovss %xmm0, (%esp)
+; AVX-NEXT: flds (%esp)
+; AVX-NEXT: popl %eax
+; AVX-NEXT: .cfi_def_cfa_offset 4
+; AVX-NEXT: retl
+ %z = call nnan float @llvm.maximumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+
+define double @maximumnum_double(double %x, double %y) {
+;
+; X86-64-LABEL: maximumnum_double:
+; X86-64: # %bb.0:
+; X86-64-NEXT: movapd %xmm0, %xmm2
+; X86-64-NEXT: cmpunordsd %xmm0, %xmm2
+; X86-64-NEXT: movapd %xmm2, %xmm3
+; X86-64-NEXT: andpd %xmm1, %xmm3
+; X86-64-NEXT: andnpd %xmm0, %xmm2
+; X86-64-NEXT: orpd %xmm3, %xmm2
+; X86-64-NEXT: movapd %xmm1, %xmm3
+; X86-64-NEXT: cmpunordsd %xmm1, %xmm3
+; X86-64-NEXT: movapd %xmm3, %xmm0
+; X86-64-NEXT: andpd %xmm2, %xmm0
+; X86-64-NEXT: andnpd %xmm1, %xmm3
+; X86-64-NEXT: orpd %xmm0, %xmm3
+; X86-64-NEXT: movapd %xmm3, %xmm0
+; X86-64-NEXT: cmpltsd %xmm2, %xmm0
+; X86-64-NEXT: movapd %xmm0, %xmm1
+; X86-64-NEXT: andpd %xmm2, %xmm1
+; X86-64-NEXT: andnpd %xmm3, %xmm0
+; X86-64-NEXT: orpd %xmm1, %xmm0
+; X86-64-NEXT: movapd %xmm0, %xmm1
+; X86-64-NEXT: addsd %xmm0, %xmm1
+; X86-64-NEXT: movapd %xmm0, %xmm4
+; X86-64-NEXT: cmpunordsd %xmm0, %xmm4
+; X86-64-NEXT: andpd %xmm4, %xmm1
+; X86-64-NEXT: andnpd %xmm0, %xmm4
+; X86-64-NEXT: orpd %xmm1, %xmm4
+; X86-64-NEXT: xorpd %xmm1, %xmm1
+; X86-64-NEXT: cmpeqsd %xmm4, %xmm1
+; X86-64-NEXT: movq %xmm2, %rax
+; X86-64-NEXT: testq %rax, %rax
+; X86-64-NEXT: je .LBB3_2
+; X86-64-NEXT: # %bb.1:
+; X86-64-NEXT: movapd %xmm4, %xmm2
+; X86-64-NEXT: .LBB3_2:
+; X86-64-NEXT: movapd %xmm1, %xmm0
+; X86-64-NEXT: andnpd %xmm4, %xmm0
+; X86-64-NEXT: movq %xmm3, %rax
+; X86-64-NEXT: testq %rax, %rax
+; X86-64-NEXT: je .LBB3_4
+; X86-64-NEXT: # %bb.3:
+; X86-64-NEXT: movapd %xmm2, %xmm3
+; X86-64-NEXT: .LBB3_4:
+; X86-64-NEXT: andpd %xmm3, %xmm1
+; X86-64-NEXT: orpd %xmm1, %xmm0
+; X86-64-NEXT: retq
+;
+; I386-LABEL: maximumnum_double:
+; I386: # %bb.0:
+; I386-NEXT: subl $16, %esp
+; I386-NEXT: .cfi_def_cfa_offset 20
+; I386-NEXT: fldl {{[0-9]+}}(%esp)
+; I386-NEXT: fldl {{[0-9]+}}(%esp)
+; I386-NEXT: fucom %st(0)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: fld %st(1)
+; I386-NEXT: jp .LBB3_2
+; I386-NEXT: # %bb.1:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: .LBB3_2:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fsts {{[0-9]+}}(%esp)
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(0)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: fld %st(1)
+; I386-NEXT: jp .LBB3_4
+; I386-NEXT: # %bb.3:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: .LBB3_4:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fsts (%esp)
+; I386-NEXT: flds {{[0-9]+}}(%esp)
+; I386-NEXT: fstps {{[0-9]+}}(%esp)
+; I386-NEXT: flds (%esp)
+; I386-NEXT: fstps {{[0-9]+}}(%esp)
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(1)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: fld %st(0)
+; I386-NEXT: ja .LBB3_6
+; I386-NEXT: # %bb.5:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: fld %st(1)
+; I386-NEXT: .LBB3_6:
+; I386-NEXT: fld %st(0)
+; I386-NEXT: fadd %st(1), %st
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(0)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: jp .LBB3_8
+; I386-NEXT: # %bb.7:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fldz
+; I386-NEXT: .LBB3_8:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: cmpl $0, {{[0-9]+}}(%esp)
+; I386-NEXT: je .LBB3_10
+; I386-NEXT: # %bb.9:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fld %st(0)
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: .LBB3_10:
+; I386-NEXT: cmpl $0, {{[0-9]+}}(%esp)
+; I386-NEXT: je .LBB3_12
+; I386-NEXT: # %bb.11:
+; I386-NEXT: fstp %st(2)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fxch %st(2)
+; I386-NEXT: .LBB3_12:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(1)
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: je .LBB3_14
+; I386-NEXT: # %bb.13:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fldz
+; I386-NEXT: .LBB3_14:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: addl $16, %esp
+; I386-NEXT: .cfi_def_cfa_offset 4
+; I386-NEXT: retl
+;
+; SSE2-LABEL: maximumnum_double:
+; SSE2: # %bb.0:
+; SSE2-NEXT: pushl %ebp
+; SSE2-NEXT: .cfi_def_cfa_offset 8
+; SSE2-NEXT: .cfi_offset %ebp, -8
+; SSE2-NEXT: movl %esp, %ebp
+; SSE2-NEXT: .cfi_def_cfa_register %ebp
+; SSE2-NEXT: andl $-8, %esp
+; SSE2-NEXT: subl $8, %esp
+; SSE2-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero
+; SSE2-NEXT: movsd {{.*#+}} xmm2 = mem[0],zero
+; SSE2-NEXT: movapd %xmm1, %xmm0
+; SSE2-NEXT: cmpunordsd %xmm1, %xmm0
+; SSE2-NEXT: movapd %xmm0, %xmm3
+; SSE2-NEXT: andpd %xmm2, %xmm3
+; SSE2-NEXT: andnpd %xmm1, %xmm0
+; SSE2-NEXT: orpd %xmm3, %xmm0
+; SSE2-NEXT: movapd %xmm2, %xmm1
+; SSE2-NEXT: cmpunordsd %xmm2, %xmm1
+; SSE2-NEXT: movapd %xmm1, %xmm3
+; SSE2-NEXT: andpd %xmm0, %xmm3
+; SSE2-NEXT: andnpd %xmm2, %xmm1
+; SSE2-NEXT: orpd %xmm3, %xmm1
+; SSE2-NEXT: movapd %xmm1, %xmm2
+; SSE2-NEXT: cmpltsd %xmm0, %xmm2
+; SSE2-NEXT: movapd %xmm2, %xmm3
+; SSE2-NEXT: andpd %xmm0, %xmm3
+; SSE2-NEXT: andnpd %xmm1, %xmm2
+; SSE2-NEXT: orpd %xmm3, %xmm2
+; SSE2-NEXT: movapd %xmm2, %xmm4
+; SSE2-NEXT: addsd %xmm2, %xmm4
+; SSE2-NEXT: movapd %xmm2, %xmm3
+; SSE2-NEXT: cmpunordsd %xmm2, %xmm3
+; SSE2-NEXT: andpd %xmm3, %xmm4
+; SSE2-NEXT: andnpd %xmm2, %xmm3
+; SSE2-NEXT: orpd %xmm4, %xmm3
+; SSE2-NEXT: xorpd %xmm2, %xmm2
+; SSE2-NEXT: cmpeqsd %xmm3, %xmm2
+; SSE2-NEXT: xorps %xmm4, %xmm4
+; SSE2-NEXT: cvtsd2ss %xmm0, %xmm4
+; SSE2-NEXT: movd %xmm4, %eax
+; SSE2-NEXT: testl %eax, %eax
+; SSE2-NEXT: je .LBB3_2
+; SSE2-NEXT: # %bb.1:
+; SSE2-NEXT: movapd %xmm3, %xmm0
+; SSE2-NEXT: .LBB3_2:
+; SSE2-NEXT: movapd %xmm2, %xmm4
+; SSE2-NEXT: andnpd %xmm3, %xmm4
+; SSE2-NEXT: xorps %xmm3, %xmm3
+; SSE2-NEXT: cvtsd2ss %xmm1, %xmm3
+; SSE2-NEXT: movd %xmm3, %eax
+; SSE2-NEXT: testl %eax, %eax
+; SSE2-NEXT: je .LBB3_4
+; SSE2-NEXT: # %bb.3:
+; SSE2-NEXT: movaps %xmm0, %xmm1
+; SSE2-NEXT: .LBB3_4:
+; SSE2-NEXT: andpd %xmm1, %xmm2
+; SSE2-NEXT: orpd %xmm2, %xmm4
+; SSE2-NEXT: movlpd %xmm4, (%esp)
+; SSE2-NEXT: fldl (%esp)
+; SSE2-NEXT: movl %ebp, %esp
+; SSE2-NEXT: popl %ebp
+; SSE2-NEXT: .cfi_def_cfa %esp, 4
+; SSE2-NEXT: retl
+;
+; AVX-LABEL: maximumnum_double:
+; AVX: # %bb.0:
+; AVX-NEXT: pushl %ebp
+; AVX-NEXT: .cfi_def_cfa_offset 8
+; AVX-NEXT: .cfi_offset %ebp, -8
+; AVX-NEXT: movl %esp, %ebp
+; AVX-NEXT: .cfi_def_cfa_register %ebp
+; AVX-NEXT: andl $-8, %esp
+; AVX-NEXT: subl $8, %esp
+; AVX-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
+; AVX-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero
+; AVX-NEXT: vcmpunordsd %xmm0, %xmm0, %xmm1
+; AVX-NEXT: vblendvpd %xmm1, %xmm2, %xmm0, %xmm1
+; AVX-NEXT: vcmpunordsd %xmm2, %xmm2, %xmm0
+; AVX-NEXT: vblendvpd %xmm0, %xmm1, %xmm2, %xmm0
+; AVX-NEXT: vcmpltsd %xmm1, %xmm0, %xmm2
+; AVX-NEXT: vblendvpd %xmm2, %xmm1, %xmm0, %xmm2
+; AVX-NEXT: vcmpunordsd %xmm2, %xmm2, %xmm3
+; AVX-NEXT: vaddsd %xmm2, %xmm2, %xmm4
+; AVX-NEXT: vblendvpd %xmm3, %xmm4, %xmm2, %xmm2
+; AVX-NEXT: vxorpd %xmm3, %xmm3, %xmm3
+; AVX-NEXT: vcvtsd2ss %xmm1, %xmm1, %xmm4
+; AVX-NEXT: vmovd %xmm4, %eax
+; AVX-NEXT: testl %eax, %eax
+; AVX-NEXT: je .LBB3_2
+; AVX-NEXT: # %bb.1:
+; AVX-NEXT: vmovapd %xmm2, %xmm1
+; AVX-NEXT: .LBB3_2:
+; AVX-NEXT: vcmpeqsd %xmm3, %xmm2, %xmm3
+; AVX-NEXT: vcvtsd2ss %xmm0, %xmm0, %xmm4
+; AVX-NEXT: vmovd %xmm4, %eax
+; AVX-NEXT: testl %eax, %eax
+; AVX-NEXT: je .LBB3_4
+; AVX-NEXT: # %bb.3:
+; AVX-NEXT: vmovaps %xmm1, %xmm0
+; AVX-NEXT: .LBB3_4:
+; AVX-NEXT: vblendvpd %xmm3, %xmm0, %xmm2, %xmm0
+; AVX-NEXT: vmovlpd %xmm0, (%esp)
+; AVX-NEXT: fldl (%esp)
+; AVX-NEXT: movl %ebp, %esp
+; AVX-NEXT: popl %ebp
+; AVX-NEXT: .cfi_def_cfa %esp, 4
+; AVX-NEXT: retl
+ %z = call double @llvm.maximumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define double @maximumnum_double_nsz(double %x, double %y) {
+;
+; X86-64-LABEL: maximumnum_double_nsz:
+; X86-64: # %bb.0:
+; X86-64-NEXT: movapd %xmm0, %xmm2
+; X86-64-NEXT: cmpunordsd %xmm0, %xmm2
+; X86-64-NEXT: movapd %xmm2, %xmm3
+; X86-64-NEXT: andpd %xmm1, %xmm3
+; X86-64-NEXT: andnpd %xmm0, %xmm2
+; X86-64-NEXT: orpd %xmm3, %xmm2
+; X86-64-NEXT: movapd %xmm1, %xmm0
+; X86-64-NEXT: cmpunordsd %xmm1, %xmm0
+; X86-64-NEXT: movapd %xmm0, %xmm3
+; X86-64-NEXT: andpd %xmm2, %xmm3
+; X86-64-NEXT: andnpd %xmm1, %xmm0
+; X86-64-NEXT: orpd %xmm3, %xmm0
+; X86-64-NEXT: movapd %xmm0, %xmm1
+; X86-64-NEXT: cmpltsd %xmm2, %xmm1
+; X86-64-NEXT: andpd %xmm1, %xmm2
+; X86-64-NEXT: andnpd %xmm0, %xmm1
+; X86-64-NEXT: orpd %xmm2, %xmm1
+; X86-64-NEXT: movapd %xmm1, %xmm2
+; X86-64-NEXT: addsd %xmm1, %xmm2
+; X86-64-NEXT: movapd %xmm1, %xmm0
+; X86-64-NEXT: cmpunordsd %xmm1, %xmm0
+; X86-64-NEXT: andpd %xmm0, %xmm2
+; X86-64-NEXT: andnpd %xmm1, %xmm0
+; X86-64-NEXT: orpd %xmm2, %xmm0
+; X86-64-NEXT: retq
+;
+; I386-LABEL: maximumnum_double_nsz:
+; I386: # %bb.0:
+; I386-NEXT: fldl {{[0-9]+}}(%esp)
+; I386-NEXT: fldl {{[0-9]+}}(%esp)
+; I386-NEXT: fucom %st(0)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: fld %st(1)
+; I386-NEXT: jp .LBB4_2
+; I386-NEXT: # %bb.1:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: .LBB4_2:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(0)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: fld %st(1)
+; I386-NEXT: jp .LBB4_4
+; I386-NEXT: # %bb.3:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: .LBB4_4:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(1)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: ja .LBB4_6
+; I386-NEXT: # %bb.5:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: .LBB4_6:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fld %st(0)
+; I386-NEXT: fadd %st(1), %st
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(0)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: jp .LBB4_8
+; I386-NEXT: # %bb.7:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fldz
+; I386-NEXT: .LBB4_8:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: retl
+;
+; SSE2-LABEL: maximumnum_double_nsz:
+; SSE2: # %bb.0:
+; SSE2-NEXT: pushl %ebp
+; SSE2-NEXT: .cfi_def_cfa_offset 8
+; SSE2-NEXT: .cfi_offset %ebp, -8
+; SSE2-NEXT: movl %esp, %ebp
+; SSE2-NEXT: .cfi_def_cfa_register %ebp
+; SSE2-NEXT: andl $-8, %esp
+; SSE2-NEXT: subl $8, %esp
+; SSE2-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero
+; SSE2-NEXT: movsd {{.*#+}} xmm2 = mem[0],zero
+; SSE2-NEXT: movapd %xmm1, %xmm0
+; SSE2-NEXT: cmpunordsd %xmm1, %xmm0
+; SSE2-NEXT: movapd %xmm0, %xmm3
+; SSE2-NEXT: andpd %xmm2, %xmm3
+; SSE2-NEXT: andnpd %xmm1, %xmm0
+; SSE2-NEXT: orpd %xmm3, %xmm0
+; SSE2-NEXT: movapd %xmm2, %xmm1
+; SSE2-NEXT: cmpunordsd %xmm2, %xmm1
+; SSE2-NEXT: movapd %xmm1, %xmm3
+; SSE2-NEXT: andpd %xmm0, %xmm3
+; SSE2-NEXT: andnpd %xmm2, %xmm1
+; SSE2-NEXT: orpd %xmm3, %xmm1
+; SSE2-NEXT: movapd %xmm1, %xmm2
+; SSE2-NEXT: cmpltsd %xmm0, %xmm2
+; SSE2-NEXT: andpd %xmm2, %xmm0
+; SSE2-NEXT: andnpd %xmm1, %xmm2
+; SSE2-NEXT: orpd %xmm0, %xmm2
+; SSE2-NEXT: movapd %xmm2, %xmm0
+; SSE2-NEXT: addsd %xmm2, %xmm0
+; SSE2-NEXT: movapd %xmm2, %xmm1
+; SSE2-NEXT: cmpunordsd %xmm2, %xmm1
+; SSE2-NEXT: andpd %xmm1, %xmm0
+; SSE2-NEXT: andnpd %xmm2, %xmm1
+; SSE2-NEXT: orpd %xmm0, %xmm1
+; SSE2-NEXT: movlpd %xmm1, (%esp)
+; SSE2-NEXT: fldl (%esp)
+; SSE2-NEXT: movl %ebp, %esp
+; SSE2-NEXT: popl %ebp
+; SSE2-NEXT: .cfi_def_cfa %esp, 4
+; SSE2-NEXT: retl
+;
+; AVX-LABEL: maximumnum_double_nsz:
+; AVX: # %bb.0:
+; AVX-NEXT: pushl %ebp
+; AVX-NEXT: .cfi_def_cfa_offset 8
+; AVX-NEXT: .cfi_offset %ebp, -8
+; AVX-NEXT: movl %esp, %ebp
+; AVX-NEXT: .cfi_def_cfa_register %ebp
+; AVX-NEXT: andl $-8, %esp
+; AVX-NEXT: subl $8, %esp
+; AVX-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
+; AVX-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero
+; AVX-NEXT: vcmpunordsd %xmm0, %xmm0, %xmm2
+; AVX-NEXT: vblendvpd %xmm2, %xmm1, %xmm0, %xmm0
+; AVX-NEXT: vcmpunordsd %xmm1, %xmm1, %xmm2
+; AVX-NEXT: vblendvpd %xmm2, %xmm0, %xmm1, %xmm1
+; AVX-NEXT: vcmpltsd %xmm0, %xmm1, %xmm2
+; AVX-NEXT: vblendvpd %xmm2, %xmm0, %xmm1, %xmm0
+; AVX-NEXT: vcmpunordsd %xmm0, %xmm0, %xmm1
+; AVX-NEXT: vaddsd %xmm0, %xmm0, %xmm2
+; AVX-NEXT: vblendvpd %xmm1, %xmm2, %xmm0, %xmm0
+; AVX-NEXT: vmovlpd %xmm0, (%esp)
+; AVX-NEXT: fldl (%esp)
+; AVX-NEXT: movl %ebp, %esp
+; AVX-NEXT: popl %ebp
+; AVX-NEXT: .cfi_def_cfa %esp, 4
+; AVX-NEXT: retl
+ %z = call nsz double @llvm.maximumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define double @maximumnum_double_nnan(double %x, double %y) {
+;
+; X86-64-LABEL: maximumnum_double_nnan:
+; X86-64: # %bb.0:
+; X86-64-NEXT: movq %xmm0, %rax
+; X86-64-NEXT: testq %rax, %rax
+; X86-64-NEXT: js .LBB5_1
+; X86-64-NEXT: # %bb.2:
+; X86-64-NEXT: movdqa %xmm0, %xmm2
+; X86-64-NEXT: jmp .LBB5_3
+; X86-64-NEXT: .LBB5_1:
+; X86-64-NEXT: movdqa %xmm1, %xmm2
+; X86-64-NEXT: movdqa %xmm0, %xmm1
+; X86-64-NEXT: .LBB5_3:
+; X86-64-NEXT: maxsd %xmm2, %xmm1
+; X86-64-NEXT: movapd %xmm1, %xmm0
+; X86-64-NEXT: retq
+;
+; I386-LABEL: maximumnum_double_nnan:
+; I386: # %bb.0:
+; I386-NEXT: subl $16, %esp
+; I386-NEXT: .cfi_def_cfa_offset 20
+; I386-NEXT: fldl {{[0-9]+}}(%esp)
+; I386-NEXT: fldl {{[0-9]+}}(%esp)
+; I386-NEXT: fsts {{[0-9]+}}(%esp)
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fsts (%esp)
+; I386-NEXT: flds {{[0-9]+}}(%esp)
+; I386-NEXT: fstps {{[0-9]+}}(%esp)
+; I386-NEXT: flds (%esp)
+; I386-NEXT: fstps {{[0-9]+}}(%esp)
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(1)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: fld %st(0)
+; I386-NEXT: jbe .LBB5_1
+; I386-NEXT: # %bb.2:
+; I386-NEXT: cmpl $0, {{[0-9]+}}(%esp)
+; I386-NEXT: jne .LBB5_3
+; I386-NEXT: .LBB5_4:
+; I386-NEXT: cmpl $0, {{[0-9]+}}(%esp)
+; I386-NEXT: je .LBB5_6
+; I386-NEXT: .LBB5_5:
+; I386-NEXT: fstp %st(2)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fxch %st(2)
+; I386-NEXT: .LBB5_6:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(1)
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: je .LBB5_8
+; I386-NEXT: # %bb.7:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fldz
+; I386-NEXT: .LBB5_8:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: addl $16, %esp
+; I386-NEXT: .cfi_def_cfa_offset 4
+; I386-NEXT: retl
+; I386-NEXT: .LBB5_1:
+; I386-NEXT: .cfi_def_cfa_offset 20
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: fld %st(1)
+; I386-NEXT: cmpl $0, {{[0-9]+}}(%esp)
+; I386-NEXT: je .LBB5_4
+; I386-NEXT: .LBB5_3:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fld %st(0)
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: cmpl $0, {{[0-9]+}}(%esp)
+; I386-NEXT: jne .LBB5_5
+; I386-NEXT: jmp .LBB5_6
+;
+; SSE2-LABEL: maximumnum_double_nnan:
+; SSE2: # %bb.0:
+; SSE2-NEXT: pushl %ebp
+; SSE2-NEXT: .cfi_def_cfa_offset 8
+; SSE2-NEXT: .cfi_offset %ebp, -8
+; SSE2-NEXT: movl %esp, %ebp
+; SSE2-NEXT: .cfi_def_cfa_register %ebp
+; SSE2-NEXT: andl $-8, %esp
+; SSE2-NEXT: subl $8, %esp
+; SSE2-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero
+; SSE2-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero
+; SSE2-NEXT: movaps %xmm1, %xmm2
+; SSE2-NEXT: shufps {{.*#+}} xmm2 = xmm2[1,1],xmm1[1,1]
+; SSE2-NEXT: movd %xmm2, %eax
+; SSE2-NEXT: testl %eax, %eax
+; SSE2-NEXT: js .LBB5_1
+; SSE2-NEXT: # %bb.2:
+; SSE2-NEXT: movaps %xmm1, %xmm2
+; SSE2-NEXT: jmp .LBB5_3
+; SSE2-NEXT: .LBB5_1:
+; SSE2-NEXT: movaps %xmm0, %xmm2
+; SSE2-NEXT: movaps %xmm1, %xmm0
+; SSE2-NEXT: .LBB5_3:
+; SSE2-NEXT: maxsd %xmm2, %xmm0
+; SSE2-NEXT: movsd %xmm0, (%esp)
+; SSE2-NEXT: fldl (%esp)
+; SSE2-NEXT: movl %ebp, %esp
+; SSE2-NEXT: popl %ebp
+; SSE2-NEXT: .cfi_def_cfa %esp, 4
+; SSE2-NEXT: retl
+;
+; AVX-LABEL: maximumnum_double_nnan:
+; AVX: # %bb.0:
+; AVX-NEXT: pushl %ebp
+; AVX-NEXT: .cfi_def_cfa_offset 8
+; AVX-NEXT: .cfi_offset %ebp, -8
+; AVX-NEXT: movl %esp, %ebp
+; AVX-NEXT: .cfi_def_cfa_register %ebp
+; AVX-NEXT: andl $-8, %esp
+; AVX-NEXT: subl $8, %esp
+; AVX-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
+; AVX-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero
+; AVX-NEXT: vextractps $1, %xmm2, %eax
+; AVX-NEXT: testl %eax, %eax
+; AVX-NEXT: js .LBB5_1
+; AVX-NEXT: # %bb.2:
+; AVX-NEXT: vmovapd %xmm2, %xmm1
+; AVX-NEXT: jmp .LBB5_3
+; AVX-NEXT: .LBB5_1:
+; AVX-NEXT: vmovapd %xmm0, %xmm1
+; AVX-NEXT: vmovapd %xmm2, %xmm0
+; AVX-NEXT: .LBB5_3:
+; AVX-NEXT: vmaxsd %xmm1, %xmm0, %xmm0
+; AVX-NEXT: vmovsd %xmm0, (%esp)
+; AVX-NEXT: fldl (%esp)
+; AVX-NEXT: movl %ebp, %esp
+; AVX-NEXT: popl %ebp
+; AVX-NEXT: .cfi_def_cfa %esp, 4
+; AVX-NEXT: retl
+ %z = call nnan double @llvm.maximumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define float @minimumnum_float(float %x, float %y) {
+;
+; X86-64-LABEL: minimumnum_float:
+; X86-64: # %bb.0:
+; X86-64-NEXT: movaps %xmm0, %xmm2
+; X86-64-NEXT: cmpunordss %xmm0, %xmm2
+; X86-64-NEXT: movaps %xmm2, %xmm3
+; X86-64-NEXT: andps %xmm1, %xmm3
+; X86-64-NEXT: andnps %xmm0, %xmm2
+; X86-64-NEXT: orps %xmm3, %xmm2
+; X86-64-NEXT: movaps %xmm1, %xmm3
+; X86-64-NEXT: cmpunordss %xmm1, %xmm3
+; X86-64-NEXT: movaps %xmm3, %xmm0
+; X86-64-NEXT: andps %xmm2, %xmm0
+; X86-64-NEXT: andnps %xmm1, %xmm3
+; X86-64-NEXT: orps %xmm0, %xmm3
+; X86-64-NEXT: movaps %xmm2, %xmm0
+; X86-64-NEXT: cmpltss %xmm3, %xmm0
+; X86-64-NEXT: movaps %xmm0, %xmm1
+; X86-64-NEXT: andps %xmm2, %xmm1
+; X86-64-NEXT: andnps %xmm3, %xmm0
+; X86-64-NEXT: orps %xmm1, %xmm0
+; X86-64-NEXT: movaps %xmm0, %xmm1
+; X86-64-NEXT: addss %xmm0, %xmm1
+; X86-64-NEXT: movaps %xmm0, %xmm4
+; X86-64-NEXT: cmpunordss %xmm0, %xmm4
+; X86-64-NEXT: andps %xmm4, %xmm1
+; X86-64-NEXT: andnps %xmm0, %xmm4
+; X86-64-NEXT: orps %xmm1, %xmm4
+; X86-64-NEXT: xorps %xmm1, %xmm1
+; X86-64-NEXT: cmpeqss %xmm4, %xmm1
+; X86-64-NEXT: movd %xmm2, %eax
+; X86-64-NEXT: negl %eax
+; X86-64-NEXT: jo .LBB6_2
+; X86-64-NEXT: # %bb.1:
+; X86-64-NEXT: movaps %xmm4, %xmm2
+; X86-64-NEXT: .LBB6_2:
+; X86-64-NEXT: movaps %xmm1, %xmm0
+; X86-64-NEXT: andnps %xmm4, %xmm0
+; X86-64-NEXT: movd %xmm3, %eax
+; X86-64-NEXT: negl %eax
+; X86-64-NEXT: jo .LBB6_4
+; X86-64-NEXT: # %bb.3:
+; X86-64-NEXT: movaps %xmm2, %xmm3
+; X86-64-NEXT: .LBB6_4:
+; X86-64-NEXT: andps %xmm3, %xmm1
+; X86-64-NEXT: orps %xmm1, %xmm0
+; X86-64-NEXT: retq
+;
+; I386-LABEL: minimumnum_float:
+; I386: # %bb.0:
+; I386-NEXT: subl $8, %esp
+; I386-NEXT: .cfi_def_cfa_offset 12
+; I386-NEXT: flds {{[0-9]+}}(%esp)
+; I386-NEXT: flds {{[0-9]+}}(%esp)
+; I386-NEXT: fucom %st(0)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: fld %st(1)
+; I386-NEXT: jp .LBB6_2
+; I386-NEXT: # %bb.1:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: .LBB6_2:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fsts {{[0-9]+}}(%esp)
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(0)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: fld %st(1)
+; I386-NEXT: jp .LBB6_4
+; I386-NEXT: # %bb.3:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: .LBB6_4:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fsts (%esp)
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(1)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: fld %st(0)
+; I386-NEXT: jb .LBB6_6
+; I386-NEXT: # %bb.5:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: fld %st(1)
+; I386-NEXT: .LBB6_6:
+; I386-NEXT: fld %st(0)
+; I386-NEXT: fadd %st(1), %st
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(0)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: jp .LBB6_8
+; I386-NEXT: # %bb.7:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fldz
+; I386-NEXT: .LBB6_8:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: xorl %eax, %eax
+; I386-NEXT: cmpl {{[0-9]+}}(%esp), %eax
+; I386-NEXT: jo .LBB6_10
+; I386-NEXT: # %bb.9:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fld %st(0)
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: .LBB6_10:
+; I386-NEXT: cmpl (%esp), %eax
+; I386-NEXT: jo .LBB6_12
+; I386-NEXT: # %bb.11:
+; I386-NEXT: fstp %st(2)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fxch %st(2)
+; I386-NEXT: .LBB6_12:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(1)
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: je .LBB6_14
+; I386-NEXT: # %bb.13:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fldz
+; I386-NEXT: .LBB6_14:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: addl $8, %esp
+; I386-NEXT: .cfi_def_cfa_offset 4
+; I386-NEXT: retl
+;
+; SSE2-LABEL: minimumnum_float:
+; SSE2: # %bb.0:
+; SSE2-NEXT: pushl %eax
+; SSE2-NEXT: .cfi_def_cfa_offset 8
+; SSE2-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
+; SSE2-NEXT: movss {{.*#+}} xmm2 = mem[0],zero,zero,zero
+; SSE2-NEXT: movaps %xmm1, %xmm0
+; SSE2-NEXT: cmpunordss %xmm1, %xmm0
+; SSE2-NEXT: movaps %xmm0, %xmm3
+; SSE2-NEXT: andps %xmm2, %xmm3
+; SSE2-NEXT: andnps %xmm1, %xmm0
+; SSE2-NEXT: orps %xmm3, %xmm0
+; SSE2-NEXT: movaps %xmm2, %xmm1
+; SSE2-NEXT: cmpunordss %xmm2, %xmm1
+; SSE2-NEXT: movaps %xmm1, %xmm3
+; SSE2-NEXT: andps %xmm0, %xmm3
+; SSE2-NEXT: andnps %xmm2, %xmm1
+; SSE2-NEXT: orps %xmm3, %xmm1
+; SSE2-NEXT: movaps %xmm0, %xmm2
+; SSE2-NEXT: cmpltss %xmm1, %xmm2
+; SSE2-NEXT: movaps %xmm2, %xmm3
+; SSE2-NEXT: andps %xmm0, %xmm3
+; SSE2-NEXT: andnps %xmm1, %xmm2
+; SSE2-NEXT: orps %xmm3, %xmm2
+; SSE2-NEXT: movaps %xmm2, %xmm4
+; SSE2-NEXT: addss %xmm2, %xmm4
+; SSE2-NEXT: movaps %xmm2, %xmm3
+; SSE2-NEXT: cmpunordss %xmm2, %xmm3
+; SSE2-NEXT: andps %xmm3, %xmm4
+; SSE2-NEXT: andnps %xmm2, %xmm3
+; SSE2-NEXT: orps %xmm4, %xmm3
+; SSE2-NEXT: xorps %xmm2, %xmm2
+; SSE2-NEXT: cmpeqss %xmm3, %xmm2
+; SSE2-NEXT: movd %xmm0, %eax
+; SSE2-NEXT: negl %eax
+; SSE2-NEXT: jo .LBB6_2
+; SSE2-NEXT: # %bb.1:
+; SSE2-NEXT: movaps %xmm3, %xmm0
+; SSE2-NEXT: .LBB6_2:
+; SSE2-NEXT: movaps %xmm2, %xmm4
+; SSE2-NEXT: andnps %xmm3, %xmm4
+; SSE2-NEXT: movd %xmm1, %eax
+; SSE2-NEXT: negl %eax
+; SSE2-NEXT: jo .LBB6_4
+; SSE2-NEXT: # %bb.3:
+; SSE2-NEXT: movaps %xmm0, %xmm1
+; SSE2-NEXT: .LBB6_4:
+; SSE2-NEXT: andps %xmm1, %xmm2
+; SSE2-NEXT: orps %xmm2, %xmm4
+; SSE2-NEXT: movss %xmm4, (%esp)
+; SSE2-NEXT: flds (%esp)
+; SSE2-NEXT: popl %eax
+; SSE2-NEXT: .cfi_def_cfa_offset 4
+; SSE2-NEXT: retl
+;
+; AVX-LABEL: minimumnum_float:
+; AVX: # %bb.0:
+; AVX-NEXT: pushl %eax
+; AVX-NEXT: .cfi_def_cfa_offset 8
+; AVX-NEXT: vmovss {{.*#+}} xmm0 = mem[0],zero,zero,zero
+; AVX-NEXT: vmovss {{.*#+}} xmm2 = mem[0],zero,zero,zero
+; AVX-NEXT: vcmpunordss %xmm0, %xmm0, %xmm1
+; AVX-NEXT: vblendvps %xmm1, %xmm2, %xmm0, %xmm1
+; AVX-NEXT: vcmpunordss %xmm2, %xmm2, %xmm0
+; AVX-NEXT: vblendvps %xmm0, %xmm1, %xmm2, %xmm0
+; AVX-NEXT: vcmpltss %xmm0, %xmm1, %xmm2
+; AVX-NEXT: vblendvps %xmm2, %xmm1, %xmm0, %xmm2
+; AVX-NEXT: vcmpunordss %xmm2, %xmm2, %xmm3
+; AVX-NEXT: vaddss %xmm2, %xmm2, %xmm4
+; AVX-NEXT: vblendvps %xmm3, %xmm4, %xmm2, %xmm2
+; AVX-NEXT: vxorps %xmm3, %xmm3, %xmm3
+; AVX-NEXT: vmovd %xmm1, %eax
+; AVX-NEXT: negl %eax
+; AVX-NEXT: jo .LBB6_2
+; AVX-NEXT: # %bb.1:
+; AVX-NEXT: vmovaps %xmm2, %xmm1
+; AVX-NEXT: .LBB6_2:
+; AVX-NEXT: vcmpeqss %xmm3, %xmm2, %xmm3
+; AVX-NEXT: vmovd %xmm0, %eax
+; AVX-NEXT: negl %eax
+; AVX-NEXT: jo .LBB6_4
+; AVX-NEXT: # %bb.3:
+; AVX-NEXT: vmovaps %xmm1, %xmm0
+; AVX-NEXT: .LBB6_4:
+; AVX-NEXT: vblendvps %xmm3, %xmm0, %xmm2, %xmm0
+; AVX-NEXT: vmovss %xmm0, (%esp)
+; AVX-NEXT: flds (%esp)
+; AVX-NEXT: popl %eax
+; AVX-NEXT: .cfi_def_cfa_offset 4
+; AVX-NEXT: retl
+ %z = call float @llvm.minimumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+define float @minimumnum_float_nsz(float %x, float %y) {
+;
+; X86-64-LABEL: minimumnum_float_nsz:
+; X86-64: # %bb.0:
+; X86-64-NEXT: movaps %xmm0, %xmm2
+; X86-64-NEXT: cmpunordss %xmm0, %xmm2
+; X86-64-NEXT: movaps %xmm2, %xmm3
+; X86-64-NEXT: andps %xmm1, %xmm3
+; X86-64-NEXT: andnps %xmm0, %xmm2
+; X86-64-NEXT: orps %xmm3, %xmm2
+; X86-64-NEXT: movaps %xmm1, %xmm0
+; X86-64-NEXT: cmpunordss %xmm1, %xmm0
+; X86-64-NEXT: movaps %xmm0, %xmm3
+; X86-64-NEXT: andps %xmm2, %xmm3
+; X86-64-NEXT: andnps %xmm1, %xmm0
+; X86-64-NEXT: orps %xmm3, %xmm0
+; X86-64-NEXT: movaps %xmm2, %xmm1
+; X86-64-NEXT: cmpltss %xmm0, %xmm1
+; X86-64-NEXT: andps %xmm1, %xmm2
+; X86-64-NEXT: andnps %xmm0, %xmm1
+; X86-64-NEXT: orps %xmm2, %xmm1
+; X86-64-NEXT: movaps %xmm1, %xmm2
+; X86-64-NEXT: addss %xmm1, %xmm2
+; X86-64-NEXT: movaps %xmm1, %xmm0
+; X86-64-NEXT: cmpunordss %xmm1, %xmm0
+; X86-64-NEXT: andps %xmm0, %xmm2
+; X86-64-NEXT: andnps %xmm1, %xmm0
+; X86-64-NEXT: orps %xmm2, %xmm0
+; X86-64-NEXT: retq
+;
+; I386-LABEL: minimumnum_float_nsz:
+; I386: # %bb.0:
+; I386-NEXT: flds {{[0-9]+}}(%esp)
+; I386-NEXT: flds {{[0-9]+}}(%esp)
+; I386-NEXT: fucom %st(0)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: fld %st(1)
+; I386-NEXT: jp .LBB7_2
+; I386-NEXT: # %bb.1:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: .LBB7_2:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(0)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: fld %st(1)
+; I386-NEXT: jp .LBB7_4
+; I386-NEXT: # %bb.3:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: .LBB7_4:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(1)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: jb .LBB7_6
+; I386-NEXT: # %bb.5:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: .LBB7_6:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fld %st(0)
+; I386-NEXT: fadd %st(1), %st
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(0)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: jp .LBB7_8
+; I386-NEXT: # %bb.7:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fldz
+; I386-NEXT: .LBB7_8:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: retl
+;
+; SSE2-LABEL: minimumnum_float_nsz:
+; SSE2: # %bb.0:
+; SSE2-NEXT: pushl %eax
+; SSE2-NEXT: .cfi_def_cfa_offset 8
+; SSE2-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
+; SSE2-NEXT: movss {{.*#+}} xmm2 = mem[0],zero,zero,zero
+; SSE2-NEXT: movaps %xmm1, %xmm0
+; SSE2-NEXT: cmpunordss %xmm1, %xmm0
+; SSE2-NEXT: movaps %xmm0, %xmm3
+; SSE2-NEXT: andps %xmm2, %xmm3
+; SSE2-NEXT: andnps %xmm1, %xmm0
+; SSE2-NEXT: orps %xmm3, %xmm0
+; SSE2-NEXT: movaps %xmm2, %xmm1
+; SSE2-NEXT: cmpunordss %xmm2, %xmm1
+; SSE2-NEXT: movaps %xmm1, %xmm3
+; SSE2-NEXT: andps %xmm0, %xmm3
+; SSE2-NEXT: andnps %xmm2, %xmm1
+; SSE2-NEXT: orps %xmm3, %xmm1
+; SSE2-NEXT: movaps %xmm0, %xmm2
+; SSE2-NEXT: cmpltss %xmm1, %xmm2
+; SSE2-NEXT: andps %xmm2, %xmm0
+; SSE2-NEXT: andnps %xmm1, %xmm2
+; SSE2-NEXT: orps %xmm0, %xmm2
+; SSE2-NEXT: movaps %xmm2, %xmm0
+; SSE2-NEXT: addss %xmm2, %xmm0
+; SSE2-NEXT: movaps %xmm2, %xmm1
+; SSE2-NEXT: cmpunordss %xmm2, %xmm1
+; SSE2-NEXT: andps %xmm1, %xmm0
+; SSE2-NEXT: andnps %xmm2, %xmm1
+; SSE2-NEXT: orps %xmm0, %xmm1
+; SSE2-NEXT: movss %xmm1, (%esp)
+; SSE2-NEXT: flds (%esp)
+; SSE2-NEXT: popl %eax
+; SSE2-NEXT: .cfi_def_cfa_offset 4
+; SSE2-NEXT: retl
+;
+; AVX-LABEL: minimumnum_float_nsz:
+; AVX: # %bb.0:
+; AVX-NEXT: pushl %eax
+; AVX-NEXT: .cfi_def_cfa_offset 8
+; AVX-NEXT: vmovss {{.*#+}} xmm0 = mem[0],zero,zero,zero
+; AVX-NEXT: vmovss {{.*#+}} xmm1 = mem[0],zero,zero,zero
+; AVX-NEXT: vcmpunordss %xmm0, %xmm0, %xmm2
+; AVX-NEXT: vblendvps %xmm2, %xmm1, %xmm0, %xmm0
+; AVX-NEXT: vcmpunordss %xmm1, %xmm1, %xmm2
+; AVX-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm1
+; AVX-NEXT: vcmpltss %xmm1, %xmm0, %xmm2
+; AVX-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm0
+; AVX-NEXT: vcmpunordss %xmm0, %xmm0, %xmm1
+; AVX-NEXT: vaddss %xmm0, %xmm0, %xmm2
+; AVX-NEXT: vblendvps %xmm1, %xmm2, %xmm0, %xmm0
+; AVX-NEXT: vmovss %xmm0, (%esp)
+; AVX-NEXT: flds (%esp)
+; AVX-NEXT: popl %eax
+; AVX-NEXT: .cfi_def_cfa_offset 4
+; AVX-NEXT: retl
+ %z = call nsz float @llvm.minimumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+define float @minimumnum_float_nnan(float %x, float %y) {
+;
+; X86-64-LABEL: minimumnum_float_nnan:
+; X86-64: # %bb.0:
+; X86-64-NEXT: movd %xmm0, %eax
+; X86-64-NEXT: testl %eax, %eax
+; X86-64-NEXT: js .LBB8_1
+; X86-64-NEXT: # %bb.2:
+; X86-64-NEXT: minss %xmm1, %xmm0
+; X86-64-NEXT: retq
+; X86-64-NEXT: .LBB8_1:
+; X86-64-NEXT: movdqa %xmm0, %xmm2
+; X86-64-NEXT: movaps %xmm1, %xmm0
+; X86-64-NEXT: minss %xmm2, %xmm0
+; X86-64-NEXT: retq
+;
+; I386-LABEL: minimumnum_float_nnan:
+; I386: # %bb.0:
+; I386-NEXT: subl $8, %esp
+; I386-NEXT: .cfi_def_cfa_offset 12
+; I386-NEXT: flds {{[0-9]+}}(%esp)
+; I386-NEXT: fsts {{[0-9]+}}(%esp)
+; I386-NEXT: flds {{[0-9]+}}(%esp)
+; I386-NEXT: fsts (%esp)
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(1)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: fld %st(0)
+; I386-NEXT: jb .LBB8_2
+; I386-NEXT: # %bb.1:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: fld %st(1)
+; I386-NEXT: .LBB8_2:
+; I386-NEXT: xorl %eax, %eax
+; I386-NEXT: cmpl {{[0-9]+}}(%esp), %eax
+; I386-NEXT: jo .LBB8_4
+; I386-NEXT: # %bb.3:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fld %st(0)
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: .LBB8_4:
+; I386-NEXT: cmpl (%esp), %eax
+; I386-NEXT: jo .LBB8_6
+; I386-NEXT: # %bb.5:
+; I386-NEXT: fstp %st(2)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fxch %st(2)
+; I386-NEXT: .LBB8_6:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(1)
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: je .LBB8_8
+; I386-NEXT: # %bb.7:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fldz
+; I386-NEXT: .LBB8_8:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: addl $8, %esp
+; I386-NEXT: .cfi_def_cfa_offset 4
+; I386-NEXT: retl
+;
+; SSE2-LABEL: minimumnum_float_nnan:
+; SSE2: # %bb.0:
+; SSE2-NEXT: pushl %eax
+; SSE2-NEXT: .cfi_def_cfa_offset 8
+; SSE2-NEXT: movd {{.*#+}} xmm2 = mem[0],zero,zero,zero
+; SSE2-NEXT: movd {{.*#+}} xmm0 = mem[0],zero,zero,zero
+; SSE2-NEXT: movd %xmm0, %eax
+; SSE2-NEXT: testl %eax, %eax
+; SSE2-NEXT: js .LBB8_1
+; SSE2-NEXT: # %bb.2:
+; SSE2-NEXT: movdqa %xmm2, %xmm1
+; SSE2-NEXT: jmp .LBB8_3
+; SSE2-NEXT: .LBB8_1:
+; SSE2-NEXT: movdqa %xmm0, %xmm1
+; SSE2-NEXT: movdqa %xmm2, %xmm0
+; SSE2-NEXT: .LBB8_3:
+; SSE2-NEXT: minss %xmm1, %xmm0
+; SSE2-NEXT: movss %xmm0, (%esp)
+; SSE2-NEXT: flds (%esp)
+; SSE2-NEXT: popl %eax
+; SSE2-NEXT: .cfi_def_cfa_offset 4
+; SSE2-NEXT: retl
+;
+; AVX-LABEL: minimumnum_float_nnan:
+; AVX: # %bb.0:
+; AVX-NEXT: pushl %eax
+; AVX-NEXT: .cfi_def_cfa_offset 8
+; AVX-NEXT: vmovd {{.*#+}} xmm1 = mem[0],zero,zero,zero
+; AVX-NEXT: vmovd {{.*#+}} xmm0 = mem[0],zero,zero,zero
+; AVX-NEXT: vmovd %xmm0, %eax
+; AVX-NEXT: testl %eax, %eax
+; AVX-NEXT: js .LBB8_1
+; AVX-NEXT: # %bb.2:
+; AVX-NEXT: vmovdqa %xmm1, %xmm2
+; AVX-NEXT: jmp .LBB8_3
+; AVX-NEXT: .LBB8_1:
+; AVX-NEXT: vmovdqa %xmm0, %xmm2
+; AVX-NEXT: vmovdqa %xmm1, %xmm0
+; AVX-NEXT: .LBB8_3:
+; AVX-NEXT: vminss %xmm2, %xmm0, %xmm0
+; AVX-NEXT: vmovss %xmm0, (%esp)
+; AVX-NEXT: flds (%esp)
+; AVX-NEXT: popl %eax
+; AVX-NEXT: .cfi_def_cfa_offset 4
+; AVX-NEXT: retl
+ %z = call nnan float @llvm.minimumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+define double @minimumnum_double(double %x, double %y) {
+;
+; X86-64-LABEL: minimumnum_double:
+; X86-64: # %bb.0:
+; X86-64-NEXT: movapd %xmm0, %xmm2
+; X86-64-NEXT: cmpunordsd %xmm0, %xmm2
+; X86-64-NEXT: movapd %xmm2, %xmm3
+; X86-64-NEXT: andpd %xmm1, %xmm3
+; X86-64-NEXT: andnpd %xmm0, %xmm2
+; X86-64-NEXT: orpd %xmm3, %xmm2
+; X86-64-NEXT: movapd %xmm1, %xmm3
+; X86-64-NEXT: cmpunordsd %xmm1, %xmm3
+; X86-64-NEXT: movapd %xmm3, %xmm0
+; X86-64-NEXT: andpd %xmm2, %xmm0
+; X86-64-NEXT: andnpd %xmm1, %xmm3
+; X86-64-NEXT: orpd %xmm0, %xmm3
+; X86-64-NEXT: movapd %xmm2, %xmm0
+; X86-64-NEXT: cmpltsd %xmm3, %xmm0
+; X86-64-NEXT: movapd %xmm0, %xmm1
+; X86-64-NEXT: andpd %xmm2, %xmm1
+; X86-64-NEXT: andnpd %xmm3, %xmm0
+; X86-64-NEXT: orpd %xmm1, %xmm0
+; X86-64-NEXT: movapd %xmm0, %xmm1
+; X86-64-NEXT: addsd %xmm0, %xmm1
+; X86-64-NEXT: movapd %xmm0, %xmm4
+; X86-64-NEXT: cmpunordsd %xmm0, %xmm4
+; X86-64-NEXT: andpd %xmm4, %xmm1
+; X86-64-NEXT: andnpd %xmm0, %xmm4
+; X86-64-NEXT: orpd %xmm1, %xmm4
+; X86-64-NEXT: xorpd %xmm1, %xmm1
+; X86-64-NEXT: cmpeqsd %xmm4, %xmm1
+; X86-64-NEXT: movq %xmm2, %rax
+; X86-64-NEXT: negq %rax
+; X86-64-NEXT: jo .LBB9_2
+; X86-64-NEXT: # %bb.1:
+; X86-64-NEXT: movapd %xmm4, %xmm2
+; X86-64-NEXT: .LBB9_2:
+; X86-64-NEXT: movapd %xmm1, %xmm0
+; X86-64-NEXT: andnpd %xmm4, %xmm0
+; X86-64-NEXT: movq %xmm3, %rax
+; X86-64-NEXT: negq %rax
+; X86-64-NEXT: jo .LBB9_4
+; X86-64-NEXT: # %bb.3:
+; X86-64-NEXT: movapd %xmm2, %xmm3
+; X86-64-NEXT: .LBB9_4:
+; X86-64-NEXT: andpd %xmm3, %xmm1
+; X86-64-NEXT: orpd %xmm1, %xmm0
+; X86-64-NEXT: retq
+;
+; I386-LABEL: minimumnum_double:
+; I386: # %bb.0:
+; I386-NEXT: subl $16, %esp
+; I386-NEXT: .cfi_def_cfa_offset 20
+; I386-NEXT: fldl {{[0-9]+}}(%esp)
+; I386-NEXT: fldl {{[0-9]+}}(%esp)
+; I386-NEXT: fucom %st(0)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: fld %st(1)
+; I386-NEXT: jp .LBB9_2
+; I386-NEXT: # %bb.1:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: .LBB9_2:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fsts {{[0-9]+}}(%esp)
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(0)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: fld %st(1)
+; I386-NEXT: jp .LBB9_4
+; I386-NEXT: # %bb.3:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: .LBB9_4:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fsts (%esp)
+; I386-NEXT: flds {{[0-9]+}}(%esp)
+; I386-NEXT: fstps {{[0-9]+}}(%esp)
+; I386-NEXT: flds (%esp)
+; I386-NEXT: fstps {{[0-9]+}}(%esp)
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(1)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: fld %st(0)
+; I386-NEXT: jb .LBB9_6
+; I386-NEXT: # %bb.5:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: fld %st(1)
+; I386-NEXT: .LBB9_6:
+; I386-NEXT: fld %st(0)
+; I386-NEXT: fadd %st(1), %st
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(0)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: jp .LBB9_8
+; I386-NEXT: # %bb.7:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fldz
+; I386-NEXT: .LBB9_8:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: xorl %eax, %eax
+; I386-NEXT: cmpl {{[0-9]+}}(%esp), %eax
+; I386-NEXT: jo .LBB9_10
+; I386-NEXT: # %bb.9:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fld %st(0)
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: .LBB9_10:
+; I386-NEXT: cmpl {{[0-9]+}}(%esp), %eax
+; I386-NEXT: jo .LBB9_12
+; I386-NEXT: # %bb.11:
+; I386-NEXT: fstp %st(2)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fxch %st(2)
+; I386-NEXT: .LBB9_12:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(1)
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: je .LBB9_14
+; I386-NEXT: # %bb.13:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fldz
+; I386-NEXT: .LBB9_14:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: addl $16, %esp
+; I386-NEXT: .cfi_def_cfa_offset 4
+; I386-NEXT: retl
+;
+; SSE2-LABEL: minimumnum_double:
+; SSE2: # %bb.0:
+; SSE2-NEXT: pushl %ebp
+; SSE2-NEXT: .cfi_def_cfa_offset 8
+; SSE2-NEXT: .cfi_offset %ebp, -8
+; SSE2-NEXT: movl %esp, %ebp
+; SSE2-NEXT: .cfi_def_cfa_register %ebp
+; SSE2-NEXT: andl $-8, %esp
+; SSE2-NEXT: subl $8, %esp
+; SSE2-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero
+; SSE2-NEXT: movsd {{.*#+}} xmm2 = mem[0],zero
+; SSE2-NEXT: movapd %xmm1, %xmm0
+; SSE2-NEXT: cmpunordsd %xmm1, %xmm0
+; SSE2-NEXT: movapd %xmm0, %xmm3
+; SSE2-NEXT: andpd %xmm2, %xmm3
+; SSE2-NEXT: andnpd %xmm1, %xmm0
+; SSE2-NEXT: orpd %xmm3, %xmm0
+; SSE2-NEXT: movapd %xmm2, %xmm1
+; SSE2-NEXT: cmpunordsd %xmm2, %xmm1
+; SSE2-NEXT: movapd %xmm1, %xmm3
+; SSE2-NEXT: andpd %xmm0, %xmm3
+; SSE2-NEXT: andnpd %xmm2, %xmm1
+; SSE2-NEXT: orpd %xmm3, %xmm1
+; SSE2-NEXT: movapd %xmm0, %xmm2
+; SSE2-NEXT: cmpltsd %xmm1, %xmm2
+; SSE2-NEXT: movapd %xmm2, %xmm3
+; SSE2-NEXT: andpd %xmm0, %xmm3
+; SSE2-NEXT: andnpd %xmm1, %xmm2
+; SSE2-NEXT: orpd %xmm3, %xmm2
+; SSE2-NEXT: movapd %xmm2, %xmm4
+; SSE2-NEXT: addsd %xmm2, %xmm4
+; SSE2-NEXT: movapd %xmm2, %xmm3
+; SSE2-NEXT: cmpunordsd %xmm2, %xmm3
+; SSE2-NEXT: andpd %xmm3, %xmm4
+; SSE2-NEXT: andnpd %xmm2, %xmm3
+; SSE2-NEXT: orpd %xmm4, %xmm3
+; SSE2-NEXT: xorpd %xmm2, %xmm2
+; SSE2-NEXT: cmpeqsd %xmm3, %xmm2
+; SSE2-NEXT: xorps %xmm4, %xmm4
+; SSE2-NEXT: cvtsd2ss %xmm0, %xmm4
+; SSE2-NEXT: movd %xmm4, %eax
+; SSE2-NEXT: negl %eax
+; SSE2-NEXT: jo .LBB9_2
+; SSE2-NEXT: # %bb.1:
+; SSE2-NEXT: movapd %xmm3, %xmm0
+; SSE2-NEXT: .LBB9_2:
+; SSE2-NEXT: movapd %xmm2, %xmm4
+; SSE2-NEXT: andnpd %xmm3, %xmm4
+; SSE2-NEXT: xorps %xmm3, %xmm3
+; SSE2-NEXT: cvtsd2ss %xmm1, %xmm3
+; SSE2-NEXT: movd %xmm3, %eax
+; SSE2-NEXT: negl %eax
+; SSE2-NEXT: jo .LBB9_4
+; SSE2-NEXT: # %bb.3:
+; SSE2-NEXT: movaps %xmm0, %xmm1
+; SSE2-NEXT: .LBB9_4:
+; SSE2-NEXT: andpd %xmm1, %xmm2
+; SSE2-NEXT: orpd %xmm2, %xmm4
+; SSE2-NEXT: movlpd %xmm4, (%esp)
+; SSE2-NEXT: fldl (%esp)
+; SSE2-NEXT: movl %ebp, %esp
+; SSE2-NEXT: popl %ebp
+; SSE2-NEXT: .cfi_def_cfa %esp, 4
+; SSE2-NEXT: retl
+;
+; AVX-LABEL: minimumnum_double:
+; AVX: # %bb.0:
+; AVX-NEXT: pushl %ebp
+; AVX-NEXT: .cfi_def_cfa_offset 8
+; AVX-NEXT: .cfi_offset %ebp, -8
+; AVX-NEXT: movl %esp, %ebp
+; AVX-NEXT: .cfi_def_cfa_register %ebp
+; AVX-NEXT: andl $-8, %esp
+; AVX-NEXT: subl $8, %esp
+; AVX-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
+; AVX-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero
+; AVX-NEXT: vcmpunordsd %xmm0, %xmm0, %xmm1
+; AVX-NEXT: vblendvpd %xmm1, %xmm2, %xmm0, %xmm1
+; AVX-NEXT: vcmpunordsd %xmm2, %xmm2, %xmm0
+; AVX-NEXT: vblendvpd %xmm0, %xmm1, %xmm2, %xmm0
+; AVX-NEXT: vcmpltsd %xmm0, %xmm1, %xmm2
+; AVX-NEXT: vblendvpd %xmm2, %xmm1, %xmm0, %xmm2
+; AVX-NEXT: vcmpunordsd %xmm2, %xmm2, %xmm3
+; AVX-NEXT: vaddsd %xmm2, %xmm2, %xmm4
+; AVX-NEXT: vblendvpd %xmm3, %xmm4, %xmm2, %xmm2
+; AVX-NEXT: vxorpd %xmm3, %xmm3, %xmm3
+; AVX-NEXT: vcvtsd2ss %xmm1, %xmm1, %xmm4
+; AVX-NEXT: vmovd %xmm4, %eax
+; AVX-NEXT: negl %eax
+; AVX-NEXT: jo .LBB9_2
+; AVX-NEXT: # %bb.1:
+; AVX-NEXT: vmovapd %xmm2, %xmm1
+; AVX-NEXT: .LBB9_2:
+; AVX-NEXT: vcmpeqsd %xmm3, %xmm2, %xmm3
+; AVX-NEXT: vcvtsd2ss %xmm0, %xmm0, %xmm4
+; AVX-NEXT: vmovd %xmm4, %eax
+; AVX-NEXT: negl %eax
+; AVX-NEXT: jo .LBB9_4
+; AVX-NEXT: # %bb.3:
+; AVX-NEXT: vmovaps %xmm1, %xmm0
+; AVX-NEXT: .LBB9_4:
+; AVX-NEXT: vblendvpd %xmm3, %xmm0, %xmm2, %xmm0
+; AVX-NEXT: vmovlpd %xmm0, (%esp)
+; AVX-NEXT: fldl (%esp)
+; AVX-NEXT: movl %ebp, %esp
+; AVX-NEXT: popl %ebp
+; AVX-NEXT: .cfi_def_cfa %esp, 4
+; AVX-NEXT: retl
+ %z = call double @llvm.minimumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define double @minimumnum_double_nsz(double %x, double %y) {
+;
+; X86-64-LABEL: minimumnum_double_nsz:
+; X86-64: # %bb.0:
+; X86-64-NEXT: movapd %xmm0, %xmm2
+; X86-64-NEXT: cmpunordsd %xmm0, %xmm2
+; X86-64-NEXT: movapd %xmm2, %xmm3
+; X86-64-NEXT: andpd %xmm1, %xmm3
+; X86-64-NEXT: andnpd %xmm0, %xmm2
+; X86-64-NEXT: orpd %xmm3, %xmm2
+; X86-64-NEXT: movapd %xmm1, %xmm0
+; X86-64-NEXT: cmpunordsd %xmm1, %xmm0
+; X86-64-NEXT: movapd %xmm0, %xmm3
+; X86-64-NEXT: andpd %xmm2, %xmm3
+; X86-64-NEXT: andnpd %xmm1, %xmm0
+; X86-64-NEXT: orpd %xmm3, %xmm0
+; X86-64-NEXT: movapd %xmm2, %xmm1
+; X86-64-NEXT: cmpltsd %xmm0, %xmm1
+; X86-64-NEXT: andpd %xmm1, %xmm2
+; X86-64-NEXT: andnpd %xmm0, %xmm1
+; X86-64-NEXT: orpd %xmm2, %xmm1
+; X86-64-NEXT: movapd %xmm1, %xmm2
+; X86-64-NEXT: addsd %xmm1, %xmm2
+; X86-64-NEXT: movapd %xmm1, %xmm0
+; X86-64-NEXT: cmpunordsd %xmm1, %xmm0
+; X86-64-NEXT: andpd %xmm0, %xmm2
+; X86-64-NEXT: andnpd %xmm1, %xmm0
+; X86-64-NEXT: orpd %xmm2, %xmm0
+; X86-64-NEXT: retq
+;
+; I386-LABEL: minimumnum_double_nsz:
+; I386: # %bb.0:
+; I386-NEXT: fldl {{[0-9]+}}(%esp)
+; I386-NEXT: fldl {{[0-9]+}}(%esp)
+; I386-NEXT: fucom %st(0)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: fld %st(1)
+; I386-NEXT: jp .LBB10_2
+; I386-NEXT: # %bb.1:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: .LBB10_2:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(0)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: fld %st(1)
+; I386-NEXT: jp .LBB10_4
+; I386-NEXT: # %bb.3:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: .LBB10_4:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(1)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: jb .LBB10_6
+; I386-NEXT: # %bb.5:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: .LBB10_6:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fld %st(0)
+; I386-NEXT: fadd %st(1), %st
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(0)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: jp .LBB10_8
+; I386-NEXT: # %bb.7:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fldz
+; I386-NEXT: .LBB10_8:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: retl
+;
+; SSE2-LABEL: minimumnum_double_nsz:
+; SSE2: # %bb.0:
+; SSE2-NEXT: pushl %ebp
+; SSE2-NEXT: .cfi_def_cfa_offset 8
+; SSE2-NEXT: .cfi_offset %ebp, -8
+; SSE2-NEXT: movl %esp, %ebp
+; SSE2-NEXT: .cfi_def_cfa_register %ebp
+; SSE2-NEXT: andl $-8, %esp
+; SSE2-NEXT: subl $8, %esp
+; SSE2-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero
+; SSE2-NEXT: movsd {{.*#+}} xmm2 = mem[0],zero
+; SSE2-NEXT: movapd %xmm1, %xmm0
+; SSE2-NEXT: cmpunordsd %xmm1, %xmm0
+; SSE2-NEXT: movapd %xmm0, %xmm3
+; SSE2-NEXT: andpd %xmm2, %xmm3
+; SSE2-NEXT: andnpd %xmm1, %xmm0
+; SSE2-NEXT: orpd %xmm3, %xmm0
+; SSE2-NEXT: movapd %xmm2, %xmm1
+; SSE2-NEXT: cmpunordsd %xmm2, %xmm1
+; SSE2-NEXT: movapd %xmm1, %xmm3
+; SSE2-NEXT: andpd %xmm0, %xmm3
+; SSE2-NEXT: andnpd %xmm2, %xmm1
+; SSE2-NEXT: orpd %xmm3, %xmm1
+; SSE2-NEXT: movapd %xmm0, %xmm2
+; SSE2-NEXT: cmpltsd %xmm1, %xmm2
+; SSE2-NEXT: andpd %xmm2, %xmm0
+; SSE2-NEXT: andnpd %xmm1, %xmm2
+; SSE2-NEXT: orpd %xmm0, %xmm2
+; SSE2-NEXT: movapd %xmm2, %xmm0
+; SSE2-NEXT: addsd %xmm2, %xmm0
+; SSE2-NEXT: movapd %xmm2, %xmm1
+; SSE2-NEXT: cmpunordsd %xmm2, %xmm1
+; SSE2-NEXT: andpd %xmm1, %xmm0
+; SSE2-NEXT: andnpd %xmm2, %xmm1
+; SSE2-NEXT: orpd %xmm0, %xmm1
+; SSE2-NEXT: movlpd %xmm1, (%esp)
+; SSE2-NEXT: fldl (%esp)
+; SSE2-NEXT: movl %ebp, %esp
+; SSE2-NEXT: popl %ebp
+; SSE2-NEXT: .cfi_def_cfa %esp, 4
+; SSE2-NEXT: retl
+;
+; AVX-LABEL: minimumnum_double_nsz:
+; AVX: # %bb.0:
+; AVX-NEXT: pushl %ebp
+; AVX-NEXT: .cfi_def_cfa_offset 8
+; AVX-NEXT: .cfi_offset %ebp, -8
+; AVX-NEXT: movl %esp, %ebp
+; AVX-NEXT: .cfi_def_cfa_register %ebp
+; AVX-NEXT: andl $-8, %esp
+; AVX-NEXT: subl $8, %esp
+; AVX-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
+; AVX-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero
+; AVX-NEXT: vcmpunordsd %xmm0, %xmm0, %xmm2
+; AVX-NEXT: vblendvpd %xmm2, %xmm1, %xmm0, %xmm0
+; AVX-NEXT: vcmpunordsd %xmm1, %xmm1, %xmm2
+; AVX-NEXT: vblendvpd %xmm2, %xmm0, %xmm1, %xmm1
+; AVX-NEXT: vcmpltsd %xmm1, %xmm0, %xmm2
+; AVX-NEXT: vblendvpd %xmm2, %xmm0, %xmm1, %xmm0
+; AVX-NEXT: vcmpunordsd %xmm0, %xmm0, %xmm1
+; AVX-NEXT: vaddsd %xmm0, %xmm0, %xmm2
+; AVX-NEXT: vblendvpd %xmm1, %xmm2, %xmm0, %xmm0
+; AVX-NEXT: vmovlpd %xmm0, (%esp)
+; AVX-NEXT: fldl (%esp)
+; AVX-NEXT: movl %ebp, %esp
+; AVX-NEXT: popl %ebp
+; AVX-NEXT: .cfi_def_cfa %esp, 4
+; AVX-NEXT: retl
+ %z = call nsz double @llvm.minimumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define double @minimumnum_double_nnan(double %x, double %y) {
+;
+; X86-64-LABEL: minimumnum_double_nnan:
+; X86-64: # %bb.0:
+; X86-64-NEXT: movq %xmm0, %rax
+; X86-64-NEXT: testq %rax, %rax
+; X86-64-NEXT: js .LBB11_1
+; X86-64-NEXT: # %bb.2:
+; X86-64-NEXT: minsd %xmm1, %xmm0
+; X86-64-NEXT: retq
+; X86-64-NEXT: .LBB11_1:
+; X86-64-NEXT: movdqa %xmm0, %xmm2
+; X86-64-NEXT: movapd %xmm1, %xmm0
+; X86-64-NEXT: minsd %xmm2, %xmm0
+; X86-64-NEXT: retq
+;
+; I386-LABEL: minimumnum_double_nnan:
+; I386: # %bb.0:
+; I386-NEXT: subl $16, %esp
+; I386-NEXT: .cfi_def_cfa_offset 20
+; I386-NEXT: fldl {{[0-9]+}}(%esp)
+; I386-NEXT: fldl {{[0-9]+}}(%esp)
+; I386-NEXT: fsts {{[0-9]+}}(%esp)
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fsts (%esp)
+; I386-NEXT: flds {{[0-9]+}}(%esp)
+; I386-NEXT: fstps {{[0-9]+}}(%esp)
+; I386-NEXT: flds (%esp)
+; I386-NEXT: fstps {{[0-9]+}}(%esp)
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(1)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: fld %st(0)
+; I386-NEXT: jb .LBB11_2
+; I386-NEXT: # %bb.1:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: fld %st(1)
+; I386-NEXT: .LBB11_2:
+; I386-NEXT: xorl %eax, %eax
+; I386-NEXT: cmpl {{[0-9]+}}(%esp), %eax
+; I386-NEXT: jo .LBB11_4
+; I386-NEXT: # %bb.3:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fld %st(0)
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: .LBB11_4:
+; I386-NEXT: cmpl {{[0-9]+}}(%esp), %eax
+; I386-NEXT: jo .LBB11_6
+; I386-NEXT: # %bb.5:
+; I386-NEXT: fstp %st(2)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fxch %st(2)
+; I386-NEXT: .LBB11_6:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fldz
+; I386-NEXT: fxch %st(1)
+; I386-NEXT: fucom %st(1)
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fnstsw %ax
+; I386-NEXT: # kill: def $ah killed $ah killed $ax
+; I386-NEXT: sahf
+; I386-NEXT: je .LBB11_8
+; I386-NEXT: # %bb.7:
+; I386-NEXT: fstp %st(1)
+; I386-NEXT: fldz
+; I386-NEXT: .LBB11_8:
+; I386-NEXT: fstp %st(0)
+; I386-NEXT: addl $16, %esp
+; I386-NEXT: .cfi_def_cfa_offset 4
+; I386-NEXT: retl
+;
+; SSE2-LABEL: minimumnum_double_nnan:
+; SSE2: # %bb.0:
+; SSE2-NEXT: pushl %ebp
+; SSE2-NEXT: .cfi_def_cfa_offset 8
+; SSE2-NEXT: .cfi_offset %ebp, -8
+; SSE2-NEXT: movl %esp, %ebp
+; SSE2-NEXT: .cfi_def_cfa_register %ebp
+; SSE2-NEXT: andl $-8, %esp
+; SSE2-NEXT: subl $8, %esp
+; SSE2-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero
+; SSE2-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero
+; SSE2-NEXT: movaps %xmm0, %xmm2
+; SSE2-NEXT: shufps {{.*#+}} xmm2 = xmm2[1,1],xmm0[1,1]
+; SSE2-NEXT: movd %xmm2, %eax
+; SSE2-NEXT: testl %eax, %eax
+; SSE2-NEXT: js .LBB11_1
+; SSE2-NEXT: # %bb.2:
+; SSE2-NEXT: movaps %xmm1, %xmm2
+; SSE2-NEXT: jmp .LBB11_3
+; SSE2-NEXT: .LBB11_1:
+; SSE2-NEXT: movaps %xmm0, %xmm2
+; SSE2-NEXT: movaps %xmm1, %xmm0
+; SSE2-NEXT: .LBB11_3:
+; SSE2-NEXT: minsd %xmm2, %xmm0
+; SSE2-NEXT: movsd %xmm0, (%esp)
+; SSE2-NEXT: fldl (%esp)
+; SSE2-NEXT: movl %ebp, %esp
+; SSE2-NEXT: popl %ebp
+; SSE2-NEXT: .cfi_def_cfa %esp, 4
+; SSE2-NEXT: retl
+;
+; AVX-LABEL: minimumnum_double_nnan:
+; AVX: # %bb.0:
+; AVX-NEXT: pushl %ebp
+; AVX-NEXT: .cfi_def_cfa_offset 8
+; AVX-NEXT: .cfi_offset %ebp, -8
+; AVX-NEXT: movl %esp, %ebp
+; AVX-NEXT: .cfi_def_cfa_register %ebp
+; AVX-NEXT: andl $-8, %esp
+; AVX-NEXT: subl $8, %esp
+; AVX-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero
+; AVX-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
+; AVX-NEXT: vextractps $1, %xmm0, %eax
+; AVX-NEXT: testl %eax, %eax
+; AVX-NEXT: js .LBB11_1
+; AVX-NEXT: # %bb.2:
+; AVX-NEXT: vmovapd %xmm1, %xmm2
+; AVX-NEXT: jmp .LBB11_3
+; AVX-NEXT: .LBB11_1:
+; AVX-NEXT: vmovapd %xmm0, %xmm2
+; AVX-NEXT: vmovapd %xmm1, %xmm0
+; AVX-NEXT: .LBB11_3:
+; AVX-NEXT: vminsd %xmm2, %xmm0, %xmm0
+; AVX-NEXT: vmovsd %xmm0, (%esp)
+; AVX-NEXT: fldl (%esp)
+; AVX-NEXT: movl %ebp, %esp
+; AVX-NEXT: popl %ebp
+; AVX-NEXT: .cfi_def_cfa %esp, 4
+; AVX-NEXT: retl
+ %z = call nnan double @llvm.minimumnum.f64(double %x, double %y)
+ ret double %z
+}
>From 678ec27fadd02795f964d762c110631c65a6bbf5 Mon Sep 17 00:00:00 2001
From: YunQiang Su <syq at gcc.gnu.org>
Date: Mon, 29 Jul 2024 19:34:06 +0800
Subject: [PATCH 12/17] fix code style
---
llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 432c0ea7e18aa7..75f8f6d94c7260 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -8610,13 +8610,16 @@ SDValue TargetLowering::expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *Node,
SDValue LRound = LHS;
SDValue RRound = RHS;
EVT RCCVT = CCVT;
- // expandIS_FPCLASS is buggy for GPR32+FPR64. Let's round them to single for this case.
- if (TT.isArch32Bit() && !isOperationLegalOrCustom(ISD::IS_FPCLASS, VT) && VT.getSizeInBits() > TT.getArchPointerBitWidth() && !TT.isX32()) {
+ // expandIS_FPCLASS is buggy for GPR32+FPR64. Let's round them to single for
+ // this case.
+ if (TT.isArch32Bit() && !isOperationLegalOrCustom(ISD::IS_FPCLASS, VT) &&
+ VT.getSizeInBits() > TT.getArchPointerBitWidth() && !TT.isX32()) {
LRound = DAG.getNode(ISD::FP_ROUND, DL, MVT::f32, LHS,
- DAG.getIntPtrConstant(0, DL, /*isTarget=*/true));
+ DAG.getIntPtrConstant(0, DL, /*isTarget=*/true));
RRound = DAG.getNode(ISD::FP_ROUND, DL, MVT::f32, RHS,
- DAG.getIntPtrConstant(0, DL, /*isTarget=*/true));
- RCCVT = getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), MVT::f32);
+ DAG.getIntPtrConstant(0, DL, /*isTarget=*/true));
+ RCCVT =
+ getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), MVT::f32);
}
SDValue TestZero =
DAG.getTargetConstant(IsMax ? fcPosZero : fcNegZero, DL, MVT::i32);
>From 8c12849813d8f42d38128026464757194f865196 Mon Sep 17 00:00:00 2001
From: YunQiang Su <syq at gcc.gnu.org>
Date: Tue, 30 Jul 2024 14:57:27 +0800
Subject: [PATCH 13/17] Use condition integer bitcast of the FP type is not
legal
---
llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 75f8f6d94c7260..a813d43b4b809f 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -8542,7 +8542,6 @@ SDValue TargetLowering::expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *Node,
bool IsMax = Opc == ISD::FMAXIMUMNUM;
const TargetOptions &Options = DAG.getTarget().Options;
SDNodeFlags Flags = Node->getFlags();
- const Triple &TT = DAG.getTarget().getTargetTriple();
unsigned NewOp =
Opc == ISD::FMINIMUMNUM ? ISD::FMINNUM_IEEE : ISD::FMAXNUM_IEEE;
@@ -8612,8 +8611,7 @@ SDValue TargetLowering::expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *Node,
EVT RCCVT = CCVT;
// expandIS_FPCLASS is buggy for GPR32+FPR64. Let's round them to single for
// this case.
- if (TT.isArch32Bit() && !isOperationLegalOrCustom(ISD::IS_FPCLASS, VT) &&
- VT.getSizeInBits() > TT.getArchPointerBitWidth() && !TT.isX32()) {
+ if (!isOperationLegal (ISD::BITCAST, VT.changeTypeToInteger())) {
LRound = DAG.getNode(ISD::FP_ROUND, DL, MVT::f32, LHS,
DAG.getIntPtrConstant(0, DL, /*isTarget=*/true));
RRound = DAG.getNode(ISD::FP_ROUND, DL, MVT::f32, RHS,
>From 83596b35856bc80915f4e46fec280c6c97342621 Mon Sep 17 00:00:00 2001
From: YunQiang Su <syq at gcc.gnu.org>
Date: Tue, 30 Jul 2024 14:59:31 +0800
Subject: [PATCH 14/17] Remove i386 tests
---
.../CodeGen/X86/fp-maximumnum-minimumnum.ll | 1693 -----------------
1 file changed, 1693 deletions(-)
diff --git a/llvm/test/CodeGen/X86/fp-maximumnum-minimumnum.ll b/llvm/test/CodeGen/X86/fp-maximumnum-minimumnum.ll
index 099fe9918c60f5..cc5df607180c70 100644
--- a/llvm/test/CodeGen/X86/fp-maximumnum-minimumnum.ll
+++ b/llvm/test/CodeGen/X86/fp-maximumnum-minimumnum.ll
@@ -1,8 +1,5 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc --mtriple=x86_64 < %s | FileCheck %s --check-prefix=X86-64
-; RUN: llc --mtriple=i386 < %s | FileCheck %s --check-prefix=I386
-; RUN: llc --mtriple=i386 -mattr=+sse2 < %s | FileCheck %s --check-prefix=SSE2
-; RUN: llc --mtriple=i386 -mattr=+avx < %s | FileCheck %s --check-prefix=AVX
declare float @llvm.maximumnum.f32(float, float)
declare double @llvm.maximumnum.f64(double, double)
@@ -57,187 +54,6 @@ define float @maximumnum_float(float %x, float %y) {
; X86-64-NEXT: andps %xmm3, %xmm1
; X86-64-NEXT: orps %xmm1, %xmm0
; X86-64-NEXT: retq
-;
-; I386-LABEL: maximumnum_float:
-; I386: # %bb.0:
-; I386-NEXT: subl $8, %esp
-; I386-NEXT: .cfi_def_cfa_offset 12
-; I386-NEXT: flds {{[0-9]+}}(%esp)
-; I386-NEXT: flds {{[0-9]+}}(%esp)
-; I386-NEXT: fucom %st(0)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: fld %st(1)
-; I386-NEXT: jp .LBB0_2
-; I386-NEXT: # %bb.1:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: .LBB0_2:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fsts {{[0-9]+}}(%esp)
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(0)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: fld %st(1)
-; I386-NEXT: jp .LBB0_4
-; I386-NEXT: # %bb.3:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: .LBB0_4:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fsts (%esp)
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(1)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: fld %st(0)
-; I386-NEXT: ja .LBB0_6
-; I386-NEXT: # %bb.5:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: fld %st(1)
-; I386-NEXT: .LBB0_6:
-; I386-NEXT: fld %st(0)
-; I386-NEXT: fadd %st(1), %st
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(0)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: jp .LBB0_8
-; I386-NEXT: # %bb.7:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fldz
-; I386-NEXT: .LBB0_8:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: cmpl $0, {{[0-9]+}}(%esp)
-; I386-NEXT: je .LBB0_10
-; I386-NEXT: # %bb.9:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fld %st(0)
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: .LBB0_10:
-; I386-NEXT: cmpl $0, (%esp)
-; I386-NEXT: je .LBB0_12
-; I386-NEXT: # %bb.11:
-; I386-NEXT: fstp %st(2)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fxch %st(2)
-; I386-NEXT: .LBB0_12:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(1)
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: je .LBB0_14
-; I386-NEXT: # %bb.13:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fldz
-; I386-NEXT: .LBB0_14:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: addl $8, %esp
-; I386-NEXT: .cfi_def_cfa_offset 4
-; I386-NEXT: retl
-;
-; SSE2-LABEL: maximumnum_float:
-; SSE2: # %bb.0:
-; SSE2-NEXT: pushl %eax
-; SSE2-NEXT: .cfi_def_cfa_offset 8
-; SSE2-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
-; SSE2-NEXT: movss {{.*#+}} xmm2 = mem[0],zero,zero,zero
-; SSE2-NEXT: movaps %xmm1, %xmm0
-; SSE2-NEXT: cmpunordss %xmm1, %xmm0
-; SSE2-NEXT: movaps %xmm0, %xmm3
-; SSE2-NEXT: andps %xmm2, %xmm3
-; SSE2-NEXT: andnps %xmm1, %xmm0
-; SSE2-NEXT: orps %xmm3, %xmm0
-; SSE2-NEXT: movaps %xmm2, %xmm1
-; SSE2-NEXT: cmpunordss %xmm2, %xmm1
-; SSE2-NEXT: movaps %xmm1, %xmm3
-; SSE2-NEXT: andps %xmm0, %xmm3
-; SSE2-NEXT: andnps %xmm2, %xmm1
-; SSE2-NEXT: orps %xmm3, %xmm1
-; SSE2-NEXT: movaps %xmm1, %xmm2
-; SSE2-NEXT: cmpltss %xmm0, %xmm2
-; SSE2-NEXT: movaps %xmm2, %xmm3
-; SSE2-NEXT: andps %xmm0, %xmm3
-; SSE2-NEXT: andnps %xmm1, %xmm2
-; SSE2-NEXT: orps %xmm3, %xmm2
-; SSE2-NEXT: movaps %xmm2, %xmm4
-; SSE2-NEXT: addss %xmm2, %xmm4
-; SSE2-NEXT: movaps %xmm2, %xmm3
-; SSE2-NEXT: cmpunordss %xmm2, %xmm3
-; SSE2-NEXT: andps %xmm3, %xmm4
-; SSE2-NEXT: andnps %xmm2, %xmm3
-; SSE2-NEXT: orps %xmm4, %xmm3
-; SSE2-NEXT: xorps %xmm2, %xmm2
-; SSE2-NEXT: cmpeqss %xmm3, %xmm2
-; SSE2-NEXT: movd %xmm0, %eax
-; SSE2-NEXT: testl %eax, %eax
-; SSE2-NEXT: je .LBB0_2
-; SSE2-NEXT: # %bb.1:
-; SSE2-NEXT: movaps %xmm3, %xmm0
-; SSE2-NEXT: .LBB0_2:
-; SSE2-NEXT: movaps %xmm2, %xmm4
-; SSE2-NEXT: andnps %xmm3, %xmm4
-; SSE2-NEXT: movd %xmm1, %eax
-; SSE2-NEXT: testl %eax, %eax
-; SSE2-NEXT: je .LBB0_4
-; SSE2-NEXT: # %bb.3:
-; SSE2-NEXT: movaps %xmm0, %xmm1
-; SSE2-NEXT: .LBB0_4:
-; SSE2-NEXT: andps %xmm1, %xmm2
-; SSE2-NEXT: orps %xmm2, %xmm4
-; SSE2-NEXT: movss %xmm4, (%esp)
-; SSE2-NEXT: flds (%esp)
-; SSE2-NEXT: popl %eax
-; SSE2-NEXT: .cfi_def_cfa_offset 4
-; SSE2-NEXT: retl
-;
-; AVX-LABEL: maximumnum_float:
-; AVX: # %bb.0:
-; AVX-NEXT: pushl %eax
-; AVX-NEXT: .cfi_def_cfa_offset 8
-; AVX-NEXT: vmovss {{.*#+}} xmm0 = mem[0],zero,zero,zero
-; AVX-NEXT: vmovss {{.*#+}} xmm2 = mem[0],zero,zero,zero
-; AVX-NEXT: vcmpunordss %xmm0, %xmm0, %xmm1
-; AVX-NEXT: vblendvps %xmm1, %xmm2, %xmm0, %xmm1
-; AVX-NEXT: vcmpunordss %xmm2, %xmm2, %xmm0
-; AVX-NEXT: vblendvps %xmm0, %xmm1, %xmm2, %xmm0
-; AVX-NEXT: vcmpltss %xmm1, %xmm0, %xmm2
-; AVX-NEXT: vblendvps %xmm2, %xmm1, %xmm0, %xmm2
-; AVX-NEXT: vcmpunordss %xmm2, %xmm2, %xmm3
-; AVX-NEXT: vaddss %xmm2, %xmm2, %xmm4
-; AVX-NEXT: vblendvps %xmm3, %xmm4, %xmm2, %xmm2
-; AVX-NEXT: vxorps %xmm3, %xmm3, %xmm3
-; AVX-NEXT: vmovd %xmm1, %eax
-; AVX-NEXT: testl %eax, %eax
-; AVX-NEXT: je .LBB0_2
-; AVX-NEXT: # %bb.1:
-; AVX-NEXT: vmovaps %xmm2, %xmm1
-; AVX-NEXT: .LBB0_2:
-; AVX-NEXT: vcmpeqss %xmm3, %xmm2, %xmm3
-; AVX-NEXT: vmovd %xmm0, %eax
-; AVX-NEXT: testl %eax, %eax
-; AVX-NEXT: je .LBB0_4
-; AVX-NEXT: # %bb.3:
-; AVX-NEXT: vmovaps %xmm1, %xmm0
-; AVX-NEXT: .LBB0_4:
-; AVX-NEXT: vblendvps %xmm3, %xmm0, %xmm2, %xmm0
-; AVX-NEXT: vmovss %xmm0, (%esp)
-; AVX-NEXT: flds (%esp)
-; AVX-NEXT: popl %eax
-; AVX-NEXT: .cfi_def_cfa_offset 4
-; AVX-NEXT: retl
%z = call float @llvm.maximumnum.f32(float %x, float %y)
ret float %z
}
@@ -271,119 +87,6 @@ define float @maximumnum_float_nsz(float %x, float %y) {
; X86-64-NEXT: andnps %xmm1, %xmm0
; X86-64-NEXT: orps %xmm2, %xmm0
; X86-64-NEXT: retq
-;
-; I386-LABEL: maximumnum_float_nsz:
-; I386: # %bb.0:
-; I386-NEXT: flds {{[0-9]+}}(%esp)
-; I386-NEXT: flds {{[0-9]+}}(%esp)
-; I386-NEXT: fucom %st(0)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: fld %st(1)
-; I386-NEXT: jp .LBB1_2
-; I386-NEXT: # %bb.1:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: .LBB1_2:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(0)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: fld %st(1)
-; I386-NEXT: jp .LBB1_4
-; I386-NEXT: # %bb.3:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: .LBB1_4:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(1)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: ja .LBB1_6
-; I386-NEXT: # %bb.5:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: .LBB1_6:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fld %st(0)
-; I386-NEXT: fadd %st(1), %st
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(0)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: jp .LBB1_8
-; I386-NEXT: # %bb.7:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fldz
-; I386-NEXT: .LBB1_8:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: retl
-;
-; SSE2-LABEL: maximumnum_float_nsz:
-; SSE2: # %bb.0:
-; SSE2-NEXT: pushl %eax
-; SSE2-NEXT: .cfi_def_cfa_offset 8
-; SSE2-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
-; SSE2-NEXT: movss {{.*#+}} xmm2 = mem[0],zero,zero,zero
-; SSE2-NEXT: movaps %xmm1, %xmm0
-; SSE2-NEXT: cmpunordss %xmm1, %xmm0
-; SSE2-NEXT: movaps %xmm0, %xmm3
-; SSE2-NEXT: andps %xmm2, %xmm3
-; SSE2-NEXT: andnps %xmm1, %xmm0
-; SSE2-NEXT: orps %xmm3, %xmm0
-; SSE2-NEXT: movaps %xmm2, %xmm1
-; SSE2-NEXT: cmpunordss %xmm2, %xmm1
-; SSE2-NEXT: movaps %xmm1, %xmm3
-; SSE2-NEXT: andps %xmm0, %xmm3
-; SSE2-NEXT: andnps %xmm2, %xmm1
-; SSE2-NEXT: orps %xmm3, %xmm1
-; SSE2-NEXT: movaps %xmm1, %xmm2
-; SSE2-NEXT: cmpltss %xmm0, %xmm2
-; SSE2-NEXT: andps %xmm2, %xmm0
-; SSE2-NEXT: andnps %xmm1, %xmm2
-; SSE2-NEXT: orps %xmm0, %xmm2
-; SSE2-NEXT: movaps %xmm2, %xmm0
-; SSE2-NEXT: addss %xmm2, %xmm0
-; SSE2-NEXT: movaps %xmm2, %xmm1
-; SSE2-NEXT: cmpunordss %xmm2, %xmm1
-; SSE2-NEXT: andps %xmm1, %xmm0
-; SSE2-NEXT: andnps %xmm2, %xmm1
-; SSE2-NEXT: orps %xmm0, %xmm1
-; SSE2-NEXT: movss %xmm1, (%esp)
-; SSE2-NEXT: flds (%esp)
-; SSE2-NEXT: popl %eax
-; SSE2-NEXT: .cfi_def_cfa_offset 4
-; SSE2-NEXT: retl
-;
-; AVX-LABEL: maximumnum_float_nsz:
-; AVX: # %bb.0:
-; AVX-NEXT: pushl %eax
-; AVX-NEXT: .cfi_def_cfa_offset 8
-; AVX-NEXT: vmovss {{.*#+}} xmm0 = mem[0],zero,zero,zero
-; AVX-NEXT: vmovss {{.*#+}} xmm1 = mem[0],zero,zero,zero
-; AVX-NEXT: vcmpunordss %xmm0, %xmm0, %xmm2
-; AVX-NEXT: vblendvps %xmm2, %xmm1, %xmm0, %xmm0
-; AVX-NEXT: vcmpunordss %xmm1, %xmm1, %xmm2
-; AVX-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm1
-; AVX-NEXT: vcmpltss %xmm0, %xmm1, %xmm2
-; AVX-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm0
-; AVX-NEXT: vcmpunordss %xmm0, %xmm0, %xmm1
-; AVX-NEXT: vaddss %xmm0, %xmm0, %xmm2
-; AVX-NEXT: vblendvps %xmm1, %xmm2, %xmm0, %xmm0
-; AVX-NEXT: vmovss %xmm0, (%esp)
-; AVX-NEXT: flds (%esp)
-; AVX-NEXT: popl %eax
-; AVX-NEXT: .cfi_def_cfa_offset 4
-; AVX-NEXT: retl
%z = call nsz float @llvm.maximumnum.f32(float %x, float %y)
ret float %z
}
@@ -405,110 +108,6 @@ define float @maximumnum_float_nnan(float %x, float %y) {
; X86-64-NEXT: maxss %xmm2, %xmm1
; X86-64-NEXT: movaps %xmm1, %xmm0
; X86-64-NEXT: retq
-;
-; I386-LABEL: maximumnum_float_nnan:
-; I386: # %bb.0:
-; I386-NEXT: subl $8, %esp
-; I386-NEXT: .cfi_def_cfa_offset 12
-; I386-NEXT: flds {{[0-9]+}}(%esp)
-; I386-NEXT: fsts {{[0-9]+}}(%esp)
-; I386-NEXT: flds {{[0-9]+}}(%esp)
-; I386-NEXT: fsts (%esp)
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(1)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: fld %st(0)
-; I386-NEXT: jbe .LBB2_1
-; I386-NEXT: # %bb.2:
-; I386-NEXT: cmpl $0, {{[0-9]+}}(%esp)
-; I386-NEXT: jne .LBB2_3
-; I386-NEXT: .LBB2_4:
-; I386-NEXT: cmpl $0, (%esp)
-; I386-NEXT: je .LBB2_6
-; I386-NEXT: .LBB2_5:
-; I386-NEXT: fstp %st(2)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fxch %st(2)
-; I386-NEXT: .LBB2_6:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(1)
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: je .LBB2_8
-; I386-NEXT: # %bb.7:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fldz
-; I386-NEXT: .LBB2_8:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: addl $8, %esp
-; I386-NEXT: .cfi_def_cfa_offset 4
-; I386-NEXT: retl
-; I386-NEXT: .LBB2_1:
-; I386-NEXT: .cfi_def_cfa_offset 12
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: fld %st(1)
-; I386-NEXT: cmpl $0, {{[0-9]+}}(%esp)
-; I386-NEXT: je .LBB2_4
-; I386-NEXT: .LBB2_3:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fld %st(0)
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: cmpl $0, (%esp)
-; I386-NEXT: jne .LBB2_5
-; I386-NEXT: jmp .LBB2_6
-;
-; SSE2-LABEL: maximumnum_float_nnan:
-; SSE2: # %bb.0:
-; SSE2-NEXT: pushl %eax
-; SSE2-NEXT: .cfi_def_cfa_offset 8
-; SSE2-NEXT: movd {{.*#+}} xmm0 = mem[0],zero,zero,zero
-; SSE2-NEXT: movd {{.*#+}} xmm2 = mem[0],zero,zero,zero
-; SSE2-NEXT: movd %xmm2, %eax
-; SSE2-NEXT: testl %eax, %eax
-; SSE2-NEXT: js .LBB2_1
-; SSE2-NEXT: # %bb.2:
-; SSE2-NEXT: movdqa %xmm2, %xmm1
-; SSE2-NEXT: jmp .LBB2_3
-; SSE2-NEXT: .LBB2_1:
-; SSE2-NEXT: movdqa %xmm0, %xmm1
-; SSE2-NEXT: movdqa %xmm2, %xmm0
-; SSE2-NEXT: .LBB2_3:
-; SSE2-NEXT: maxss %xmm1, %xmm0
-; SSE2-NEXT: movss %xmm0, (%esp)
-; SSE2-NEXT: flds (%esp)
-; SSE2-NEXT: popl %eax
-; SSE2-NEXT: .cfi_def_cfa_offset 4
-; SSE2-NEXT: retl
-;
-; AVX-LABEL: maximumnum_float_nnan:
-; AVX: # %bb.0:
-; AVX-NEXT: pushl %eax
-; AVX-NEXT: .cfi_def_cfa_offset 8
-; AVX-NEXT: vmovd {{.*#+}} xmm0 = mem[0],zero,zero,zero
-; AVX-NEXT: vmovd {{.*#+}} xmm2 = mem[0],zero,zero,zero
-; AVX-NEXT: vmovd %xmm2, %eax
-; AVX-NEXT: testl %eax, %eax
-; AVX-NEXT: js .LBB2_1
-; AVX-NEXT: # %bb.2:
-; AVX-NEXT: vmovdqa %xmm2, %xmm1
-; AVX-NEXT: jmp .LBB2_3
-; AVX-NEXT: .LBB2_1:
-; AVX-NEXT: vmovdqa %xmm0, %xmm1
-; AVX-NEXT: vmovdqa %xmm2, %xmm0
-; AVX-NEXT: .LBB2_3:
-; AVX-NEXT: vmaxss %xmm1, %xmm0, %xmm0
-; AVX-NEXT: vmovss %xmm0, (%esp)
-; AVX-NEXT: flds (%esp)
-; AVX-NEXT: popl %eax
-; AVX-NEXT: .cfi_def_cfa_offset 4
-; AVX-NEXT: retl
%z = call nnan float @llvm.maximumnum.f32(float %x, float %y)
ret float %z
}
@@ -562,209 +161,6 @@ define double @maximumnum_double(double %x, double %y) {
; X86-64-NEXT: andpd %xmm3, %xmm1
; X86-64-NEXT: orpd %xmm1, %xmm0
; X86-64-NEXT: retq
-;
-; I386-LABEL: maximumnum_double:
-; I386: # %bb.0:
-; I386-NEXT: subl $16, %esp
-; I386-NEXT: .cfi_def_cfa_offset 20
-; I386-NEXT: fldl {{[0-9]+}}(%esp)
-; I386-NEXT: fldl {{[0-9]+}}(%esp)
-; I386-NEXT: fucom %st(0)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: fld %st(1)
-; I386-NEXT: jp .LBB3_2
-; I386-NEXT: # %bb.1:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: .LBB3_2:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fsts {{[0-9]+}}(%esp)
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(0)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: fld %st(1)
-; I386-NEXT: jp .LBB3_4
-; I386-NEXT: # %bb.3:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: .LBB3_4:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fsts (%esp)
-; I386-NEXT: flds {{[0-9]+}}(%esp)
-; I386-NEXT: fstps {{[0-9]+}}(%esp)
-; I386-NEXT: flds (%esp)
-; I386-NEXT: fstps {{[0-9]+}}(%esp)
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(1)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: fld %st(0)
-; I386-NEXT: ja .LBB3_6
-; I386-NEXT: # %bb.5:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: fld %st(1)
-; I386-NEXT: .LBB3_6:
-; I386-NEXT: fld %st(0)
-; I386-NEXT: fadd %st(1), %st
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(0)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: jp .LBB3_8
-; I386-NEXT: # %bb.7:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fldz
-; I386-NEXT: .LBB3_8:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: cmpl $0, {{[0-9]+}}(%esp)
-; I386-NEXT: je .LBB3_10
-; I386-NEXT: # %bb.9:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fld %st(0)
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: .LBB3_10:
-; I386-NEXT: cmpl $0, {{[0-9]+}}(%esp)
-; I386-NEXT: je .LBB3_12
-; I386-NEXT: # %bb.11:
-; I386-NEXT: fstp %st(2)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fxch %st(2)
-; I386-NEXT: .LBB3_12:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(1)
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: je .LBB3_14
-; I386-NEXT: # %bb.13:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fldz
-; I386-NEXT: .LBB3_14:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: addl $16, %esp
-; I386-NEXT: .cfi_def_cfa_offset 4
-; I386-NEXT: retl
-;
-; SSE2-LABEL: maximumnum_double:
-; SSE2: # %bb.0:
-; SSE2-NEXT: pushl %ebp
-; SSE2-NEXT: .cfi_def_cfa_offset 8
-; SSE2-NEXT: .cfi_offset %ebp, -8
-; SSE2-NEXT: movl %esp, %ebp
-; SSE2-NEXT: .cfi_def_cfa_register %ebp
-; SSE2-NEXT: andl $-8, %esp
-; SSE2-NEXT: subl $8, %esp
-; SSE2-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero
-; SSE2-NEXT: movsd {{.*#+}} xmm2 = mem[0],zero
-; SSE2-NEXT: movapd %xmm1, %xmm0
-; SSE2-NEXT: cmpunordsd %xmm1, %xmm0
-; SSE2-NEXT: movapd %xmm0, %xmm3
-; SSE2-NEXT: andpd %xmm2, %xmm3
-; SSE2-NEXT: andnpd %xmm1, %xmm0
-; SSE2-NEXT: orpd %xmm3, %xmm0
-; SSE2-NEXT: movapd %xmm2, %xmm1
-; SSE2-NEXT: cmpunordsd %xmm2, %xmm1
-; SSE2-NEXT: movapd %xmm1, %xmm3
-; SSE2-NEXT: andpd %xmm0, %xmm3
-; SSE2-NEXT: andnpd %xmm2, %xmm1
-; SSE2-NEXT: orpd %xmm3, %xmm1
-; SSE2-NEXT: movapd %xmm1, %xmm2
-; SSE2-NEXT: cmpltsd %xmm0, %xmm2
-; SSE2-NEXT: movapd %xmm2, %xmm3
-; SSE2-NEXT: andpd %xmm0, %xmm3
-; SSE2-NEXT: andnpd %xmm1, %xmm2
-; SSE2-NEXT: orpd %xmm3, %xmm2
-; SSE2-NEXT: movapd %xmm2, %xmm4
-; SSE2-NEXT: addsd %xmm2, %xmm4
-; SSE2-NEXT: movapd %xmm2, %xmm3
-; SSE2-NEXT: cmpunordsd %xmm2, %xmm3
-; SSE2-NEXT: andpd %xmm3, %xmm4
-; SSE2-NEXT: andnpd %xmm2, %xmm3
-; SSE2-NEXT: orpd %xmm4, %xmm3
-; SSE2-NEXT: xorpd %xmm2, %xmm2
-; SSE2-NEXT: cmpeqsd %xmm3, %xmm2
-; SSE2-NEXT: xorps %xmm4, %xmm4
-; SSE2-NEXT: cvtsd2ss %xmm0, %xmm4
-; SSE2-NEXT: movd %xmm4, %eax
-; SSE2-NEXT: testl %eax, %eax
-; SSE2-NEXT: je .LBB3_2
-; SSE2-NEXT: # %bb.1:
-; SSE2-NEXT: movapd %xmm3, %xmm0
-; SSE2-NEXT: .LBB3_2:
-; SSE2-NEXT: movapd %xmm2, %xmm4
-; SSE2-NEXT: andnpd %xmm3, %xmm4
-; SSE2-NEXT: xorps %xmm3, %xmm3
-; SSE2-NEXT: cvtsd2ss %xmm1, %xmm3
-; SSE2-NEXT: movd %xmm3, %eax
-; SSE2-NEXT: testl %eax, %eax
-; SSE2-NEXT: je .LBB3_4
-; SSE2-NEXT: # %bb.3:
-; SSE2-NEXT: movaps %xmm0, %xmm1
-; SSE2-NEXT: .LBB3_4:
-; SSE2-NEXT: andpd %xmm1, %xmm2
-; SSE2-NEXT: orpd %xmm2, %xmm4
-; SSE2-NEXT: movlpd %xmm4, (%esp)
-; SSE2-NEXT: fldl (%esp)
-; SSE2-NEXT: movl %ebp, %esp
-; SSE2-NEXT: popl %ebp
-; SSE2-NEXT: .cfi_def_cfa %esp, 4
-; SSE2-NEXT: retl
-;
-; AVX-LABEL: maximumnum_double:
-; AVX: # %bb.0:
-; AVX-NEXT: pushl %ebp
-; AVX-NEXT: .cfi_def_cfa_offset 8
-; AVX-NEXT: .cfi_offset %ebp, -8
-; AVX-NEXT: movl %esp, %ebp
-; AVX-NEXT: .cfi_def_cfa_register %ebp
-; AVX-NEXT: andl $-8, %esp
-; AVX-NEXT: subl $8, %esp
-; AVX-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
-; AVX-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero
-; AVX-NEXT: vcmpunordsd %xmm0, %xmm0, %xmm1
-; AVX-NEXT: vblendvpd %xmm1, %xmm2, %xmm0, %xmm1
-; AVX-NEXT: vcmpunordsd %xmm2, %xmm2, %xmm0
-; AVX-NEXT: vblendvpd %xmm0, %xmm1, %xmm2, %xmm0
-; AVX-NEXT: vcmpltsd %xmm1, %xmm0, %xmm2
-; AVX-NEXT: vblendvpd %xmm2, %xmm1, %xmm0, %xmm2
-; AVX-NEXT: vcmpunordsd %xmm2, %xmm2, %xmm3
-; AVX-NEXT: vaddsd %xmm2, %xmm2, %xmm4
-; AVX-NEXT: vblendvpd %xmm3, %xmm4, %xmm2, %xmm2
-; AVX-NEXT: vxorpd %xmm3, %xmm3, %xmm3
-; AVX-NEXT: vcvtsd2ss %xmm1, %xmm1, %xmm4
-; AVX-NEXT: vmovd %xmm4, %eax
-; AVX-NEXT: testl %eax, %eax
-; AVX-NEXT: je .LBB3_2
-; AVX-NEXT: # %bb.1:
-; AVX-NEXT: vmovapd %xmm2, %xmm1
-; AVX-NEXT: .LBB3_2:
-; AVX-NEXT: vcmpeqsd %xmm3, %xmm2, %xmm3
-; AVX-NEXT: vcvtsd2ss %xmm0, %xmm0, %xmm4
-; AVX-NEXT: vmovd %xmm4, %eax
-; AVX-NEXT: testl %eax, %eax
-; AVX-NEXT: je .LBB3_4
-; AVX-NEXT: # %bb.3:
-; AVX-NEXT: vmovaps %xmm1, %xmm0
-; AVX-NEXT: .LBB3_4:
-; AVX-NEXT: vblendvpd %xmm3, %xmm0, %xmm2, %xmm0
-; AVX-NEXT: vmovlpd %xmm0, (%esp)
-; AVX-NEXT: fldl (%esp)
-; AVX-NEXT: movl %ebp, %esp
-; AVX-NEXT: popl %ebp
-; AVX-NEXT: .cfi_def_cfa %esp, 4
-; AVX-NEXT: retl
%z = call double @llvm.maximumnum.f64(double %x, double %y)
ret double %z
}
@@ -798,131 +194,6 @@ define double @maximumnum_double_nsz(double %x, double %y) {
; X86-64-NEXT: andnpd %xmm1, %xmm0
; X86-64-NEXT: orpd %xmm2, %xmm0
; X86-64-NEXT: retq
-;
-; I386-LABEL: maximumnum_double_nsz:
-; I386: # %bb.0:
-; I386-NEXT: fldl {{[0-9]+}}(%esp)
-; I386-NEXT: fldl {{[0-9]+}}(%esp)
-; I386-NEXT: fucom %st(0)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: fld %st(1)
-; I386-NEXT: jp .LBB4_2
-; I386-NEXT: # %bb.1:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: .LBB4_2:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(0)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: fld %st(1)
-; I386-NEXT: jp .LBB4_4
-; I386-NEXT: # %bb.3:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: .LBB4_4:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(1)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: ja .LBB4_6
-; I386-NEXT: # %bb.5:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: .LBB4_6:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fld %st(0)
-; I386-NEXT: fadd %st(1), %st
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(0)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: jp .LBB4_8
-; I386-NEXT: # %bb.7:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fldz
-; I386-NEXT: .LBB4_8:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: retl
-;
-; SSE2-LABEL: maximumnum_double_nsz:
-; SSE2: # %bb.0:
-; SSE2-NEXT: pushl %ebp
-; SSE2-NEXT: .cfi_def_cfa_offset 8
-; SSE2-NEXT: .cfi_offset %ebp, -8
-; SSE2-NEXT: movl %esp, %ebp
-; SSE2-NEXT: .cfi_def_cfa_register %ebp
-; SSE2-NEXT: andl $-8, %esp
-; SSE2-NEXT: subl $8, %esp
-; SSE2-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero
-; SSE2-NEXT: movsd {{.*#+}} xmm2 = mem[0],zero
-; SSE2-NEXT: movapd %xmm1, %xmm0
-; SSE2-NEXT: cmpunordsd %xmm1, %xmm0
-; SSE2-NEXT: movapd %xmm0, %xmm3
-; SSE2-NEXT: andpd %xmm2, %xmm3
-; SSE2-NEXT: andnpd %xmm1, %xmm0
-; SSE2-NEXT: orpd %xmm3, %xmm0
-; SSE2-NEXT: movapd %xmm2, %xmm1
-; SSE2-NEXT: cmpunordsd %xmm2, %xmm1
-; SSE2-NEXT: movapd %xmm1, %xmm3
-; SSE2-NEXT: andpd %xmm0, %xmm3
-; SSE2-NEXT: andnpd %xmm2, %xmm1
-; SSE2-NEXT: orpd %xmm3, %xmm1
-; SSE2-NEXT: movapd %xmm1, %xmm2
-; SSE2-NEXT: cmpltsd %xmm0, %xmm2
-; SSE2-NEXT: andpd %xmm2, %xmm0
-; SSE2-NEXT: andnpd %xmm1, %xmm2
-; SSE2-NEXT: orpd %xmm0, %xmm2
-; SSE2-NEXT: movapd %xmm2, %xmm0
-; SSE2-NEXT: addsd %xmm2, %xmm0
-; SSE2-NEXT: movapd %xmm2, %xmm1
-; SSE2-NEXT: cmpunordsd %xmm2, %xmm1
-; SSE2-NEXT: andpd %xmm1, %xmm0
-; SSE2-NEXT: andnpd %xmm2, %xmm1
-; SSE2-NEXT: orpd %xmm0, %xmm1
-; SSE2-NEXT: movlpd %xmm1, (%esp)
-; SSE2-NEXT: fldl (%esp)
-; SSE2-NEXT: movl %ebp, %esp
-; SSE2-NEXT: popl %ebp
-; SSE2-NEXT: .cfi_def_cfa %esp, 4
-; SSE2-NEXT: retl
-;
-; AVX-LABEL: maximumnum_double_nsz:
-; AVX: # %bb.0:
-; AVX-NEXT: pushl %ebp
-; AVX-NEXT: .cfi_def_cfa_offset 8
-; AVX-NEXT: .cfi_offset %ebp, -8
-; AVX-NEXT: movl %esp, %ebp
-; AVX-NEXT: .cfi_def_cfa_register %ebp
-; AVX-NEXT: andl $-8, %esp
-; AVX-NEXT: subl $8, %esp
-; AVX-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
-; AVX-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero
-; AVX-NEXT: vcmpunordsd %xmm0, %xmm0, %xmm2
-; AVX-NEXT: vblendvpd %xmm2, %xmm1, %xmm0, %xmm0
-; AVX-NEXT: vcmpunordsd %xmm1, %xmm1, %xmm2
-; AVX-NEXT: vblendvpd %xmm2, %xmm0, %xmm1, %xmm1
-; AVX-NEXT: vcmpltsd %xmm0, %xmm1, %xmm2
-; AVX-NEXT: vblendvpd %xmm2, %xmm0, %xmm1, %xmm0
-; AVX-NEXT: vcmpunordsd %xmm0, %xmm0, %xmm1
-; AVX-NEXT: vaddsd %xmm0, %xmm0, %xmm2
-; AVX-NEXT: vblendvpd %xmm1, %xmm2, %xmm0, %xmm0
-; AVX-NEXT: vmovlpd %xmm0, (%esp)
-; AVX-NEXT: fldl (%esp)
-; AVX-NEXT: movl %ebp, %esp
-; AVX-NEXT: popl %ebp
-; AVX-NEXT: .cfi_def_cfa %esp, 4
-; AVX-NEXT: retl
%z = call nsz double @llvm.maximumnum.f64(double %x, double %y)
ret double %z
}
@@ -944,129 +215,6 @@ define double @maximumnum_double_nnan(double %x, double %y) {
; X86-64-NEXT: maxsd %xmm2, %xmm1
; X86-64-NEXT: movapd %xmm1, %xmm0
; X86-64-NEXT: retq
-;
-; I386-LABEL: maximumnum_double_nnan:
-; I386: # %bb.0:
-; I386-NEXT: subl $16, %esp
-; I386-NEXT: .cfi_def_cfa_offset 20
-; I386-NEXT: fldl {{[0-9]+}}(%esp)
-; I386-NEXT: fldl {{[0-9]+}}(%esp)
-; I386-NEXT: fsts {{[0-9]+}}(%esp)
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fsts (%esp)
-; I386-NEXT: flds {{[0-9]+}}(%esp)
-; I386-NEXT: fstps {{[0-9]+}}(%esp)
-; I386-NEXT: flds (%esp)
-; I386-NEXT: fstps {{[0-9]+}}(%esp)
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(1)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: fld %st(0)
-; I386-NEXT: jbe .LBB5_1
-; I386-NEXT: # %bb.2:
-; I386-NEXT: cmpl $0, {{[0-9]+}}(%esp)
-; I386-NEXT: jne .LBB5_3
-; I386-NEXT: .LBB5_4:
-; I386-NEXT: cmpl $0, {{[0-9]+}}(%esp)
-; I386-NEXT: je .LBB5_6
-; I386-NEXT: .LBB5_5:
-; I386-NEXT: fstp %st(2)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fxch %st(2)
-; I386-NEXT: .LBB5_6:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(1)
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: je .LBB5_8
-; I386-NEXT: # %bb.7:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fldz
-; I386-NEXT: .LBB5_8:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: addl $16, %esp
-; I386-NEXT: .cfi_def_cfa_offset 4
-; I386-NEXT: retl
-; I386-NEXT: .LBB5_1:
-; I386-NEXT: .cfi_def_cfa_offset 20
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: fld %st(1)
-; I386-NEXT: cmpl $0, {{[0-9]+}}(%esp)
-; I386-NEXT: je .LBB5_4
-; I386-NEXT: .LBB5_3:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fld %st(0)
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: cmpl $0, {{[0-9]+}}(%esp)
-; I386-NEXT: jne .LBB5_5
-; I386-NEXT: jmp .LBB5_6
-;
-; SSE2-LABEL: maximumnum_double_nnan:
-; SSE2: # %bb.0:
-; SSE2-NEXT: pushl %ebp
-; SSE2-NEXT: .cfi_def_cfa_offset 8
-; SSE2-NEXT: .cfi_offset %ebp, -8
-; SSE2-NEXT: movl %esp, %ebp
-; SSE2-NEXT: .cfi_def_cfa_register %ebp
-; SSE2-NEXT: andl $-8, %esp
-; SSE2-NEXT: subl $8, %esp
-; SSE2-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero
-; SSE2-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero
-; SSE2-NEXT: movaps %xmm1, %xmm2
-; SSE2-NEXT: shufps {{.*#+}} xmm2 = xmm2[1,1],xmm1[1,1]
-; SSE2-NEXT: movd %xmm2, %eax
-; SSE2-NEXT: testl %eax, %eax
-; SSE2-NEXT: js .LBB5_1
-; SSE2-NEXT: # %bb.2:
-; SSE2-NEXT: movaps %xmm1, %xmm2
-; SSE2-NEXT: jmp .LBB5_3
-; SSE2-NEXT: .LBB5_1:
-; SSE2-NEXT: movaps %xmm0, %xmm2
-; SSE2-NEXT: movaps %xmm1, %xmm0
-; SSE2-NEXT: .LBB5_3:
-; SSE2-NEXT: maxsd %xmm2, %xmm0
-; SSE2-NEXT: movsd %xmm0, (%esp)
-; SSE2-NEXT: fldl (%esp)
-; SSE2-NEXT: movl %ebp, %esp
-; SSE2-NEXT: popl %ebp
-; SSE2-NEXT: .cfi_def_cfa %esp, 4
-; SSE2-NEXT: retl
-;
-; AVX-LABEL: maximumnum_double_nnan:
-; AVX: # %bb.0:
-; AVX-NEXT: pushl %ebp
-; AVX-NEXT: .cfi_def_cfa_offset 8
-; AVX-NEXT: .cfi_offset %ebp, -8
-; AVX-NEXT: movl %esp, %ebp
-; AVX-NEXT: .cfi_def_cfa_register %ebp
-; AVX-NEXT: andl $-8, %esp
-; AVX-NEXT: subl $8, %esp
-; AVX-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
-; AVX-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero
-; AVX-NEXT: vextractps $1, %xmm2, %eax
-; AVX-NEXT: testl %eax, %eax
-; AVX-NEXT: js .LBB5_1
-; AVX-NEXT: # %bb.2:
-; AVX-NEXT: vmovapd %xmm2, %xmm1
-; AVX-NEXT: jmp .LBB5_3
-; AVX-NEXT: .LBB5_1:
-; AVX-NEXT: vmovapd %xmm0, %xmm1
-; AVX-NEXT: vmovapd %xmm2, %xmm0
-; AVX-NEXT: .LBB5_3:
-; AVX-NEXT: vmaxsd %xmm1, %xmm0, %xmm0
-; AVX-NEXT: vmovsd %xmm0, (%esp)
-; AVX-NEXT: fldl (%esp)
-; AVX-NEXT: movl %ebp, %esp
-; AVX-NEXT: popl %ebp
-; AVX-NEXT: .cfi_def_cfa %esp, 4
-; AVX-NEXT: retl
%z = call nnan double @llvm.maximumnum.f64(double %x, double %y)
ret double %z
}
@@ -1119,188 +267,6 @@ define float @minimumnum_float(float %x, float %y) {
; X86-64-NEXT: andps %xmm3, %xmm1
; X86-64-NEXT: orps %xmm1, %xmm0
; X86-64-NEXT: retq
-;
-; I386-LABEL: minimumnum_float:
-; I386: # %bb.0:
-; I386-NEXT: subl $8, %esp
-; I386-NEXT: .cfi_def_cfa_offset 12
-; I386-NEXT: flds {{[0-9]+}}(%esp)
-; I386-NEXT: flds {{[0-9]+}}(%esp)
-; I386-NEXT: fucom %st(0)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: fld %st(1)
-; I386-NEXT: jp .LBB6_2
-; I386-NEXT: # %bb.1:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: .LBB6_2:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fsts {{[0-9]+}}(%esp)
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(0)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: fld %st(1)
-; I386-NEXT: jp .LBB6_4
-; I386-NEXT: # %bb.3:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: .LBB6_4:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fsts (%esp)
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(1)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: fld %st(0)
-; I386-NEXT: jb .LBB6_6
-; I386-NEXT: # %bb.5:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: fld %st(1)
-; I386-NEXT: .LBB6_6:
-; I386-NEXT: fld %st(0)
-; I386-NEXT: fadd %st(1), %st
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(0)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: jp .LBB6_8
-; I386-NEXT: # %bb.7:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fldz
-; I386-NEXT: .LBB6_8:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: xorl %eax, %eax
-; I386-NEXT: cmpl {{[0-9]+}}(%esp), %eax
-; I386-NEXT: jo .LBB6_10
-; I386-NEXT: # %bb.9:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fld %st(0)
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: .LBB6_10:
-; I386-NEXT: cmpl (%esp), %eax
-; I386-NEXT: jo .LBB6_12
-; I386-NEXT: # %bb.11:
-; I386-NEXT: fstp %st(2)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fxch %st(2)
-; I386-NEXT: .LBB6_12:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(1)
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: je .LBB6_14
-; I386-NEXT: # %bb.13:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fldz
-; I386-NEXT: .LBB6_14:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: addl $8, %esp
-; I386-NEXT: .cfi_def_cfa_offset 4
-; I386-NEXT: retl
-;
-; SSE2-LABEL: minimumnum_float:
-; SSE2: # %bb.0:
-; SSE2-NEXT: pushl %eax
-; SSE2-NEXT: .cfi_def_cfa_offset 8
-; SSE2-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
-; SSE2-NEXT: movss {{.*#+}} xmm2 = mem[0],zero,zero,zero
-; SSE2-NEXT: movaps %xmm1, %xmm0
-; SSE2-NEXT: cmpunordss %xmm1, %xmm0
-; SSE2-NEXT: movaps %xmm0, %xmm3
-; SSE2-NEXT: andps %xmm2, %xmm3
-; SSE2-NEXT: andnps %xmm1, %xmm0
-; SSE2-NEXT: orps %xmm3, %xmm0
-; SSE2-NEXT: movaps %xmm2, %xmm1
-; SSE2-NEXT: cmpunordss %xmm2, %xmm1
-; SSE2-NEXT: movaps %xmm1, %xmm3
-; SSE2-NEXT: andps %xmm0, %xmm3
-; SSE2-NEXT: andnps %xmm2, %xmm1
-; SSE2-NEXT: orps %xmm3, %xmm1
-; SSE2-NEXT: movaps %xmm0, %xmm2
-; SSE2-NEXT: cmpltss %xmm1, %xmm2
-; SSE2-NEXT: movaps %xmm2, %xmm3
-; SSE2-NEXT: andps %xmm0, %xmm3
-; SSE2-NEXT: andnps %xmm1, %xmm2
-; SSE2-NEXT: orps %xmm3, %xmm2
-; SSE2-NEXT: movaps %xmm2, %xmm4
-; SSE2-NEXT: addss %xmm2, %xmm4
-; SSE2-NEXT: movaps %xmm2, %xmm3
-; SSE2-NEXT: cmpunordss %xmm2, %xmm3
-; SSE2-NEXT: andps %xmm3, %xmm4
-; SSE2-NEXT: andnps %xmm2, %xmm3
-; SSE2-NEXT: orps %xmm4, %xmm3
-; SSE2-NEXT: xorps %xmm2, %xmm2
-; SSE2-NEXT: cmpeqss %xmm3, %xmm2
-; SSE2-NEXT: movd %xmm0, %eax
-; SSE2-NEXT: negl %eax
-; SSE2-NEXT: jo .LBB6_2
-; SSE2-NEXT: # %bb.1:
-; SSE2-NEXT: movaps %xmm3, %xmm0
-; SSE2-NEXT: .LBB6_2:
-; SSE2-NEXT: movaps %xmm2, %xmm4
-; SSE2-NEXT: andnps %xmm3, %xmm4
-; SSE2-NEXT: movd %xmm1, %eax
-; SSE2-NEXT: negl %eax
-; SSE2-NEXT: jo .LBB6_4
-; SSE2-NEXT: # %bb.3:
-; SSE2-NEXT: movaps %xmm0, %xmm1
-; SSE2-NEXT: .LBB6_4:
-; SSE2-NEXT: andps %xmm1, %xmm2
-; SSE2-NEXT: orps %xmm2, %xmm4
-; SSE2-NEXT: movss %xmm4, (%esp)
-; SSE2-NEXT: flds (%esp)
-; SSE2-NEXT: popl %eax
-; SSE2-NEXT: .cfi_def_cfa_offset 4
-; SSE2-NEXT: retl
-;
-; AVX-LABEL: minimumnum_float:
-; AVX: # %bb.0:
-; AVX-NEXT: pushl %eax
-; AVX-NEXT: .cfi_def_cfa_offset 8
-; AVX-NEXT: vmovss {{.*#+}} xmm0 = mem[0],zero,zero,zero
-; AVX-NEXT: vmovss {{.*#+}} xmm2 = mem[0],zero,zero,zero
-; AVX-NEXT: vcmpunordss %xmm0, %xmm0, %xmm1
-; AVX-NEXT: vblendvps %xmm1, %xmm2, %xmm0, %xmm1
-; AVX-NEXT: vcmpunordss %xmm2, %xmm2, %xmm0
-; AVX-NEXT: vblendvps %xmm0, %xmm1, %xmm2, %xmm0
-; AVX-NEXT: vcmpltss %xmm0, %xmm1, %xmm2
-; AVX-NEXT: vblendvps %xmm2, %xmm1, %xmm0, %xmm2
-; AVX-NEXT: vcmpunordss %xmm2, %xmm2, %xmm3
-; AVX-NEXT: vaddss %xmm2, %xmm2, %xmm4
-; AVX-NEXT: vblendvps %xmm3, %xmm4, %xmm2, %xmm2
-; AVX-NEXT: vxorps %xmm3, %xmm3, %xmm3
-; AVX-NEXT: vmovd %xmm1, %eax
-; AVX-NEXT: negl %eax
-; AVX-NEXT: jo .LBB6_2
-; AVX-NEXT: # %bb.1:
-; AVX-NEXT: vmovaps %xmm2, %xmm1
-; AVX-NEXT: .LBB6_2:
-; AVX-NEXT: vcmpeqss %xmm3, %xmm2, %xmm3
-; AVX-NEXT: vmovd %xmm0, %eax
-; AVX-NEXT: negl %eax
-; AVX-NEXT: jo .LBB6_4
-; AVX-NEXT: # %bb.3:
-; AVX-NEXT: vmovaps %xmm1, %xmm0
-; AVX-NEXT: .LBB6_4:
-; AVX-NEXT: vblendvps %xmm3, %xmm0, %xmm2, %xmm0
-; AVX-NEXT: vmovss %xmm0, (%esp)
-; AVX-NEXT: flds (%esp)
-; AVX-NEXT: popl %eax
-; AVX-NEXT: .cfi_def_cfa_offset 4
-; AVX-NEXT: retl
%z = call float @llvm.minimumnum.f32(float %x, float %y)
ret float %z
}
@@ -1334,119 +300,6 @@ define float @minimumnum_float_nsz(float %x, float %y) {
; X86-64-NEXT: andnps %xmm1, %xmm0
; X86-64-NEXT: orps %xmm2, %xmm0
; X86-64-NEXT: retq
-;
-; I386-LABEL: minimumnum_float_nsz:
-; I386: # %bb.0:
-; I386-NEXT: flds {{[0-9]+}}(%esp)
-; I386-NEXT: flds {{[0-9]+}}(%esp)
-; I386-NEXT: fucom %st(0)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: fld %st(1)
-; I386-NEXT: jp .LBB7_2
-; I386-NEXT: # %bb.1:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: .LBB7_2:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(0)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: fld %st(1)
-; I386-NEXT: jp .LBB7_4
-; I386-NEXT: # %bb.3:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: .LBB7_4:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(1)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: jb .LBB7_6
-; I386-NEXT: # %bb.5:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: .LBB7_6:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fld %st(0)
-; I386-NEXT: fadd %st(1), %st
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(0)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: jp .LBB7_8
-; I386-NEXT: # %bb.7:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fldz
-; I386-NEXT: .LBB7_8:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: retl
-;
-; SSE2-LABEL: minimumnum_float_nsz:
-; SSE2: # %bb.0:
-; SSE2-NEXT: pushl %eax
-; SSE2-NEXT: .cfi_def_cfa_offset 8
-; SSE2-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
-; SSE2-NEXT: movss {{.*#+}} xmm2 = mem[0],zero,zero,zero
-; SSE2-NEXT: movaps %xmm1, %xmm0
-; SSE2-NEXT: cmpunordss %xmm1, %xmm0
-; SSE2-NEXT: movaps %xmm0, %xmm3
-; SSE2-NEXT: andps %xmm2, %xmm3
-; SSE2-NEXT: andnps %xmm1, %xmm0
-; SSE2-NEXT: orps %xmm3, %xmm0
-; SSE2-NEXT: movaps %xmm2, %xmm1
-; SSE2-NEXT: cmpunordss %xmm2, %xmm1
-; SSE2-NEXT: movaps %xmm1, %xmm3
-; SSE2-NEXT: andps %xmm0, %xmm3
-; SSE2-NEXT: andnps %xmm2, %xmm1
-; SSE2-NEXT: orps %xmm3, %xmm1
-; SSE2-NEXT: movaps %xmm0, %xmm2
-; SSE2-NEXT: cmpltss %xmm1, %xmm2
-; SSE2-NEXT: andps %xmm2, %xmm0
-; SSE2-NEXT: andnps %xmm1, %xmm2
-; SSE2-NEXT: orps %xmm0, %xmm2
-; SSE2-NEXT: movaps %xmm2, %xmm0
-; SSE2-NEXT: addss %xmm2, %xmm0
-; SSE2-NEXT: movaps %xmm2, %xmm1
-; SSE2-NEXT: cmpunordss %xmm2, %xmm1
-; SSE2-NEXT: andps %xmm1, %xmm0
-; SSE2-NEXT: andnps %xmm2, %xmm1
-; SSE2-NEXT: orps %xmm0, %xmm1
-; SSE2-NEXT: movss %xmm1, (%esp)
-; SSE2-NEXT: flds (%esp)
-; SSE2-NEXT: popl %eax
-; SSE2-NEXT: .cfi_def_cfa_offset 4
-; SSE2-NEXT: retl
-;
-; AVX-LABEL: minimumnum_float_nsz:
-; AVX: # %bb.0:
-; AVX-NEXT: pushl %eax
-; AVX-NEXT: .cfi_def_cfa_offset 8
-; AVX-NEXT: vmovss {{.*#+}} xmm0 = mem[0],zero,zero,zero
-; AVX-NEXT: vmovss {{.*#+}} xmm1 = mem[0],zero,zero,zero
-; AVX-NEXT: vcmpunordss %xmm0, %xmm0, %xmm2
-; AVX-NEXT: vblendvps %xmm2, %xmm1, %xmm0, %xmm0
-; AVX-NEXT: vcmpunordss %xmm1, %xmm1, %xmm2
-; AVX-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm1
-; AVX-NEXT: vcmpltss %xmm1, %xmm0, %xmm2
-; AVX-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm0
-; AVX-NEXT: vcmpunordss %xmm0, %xmm0, %xmm1
-; AVX-NEXT: vaddss %xmm0, %xmm0, %xmm2
-; AVX-NEXT: vblendvps %xmm1, %xmm2, %xmm0, %xmm0
-; AVX-NEXT: vmovss %xmm0, (%esp)
-; AVX-NEXT: flds (%esp)
-; AVX-NEXT: popl %eax
-; AVX-NEXT: .cfi_def_cfa_offset 4
-; AVX-NEXT: retl
%z = call nsz float @llvm.minimumnum.f32(float %x, float %y)
ret float %z
}
@@ -1466,105 +319,6 @@ define float @minimumnum_float_nnan(float %x, float %y) {
; X86-64-NEXT: movaps %xmm1, %xmm0
; X86-64-NEXT: minss %xmm2, %xmm0
; X86-64-NEXT: retq
-;
-; I386-LABEL: minimumnum_float_nnan:
-; I386: # %bb.0:
-; I386-NEXT: subl $8, %esp
-; I386-NEXT: .cfi_def_cfa_offset 12
-; I386-NEXT: flds {{[0-9]+}}(%esp)
-; I386-NEXT: fsts {{[0-9]+}}(%esp)
-; I386-NEXT: flds {{[0-9]+}}(%esp)
-; I386-NEXT: fsts (%esp)
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(1)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: fld %st(0)
-; I386-NEXT: jb .LBB8_2
-; I386-NEXT: # %bb.1:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: fld %st(1)
-; I386-NEXT: .LBB8_2:
-; I386-NEXT: xorl %eax, %eax
-; I386-NEXT: cmpl {{[0-9]+}}(%esp), %eax
-; I386-NEXT: jo .LBB8_4
-; I386-NEXT: # %bb.3:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fld %st(0)
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: .LBB8_4:
-; I386-NEXT: cmpl (%esp), %eax
-; I386-NEXT: jo .LBB8_6
-; I386-NEXT: # %bb.5:
-; I386-NEXT: fstp %st(2)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fxch %st(2)
-; I386-NEXT: .LBB8_6:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(1)
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: je .LBB8_8
-; I386-NEXT: # %bb.7:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fldz
-; I386-NEXT: .LBB8_8:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: addl $8, %esp
-; I386-NEXT: .cfi_def_cfa_offset 4
-; I386-NEXT: retl
-;
-; SSE2-LABEL: minimumnum_float_nnan:
-; SSE2: # %bb.0:
-; SSE2-NEXT: pushl %eax
-; SSE2-NEXT: .cfi_def_cfa_offset 8
-; SSE2-NEXT: movd {{.*#+}} xmm2 = mem[0],zero,zero,zero
-; SSE2-NEXT: movd {{.*#+}} xmm0 = mem[0],zero,zero,zero
-; SSE2-NEXT: movd %xmm0, %eax
-; SSE2-NEXT: testl %eax, %eax
-; SSE2-NEXT: js .LBB8_1
-; SSE2-NEXT: # %bb.2:
-; SSE2-NEXT: movdqa %xmm2, %xmm1
-; SSE2-NEXT: jmp .LBB8_3
-; SSE2-NEXT: .LBB8_1:
-; SSE2-NEXT: movdqa %xmm0, %xmm1
-; SSE2-NEXT: movdqa %xmm2, %xmm0
-; SSE2-NEXT: .LBB8_3:
-; SSE2-NEXT: minss %xmm1, %xmm0
-; SSE2-NEXT: movss %xmm0, (%esp)
-; SSE2-NEXT: flds (%esp)
-; SSE2-NEXT: popl %eax
-; SSE2-NEXT: .cfi_def_cfa_offset 4
-; SSE2-NEXT: retl
-;
-; AVX-LABEL: minimumnum_float_nnan:
-; AVX: # %bb.0:
-; AVX-NEXT: pushl %eax
-; AVX-NEXT: .cfi_def_cfa_offset 8
-; AVX-NEXT: vmovd {{.*#+}} xmm1 = mem[0],zero,zero,zero
-; AVX-NEXT: vmovd {{.*#+}} xmm0 = mem[0],zero,zero,zero
-; AVX-NEXT: vmovd %xmm0, %eax
-; AVX-NEXT: testl %eax, %eax
-; AVX-NEXT: js .LBB8_1
-; AVX-NEXT: # %bb.2:
-; AVX-NEXT: vmovdqa %xmm1, %xmm2
-; AVX-NEXT: jmp .LBB8_3
-; AVX-NEXT: .LBB8_1:
-; AVX-NEXT: vmovdqa %xmm0, %xmm2
-; AVX-NEXT: vmovdqa %xmm1, %xmm0
-; AVX-NEXT: .LBB8_3:
-; AVX-NEXT: vminss %xmm2, %xmm0, %xmm0
-; AVX-NEXT: vmovss %xmm0, (%esp)
-; AVX-NEXT: flds (%esp)
-; AVX-NEXT: popl %eax
-; AVX-NEXT: .cfi_def_cfa_offset 4
-; AVX-NEXT: retl
%z = call nnan float @llvm.minimumnum.f32(float %x, float %y)
ret float %z
}
@@ -1617,210 +371,6 @@ define double @minimumnum_double(double %x, double %y) {
; X86-64-NEXT: andpd %xmm3, %xmm1
; X86-64-NEXT: orpd %xmm1, %xmm0
; X86-64-NEXT: retq
-;
-; I386-LABEL: minimumnum_double:
-; I386: # %bb.0:
-; I386-NEXT: subl $16, %esp
-; I386-NEXT: .cfi_def_cfa_offset 20
-; I386-NEXT: fldl {{[0-9]+}}(%esp)
-; I386-NEXT: fldl {{[0-9]+}}(%esp)
-; I386-NEXT: fucom %st(0)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: fld %st(1)
-; I386-NEXT: jp .LBB9_2
-; I386-NEXT: # %bb.1:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: .LBB9_2:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fsts {{[0-9]+}}(%esp)
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(0)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: fld %st(1)
-; I386-NEXT: jp .LBB9_4
-; I386-NEXT: # %bb.3:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: .LBB9_4:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fsts (%esp)
-; I386-NEXT: flds {{[0-9]+}}(%esp)
-; I386-NEXT: fstps {{[0-9]+}}(%esp)
-; I386-NEXT: flds (%esp)
-; I386-NEXT: fstps {{[0-9]+}}(%esp)
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(1)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: fld %st(0)
-; I386-NEXT: jb .LBB9_6
-; I386-NEXT: # %bb.5:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: fld %st(1)
-; I386-NEXT: .LBB9_6:
-; I386-NEXT: fld %st(0)
-; I386-NEXT: fadd %st(1), %st
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(0)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: jp .LBB9_8
-; I386-NEXT: # %bb.7:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fldz
-; I386-NEXT: .LBB9_8:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: xorl %eax, %eax
-; I386-NEXT: cmpl {{[0-9]+}}(%esp), %eax
-; I386-NEXT: jo .LBB9_10
-; I386-NEXT: # %bb.9:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fld %st(0)
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: .LBB9_10:
-; I386-NEXT: cmpl {{[0-9]+}}(%esp), %eax
-; I386-NEXT: jo .LBB9_12
-; I386-NEXT: # %bb.11:
-; I386-NEXT: fstp %st(2)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fxch %st(2)
-; I386-NEXT: .LBB9_12:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(1)
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: je .LBB9_14
-; I386-NEXT: # %bb.13:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fldz
-; I386-NEXT: .LBB9_14:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: addl $16, %esp
-; I386-NEXT: .cfi_def_cfa_offset 4
-; I386-NEXT: retl
-;
-; SSE2-LABEL: minimumnum_double:
-; SSE2: # %bb.0:
-; SSE2-NEXT: pushl %ebp
-; SSE2-NEXT: .cfi_def_cfa_offset 8
-; SSE2-NEXT: .cfi_offset %ebp, -8
-; SSE2-NEXT: movl %esp, %ebp
-; SSE2-NEXT: .cfi_def_cfa_register %ebp
-; SSE2-NEXT: andl $-8, %esp
-; SSE2-NEXT: subl $8, %esp
-; SSE2-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero
-; SSE2-NEXT: movsd {{.*#+}} xmm2 = mem[0],zero
-; SSE2-NEXT: movapd %xmm1, %xmm0
-; SSE2-NEXT: cmpunordsd %xmm1, %xmm0
-; SSE2-NEXT: movapd %xmm0, %xmm3
-; SSE2-NEXT: andpd %xmm2, %xmm3
-; SSE2-NEXT: andnpd %xmm1, %xmm0
-; SSE2-NEXT: orpd %xmm3, %xmm0
-; SSE2-NEXT: movapd %xmm2, %xmm1
-; SSE2-NEXT: cmpunordsd %xmm2, %xmm1
-; SSE2-NEXT: movapd %xmm1, %xmm3
-; SSE2-NEXT: andpd %xmm0, %xmm3
-; SSE2-NEXT: andnpd %xmm2, %xmm1
-; SSE2-NEXT: orpd %xmm3, %xmm1
-; SSE2-NEXT: movapd %xmm0, %xmm2
-; SSE2-NEXT: cmpltsd %xmm1, %xmm2
-; SSE2-NEXT: movapd %xmm2, %xmm3
-; SSE2-NEXT: andpd %xmm0, %xmm3
-; SSE2-NEXT: andnpd %xmm1, %xmm2
-; SSE2-NEXT: orpd %xmm3, %xmm2
-; SSE2-NEXT: movapd %xmm2, %xmm4
-; SSE2-NEXT: addsd %xmm2, %xmm4
-; SSE2-NEXT: movapd %xmm2, %xmm3
-; SSE2-NEXT: cmpunordsd %xmm2, %xmm3
-; SSE2-NEXT: andpd %xmm3, %xmm4
-; SSE2-NEXT: andnpd %xmm2, %xmm3
-; SSE2-NEXT: orpd %xmm4, %xmm3
-; SSE2-NEXT: xorpd %xmm2, %xmm2
-; SSE2-NEXT: cmpeqsd %xmm3, %xmm2
-; SSE2-NEXT: xorps %xmm4, %xmm4
-; SSE2-NEXT: cvtsd2ss %xmm0, %xmm4
-; SSE2-NEXT: movd %xmm4, %eax
-; SSE2-NEXT: negl %eax
-; SSE2-NEXT: jo .LBB9_2
-; SSE2-NEXT: # %bb.1:
-; SSE2-NEXT: movapd %xmm3, %xmm0
-; SSE2-NEXT: .LBB9_2:
-; SSE2-NEXT: movapd %xmm2, %xmm4
-; SSE2-NEXT: andnpd %xmm3, %xmm4
-; SSE2-NEXT: xorps %xmm3, %xmm3
-; SSE2-NEXT: cvtsd2ss %xmm1, %xmm3
-; SSE2-NEXT: movd %xmm3, %eax
-; SSE2-NEXT: negl %eax
-; SSE2-NEXT: jo .LBB9_4
-; SSE2-NEXT: # %bb.3:
-; SSE2-NEXT: movaps %xmm0, %xmm1
-; SSE2-NEXT: .LBB9_4:
-; SSE2-NEXT: andpd %xmm1, %xmm2
-; SSE2-NEXT: orpd %xmm2, %xmm4
-; SSE2-NEXT: movlpd %xmm4, (%esp)
-; SSE2-NEXT: fldl (%esp)
-; SSE2-NEXT: movl %ebp, %esp
-; SSE2-NEXT: popl %ebp
-; SSE2-NEXT: .cfi_def_cfa %esp, 4
-; SSE2-NEXT: retl
-;
-; AVX-LABEL: minimumnum_double:
-; AVX: # %bb.0:
-; AVX-NEXT: pushl %ebp
-; AVX-NEXT: .cfi_def_cfa_offset 8
-; AVX-NEXT: .cfi_offset %ebp, -8
-; AVX-NEXT: movl %esp, %ebp
-; AVX-NEXT: .cfi_def_cfa_register %ebp
-; AVX-NEXT: andl $-8, %esp
-; AVX-NEXT: subl $8, %esp
-; AVX-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
-; AVX-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero
-; AVX-NEXT: vcmpunordsd %xmm0, %xmm0, %xmm1
-; AVX-NEXT: vblendvpd %xmm1, %xmm2, %xmm0, %xmm1
-; AVX-NEXT: vcmpunordsd %xmm2, %xmm2, %xmm0
-; AVX-NEXT: vblendvpd %xmm0, %xmm1, %xmm2, %xmm0
-; AVX-NEXT: vcmpltsd %xmm0, %xmm1, %xmm2
-; AVX-NEXT: vblendvpd %xmm2, %xmm1, %xmm0, %xmm2
-; AVX-NEXT: vcmpunordsd %xmm2, %xmm2, %xmm3
-; AVX-NEXT: vaddsd %xmm2, %xmm2, %xmm4
-; AVX-NEXT: vblendvpd %xmm3, %xmm4, %xmm2, %xmm2
-; AVX-NEXT: vxorpd %xmm3, %xmm3, %xmm3
-; AVX-NEXT: vcvtsd2ss %xmm1, %xmm1, %xmm4
-; AVX-NEXT: vmovd %xmm4, %eax
-; AVX-NEXT: negl %eax
-; AVX-NEXT: jo .LBB9_2
-; AVX-NEXT: # %bb.1:
-; AVX-NEXT: vmovapd %xmm2, %xmm1
-; AVX-NEXT: .LBB9_2:
-; AVX-NEXT: vcmpeqsd %xmm3, %xmm2, %xmm3
-; AVX-NEXT: vcvtsd2ss %xmm0, %xmm0, %xmm4
-; AVX-NEXT: vmovd %xmm4, %eax
-; AVX-NEXT: negl %eax
-; AVX-NEXT: jo .LBB9_4
-; AVX-NEXT: # %bb.3:
-; AVX-NEXT: vmovaps %xmm1, %xmm0
-; AVX-NEXT: .LBB9_4:
-; AVX-NEXT: vblendvpd %xmm3, %xmm0, %xmm2, %xmm0
-; AVX-NEXT: vmovlpd %xmm0, (%esp)
-; AVX-NEXT: fldl (%esp)
-; AVX-NEXT: movl %ebp, %esp
-; AVX-NEXT: popl %ebp
-; AVX-NEXT: .cfi_def_cfa %esp, 4
-; AVX-NEXT: retl
%z = call double @llvm.minimumnum.f64(double %x, double %y)
ret double %z
}
@@ -1854,131 +404,6 @@ define double @minimumnum_double_nsz(double %x, double %y) {
; X86-64-NEXT: andnpd %xmm1, %xmm0
; X86-64-NEXT: orpd %xmm2, %xmm0
; X86-64-NEXT: retq
-;
-; I386-LABEL: minimumnum_double_nsz:
-; I386: # %bb.0:
-; I386-NEXT: fldl {{[0-9]+}}(%esp)
-; I386-NEXT: fldl {{[0-9]+}}(%esp)
-; I386-NEXT: fucom %st(0)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: fld %st(1)
-; I386-NEXT: jp .LBB10_2
-; I386-NEXT: # %bb.1:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: .LBB10_2:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(0)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: fld %st(1)
-; I386-NEXT: jp .LBB10_4
-; I386-NEXT: # %bb.3:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: .LBB10_4:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(1)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: jb .LBB10_6
-; I386-NEXT: # %bb.5:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: .LBB10_6:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fld %st(0)
-; I386-NEXT: fadd %st(1), %st
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(0)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: jp .LBB10_8
-; I386-NEXT: # %bb.7:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fldz
-; I386-NEXT: .LBB10_8:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: retl
-;
-; SSE2-LABEL: minimumnum_double_nsz:
-; SSE2: # %bb.0:
-; SSE2-NEXT: pushl %ebp
-; SSE2-NEXT: .cfi_def_cfa_offset 8
-; SSE2-NEXT: .cfi_offset %ebp, -8
-; SSE2-NEXT: movl %esp, %ebp
-; SSE2-NEXT: .cfi_def_cfa_register %ebp
-; SSE2-NEXT: andl $-8, %esp
-; SSE2-NEXT: subl $8, %esp
-; SSE2-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero
-; SSE2-NEXT: movsd {{.*#+}} xmm2 = mem[0],zero
-; SSE2-NEXT: movapd %xmm1, %xmm0
-; SSE2-NEXT: cmpunordsd %xmm1, %xmm0
-; SSE2-NEXT: movapd %xmm0, %xmm3
-; SSE2-NEXT: andpd %xmm2, %xmm3
-; SSE2-NEXT: andnpd %xmm1, %xmm0
-; SSE2-NEXT: orpd %xmm3, %xmm0
-; SSE2-NEXT: movapd %xmm2, %xmm1
-; SSE2-NEXT: cmpunordsd %xmm2, %xmm1
-; SSE2-NEXT: movapd %xmm1, %xmm3
-; SSE2-NEXT: andpd %xmm0, %xmm3
-; SSE2-NEXT: andnpd %xmm2, %xmm1
-; SSE2-NEXT: orpd %xmm3, %xmm1
-; SSE2-NEXT: movapd %xmm0, %xmm2
-; SSE2-NEXT: cmpltsd %xmm1, %xmm2
-; SSE2-NEXT: andpd %xmm2, %xmm0
-; SSE2-NEXT: andnpd %xmm1, %xmm2
-; SSE2-NEXT: orpd %xmm0, %xmm2
-; SSE2-NEXT: movapd %xmm2, %xmm0
-; SSE2-NEXT: addsd %xmm2, %xmm0
-; SSE2-NEXT: movapd %xmm2, %xmm1
-; SSE2-NEXT: cmpunordsd %xmm2, %xmm1
-; SSE2-NEXT: andpd %xmm1, %xmm0
-; SSE2-NEXT: andnpd %xmm2, %xmm1
-; SSE2-NEXT: orpd %xmm0, %xmm1
-; SSE2-NEXT: movlpd %xmm1, (%esp)
-; SSE2-NEXT: fldl (%esp)
-; SSE2-NEXT: movl %ebp, %esp
-; SSE2-NEXT: popl %ebp
-; SSE2-NEXT: .cfi_def_cfa %esp, 4
-; SSE2-NEXT: retl
-;
-; AVX-LABEL: minimumnum_double_nsz:
-; AVX: # %bb.0:
-; AVX-NEXT: pushl %ebp
-; AVX-NEXT: .cfi_def_cfa_offset 8
-; AVX-NEXT: .cfi_offset %ebp, -8
-; AVX-NEXT: movl %esp, %ebp
-; AVX-NEXT: .cfi_def_cfa_register %ebp
-; AVX-NEXT: andl $-8, %esp
-; AVX-NEXT: subl $8, %esp
-; AVX-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
-; AVX-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero
-; AVX-NEXT: vcmpunordsd %xmm0, %xmm0, %xmm2
-; AVX-NEXT: vblendvpd %xmm2, %xmm1, %xmm0, %xmm0
-; AVX-NEXT: vcmpunordsd %xmm1, %xmm1, %xmm2
-; AVX-NEXT: vblendvpd %xmm2, %xmm0, %xmm1, %xmm1
-; AVX-NEXT: vcmpltsd %xmm1, %xmm0, %xmm2
-; AVX-NEXT: vblendvpd %xmm2, %xmm0, %xmm1, %xmm0
-; AVX-NEXT: vcmpunordsd %xmm0, %xmm0, %xmm1
-; AVX-NEXT: vaddsd %xmm0, %xmm0, %xmm2
-; AVX-NEXT: vblendvpd %xmm1, %xmm2, %xmm0, %xmm0
-; AVX-NEXT: vmovlpd %xmm0, (%esp)
-; AVX-NEXT: fldl (%esp)
-; AVX-NEXT: movl %ebp, %esp
-; AVX-NEXT: popl %ebp
-; AVX-NEXT: .cfi_def_cfa %esp, 4
-; AVX-NEXT: retl
%z = call nsz double @llvm.minimumnum.f64(double %x, double %y)
ret double %z
}
@@ -1998,124 +423,6 @@ define double @minimumnum_double_nnan(double %x, double %y) {
; X86-64-NEXT: movapd %xmm1, %xmm0
; X86-64-NEXT: minsd %xmm2, %xmm0
; X86-64-NEXT: retq
-;
-; I386-LABEL: minimumnum_double_nnan:
-; I386: # %bb.0:
-; I386-NEXT: subl $16, %esp
-; I386-NEXT: .cfi_def_cfa_offset 20
-; I386-NEXT: fldl {{[0-9]+}}(%esp)
-; I386-NEXT: fldl {{[0-9]+}}(%esp)
-; I386-NEXT: fsts {{[0-9]+}}(%esp)
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fsts (%esp)
-; I386-NEXT: flds {{[0-9]+}}(%esp)
-; I386-NEXT: fstps {{[0-9]+}}(%esp)
-; I386-NEXT: flds (%esp)
-; I386-NEXT: fstps {{[0-9]+}}(%esp)
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(1)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: fld %st(0)
-; I386-NEXT: jb .LBB11_2
-; I386-NEXT: # %bb.1:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: fld %st(1)
-; I386-NEXT: .LBB11_2:
-; I386-NEXT: xorl %eax, %eax
-; I386-NEXT: cmpl {{[0-9]+}}(%esp), %eax
-; I386-NEXT: jo .LBB11_4
-; I386-NEXT: # %bb.3:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fld %st(0)
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: .LBB11_4:
-; I386-NEXT: cmpl {{[0-9]+}}(%esp), %eax
-; I386-NEXT: jo .LBB11_6
-; I386-NEXT: # %bb.5:
-; I386-NEXT: fstp %st(2)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fxch %st(2)
-; I386-NEXT: .LBB11_6:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fldz
-; I386-NEXT: fxch %st(1)
-; I386-NEXT: fucom %st(1)
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fnstsw %ax
-; I386-NEXT: # kill: def $ah killed $ah killed $ax
-; I386-NEXT: sahf
-; I386-NEXT: je .LBB11_8
-; I386-NEXT: # %bb.7:
-; I386-NEXT: fstp %st(1)
-; I386-NEXT: fldz
-; I386-NEXT: .LBB11_8:
-; I386-NEXT: fstp %st(0)
-; I386-NEXT: addl $16, %esp
-; I386-NEXT: .cfi_def_cfa_offset 4
-; I386-NEXT: retl
-;
-; SSE2-LABEL: minimumnum_double_nnan:
-; SSE2: # %bb.0:
-; SSE2-NEXT: pushl %ebp
-; SSE2-NEXT: .cfi_def_cfa_offset 8
-; SSE2-NEXT: .cfi_offset %ebp, -8
-; SSE2-NEXT: movl %esp, %ebp
-; SSE2-NEXT: .cfi_def_cfa_register %ebp
-; SSE2-NEXT: andl $-8, %esp
-; SSE2-NEXT: subl $8, %esp
-; SSE2-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero
-; SSE2-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero
-; SSE2-NEXT: movaps %xmm0, %xmm2
-; SSE2-NEXT: shufps {{.*#+}} xmm2 = xmm2[1,1],xmm0[1,1]
-; SSE2-NEXT: movd %xmm2, %eax
-; SSE2-NEXT: testl %eax, %eax
-; SSE2-NEXT: js .LBB11_1
-; SSE2-NEXT: # %bb.2:
-; SSE2-NEXT: movaps %xmm1, %xmm2
-; SSE2-NEXT: jmp .LBB11_3
-; SSE2-NEXT: .LBB11_1:
-; SSE2-NEXT: movaps %xmm0, %xmm2
-; SSE2-NEXT: movaps %xmm1, %xmm0
-; SSE2-NEXT: .LBB11_3:
-; SSE2-NEXT: minsd %xmm2, %xmm0
-; SSE2-NEXT: movsd %xmm0, (%esp)
-; SSE2-NEXT: fldl (%esp)
-; SSE2-NEXT: movl %ebp, %esp
-; SSE2-NEXT: popl %ebp
-; SSE2-NEXT: .cfi_def_cfa %esp, 4
-; SSE2-NEXT: retl
-;
-; AVX-LABEL: minimumnum_double_nnan:
-; AVX: # %bb.0:
-; AVX-NEXT: pushl %ebp
-; AVX-NEXT: .cfi_def_cfa_offset 8
-; AVX-NEXT: .cfi_offset %ebp, -8
-; AVX-NEXT: movl %esp, %ebp
-; AVX-NEXT: .cfi_def_cfa_register %ebp
-; AVX-NEXT: andl $-8, %esp
-; AVX-NEXT: subl $8, %esp
-; AVX-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero
-; AVX-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
-; AVX-NEXT: vextractps $1, %xmm0, %eax
-; AVX-NEXT: testl %eax, %eax
-; AVX-NEXT: js .LBB11_1
-; AVX-NEXT: # %bb.2:
-; AVX-NEXT: vmovapd %xmm1, %xmm2
-; AVX-NEXT: jmp .LBB11_3
-; AVX-NEXT: .LBB11_1:
-; AVX-NEXT: vmovapd %xmm0, %xmm2
-; AVX-NEXT: vmovapd %xmm1, %xmm0
-; AVX-NEXT: .LBB11_3:
-; AVX-NEXT: vminsd %xmm2, %xmm0, %xmm0
-; AVX-NEXT: vmovsd %xmm0, (%esp)
-; AVX-NEXT: fldl (%esp)
-; AVX-NEXT: movl %ebp, %esp
-; AVX-NEXT: popl %ebp
-; AVX-NEXT: .cfi_def_cfa %esp, 4
-; AVX-NEXT: retl
%z = call nnan double @llvm.minimumnum.f64(double %x, double %y)
ret double %z
}
>From 7b35f9b57738c93833fac3d1af2ba0eaf7498ef1 Mon Sep 17 00:00:00 2001
From: YunQiang Su <syq at gcc.gnu.org>
Date: Tue, 30 Jul 2024 15:35:11 +0800
Subject: [PATCH 15/17] fix sparc test
---
.../CodeGen/SPARC/fp-maximumnum-minimumnum.ll | 116 +++++++++---------
1 file changed, 59 insertions(+), 57 deletions(-)
diff --git a/llvm/test/CodeGen/SPARC/fp-maximumnum-minimumnum.ll b/llvm/test/CodeGen/SPARC/fp-maximumnum-minimumnum.ll
index 6d3766fafe7324..10db34b4d0ae84 100644
--- a/llvm/test/CodeGen/SPARC/fp-maximumnum-minimumnum.ll
+++ b/llvm/test/CodeGen/SPARC/fp-maximumnum-minimumnum.ll
@@ -331,31 +331,35 @@ define double @maximumnum_double(double %x, double %y) {
; SPARC64-NEXT: mov %g0, %o1
; SPARC64-NEXT: fcmpd %fcc0, %f0, %f0
; SPARC64-NEXT: fmovdu %fcc0, %f2, %f0
-; SPARC64-NEXT: std %f0, [%sp+2183]
+; SPARC64-NEXT: fdtos %f0, %f4
+; SPARC64-NEXT: st %f4, [%sp+2187]
; SPARC64-NEXT: fcmpd %fcc0, %f2, %f2
; SPARC64-NEXT: fmovdu %fcc0, %f0, %f2
-; SPARC64-NEXT: std %f2, [%sp+2175]
+; SPARC64-NEXT: fdtos %f2, %f4
+; SPARC64-NEXT: st %f4, [%sp+2183]
; SPARC64-NEXT: fcmpd %fcc0, %f0, %f2
; SPARC64-NEXT: fmovd %f2, %f4
; SPARC64-NEXT: fmovdg %fcc0, %f0, %f4
-; SPARC64-NEXT: ldx [%sp+2183], %o2
+; SPARC64-NEXT: ld [%sp+2187], %o2
; SPARC64-NEXT: faddd %f4, %f4, %f6
; SPARC64-NEXT: fcmpd %fcc0, %f4, %f4
; SPARC64-NEXT: fmovdu %fcc0, %f6, %f4
-; SPARC64-NEXT: movrz %o2, 1, %o0
+; SPARC64-NEXT: cmp %o2, 0
+; SPARC64-NEXT: ld [%sp+2183], %o2
+; SPARC64-NEXT: move %icc, 1, %o0
; SPARC64-NEXT: cmp %o0, 0
-; SPARC64-NEXT: ldx [%sp+2175], %o0
-; SPARC64-NEXT: sethi %h44(.LCPI3_0), %o2
-; SPARC64-NEXT: add %o2, %m44(.LCPI3_0), %o2
-; SPARC64-NEXT: sllx %o2, 12, %o2
-; SPARC64-NEXT: ldd [%o2+%l44(.LCPI3_0)], %f6
-; SPARC64-NEXT: fmovd %f4, %f8
-; SPARC64-NEXT: fmovdne %icc, %f0, %f8
-; SPARC64-NEXT: movrz %o0, 1, %o1
+; SPARC64-NEXT: fmovd %f4, %f6
+; SPARC64-NEXT: fmovdne %icc, %f0, %f6
+; SPARC64-NEXT: cmp %o2, 0
+; SPARC64-NEXT: sethi %h44(.LCPI3_0), %o0
+; SPARC64-NEXT: add %o0, %m44(.LCPI3_0), %o0
+; SPARC64-NEXT: sllx %o0, 12, %o0
+; SPARC64-NEXT: ldd [%o0+%l44(.LCPI3_0)], %f0
+; SPARC64-NEXT: move %icc, 1, %o1
; SPARC64-NEXT: cmp %o1, 0
-; SPARC64-NEXT: fmovdne %icc, %f2, %f8
-; SPARC64-NEXT: fcmpd %fcc0, %f4, %f6
-; SPARC64-NEXT: fmovde %fcc0, %f8, %f4
+; SPARC64-NEXT: fmovdne %icc, %f2, %f6
+; SPARC64-NEXT: fcmpd %fcc0, %f4, %f0
+; SPARC64-NEXT: fmovde %fcc0, %f6, %f4
; SPARC64-NEXT: fmovd %f4, %f0
; SPARC64-NEXT: retl
; SPARC64-NEXT: add %sp, 144, %sp
@@ -554,24 +558,28 @@ define double @maximumnum_double_nnan(double %x, double %y) {
; SPARC64-NEXT: .cfi_def_cfa_register %fp
; SPARC64-NEXT: .cfi_window_save
; SPARC64-NEXT: .cfi_register %o7, %i7
-; SPARC64-NEXT: std %f2, [%sp+2175]
-; SPARC64-NEXT: std %f0, [%sp+2183]
-; SPARC64-NEXT: ldx [%sp+2183], %o0
+; SPARC64-NEXT: fdtos %f0, %f4
+; SPARC64-NEXT: st %f4, [%sp+2187]
+; SPARC64-NEXT: fdtos %f2, %f4
+; SPARC64-NEXT: st %f4, [%sp+2183]
+; SPARC64-NEXT: ld [%sp+2187], %o0
; SPARC64-NEXT: mov %g0, %o1
; SPARC64-NEXT: mov %g0, %o2
-; SPARC64-NEXT: movrz %o0, 1, %o1
-; SPARC64-NEXT: ldx [%sp+2175], %o0
; SPARC64-NEXT: fcmpd %fcc0, %f0, %f2
; SPARC64-NEXT: fmovd %f2, %f4
; SPARC64-NEXT: fmovdg %fcc0, %f0, %f4
+; SPARC64-NEXT: cmp %o0, 0
+; SPARC64-NEXT: ld [%sp+2183], %o0
+; SPARC64-NEXT: move %icc, 1, %o1
; SPARC64-NEXT: cmp %o1, 0
; SPARC64-NEXT: fmovd %f4, %f6
; SPARC64-NEXT: fmovdne %icc, %f0, %f6
-; SPARC64-NEXT: sethi %h44(.LCPI5_0), %o1
-; SPARC64-NEXT: add %o1, %m44(.LCPI5_0), %o1
-; SPARC64-NEXT: sllx %o1, 12, %o1
-; SPARC64-NEXT: ldd [%o1+%l44(.LCPI5_0)], %f0
-; SPARC64-NEXT: movrz %o0, 1, %o2
+; SPARC64-NEXT: cmp %o0, 0
+; SPARC64-NEXT: sethi %h44(.LCPI5_0), %o0
+; SPARC64-NEXT: add %o0, %m44(.LCPI5_0), %o0
+; SPARC64-NEXT: sllx %o0, 12, %o0
+; SPARC64-NEXT: ldd [%o0+%l44(.LCPI5_0)], %f0
+; SPARC64-NEXT: move %icc, 1, %o2
; SPARC64-NEXT: cmp %o2, 0
; SPARC64-NEXT: fmovdne %icc, %f2, %f6
; SPARC64-NEXT: fcmpd %fcc0, %f4, %f0
@@ -997,35 +1005,32 @@ define double @minimumnum_double(double %x, double %y) {
; SPARC64-NEXT: mov %g0, %o1
; SPARC64-NEXT: fcmpd %fcc0, %f0, %f0
; SPARC64-NEXT: fmovdu %fcc0, %f2, %f0
-; SPARC64-NEXT: std %f0, [%sp+2183]
+; SPARC64-NEXT: fdtos %f0, %f4
+; SPARC64-NEXT: st %f4, [%sp+2187]
; SPARC64-NEXT: fcmpd %fcc0, %f2, %f2
; SPARC64-NEXT: fmovdu %fcc0, %f0, %f2
-; SPARC64-NEXT: std %f2, [%sp+2175]
+; SPARC64-NEXT: fdtos %f2, %f4
+; SPARC64-NEXT: st %f4, [%sp+2183]
; SPARC64-NEXT: fcmpd %fcc0, %f0, %f2
; SPARC64-NEXT: fmovd %f2, %f4
; SPARC64-NEXT: fmovdl %fcc0, %f0, %f4
-; SPARC64-NEXT: sethi 0, %o2
-; SPARC64-NEXT: or %o2, 0, %o2
-; SPARC64-NEXT: sethi 2097152, %o3
-; SPARC64-NEXT: or %o3, 0, %o3
-; SPARC64-NEXT: sllx %o3, 32, %o3
-; SPARC64-NEXT: or %o3, %o2, %o2
-; SPARC64-NEXT: ldx [%sp+2183], %o3
; SPARC64-NEXT: faddd %f4, %f4, %f6
+; SPARC64-NEXT: ld [%sp+2187], %o2
; SPARC64-NEXT: fcmpd %fcc0, %f4, %f4
; SPARC64-NEXT: fmovdu %fcc0, %f6, %f4
-; SPARC64-NEXT: cmp %o3, %o2
-; SPARC64-NEXT: ldx [%sp+2175], %o3
-; SPARC64-NEXT: move %xcc, 1, %o0
+; SPARC64-NEXT: sethi 2097152, %o3
+; SPARC64-NEXT: cmp %o2, %o3
+; SPARC64-NEXT: ld [%sp+2183], %o2
+; SPARC64-NEXT: move %icc, 1, %o0
; SPARC64-NEXT: cmp %o0, 0
; SPARC64-NEXT: fmovd %f4, %f6
; SPARC64-NEXT: fmovdne %icc, %f0, %f6
-; SPARC64-NEXT: cmp %o3, %o2
+; SPARC64-NEXT: cmp %o2, %o3
; SPARC64-NEXT: sethi %h44(.LCPI9_0), %o0
; SPARC64-NEXT: add %o0, %m44(.LCPI9_0), %o0
; SPARC64-NEXT: sllx %o0, 12, %o0
; SPARC64-NEXT: ldd [%o0+%l44(.LCPI9_0)], %f0
-; SPARC64-NEXT: move %xcc, 1, %o1
+; SPARC64-NEXT: move %icc, 1, %o1
; SPARC64-NEXT: cmp %o1, 0
; SPARC64-NEXT: fmovdne %icc, %f2, %f6
; SPARC64-NEXT: fcmpd %fcc0, %f4, %f0
@@ -1237,35 +1242,32 @@ define double @minimumnum_double_nnan(double %x, double %y) {
; SPARC64-NEXT: .cfi_def_cfa_register %fp
; SPARC64-NEXT: .cfi_window_save
; SPARC64-NEXT: .cfi_register %o7, %i7
-; SPARC64-NEXT: mov %g0, %o0
+; SPARC64-NEXT: fdtos %f2, %f4
+; SPARC64-NEXT: st %f4, [%sp+2183]
+; SPARC64-NEXT: fdtos %f0, %f4
+; SPARC64-NEXT: st %f4, [%sp+2187]
+; SPARC64-NEXT: ld [%sp+2183], %o0
; SPARC64-NEXT: mov %g0, %o1
-; SPARC64-NEXT: std %f2, [%sp+2175]
-; SPARC64-NEXT: std %f0, [%sp+2183]
-; SPARC64-NEXT: ldx [%sp+2183], %o2
-; SPARC64-NEXT: sethi 0, %o3
-; SPARC64-NEXT: or %o3, 0, %o3
+; SPARC64-NEXT: mov %g0, %o2
+; SPARC64-NEXT: ld [%sp+2187], %o3
; SPARC64-NEXT: sethi 2097152, %o4
-; SPARC64-NEXT: or %o4, 0, %o4
-; SPARC64-NEXT: sllx %o4, 32, %o4
-; SPARC64-NEXT: or %o4, %o3, %o3
-; SPARC64-NEXT: cmp %o2, %o3
-; SPARC64-NEXT: ldx [%sp+2175], %o2
-; SPARC64-NEXT: move %xcc, 1, %o0
+; SPARC64-NEXT: cmp %o0, %o4
+; SPARC64-NEXT: move %icc, 1, %o1
+; SPARC64-NEXT: cmp %o3, %o4
+; SPARC64-NEXT: move %icc, 1, %o2
; SPARC64-NEXT: fcmpd %fcc0, %f0, %f2
; SPARC64-NEXT: fmovd %f2, %f4
; SPARC64-NEXT: fmovdl %fcc0, %f0, %f4
-; SPARC64-NEXT: cmp %o0, 0
+; SPARC64-NEXT: cmp %o2, 0
; SPARC64-NEXT: fmovd %f4, %f6
-; SPARC64-NEXT: fmovdne %icc, %f0, %f6
-; SPARC64-NEXT: cmp %o2, %o3
; SPARC64-NEXT: sethi %h44(.LCPI11_0), %o0
; SPARC64-NEXT: add %o0, %m44(.LCPI11_0), %o0
; SPARC64-NEXT: sllx %o0, 12, %o0
-; SPARC64-NEXT: ldd [%o0+%l44(.LCPI11_0)], %f0
-; SPARC64-NEXT: move %xcc, 1, %o1
+; SPARC64-NEXT: ldd [%o0+%l44(.LCPI11_0)], %f8
+; SPARC64-NEXT: fmovdne %icc, %f0, %f6
; SPARC64-NEXT: cmp %o1, 0
; SPARC64-NEXT: fmovdne %icc, %f2, %f6
-; SPARC64-NEXT: fcmpd %fcc0, %f4, %f0
+; SPARC64-NEXT: fcmpd %fcc0, %f4, %f8
; SPARC64-NEXT: fmovde %fcc0, %f6, %f4
; SPARC64-NEXT: fmovd %f4, %f0
; SPARC64-NEXT: retl
>From a78fc31762a725b00171fc925aea624e0c1d834f Mon Sep 17 00:00:00 2001
From: YunQiang Su <syq at gcc.gnu.org>
Date: Tue, 30 Jul 2024 15:35:38 +0800
Subject: [PATCH 16/17] fix code style
---
.../CodeGen/SelectionDAG/TargetLowering.cpp | 49 +++++++++----------
1 file changed, 24 insertions(+), 25 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index a813d43b4b809f..fe491b87273a5e 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -8605,32 +8605,31 @@ SDValue TargetLowering::expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *Node,
if (Options.NoSignedZerosFPMath || Flags.hasNoSignedZeros() ||
DAG.isKnownNeverZeroFloat(LHS) || DAG.isKnownNeverZeroFloat(RHS)) {
return MinMax;
- } else {
- SDValue LRound = LHS;
- SDValue RRound = RHS;
- EVT RCCVT = CCVT;
- // expandIS_FPCLASS is buggy for GPR32+FPR64. Let's round them to single for
- // this case.
- if (!isOperationLegal (ISD::BITCAST, VT.changeTypeToInteger())) {
- LRound = DAG.getNode(ISD::FP_ROUND, DL, MVT::f32, LHS,
- DAG.getIntPtrConstant(0, DL, /*isTarget=*/true));
- RRound = DAG.getNode(ISD::FP_ROUND, DL, MVT::f32, RHS,
- DAG.getIntPtrConstant(0, DL, /*isTarget=*/true));
- RCCVT =
- getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), MVT::f32);
- }
- SDValue TestZero =
- DAG.getTargetConstant(IsMax ? fcPosZero : fcNegZero, DL, MVT::i32);
- SDValue IsZero = DAG.getSetCC(DL, CCVT, MinMax,
- DAG.getConstantFP(0.0, DL, VT), ISD::SETEQ);
- SDValue LCmp = DAG.getSelect(
- DL, VT, DAG.getNode(ISD::IS_FPCLASS, DL, RCCVT, LRound, TestZero), LHS,
- MinMax, Flags);
- SDValue RCmp = DAG.getSelect(
- DL, VT, DAG.getNode(ISD::IS_FPCLASS, DL, RCCVT, RRound, TestZero), RHS,
- LCmp, Flags);
- return DAG.getSelect(DL, VT, IsZero, RCmp, MinMax, Flags);
}
+ SDValue LRound = LHS;
+ SDValue RRound = RHS;
+ EVT RCCVT = CCVT;
+ // expandIS_FPCLASS is buggy for GPR32+FPR64. Let's round them to single for
+ // this case.
+ if (!isOperationLegal(ISD::BITCAST, VT.changeTypeToInteger())) {
+ LRound = DAG.getNode(ISD::FP_ROUND, DL, MVT::f32, LHS,
+ DAG.getIntPtrConstant(0, DL, /*isTarget=*/true));
+ RRound = DAG.getNode(ISD::FP_ROUND, DL, MVT::f32, RHS,
+ DAG.getIntPtrConstant(0, DL, /*isTarget=*/true));
+ RCCVT =
+ getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), MVT::f32);
+ }
+ SDValue TestZero =
+ DAG.getTargetConstant(IsMax ? fcPosZero : fcNegZero, DL, MVT::i32);
+ SDValue IsZero = DAG.getSetCC(DL, CCVT, MinMax,
+ DAG.getConstantFP(0.0, DL, VT), ISD::SETEQ);
+ SDValue LCmp = DAG.getSelect(
+ DL, VT, DAG.getNode(ISD::IS_FPCLASS, DL, RCCVT, LRound, TestZero), LHS,
+ MinMax, Flags);
+ SDValue RCmp = DAG.getSelect(
+ DL, VT, DAG.getNode(ISD::IS_FPCLASS, DL, RCCVT, RRound, TestZero), RHS,
+ LCmp, Flags);
+ return DAG.getSelect(DL, VT, IsZero, RCmp, MinMax, Flags);
}
/// Returns a true value if if this FPClassTest can be performed with an ordered
>From e3e993820bdc841e861355f738a841f84922d3b8 Mon Sep 17 00:00:00 2001
From: YunQiang Su <syq at gcc.gnu.org>
Date: Wed, 14 Aug 2024 10:27:34 +0800
Subject: [PATCH 17/17] remove dirty hack about fadd/fround
---
.../CodeGen/SelectionDAG/TargetLowering.cpp | 23 ++++---------------
1 file changed, 5 insertions(+), 18 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index fe491b87273a5e..a899dd21f61f66 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -8595,8 +8595,8 @@ SDValue TargetLowering::expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *Node,
// If MinMax is NaN, let's quiet it.
if (!Flags.hasNoNaNs() && !DAG.isKnownNeverNaN(LHS) &&
!DAG.isKnownNeverNaN(RHS)) {
- // Only use FADD to quiet it if it is NaN, because -0.0+0.0->+0.0.
- SDValue MinMaxQuiet = DAG.getNode(ISD::FADD, DL, VT, MinMax, MinMax, Flags);
+ SDValue MinMaxQuiet =
+ DAG.getNode(ISD::FCANONICALIZE, DL, VT, MinMax, Flags);
MinMax =
DAG.getSelectCC(DL, MinMax, MinMax, MinMaxQuiet, MinMax, ISD::SETUO);
}
@@ -8606,29 +8606,16 @@ SDValue TargetLowering::expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *Node,
DAG.isKnownNeverZeroFloat(LHS) || DAG.isKnownNeverZeroFloat(RHS)) {
return MinMax;
}
- SDValue LRound = LHS;
- SDValue RRound = RHS;
- EVT RCCVT = CCVT;
- // expandIS_FPCLASS is buggy for GPR32+FPR64. Let's round them to single for
- // this case.
- if (!isOperationLegal(ISD::BITCAST, VT.changeTypeToInteger())) {
- LRound = DAG.getNode(ISD::FP_ROUND, DL, MVT::f32, LHS,
- DAG.getIntPtrConstant(0, DL, /*isTarget=*/true));
- RRound = DAG.getNode(ISD::FP_ROUND, DL, MVT::f32, RHS,
- DAG.getIntPtrConstant(0, DL, /*isTarget=*/true));
- RCCVT =
- getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), MVT::f32);
- }
SDValue TestZero =
DAG.getTargetConstant(IsMax ? fcPosZero : fcNegZero, DL, MVT::i32);
SDValue IsZero = DAG.getSetCC(DL, CCVT, MinMax,
DAG.getConstantFP(0.0, DL, VT), ISD::SETEQ);
SDValue LCmp = DAG.getSelect(
- DL, VT, DAG.getNode(ISD::IS_FPCLASS, DL, RCCVT, LRound, TestZero), LHS,
+ DL, VT, DAG.getNode(ISD::IS_FPCLASS, DL, CCVT, LHS, TestZero), LHS,
MinMax, Flags);
SDValue RCmp = DAG.getSelect(
- DL, VT, DAG.getNode(ISD::IS_FPCLASS, DL, RCCVT, RRound, TestZero), RHS,
- LCmp, Flags);
+ DL, VT, DAG.getNode(ISD::IS_FPCLASS, DL, CCVT, RHS, TestZero), RHS, LCmp,
+ Flags);
return DAG.getSelect(DL, VT, IsZero, RCmp, MinMax, Flags);
}
More information about the llvm-commits
mailing list