[llvm] expandFMINNUM_FMAXNUM: Improve for backend with FMINIMUMNUM and FMINN… (PR #181083)

YunQiang Su via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 11 19:50:29 PST 2026


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

…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.

>From 1a7962cb3c8b2e406cb9c71d9ebc5fc9436d8ce3 Mon Sep 17 00:00:00 2001
From: YunQiang Su <yunqiang at isrc.iscas.ac.cn>
Date: Thu, 12 Feb 2026 11:46:47 +0800
Subject: [PATCH] expandFMINNUM_FMAXNUM: Improve for backend with FMINIMUMNUM
 and FMINNUM_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.
---
 llvm/include/llvm/CodeGen/ISDOpcodes.h        |   4 +-
 .../CodeGen/SelectionDAG/TargetLowering.cpp   |  61 ++---
 llvm/lib/Target/Mips/MipsISelLowering.cpp     |   4 -
 .../Hexagon/expandFMINNUM_FMAXNUM-v67.ll      | 233 +++++++++++++++++
 .../CodeGen/Mips/expandFMINNUM_FMAXNUM-r6.ll  | 189 ++++++++++++++
 .../WebAssembly/expandFMINNUM_FMAXNUM.ll      | 243 ++++++++++++++++++
 6 files changed, 694 insertions(+), 40 deletions(-)
 create mode 100644 llvm/test/CodeGen/Hexagon/expandFMINNUM_FMAXNUM-v67.ll
 create mode 100644 llvm/test/CodeGen/Mips/expandFMINNUM_FMAXNUM-r6.ll
 create mode 100644 llvm/test/CodeGen/WebAssembly/expandFMINNUM_FMAXNUM.ll

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
+; CHECK-NEXT:    return $pop0
+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:         .functype test_maxnumNS (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_maxnumNY(double nofpclass(nan) %f1, double nofpclass(zero) %f2) {
+; CHECK-LABEL: test_maxnumNY:
+; CHECK:         .functype test_maxnumNY (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_maxnumSN(double nofpclass(snan) %f1, double nofpclass(nan) %f2) {
+; CHECK-LABEL: test_maxnumSN:
+; CHECK:         .functype test_maxnumSN (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_maxnumSY(double nofpclass(snan) %f1, double nofpclass(zero) %f2) {
+; CHECK-LABEL: test_maxnumSY:
+; CHECK:         .functype test_maxnumSY (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_maxnumYN(double nofpclass(zero) %f1, double nofpclass(nan) %f2) {
+; CHECK-LABEL: test_maxnumYN:
+; CHECK:         .functype test_maxnumYN (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_maxnumYS(double nofpclass(zero) %f1, double nofpclass(snan) %f2) {
+; CHECK-LABEL: test_maxnumYS:
+; CHECK:         .functype test_maxnumYS (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_minnumNN(double nofpclass(nan) %f1, double nofpclass(nan) %f2) {
+; CHECK-LABEL: test_minnumNN:
+; CHECK:         .functype test_minnumNN (f64, f64) -> (f64)
+; CHECK-NEXT:  # %bb.0: # %entry
+; CHECK-NEXT:    local.get $push2=, 0
+; CHECK-NEXT:    local.get $push1=, 1
+; CHECK-NEXT:    f64.min $push0=, $pop2, $pop1
+; CHECK-NEXT:    return $pop0
+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:         .functype test_minnumSS (f64, f64) -> (f64)
+; CHECK-NEXT:  # %bb.0: # %entry
+; CHECK-NEXT:    local.get $push2=, 0
+; CHECK-NEXT:    local.get $push1=, 1
+; CHECK-NEXT:    call $push0=, fmin, $pop2, $pop1
+; CHECK-NEXT:    return $pop0
+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:         .functype test_minnumYY (f64, f64) -> (f64)
+; CHECK-NEXT:  # %bb.0: # %entry
+; CHECK-NEXT:    local.get $push2=, 0
+; CHECK-NEXT:    local.get $push1=, 1
+; CHECK-NEXT:    call $push0=, fmin, $pop2, $pop1
+; CHECK-NEXT:    return $pop0
+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:         .functype test_minnumNS (f64, f64) -> (f64)
+; CHECK-NEXT:  # %bb.0: # %entry
+; CHECK-NEXT:    local.get $push2=, 0
+; CHECK-NEXT:    local.get $push1=, 1
+; CHECK-NEXT:    call $push0=, fmin, $pop2, $pop1
+; CHECK-NEXT:    return $pop0
+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:         .functype test_minnumNY (f64, f64) -> (f64)
+; CHECK-NEXT:  # %bb.0: # %entry
+; CHECK-NEXT:    local.get $push2=, 0
+; CHECK-NEXT:    local.get $push1=, 1
+; CHECK-NEXT:    call $push0=, fmin, $pop2, $pop1
+; CHECK-NEXT:    return $pop0
+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:         .functype test_minnumSN (f64, f64) -> (f64)
+; CHECK-NEXT:  # %bb.0: # %entry
+; CHECK-NEXT:    local.get $push2=, 0
+; CHECK-NEXT:    local.get $push1=, 1
+; CHECK-NEXT:    call $push0=, fmin, $pop2, $pop1
+; CHECK-NEXT:    return $pop0
+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:         .functype test_minnumSY (f64, f64) -> (f64)
+; CHECK-NEXT:  # %bb.0: # %entry
+; CHECK-NEXT:    local.get $push2=, 0
+; CHECK-NEXT:    local.get $push1=, 1
+; CHECK-NEXT:    call $push0=, fmin, $pop2, $pop1
+; CHECK-NEXT:    return $pop0
+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:         .functype test_minnumYN (f64, f64) -> (f64)
+; CHECK-NEXT:  # %bb.0: # %entry
+; CHECK-NEXT:    local.get $push2=, 0
+; CHECK-NEXT:    local.get $push1=, 1
+; CHECK-NEXT:    call $push0=, fmin, $pop2, $pop1
+; CHECK-NEXT:    return $pop0
+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:         .functype test_minnumYS (f64, f64) -> (f64)
+; CHECK-NEXT:  # %bb.0: # %entry
+; CHECK-NEXT:    local.get $push2=, 0
+; CHECK-NEXT:    local.get $push1=, 1
+; CHECK-NEXT:    call $push0=, fmin, $pop2, $pop1
+; CHECK-NEXT:    return $pop0
+entry:
+  %0 = tail call double @llvm.minnum.f64(double %f1, double %f2)
+  ret double %0
+}
+



More information about the llvm-commits mailing list