[llvm] expandFMINNUM_FMAXNUM: Improve for backends with FMINIMUMNUM and FMINNUM_IEEE (PR #181083)

via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 11 19:51:07 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-mips

Author: YunQiang Su (wzssyqa)

<details>
<summary>Changes</summary>

…UM_IEEE

1. FMINNUM_IEEE is a strict version of FMINNUM. We can map it directly.
2. If both operands are non-SNaN, we can map FMINNUM to FMINIMUMNUM directly.

---

Patch is 27.01 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/181083.diff


6 Files Affected:

- (modified) llvm/include/llvm/CodeGen/ISDOpcodes.h (+2-2) 
- (modified) llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp (+27-34) 
- (modified) llvm/lib/Target/Mips/MipsISelLowering.cpp (-4) 
- (added) llvm/test/CodeGen/Hexagon/expandFMINNUM_FMAXNUM-v67.ll (+233) 
- (added) llvm/test/CodeGen/Mips/expandFMINNUM_FMAXNUM-r6.ll (+189) 
- (added) llvm/test/CodeGen/WebAssembly/expandFMINNUM_FMAXNUM.ll (+243) 


``````````diff
diff --git a/llvm/include/llvm/CodeGen/ISDOpcodes.h b/llvm/include/llvm/CodeGen/ISDOpcodes.h
index b8c6788e0bc03..e1d7b7fa85221 100644
--- a/llvm/include/llvm/CodeGen/ISDOpcodes.h
+++ b/llvm/include/llvm/CodeGen/ISDOpcodes.h
@@ -1088,8 +1088,8 @@ enum NodeType {
   /// These treat -0 as ordered less than +0, matching the behavior of IEEE-754
   /// 2019's minimumNumber/maximumNumber.
   ///
-  /// Deprecated, and will be removed soon, as FMINNUM/FMAXNUM have the same
-  /// semantics now.
+  /// Some ISAs have such instructions, such as AArch64, MIPSr6, LoongArch etc.
+  /// Normally these ISAs claim that they have maxNum/minNum of IEEE754-2008.
   FMINNUM_IEEE,
   FMAXNUM_IEEE,
 
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 99968baec98e4..31b581e76ea02 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -8801,50 +8801,43 @@ TargetLowering::createSelectForFMINNUM_FMAXNUM(SDNode *Node,
 
 SDValue TargetLowering::expandFMINNUM_FMAXNUM(SDNode *Node,
                                               SelectionDAG &DAG) const {
-  if (SDValue Expanded = expandVectorNaryOpBySplitting(Node, DAG))
-    return Expanded;
-
   EVT VT = Node->getValueType(0);
-  if (VT.isScalableVector())
-    report_fatal_error(
-        "Expanding fminnum/fmaxnum for scalable vectors is undefined.");
-
   SDLoc dl(Node);
-  unsigned NewOp =
-      Node->getOpcode() == ISD::FMINNUM ? ISD::FMINNUM_IEEE : ISD::FMAXNUM_IEEE;
+  SDValue Op0 = Node->getOperand(0);
+  SDValue Op1 = Node->getOperand(1);
+  SDNodeFlags Flags = Node->getFlags();
+  unsigned Opc = Node->getOpcode();
 
-  if (isOperationLegalOrCustom(NewOp, VT)) {
-    SDValue Quiet0 = Node->getOperand(0);
-    SDValue Quiet1 = Node->getOperand(1);
+  unsigned NewOp = Opc == ISD::FMINNUM ? ISD::FMINNUM_IEEE : ISD::FMAXNUM_IEEE;
+  if (isOperationLegalOrCustom(NewOp, VT))
+    return DAG.getNode(NewOp, dl, VT, Op0, Op1, Flags);
 
-    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());
+  // If the target has FMINIMUM/FMAXIMUM but not FMINNUM/FMAXNUM use that
+  // instead if there are no NaNs.
+  if (Flags.hasNoNaNs() ||
+      (DAG.isKnownNeverNaN(Op0) && DAG.isKnownNeverNaN(Op1))) {
+    unsigned IEEE2019Op = Opc == ISD::FMINNUM ? ISD::FMINIMUM : ISD::FMAXIMUM;
+    if (isOperationLegalOrCustom(IEEE2019Op, VT))
+      return DAG.getNode(IEEE2019Op, dl, VT, Op0, Op1, Flags);
   }
 
   // If the target has FMINIMUM/FMAXIMUM but not FMINNUM/FMAXNUM use that
   // instead if there are no NaNs.
-  if (Node->getFlags().hasNoNaNs() ||
-      (DAG.isKnownNeverNaN(Node->getOperand(0)) &&
-       DAG.isKnownNeverNaN(Node->getOperand(1)))) {
-    unsigned IEEE2018Op =
-        Node->getOpcode() == ISD::FMINNUM ? ISD::FMINIMUM : ISD::FMAXIMUM;
-    if (isOperationLegalOrCustom(IEEE2018Op, VT))
-      return DAG.getNode(IEEE2018Op, dl, VT, Node->getOperand(0),
-                         Node->getOperand(1), Node->getFlags());
+  if (Flags.hasNoNaNs() ||
+      (DAG.isKnownNeverSNaN(Op0) && DAG.isKnownNeverSNaN(Op1))) {
+    unsigned IEEE2019NumOp =
+        Opc == ISD::FMINNUM ? ISD::FMINIMUMNUM : ISD::FMAXIMUMNUM;
+    if (isOperationLegalOrCustom(IEEE2019NumOp, VT))
+      return DAG.getNode(IEEE2019NumOp, dl, VT, Op0, Op1, Flags);
   }
 
+  if (SDValue Expanded = expandVectorNaryOpBySplitting(Node, DAG))
+    return Expanded;
+
+  if (VT.isScalableVector())
+    report_fatal_error(
+        "Expanding fminnum/fmaxnum for scalable vectors is undefined.");
+
   if (SDValue SelCC = createSelectForFMINNUM_FMAXNUM(Node, DAG))
     return SelCC;
 
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp
index c920e912f49ac..a26b184f41c0a 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp
@@ -253,12 +253,8 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM,
   if (Subtarget.hasMips32r6()) {
     setOperationAction(ISD::FMINNUM_IEEE, MVT::f32, Legal);
     setOperationAction(ISD::FMAXNUM_IEEE, MVT::f32, Legal);
-    setOperationAction(ISD::FMINNUM, MVT::f32, Legal);
-    setOperationAction(ISD::FMAXNUM, MVT::f32, Legal);
     setOperationAction(ISD::FMINNUM_IEEE, MVT::f64, Legal);
     setOperationAction(ISD::FMAXNUM_IEEE, MVT::f64, Legal);
-    setOperationAction(ISD::FMINNUM, MVT::f64, Legal);
-    setOperationAction(ISD::FMAXNUM, MVT::f64, Legal);
     setOperationAction(ISD::IS_FPCLASS, MVT::f32, Legal);
     setOperationAction(ISD::IS_FPCLASS, MVT::f64, Legal);
     setOperationAction(ISD::FCANONICALIZE, MVT::f32, Legal);
diff --git a/llvm/test/CodeGen/Hexagon/expandFMINNUM_FMAXNUM-v67.ll b/llvm/test/CodeGen/Hexagon/expandFMINNUM_FMAXNUM-v67.ll
new file mode 100644
index 0000000000000..3317503f9166f
--- /dev/null
+++ b/llvm/test/CodeGen/Hexagon/expandFMINNUM_FMAXNUM-v67.ll
@@ -0,0 +1,233 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=hexagon -mcpu=hexagonv67 < %s | FileCheck %s
+
+; test expandFMINNUM_FMAXNUM on backend with FMINIMUMNUM/FMAXIMUMNUM.
+; N -> not NaN
+; S -> not SNaN
+; Y -> may be NaN or SNaN
+
+define double @test_maxnumNN(double nofpclass(nan) %f1, double nofpclass(nan) %f2) {
+; CHECK-LABEL: test_maxnumNN:
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  // %bb.0: // %entry
+; CHECK-NEXT:    {
+; CHECK-NEXT:     r1:0 = dfmax(r1:0,r3:2)
+; CHECK-NEXT:     jumpr r31
+; CHECK-NEXT:    }
+entry:
+  %0 = tail call double @llvm.maxnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+define double @test_maxnumSS(double nofpclass(snan) %f1, double nofpclass(snan) %f2) {
+; CHECK-LABEL: test_maxnumSS:
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  // %bb.0: // %entry
+; CHECK-NEXT:    {
+; CHECK-NEXT:     r1:0 = dfmax(r1:0,r3:2)
+; CHECK-NEXT:     jumpr r31
+; CHECK-NEXT:    }
+entry:
+  %0 = tail call double @llvm.maxnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+define double @test_maxnumYY(double nofpclass(zero) %f1, double nofpclass(zero) %f2) {
+; CHECK-LABEL: test_maxnumYY:
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  // %bb.0: // %entry
+; CHECK-NEXT:    {
+; CHECK-NEXT:     jump fmax
+; CHECK-NEXT:    }
+entry:
+  %0 = tail call double @llvm.maxnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+define double @test_maxnumNS(double nofpclass(nan) %f1, double nofpclass(snan) %f2) {
+; CHECK-LABEL: test_maxnumNS:
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  // %bb.0: // %entry
+; CHECK-NEXT:    {
+; CHECK-NEXT:     r1:0 = dfmax(r1:0,r3:2)
+; CHECK-NEXT:     jumpr r31
+; CHECK-NEXT:    }
+entry:
+  %0 = tail call double @llvm.maxnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+define double @test_maxnumNY(double nofpclass(nan) %f1, double nofpclass(zero) %f2) {
+; CHECK-LABEL: test_maxnumNY:
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  // %bb.0: // %entry
+; CHECK-NEXT:    {
+; CHECK-NEXT:     jump fmax
+; CHECK-NEXT:    }
+entry:
+  %0 = tail call double @llvm.maxnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+define double @test_maxnumSN(double nofpclass(snan) %f1, double nofpclass(nan) %f2) {
+; CHECK-LABEL: test_maxnumSN:
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  // %bb.0: // %entry
+; CHECK-NEXT:    {
+; CHECK-NEXT:     r1:0 = dfmax(r1:0,r3:2)
+; CHECK-NEXT:     jumpr r31
+; CHECK-NEXT:    }
+entry:
+  %0 = tail call double @llvm.maxnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+define double @test_maxnumSY(double nofpclass(snan) %f1, double nofpclass(zero) %f2) {
+; CHECK-LABEL: test_maxnumSY:
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  // %bb.0: // %entry
+; CHECK-NEXT:    {
+; CHECK-NEXT:     jump fmax
+; CHECK-NEXT:    }
+entry:
+  %0 = tail call double @llvm.maxnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+define double @test_maxnumYN(double nofpclass(zero) %f1, double nofpclass(nan) %f2) {
+; CHECK-LABEL: test_maxnumYN:
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  // %bb.0: // %entry
+; CHECK-NEXT:    {
+; CHECK-NEXT:     jump fmax
+; CHECK-NEXT:    }
+entry:
+  %0 = tail call double @llvm.maxnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+define double @test_maxnumYS(double nofpclass(zero) %f1, double nofpclass(snan) %f2) {
+; CHECK-LABEL: test_maxnumYS:
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  // %bb.0: // %entry
+; CHECK-NEXT:    {
+; CHECK-NEXT:     jump fmax
+; CHECK-NEXT:    }
+entry:
+  %0 = tail call double @llvm.maxnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+
+define double @test_minnumNN(double nofpclass(nan) %f1, double nofpclass(nan) %f2) {
+; CHECK-LABEL: test_minnumNN:
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  // %bb.0: // %entry
+; CHECK-NEXT:    {
+; CHECK-NEXT:     r1:0 = dfmin(r1:0,r3:2)
+; CHECK-NEXT:     jumpr r31
+; CHECK-NEXT:    }
+entry:
+  %0 = tail call double @llvm.minnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+define double @test_minnumSS(double nofpclass(snan) %f1, double nofpclass(snan) %f2) {
+; CHECK-LABEL: test_minnumSS:
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  // %bb.0: // %entry
+; CHECK-NEXT:    {
+; CHECK-NEXT:     r1:0 = dfmin(r1:0,r3:2)
+; CHECK-NEXT:     jumpr r31
+; CHECK-NEXT:    }
+entry:
+  %0 = tail call double @llvm.minnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+define double @test_minnumYY(double nofpclass(zero) %f1, double nofpclass(zero) %f2) {
+; CHECK-LABEL: test_minnumYY:
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  // %bb.0: // %entry
+; CHECK-NEXT:    {
+; CHECK-NEXT:     jump fmin
+; CHECK-NEXT:    }
+entry:
+  %0 = tail call double @llvm.minnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+define double @test_minnumNS(double nofpclass(nan) %f1, double nofpclass(snan) %f2) {
+; CHECK-LABEL: test_minnumNS:
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  // %bb.0: // %entry
+; CHECK-NEXT:    {
+; CHECK-NEXT:     r1:0 = dfmin(r1:0,r3:2)
+; CHECK-NEXT:     jumpr r31
+; CHECK-NEXT:    }
+entry:
+  %0 = tail call double @llvm.minnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+define double @test_minnumNY(double nofpclass(nan) %f1, double nofpclass(zero) %f2) {
+; CHECK-LABEL: test_minnumNY:
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  // %bb.0: // %entry
+; CHECK-NEXT:    {
+; CHECK-NEXT:     jump fmin
+; CHECK-NEXT:    }
+entry:
+  %0 = tail call double @llvm.minnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+define double @test_minnumSN(double nofpclass(snan) %f1, double nofpclass(nan) %f2) {
+; CHECK-LABEL: test_minnumSN:
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  // %bb.0: // %entry
+; CHECK-NEXT:    {
+; CHECK-NEXT:     r1:0 = dfmin(r1:0,r3:2)
+; CHECK-NEXT:     jumpr r31
+; CHECK-NEXT:    }
+entry:
+  %0 = tail call double @llvm.minnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+define double @test_minnumSY(double nofpclass(snan) %f1, double nofpclass(zero) %f2) {
+; CHECK-LABEL: test_minnumSY:
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  // %bb.0: // %entry
+; CHECK-NEXT:    {
+; CHECK-NEXT:     jump fmin
+; CHECK-NEXT:    }
+entry:
+  %0 = tail call double @llvm.minnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+define double @test_minnumYN(double nofpclass(zero) %f1, double nofpclass(nan) %f2) {
+; CHECK-LABEL: test_minnumYN:
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  // %bb.0: // %entry
+; CHECK-NEXT:    {
+; CHECK-NEXT:     jump fmin
+; CHECK-NEXT:    }
+entry:
+  %0 = tail call double @llvm.minnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+define double @test_minnumYS(double nofpclass(zero) %f1, double nofpclass(snan) %f2) {
+; CHECK-LABEL: test_minnumYS:
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  // %bb.0: // %entry
+; CHECK-NEXT:    {
+; CHECK-NEXT:     jump fmin
+; CHECK-NEXT:    }
+entry:
+  %0 = tail call double @llvm.minnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
diff --git a/llvm/test/CodeGen/Mips/expandFMINNUM_FMAXNUM-r6.ll b/llvm/test/CodeGen/Mips/expandFMINNUM_FMAXNUM-r6.ll
new file mode 100644
index 0000000000000..2282c8f7f8e1d
--- /dev/null
+++ b/llvm/test/CodeGen/Mips/expandFMINNUM_FMAXNUM-r6.ll
@@ -0,0 +1,189 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=mipsisa32r6-linux-gnu < %s | FileCheck %s
+
+; test expandFMINNUM_FMAXNUM on backend with FMINNUM_IEEE/FMAXNUM_IEEE.
+; N -> not NaN
+; S -> not SNaN
+; Y -> may be NaN or SNaN
+
+define double @test_maxnumNN(double nofpclass(nan) %f1, double nofpclass(nan) %f2) {
+; CHECK-LABEL: test_maxnumNN:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    max.d $f0, $f12, $f14
+entry:
+  %0 = tail call double @llvm.maxnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+define double @test_maxnumSS(double nofpclass(snan) %f1, double nofpclass(snan) %f2) {
+; CHECK-LABEL: test_maxnumSS:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    max.d $f0, $f12, $f14
+entry:
+  %0 = tail call double @llvm.maxnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+define double @test_maxnumYY(double nofpclass(zero) %f1, double nofpclass(zero) %f2) {
+; CHECK-LABEL: test_maxnumYY:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    max.d $f0, $f12, $f14
+entry:
+  %0 = tail call double @llvm.maxnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+define double @test_maxnumNS(double nofpclass(nan) %f1, double nofpclass(snan) %f2) {
+; CHECK-LABEL: test_maxnumNS:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    max.d $f0, $f12, $f14
+entry:
+  %0 = tail call double @llvm.maxnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+define double @test_maxnumNY(double nofpclass(nan) %f1, double nofpclass(zero) %f2) {
+; CHECK-LABEL: test_maxnumNY:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    max.d $f0, $f12, $f14
+entry:
+  %0 = tail call double @llvm.maxnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+define double @test_maxnumSN(double nofpclass(snan) %f1, double nofpclass(nan) %f2) {
+; CHECK-LABEL: test_maxnumSN:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    max.d $f0, $f12, $f14
+entry:
+  %0 = tail call double @llvm.maxnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+define double @test_maxnumSY(double nofpclass(snan) %f1, double nofpclass(zero) %f2) {
+; CHECK-LABEL: test_maxnumSY:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    max.d $f0, $f12, $f14
+entry:
+  %0 = tail call double @llvm.maxnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+define double @test_maxnumYN(double nofpclass(zero) %f1, double nofpclass(nan) %f2) {
+; CHECK-LABEL: test_maxnumYN:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    max.d $f0, $f12, $f14
+entry:
+  %0 = tail call double @llvm.maxnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+define double @test_maxnumYS(double nofpclass(zero) %f1, double nofpclass(snan) %f2) {
+; CHECK-LABEL: test_maxnumYS:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    max.d $f0, $f12, $f14
+entry:
+  %0 = tail call double @llvm.maxnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+
+define double @test_minnumNN(double nofpclass(nan) %f1, double nofpclass(nan) %f2) {
+; CHECK-LABEL: test_minnumNN:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    min.d $f0, $f12, $f14
+entry:
+  %0 = tail call double @llvm.minnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+define double @test_minnumSS(double nofpclass(snan) %f1, double nofpclass(snan) %f2) {
+; CHECK-LABEL: test_minnumSS:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    min.d $f0, $f12, $f14
+entry:
+  %0 = tail call double @llvm.minnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+define double @test_minnumYY(double nofpclass(zero) %f1, double nofpclass(zero) %f2) {
+; CHECK-LABEL: test_minnumYY:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    min.d $f0, $f12, $f14
+entry:
+  %0 = tail call double @llvm.minnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+define double @test_minnumNS(double nofpclass(nan) %f1, double nofpclass(snan) %f2) {
+; CHECK-LABEL: test_minnumNS:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    min.d $f0, $f12, $f14
+entry:
+  %0 = tail call double @llvm.minnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+define double @test_minnumNY(double nofpclass(nan) %f1, double nofpclass(zero) %f2) {
+; CHECK-LABEL: test_minnumNY:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    min.d $f0, $f12, $f14
+entry:
+  %0 = tail call double @llvm.minnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+define double @test_minnumSN(double nofpclass(snan) %f1, double nofpclass(nan) %f2) {
+; CHECK-LABEL: test_minnumSN:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    min.d $f0, $f12, $f14
+entry:
+  %0 = tail call double @llvm.minnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+define double @test_minnumSY(double nofpclass(snan) %f1, double nofpclass(zero) %f2) {
+; CHECK-LABEL: test_minnumSY:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    min.d $f0, $f12, $f14
+entry:
+  %0 = tail call double @llvm.minnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+define double @test_minnumYN(double nofpclass(zero) %f1, double nofpclass(nan) %f2) {
+; CHECK-LABEL: test_minnumYN:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    min.d $f0, $f12, $f14
+entry:
+  %0 = tail call double @llvm.minnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+define double @test_minnumYS(double nofpclass(zero) %f1, double nofpclass(snan) %f2) {
+; CHECK-LABEL: test_minnumYS:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    jr $ra
+; CHECK-NEXT:    min.d $f0, $f12, $f14
+entry:
+  %0 = tail call double @llvm.minnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
diff --git a/llvm/test/CodeGen/WebAssembly/expandFMINNUM_FMAXNUM.ll b/llvm/test/CodeGen/WebAssembly/expandFMINNUM_FMAXNUM.ll
new file mode 100644
index 0000000000000..eb2931361bcc9
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/expandFMINNUM_FMAXNUM.ll
@@ -0,0 +1,243 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=wasm32 -disable-wasm-fallthrough-return-opt -wasm-keep-registers < %s | FileCheck %s
+
+; test expandFMINNUM_FMAXNUM on backend with FMINIMUM/FMAXIMUM.
+; N -> not NaN
+; S -> not SNaN
+; Y -> may be NaN or SNaN
+
+define double @test_maxnumNN(double nofpclass(nan) %f1, double nofpclass(nan) %f2) {
+; CHECK-LABEL: test_maxnumNN:
+; CHECK:         .functype test_maxnumNN (f64, f64) -> (f64)
+; CHECK-NEXT:  # %bb.0: # %entry
+; CHECK-NEXT:    local.get $push2=, 0
+; CHECK-NEXT:    local.get $push1=, 1
+; CHECK-NEXT:    f64.max $push0=, $pop2, $pop1
+; CHECK-NEXT:    return $pop0
+entry:
+  %0 = tail call double @llvm.maxnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+define double @test_maxnumSS(double nofpclass(snan) %f1, double nofpclass(snan) %f2) {
+; CHECK-LABEL: test_maxnumSS:
+; CHECK:         .functype test_maxnumSS (f64, f64) -> (f64)
+; CHECK-NEXT:  # %bb.0: # %entry
+; CHECK-NEXT:    local.get $push2=, 0
+; CHECK-NEXT:    local.get $push1=, 1
+; CHECK-NEXT:    call $push0=, fmax, $pop2, $pop1
+; CHECK-NEXT:    return $pop0
+entry:
+  %0 = tail call double @llvm.maxnum.f64(double %f1, double %f2)
+  ret double %0
+}
+
+define double @test_maxnumYY(double nofpclass(zero) %f1, double nofpclass(zero) %f2) {
+; CHECK-LABEL: test_maxnumYY:
+; CHECK:         .functype test_maxnumYY (f64, f64) -> (f64)
+; CHECK-NEXT:  # %bb.0: # %entry
+; CHECK-NEXT:    local.get $push2=, 0
+; CHECK-NEXT:    local.get $push1=, 1
+; CHECK-NEXT:    call $push0=, fmax, $pop2, $pop1
+; CH...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/181083


More information about the llvm-commits mailing list