[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