expandFMINNUM_FMAXNUM: Improve for backends with FMINIMUMNUM and FMINNUM_IEEE#181083
expandFMINNUM_FMAXNUM: Improve for backends with FMINIMUMNUM and FMINNUM_IEEE#181083
Conversation
…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.
|
@llvm/pr-subscribers-backend-amdgpu @llvm/pr-subscribers-backend-mips Author: YunQiang Su (wzssyqa) Changes…UM_IEEE
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:
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]
|
|
@llvm/pr-subscribers-backend-hexagon Author: YunQiang Su (wzssyqa) Changes…UM_IEEE
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:
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]
|
valadaptive
left a comment
There was a problem hiding this comment.
I think there's more leeway for FMINNUM and FMAXNUM now.
I'm OK with leaving that for a follow-up PR as long as it's commented here that the "never sNaN" precondition for the FMINIMUMNUM/FMAXIMUMNUM lowering is overly conservative considering the newer FMINNUM/FMAXNUM semantics.
That one comment above the FMINIMUMNUM/FMAXIMUMNUM lowering needs to be updated either way.
STRICT_FMAXNUM requires FMAXNUM to be Legal. For test, AMDGPU is good enough.
I fully agree. I think that we can do something like we had done for fminimum and fminimumnum:
to reduce the libc calls and fully compatible with C23. |
🐧 Linux x64 Test Results
Failed Tests(click on a test name to see its output) ClangClang.CodeGenOpenCL/amdgpu-ieee.clLLVMLLVM.CodeGen/AMDGPU/a-v-flat-atomicrmw.llLLVM.CodeGen/AMDGPU/a-v-global-atomicrmw.llLLVM.CodeGen/AMDGPU/amdgcn-ieee.llLLVM.CodeGen/AMDGPU/atomics-system-scope.llLLVM.CodeGen/AMDGPU/fcanonicalize-elimination.llLLVM.CodeGen/AMDGPU/fmax3.f64.llLLVM.CodeGen/AMDGPU/fmaxnum.llLLVM.CodeGen/AMDGPU/fminnum.f64.llLLVM.CodeGen/AMDGPU/fminnum.llIf these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the |
🪟 Windows x64 Test Results
Failed Tests(click on a test name to see its output) ClangClang.CodeGenOpenCL/amdgpu-ieee.clLLVMLLVM.CodeGen/AMDGPU/a-v-flat-atomicrmw.llLLVM.CodeGen/AMDGPU/a-v-global-atomicrmw.llLLVM.CodeGen/AMDGPU/amdgcn-ieee.llLLVM.CodeGen/AMDGPU/atomics-system-scope.llLLVM.CodeGen/AMDGPU/fcanonicalize-elimination.llLLVM.CodeGen/AMDGPU/fmax3.f64.llLLVM.CodeGen/AMDGPU/fmaxnum.llLLVM.CodeGen/AMDGPU/fminnum.f64.llLLVM.CodeGen/AMDGPU/fminnum.llIf these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the |
Uh oh!
There was an error while loading. Please reload this page.