Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions llvm/include/llvm/CodeGen/ISDOpcodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,

Expand Down
61 changes: 27 additions & 34 deletions llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Comment thread
wzssyqa marked this conversation as resolved.
Outdated
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))) {
Comment thread
wzssyqa marked this conversation as resolved.
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;

Expand Down
4 changes: 0 additions & 4 deletions llvm/lib/Target/Mips/MipsISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
233 changes: 233 additions & 0 deletions llvm/test/CodeGen/Hexagon/expandFMINNUM_FMAXNUM-v67.ll
Original file line number Diff line number Diff line change
@@ -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
}

Loading
Loading