[llvm] SelectionDAG: Support nofpclass (PR #108350)
YunQiang Su via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 13 01:03:38 PDT 2024
https://github.com/wzssyqa updated https://github.com/llvm/llvm-project/pull/108350
>From 314ccabb7284a7bb0f48377783dd85b3c854d44f Mon Sep 17 00:00:00 2001
From: YunQiang Su <syq at debian.org>
Date: Thu, 12 Sep 2024 17:00:13 +0800
Subject: [PATCH] SelectionDAG: Support nofpclass
Currently SelectionDAG ignroes the nofpclass information from arguments.
Such as
define dso_local float @f(float noundef nofpclass(nan zero) %a, float noundef nofpclass(nan zero) %b) #0 {
entry:
%cond = tail call float @llvm.maximumnum.f32(float %a, float %b)
ret float %cond
}
In SelectionDAG::isKnownNeverNaN, a false is returned.
TODO:
1) bool SelectionDAG::isKnownNeverNaN(SDValue Op, bool SNaN, unsigned Depth)
needs to process hasNoSNaN;
2) bool SelectionDAG::isKnownNeverZeroFloat(SDValue Op)
needs to process Zero and SignedZero.
These 2 problems will be fixed with other PRs.
---
llvm/include/llvm/CodeGen/SelectionDAG.h | 8 +
llvm/include/llvm/CodeGen/SelectionDAGNodes.h | 33 +-
.../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 35 +-
.../SelectionDAG/SelectionDAGBuilder.cpp | 16 +
.../CodeGen/SelectionDAG/TargetLowering.cpp | 36 +-
.../LoongArch/fp-maximumnum-minimumnum.ll | 403 ++++++
.../CodeGen/Mips/fp-maximumnum-minimumnum.ll | 678 +++++++++
.../CodeGen/X86/fminimumnum-fmaximumnum.ll | 1210 +++++++++++++++++
8 files changed, 2410 insertions(+), 9 deletions(-)
create mode 100644 llvm/test/CodeGen/X86/fminimumnum-fmaximumnum.ll
diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h
index 7ee8ca18c2c1de..0c49b4d4ee1229 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAG.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAG.h
@@ -2136,6 +2136,14 @@ class SelectionDAG {
/// positive or negative zero.
bool isKnownNeverZeroFloat(SDValue Op) const;
+ /// Test whether the given floating point SDValue is known to never be
+ /// positive zero.
+ bool isKnownNeverPosZeroFloat(SDValue Op) const;
+
+ /// Test whether the given floating point SDValue is known to never be
+ /// negative zero.
+ bool isKnownNeverNegZeroFloat(SDValue Op) const;
+
/// Test whether the given SDValue is known to contain non-zero value(s).
bool isKnownNeverZero(SDValue Op, unsigned Depth = 0) const;
diff --git a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
index 6067b3b29ea181..737927aba67edf 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -383,6 +383,7 @@ struct SDNodeFlags {
bool Exact : 1;
bool Disjoint : 1;
bool NonNeg : 1;
+ // deprecated: Use NoQNanS && NoSNaNs
bool NoNaNs : 1;
bool NoInfs : 1;
bool NoSignedZeros : 1;
@@ -400,6 +401,11 @@ struct SDNodeFlags {
// Instructions with attached 'unpredictable' metadata on IR level.
bool Unpredictable : 1;
+ bool NoQNaNs : 1;
+ bool NoSNaNs : 1;
+ bool NoPosZeros : 1;
+ bool NoNegZeros : 1;
+
public:
/// Default constructor turns off all optimization flags.
SDNodeFlags()
@@ -407,12 +413,15 @@ struct SDNodeFlags {
Disjoint(false), NonNeg(false), NoNaNs(false), NoInfs(false),
NoSignedZeros(false), AllowReciprocal(false), AllowContract(false),
ApproximateFuncs(false), AllowReassociation(false), NoFPExcept(false),
- Unpredictable(false) {}
+ Unpredictable(false), NoQNaNs(false), NoSNaNs(false), NoPosZeros(false),
+ NoNegZeros(false) {}
/// Propagate the fast-math-flags from an IR FPMathOperator.
void copyFMF(const FPMathOperator &FPMO) {
- setNoNaNs(FPMO.hasNoNaNs());
+ setNoSNaNs(FPMO.hasNoNaNs());
+ setNoQNaNs(FPMO.hasNoNaNs());
setNoInfs(FPMO.hasNoInfs());
+ setNoNegZeros(FPMO.hasNoSignedZeros());
setNoSignedZeros(FPMO.hasNoSignedZeros());
setAllowReciprocal(FPMO.hasAllowReciprocal());
setAllowContract(FPMO.hasAllowContract());
@@ -426,8 +435,20 @@ struct SDNodeFlags {
void setExact(bool b) { Exact = b; }
void setDisjoint(bool b) { Disjoint = b; }
void setNonNeg(bool b) { NonNeg = b; }
- void setNoNaNs(bool b) { NoNaNs = b; }
+ [[deprecated("Use SetSNaNs() and SetQNaNs()")]] void setNoNaNs(bool b) {
+ NoNaNs = NoQNaNs = NoSNaNs = b;
+ }
+ void setNoQNaNs(bool b) {
+ NoQNaNs = b;
+ NoNaNs = (NoQNaNs && NoSNaNs);
+ }
+ void setNoSNaNs(bool b) {
+ NoSNaNs = b;
+ NoNaNs = (NoQNaNs && NoSNaNs);
+ }
void setNoInfs(bool b) { NoInfs = b; }
+ void setNoPosZeros(bool b) { NoPosZeros = b; }
+ void setNoNegZeros(bool b) { NoNegZeros = b; }
void setNoSignedZeros(bool b) { NoSignedZeros = b; }
void setAllowReciprocal(bool b) { AllowReciprocal = b; }
void setAllowContract(bool b) { AllowContract = b; }
@@ -442,8 +463,12 @@ struct SDNodeFlags {
bool hasExact() const { return Exact; }
bool hasDisjoint() const { return Disjoint; }
bool hasNonNeg() const { return NonNeg; }
- bool hasNoNaNs() const { return NoNaNs; }
+ bool hasNoNaNs() const { return (NoSNaNs && NoQNaNs); }
+ bool hasNoSNaNs() const { return NoSNaNs; }
+ bool hasNoQNaNs() const { return NoQNaNs; }
bool hasNoInfs() const { return NoInfs; }
+ bool hasNoPosZeros() const { return NoPosZeros; }
+ bool hasNoNegZeros() const { return NoNegZeros; }
bool hasNoSignedZeros() const { return NoSignedZeros; }
bool hasAllowReciprocal() const { return AllowReciprocal; }
bool hasAllowContract() const { return AllowContract; }
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 29505f444b7650..34f719f6678b62 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -5435,7 +5435,12 @@ bool SelectionDAG::isBaseWithConstantOffset(SDValue Op) const {
bool SelectionDAG::isKnownNeverNaN(SDValue Op, bool SNaN, unsigned Depth) const {
// If we're told that NaNs won't happen, assume they won't.
- if (getTarget().Options.NoNaNsFPMath || Op->getFlags().hasNoNaNs())
+ if (getTarget().Options.NoNaNsFPMath)
+ return true;
+ SDNodeFlags OpFlags = Op->getFlags();
+ if (SNaN && OpFlags.hasNoSNaNs())
+ return true;
+ if (OpFlags.hasNoSNaNs() && OpFlags.hasNoQNaNs())
return true;
if (Depth >= MaxRecursionDepth)
@@ -5569,11 +5574,39 @@ bool SelectionDAG::isKnownNeverZeroFloat(SDValue Op) const {
assert(Op.getValueType().isFloatingPoint() &&
"Floating point type expected");
+ SDNodeFlags OpFlags = Op->getFlags();
+ if (OpFlags.hasNoPosZeros() && OpFlags.hasNoNegZeros())
+ return true;
+
// If the value is a constant, we can obviously see if it is a zero or not.
return ISD::matchUnaryFpPredicate(
Op, [](ConstantFPSDNode *C) { return !C->isZero(); });
}
+bool SelectionDAG::isKnownNeverPosZeroFloat(SDValue Op) const {
+ assert(Op.getValueType().isFloatingPoint() && "Floating point type expected");
+
+ SDNodeFlags OpFlags = Op->getFlags();
+ if (OpFlags.hasNoPosZeros())
+ return true;
+
+ // If the value is a constant, we can obviously see if it is a zero or not.
+ return ISD::matchUnaryFpPredicate(
+ Op, [](ConstantFPSDNode *C) { return !C->isZero() || C->isNegative(); });
+}
+
+bool SelectionDAG::isKnownNeverNegZeroFloat(SDValue Op) const {
+ assert(Op.getValueType().isFloatingPoint() && "Floating point type expected");
+
+ SDNodeFlags OpFlags = Op->getFlags();
+ if (OpFlags.hasNoNegZeros())
+ return true;
+
+ // If the value is a constant, we can obviously see if it is a zero or not.
+ return ISD::matchUnaryFpPredicate(
+ Op, [](ConstantFPSDNode *C) { return !C->isZero() || !C->isNegative(); });
+}
+
bool SelectionDAG::isKnownNeverZero(SDValue Op, unsigned Depth) const {
if (Depth >= MaxRecursionDepth)
return false; // Limit search depth.
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 1dbcf8fd765101..dfefb29a931b99 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -11773,6 +11773,22 @@ void SelectionDAGISel::LowerArguments(const Function &F) {
AssertOp = ISD::AssertSext;
else if (Arg.hasAttribute(Attribute::ZExt))
AssertOp = ISD::AssertZext;
+ if (Arg.hasAttribute(Attribute::NoFPClass)) {
+ SDNodeFlags InValFlags = InVals[i]->getFlags();
+ bool NoSNaN = ((Arg.getNoFPClass() & llvm::fcSNan) == llvm::fcSNan);
+ bool NoQNaN = ((Arg.getNoFPClass() & llvm::fcQNan) == llvm::fcQNan);
+ InValFlags.setNoSNaNs(NoSNaN);
+ InValFlags.setNoQNaNs(NoQNaN);
+ bool NoPosZeros =
+ ((Arg.getNoFPClass() & llvm::fcPosZero) == llvm::fcPosZero);
+ bool NoNegZeros =
+ ((Arg.getNoFPClass() & llvm::fcNegZero) == llvm::fcNegZero);
+ InValFlags.setNoPosZeros(NoPosZeros);
+ InValFlags.setNoNegZeros(NoNegZeros);
+ InValFlags.setNoInfs((Arg.getNoFPClass() & llvm::fcInf) ==
+ llvm::fcInf);
+ InVals[i]->setFlags(InValFlags);
+ }
ArgValues.push_back(getCopyFromParts(DAG, dl, &InVals[i], NumParts,
PartVT, VT, nullptr, NewRoot,
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 03010c1df00145..747696bd5243d3 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -8563,6 +8563,8 @@ SDValue TargetLowering::expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *Node,
bool IsMax = Opc == ISD::FMAXIMUMNUM;
const TargetOptions &Options = DAG.getTarget().Options;
SDNodeFlags Flags = Node->getFlags();
+ SDNodeFlags LHSFlagsOrig = LHS->getFlags();
+ SDNodeFlags RHSFlagsOrig = RHS->getFlags();
unsigned NewOp =
Opc == ISD::FMINIMUMNUM ? ISD::FMINNUM_IEEE : ISD::FMAXNUM_IEEE;
@@ -8597,7 +8599,11 @@ SDValue TargetLowering::expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *Node,
if ((Flags.hasNoNaNs() ||
(DAG.isKnownNeverSNaN(LHS) && DAG.isKnownNeverSNaN(RHS))) &&
(Flags.hasNoSignedZeros() || DAG.isKnownNeverZeroFloat(LHS) ||
- DAG.isKnownNeverZeroFloat(RHS))) {
+ DAG.isKnownNeverZeroFloat(RHS) ||
+ (DAG.isKnownNeverPosZeroFloat(LHS) &&
+ DAG.isKnownNeverPosZeroFloat(RHS)) ||
+ (DAG.isKnownNeverNegZeroFloat(LHS) &&
+ DAG.isKnownNeverNegZeroFloat(RHS)))) {
unsigned IEEE2008Op = Opc == ISD::FMINIMUMNUM ? ISD::FMINNUM : ISD::FMAXNUM;
if (isOperationLegalOrCustom(IEEE2008Op, VT))
return DAG.getNode(IEEE2008Op, DL, VT, LHS, RHS, Flags);
@@ -8606,22 +8612,44 @@ SDValue TargetLowering::expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *Node,
// If only one operand is NaN, override it with another operand.
if (!Flags.hasNoNaNs() && !DAG.isKnownNeverNaN(LHS)) {
LHS = DAG.getSelectCC(DL, LHS, LHS, RHS, LHS, ISD::SETUO);
+ SDNodeFlags LHSFlags = LHS->getFlags();
+ SDNodeFlags RHSFlags = RHS->getFlags();
+ if (RHSFlags.hasNoSNaNs())
+ LHSFlags.setNoSNaNs(true);
+ if (RHSFlags.hasNoQNaNs())
+ LHSFlags.setNoQNaNs(true);
+ LHSFlags.setNoPosZeros(LHSFlagsOrig.hasNoPosZeros());
+ LHSFlags.setNoNegZeros(LHSFlagsOrig.hasNoNegZeros());
+ LHS->setFlags(LHSFlags);
}
if (!Flags.hasNoNaNs() && !DAG.isKnownNeverNaN(RHS)) {
RHS = DAG.getSelectCC(DL, RHS, RHS, LHS, RHS, ISD::SETUO);
+ SDNodeFlags LHSFlags = LHS->getFlags();
+ SDNodeFlags RHSFlags = RHS->getFlags();
+ if (LHSFlags.hasNoSNaNs())
+ RHSFlags.setNoSNaNs(true);
+ if (LHSFlags.hasNoQNaNs())
+ RHSFlags.setNoQNaNs(true);
+ RHSFlags.setNoPosZeros(RHSFlagsOrig.hasNoPosZeros());
+ RHSFlags.setNoNegZeros(RHSFlagsOrig.hasNoNegZeros());
+ RHS->setFlags(RHSFlags);
}
SDValue MinMax =
DAG.getSelectCC(DL, LHS, RHS, LHS, RHS, IsMax ? ISD::SETGT : ISD::SETLT);
// If MinMax is NaN, let's quiet it.
- if (!Flags.hasNoNaNs() && !DAG.isKnownNeverNaN(LHS) &&
- !DAG.isKnownNeverNaN(RHS)) {
+ if (!Flags.hasNoNaNs() && !DAG.isKnownNeverSNaN(LHS) &&
+ !DAG.isKnownNeverSNaN(RHS)) {
MinMax = DAG.getNode(ISD::FCANONICALIZE, DL, VT, MinMax, Flags);
}
// Fixup signed zero behavior.
if (Options.NoSignedZerosFPMath || Flags.hasNoSignedZeros() ||
- DAG.isKnownNeverZeroFloat(LHS) || DAG.isKnownNeverZeroFloat(RHS)) {
+ DAG.isKnownNeverZeroFloat(LHS) || DAG.isKnownNeverZeroFloat(RHS) ||
+ (DAG.isKnownNeverPosZeroFloat(LHS) &&
+ DAG.isKnownNeverPosZeroFloat(RHS)) ||
+ (DAG.isKnownNeverNegZeroFloat(LHS) &&
+ DAG.isKnownNeverNegZeroFloat(RHS))) {
return MinMax;
}
SDValue TestZero =
diff --git a/llvm/test/CodeGen/LoongArch/fp-maximumnum-minimumnum.ll b/llvm/test/CodeGen/LoongArch/fp-maximumnum-minimumnum.ll
index b4fdd954b856c8..05b55bda6fafc4 100644
--- a/llvm/test/CodeGen/LoongArch/fp-maximumnum-minimumnum.ll
+++ b/llvm/test/CodeGen/LoongArch/fp-maximumnum-minimumnum.ll
@@ -100,6 +100,109 @@ define float @maximumnum_float_nnan(float %x, float %y) {
ret float %z
}
+define float @maximumnum_float_nnan_arg(float nofpclass(nan) %x, float nofpclass(nan) %y) {
+;
+; LA32F-LABEL: maximumnum_float_nnan_arg:
+; LA32F: # %bb.0:
+; LA32F-NEXT: fmax.s $fa0, $fa0, $fa1
+; LA32F-NEXT: ret
+;
+; LA32D-LABEL: maximumnum_float_nnan_arg:
+; LA32D: # %bb.0:
+; LA32D-NEXT: fmax.s $fa0, $fa0, $fa1
+; LA32D-NEXT: ret
+;
+; LA64F-LABEL: maximumnum_float_nnan_arg:
+; LA64F: # %bb.0:
+; LA64F-NEXT: fmax.s $fa0, $fa0, $fa1
+; LA64F-NEXT: ret
+;
+; LA64D-LABEL: maximumnum_float_nnan_arg:
+; LA64D: # %bb.0:
+; LA64D-NEXT: fmax.s $fa0, $fa0, $fa1
+; LA64D-NEXT: ret
+ %z = call float @llvm.maximumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+define float @maximumnum_float_n2nan_arg(float nofpclass(qnan snan) %x, float nofpclass(qnan snan) %y) {
+;
+; LA32F-LABEL: maximumnum_float_n2nan_arg:
+; LA32F: # %bb.0:
+; LA32F-NEXT: fmax.s $fa0, $fa0, $fa1
+; LA32F-NEXT: ret
+;
+; LA32D-LABEL: maximumnum_float_n2nan_arg:
+; LA32D: # %bb.0:
+; LA32D-NEXT: fmax.s $fa0, $fa0, $fa1
+; LA32D-NEXT: ret
+;
+; LA64F-LABEL: maximumnum_float_n2nan_arg:
+; LA64F: # %bb.0:
+; LA64F-NEXT: fmax.s $fa0, $fa0, $fa1
+; LA64F-NEXT: ret
+;
+; LA64D-LABEL: maximumnum_float_n2nan_arg:
+; LA64D: # %bb.0:
+; LA64D-NEXT: fmax.s $fa0, $fa0, $fa1
+; LA64D-NEXT: ret
+ %z = call float @llvm.maximumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+define float @maximumnum_float_nsnan_arg(float nofpclass(snan) %x, float nofpclass(snan) %y) {
+;
+; LA32F-LABEL: maximumnum_float_nsnan_arg:
+; LA32F: # %bb.0:
+; LA32F-NEXT: fmax.s $fa0, $fa0, $fa1
+; LA32F-NEXT: ret
+;
+; LA32D-LABEL: maximumnum_float_nsnan_arg:
+; LA32D: # %bb.0:
+; LA32D-NEXT: fmax.s $fa0, $fa0, $fa1
+; LA32D-NEXT: ret
+;
+; LA64F-LABEL: maximumnum_float_nsnan_arg:
+; LA64F: # %bb.0:
+; LA64F-NEXT: fmax.s $fa0, $fa0, $fa1
+; LA64F-NEXT: ret
+;
+; LA64D-LABEL: maximumnum_float_nsnan_arg:
+; LA64D: # %bb.0:
+; LA64D-NEXT: fmax.s $fa0, $fa0, $fa1
+; LA64D-NEXT: ret
+ %z = call float @llvm.maximumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+define float @maximumnum_float_n1snan_arg(float nofpclass(snan) %x, float %y) {
+;
+; LA32F-LABEL: maximumnum_float_n1snan_arg:
+; LA32F: # %bb.0:
+; LA32F-NEXT: fmax.s $fa1, $fa1, $fa1
+; LA32F-NEXT: fmax.s $fa0, $fa0, $fa1
+; LA32F-NEXT: ret
+;
+; LA32D-LABEL: maximumnum_float_n1snan_arg:
+; LA32D: # %bb.0:
+; LA32D-NEXT: fmax.s $fa1, $fa1, $fa1
+; LA32D-NEXT: fmax.s $fa0, $fa0, $fa1
+; LA32D-NEXT: ret
+;
+; LA64F-LABEL: maximumnum_float_n1snan_arg:
+; LA64F: # %bb.0:
+; LA64F-NEXT: fmax.s $fa1, $fa1, $fa1
+; LA64F-NEXT: fmax.s $fa0, $fa0, $fa1
+; LA64F-NEXT: ret
+;
+; LA64D-LABEL: maximumnum_float_n1snan_arg:
+; LA64D: # %bb.0:
+; LA64D-NEXT: fmax.s $fa1, $fa1, $fa1
+; LA64D-NEXT: fmax.s $fa0, $fa0, $fa1
+; LA64D-NEXT: ret
+ %z = call float @llvm.maximumnum.f32(float %x, float %y)
+ ret float %z
+}
define double @maximumnum_double(double %x, double %y) {
;
@@ -220,6 +323,156 @@ define double @maximumnum_double_nnan(double %x, double %y) {
ret double %z
}
+define double @maximumnum_double_nnan_arg(double nofpclass(nan) %x, double nofpclass(nan) %y) {
+;
+; LA32F-LABEL: maximumnum_double_nnan_arg:
+; LA32F: # %bb.0:
+; LA32F-NEXT: addi.w $sp, $sp, -16
+; LA32F-NEXT: .cfi_def_cfa_offset 16
+; LA32F-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill
+; LA32F-NEXT: .cfi_offset 1, -4
+; LA32F-NEXT: bl %plt(fmaximum_num)
+; LA32F-NEXT: ld.w $ra, $sp, 12 # 4-byte Folded Reload
+; LA32F-NEXT: addi.w $sp, $sp, 16
+; LA32F-NEXT: ret
+;
+; LA32D-LABEL: maximumnum_double_nnan_arg:
+; LA32D: # %bb.0:
+; LA32D-NEXT: fmax.d $fa0, $fa0, $fa1
+; LA32D-NEXT: ret
+;
+; LA64F-LABEL: maximumnum_double_nnan_arg:
+; LA64F: # %bb.0:
+; LA64F-NEXT: addi.d $sp, $sp, -16
+; LA64F-NEXT: .cfi_def_cfa_offset 16
+; LA64F-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
+; LA64F-NEXT: .cfi_offset 1, -8
+; LA64F-NEXT: bl %plt(fmaximum_num)
+; LA64F-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
+; LA64F-NEXT: addi.d $sp, $sp, 16
+; LA64F-NEXT: ret
+;
+; LA64D-LABEL: maximumnum_double_nnan_arg:
+; LA64D: # %bb.0:
+; LA64D-NEXT: fmax.d $fa0, $fa0, $fa1
+; LA64D-NEXT: ret
+ %z = call double @llvm.maximumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define double @maximumnum_double_n2nan_arg(double nofpclass(qnan snan) %x, double nofpclass(qnan snan) %y) {
+;
+; LA32F-LABEL: maximumnum_double_n2nan_arg:
+; LA32F: # %bb.0:
+; LA32F-NEXT: addi.w $sp, $sp, -16
+; LA32F-NEXT: .cfi_def_cfa_offset 16
+; LA32F-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill
+; LA32F-NEXT: .cfi_offset 1, -4
+; LA32F-NEXT: bl %plt(fmaximum_num)
+; LA32F-NEXT: ld.w $ra, $sp, 12 # 4-byte Folded Reload
+; LA32F-NEXT: addi.w $sp, $sp, 16
+; LA32F-NEXT: ret
+;
+; LA32D-LABEL: maximumnum_double_n2nan_arg:
+; LA32D: # %bb.0:
+; LA32D-NEXT: fmax.d $fa0, $fa0, $fa1
+; LA32D-NEXT: ret
+;
+; LA64F-LABEL: maximumnum_double_n2nan_arg:
+; LA64F: # %bb.0:
+; LA64F-NEXT: addi.d $sp, $sp, -16
+; LA64F-NEXT: .cfi_def_cfa_offset 16
+; LA64F-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
+; LA64F-NEXT: .cfi_offset 1, -8
+; LA64F-NEXT: bl %plt(fmaximum_num)
+; LA64F-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
+; LA64F-NEXT: addi.d $sp, $sp, 16
+; LA64F-NEXT: ret
+;
+; LA64D-LABEL: maximumnum_double_n2nan_arg:
+; LA64D: # %bb.0:
+; LA64D-NEXT: fmax.d $fa0, $fa0, $fa1
+; LA64D-NEXT: ret
+ %z = call double @llvm.maximumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define double @maximumnum_double_nsnan_arg(double nofpclass(snan) %x, double nofpclass(snan) %y) {
+;
+; LA32F-LABEL: maximumnum_double_nsnan_arg:
+; LA32F: # %bb.0:
+; LA32F-NEXT: addi.w $sp, $sp, -16
+; LA32F-NEXT: .cfi_def_cfa_offset 16
+; LA32F-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill
+; LA32F-NEXT: .cfi_offset 1, -4
+; LA32F-NEXT: bl %plt(fmaximum_num)
+; LA32F-NEXT: ld.w $ra, $sp, 12 # 4-byte Folded Reload
+; LA32F-NEXT: addi.w $sp, $sp, 16
+; LA32F-NEXT: ret
+;
+; LA32D-LABEL: maximumnum_double_nsnan_arg:
+; LA32D: # %bb.0:
+; LA32D-NEXT: fmax.d $fa0, $fa0, $fa1
+; LA32D-NEXT: ret
+;
+; LA64F-LABEL: maximumnum_double_nsnan_arg:
+; LA64F: # %bb.0:
+; LA64F-NEXT: addi.d $sp, $sp, -16
+; LA64F-NEXT: .cfi_def_cfa_offset 16
+; LA64F-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
+; LA64F-NEXT: .cfi_offset 1, -8
+; LA64F-NEXT: bl %plt(fmaximum_num)
+; LA64F-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
+; LA64F-NEXT: addi.d $sp, $sp, 16
+; LA64F-NEXT: ret
+;
+; LA64D-LABEL: maximumnum_double_nsnan_arg:
+; LA64D: # %bb.0:
+; LA64D-NEXT: fmax.d $fa0, $fa0, $fa1
+; LA64D-NEXT: ret
+ %z = call double @llvm.maximumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define double @maximumnum_double_n1snan_arg(double nofpclass(snan) %x, double %y) {
+;
+; LA32F-LABEL: maximumnum_double_n1snan_arg:
+; LA32F: # %bb.0:
+; LA32F-NEXT: addi.w $sp, $sp, -16
+; LA32F-NEXT: .cfi_def_cfa_offset 16
+; LA32F-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill
+; LA32F-NEXT: .cfi_offset 1, -4
+; LA32F-NEXT: bl %plt(fmaximum_num)
+; LA32F-NEXT: ld.w $ra, $sp, 12 # 4-byte Folded Reload
+; LA32F-NEXT: addi.w $sp, $sp, 16
+; LA32F-NEXT: ret
+;
+; LA32D-LABEL: maximumnum_double_n1snan_arg:
+; LA32D: # %bb.0:
+; LA32D-NEXT: fmax.d $fa1, $fa1, $fa1
+; LA32D-NEXT: fmax.d $fa0, $fa0, $fa1
+; LA32D-NEXT: ret
+;
+; LA64F-LABEL: maximumnum_double_n1snan_arg:
+; LA64F: # %bb.0:
+; LA64F-NEXT: addi.d $sp, $sp, -16
+; LA64F-NEXT: .cfi_def_cfa_offset 16
+; LA64F-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
+; LA64F-NEXT: .cfi_offset 1, -8
+; LA64F-NEXT: bl %plt(fmaximum_num)
+; LA64F-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
+; LA64F-NEXT: addi.d $sp, $sp, 16
+; LA64F-NEXT: ret
+;
+; LA64D-LABEL: maximumnum_double_n1snan_arg:
+; LA64D: # %bb.0:
+; LA64D-NEXT: fmax.d $fa1, $fa1, $fa1
+; LA64D-NEXT: fmax.d $fa0, $fa0, $fa1
+; LA64D-NEXT: ret
+ %z = call double @llvm.maximumnum.f64(double %x, double %y)
+ ret double %z
+}
+
define float @minimumnum_float(float %x, float %y) {
;
; LA32F-LABEL: minimumnum_float:
@@ -429,3 +682,153 @@ define double @minimumnum_double_nnan(double %x, double %y) {
%z = call nnan double @llvm.minimumnum.f64(double %x, double %y)
ret double %z
}
+
+define double @minimumnum_double_nnan_arg(double nofpclass(nan) %x, double nofpclass(nan) %y) {
+;
+; LA32F-LABEL: minimumnum_double_nnan_arg:
+; LA32F: # %bb.0:
+; LA32F-NEXT: addi.w $sp, $sp, -16
+; LA32F-NEXT: .cfi_def_cfa_offset 16
+; LA32F-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill
+; LA32F-NEXT: .cfi_offset 1, -4
+; LA32F-NEXT: bl %plt(fminimum_num)
+; LA32F-NEXT: ld.w $ra, $sp, 12 # 4-byte Folded Reload
+; LA32F-NEXT: addi.w $sp, $sp, 16
+; LA32F-NEXT: ret
+;
+; LA32D-LABEL: minimumnum_double_nnan_arg:
+; LA32D: # %bb.0:
+; LA32D-NEXT: fmin.d $fa0, $fa0, $fa1
+; LA32D-NEXT: ret
+;
+; LA64F-LABEL: minimumnum_double_nnan_arg:
+; LA64F: # %bb.0:
+; LA64F-NEXT: addi.d $sp, $sp, -16
+; LA64F-NEXT: .cfi_def_cfa_offset 16
+; LA64F-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
+; LA64F-NEXT: .cfi_offset 1, -8
+; LA64F-NEXT: bl %plt(fminimum_num)
+; LA64F-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
+; LA64F-NEXT: addi.d $sp, $sp, 16
+; LA64F-NEXT: ret
+;
+; LA64D-LABEL: minimumnum_double_nnan_arg:
+; LA64D: # %bb.0:
+; LA64D-NEXT: fmin.d $fa0, $fa0, $fa1
+; LA64D-NEXT: ret
+ %z = call double @llvm.minimumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define double @minimumnum_double_n2nan_arg(double nofpclass(qnan snan) %x, double nofpclass(qnan snan) %y) {
+;
+; LA32F-LABEL: minimumnum_double_n2nan_arg:
+; LA32F: # %bb.0:
+; LA32F-NEXT: addi.w $sp, $sp, -16
+; LA32F-NEXT: .cfi_def_cfa_offset 16
+; LA32F-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill
+; LA32F-NEXT: .cfi_offset 1, -4
+; LA32F-NEXT: bl %plt(fminimum_num)
+; LA32F-NEXT: ld.w $ra, $sp, 12 # 4-byte Folded Reload
+; LA32F-NEXT: addi.w $sp, $sp, 16
+; LA32F-NEXT: ret
+;
+; LA32D-LABEL: minimumnum_double_n2nan_arg:
+; LA32D: # %bb.0:
+; LA32D-NEXT: fmin.d $fa0, $fa0, $fa1
+; LA32D-NEXT: ret
+;
+; LA64F-LABEL: minimumnum_double_n2nan_arg:
+; LA64F: # %bb.0:
+; LA64F-NEXT: addi.d $sp, $sp, -16
+; LA64F-NEXT: .cfi_def_cfa_offset 16
+; LA64F-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
+; LA64F-NEXT: .cfi_offset 1, -8
+; LA64F-NEXT: bl %plt(fminimum_num)
+; LA64F-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
+; LA64F-NEXT: addi.d $sp, $sp, 16
+; LA64F-NEXT: ret
+;
+; LA64D-LABEL: minimumnum_double_n2nan_arg:
+; LA64D: # %bb.0:
+; LA64D-NEXT: fmin.d $fa0, $fa0, $fa1
+; LA64D-NEXT: ret
+ %z = call double @llvm.minimumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define double @minimumnum_double_nsnan_arg(double nofpclass(snan) %x, double nofpclass(snan) %y) {
+;
+; LA32F-LABEL: minimumnum_double_nsnan_arg:
+; LA32F: # %bb.0:
+; LA32F-NEXT: addi.w $sp, $sp, -16
+; LA32F-NEXT: .cfi_def_cfa_offset 16
+; LA32F-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill
+; LA32F-NEXT: .cfi_offset 1, -4
+; LA32F-NEXT: bl %plt(fminimum_num)
+; LA32F-NEXT: ld.w $ra, $sp, 12 # 4-byte Folded Reload
+; LA32F-NEXT: addi.w $sp, $sp, 16
+; LA32F-NEXT: ret
+;
+; LA32D-LABEL: minimumnum_double_nsnan_arg:
+; LA32D: # %bb.0:
+; LA32D-NEXT: fmin.d $fa0, $fa0, $fa1
+; LA32D-NEXT: ret
+;
+; LA64F-LABEL: minimumnum_double_nsnan_arg:
+; LA64F: # %bb.0:
+; LA64F-NEXT: addi.d $sp, $sp, -16
+; LA64F-NEXT: .cfi_def_cfa_offset 16
+; LA64F-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
+; LA64F-NEXT: .cfi_offset 1, -8
+; LA64F-NEXT: bl %plt(fminimum_num)
+; LA64F-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
+; LA64F-NEXT: addi.d $sp, $sp, 16
+; LA64F-NEXT: ret
+;
+; LA64D-LABEL: minimumnum_double_nsnan_arg:
+; LA64D: # %bb.0:
+; LA64D-NEXT: fmin.d $fa0, $fa0, $fa1
+; LA64D-NEXT: ret
+ %z = call double @llvm.minimumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define double @minimumnum_double_n1snan_arg(double nofpclass(snan) %x, double %y) {
+;
+; LA32F-LABEL: minimumnum_double_n1snan_arg:
+; LA32F: # %bb.0:
+; LA32F-NEXT: addi.w $sp, $sp, -16
+; LA32F-NEXT: .cfi_def_cfa_offset 16
+; LA32F-NEXT: st.w $ra, $sp, 12 # 4-byte Folded Spill
+; LA32F-NEXT: .cfi_offset 1, -4
+; LA32F-NEXT: bl %plt(fminimum_num)
+; LA32F-NEXT: ld.w $ra, $sp, 12 # 4-byte Folded Reload
+; LA32F-NEXT: addi.w $sp, $sp, 16
+; LA32F-NEXT: ret
+;
+; LA32D-LABEL: minimumnum_double_n1snan_arg:
+; LA32D: # %bb.0:
+; LA32D-NEXT: fmax.d $fa1, $fa1, $fa1
+; LA32D-NEXT: fmin.d $fa0, $fa0, $fa1
+; LA32D-NEXT: ret
+;
+; LA64F-LABEL: minimumnum_double_n1snan_arg:
+; LA64F: # %bb.0:
+; LA64F-NEXT: addi.d $sp, $sp, -16
+; LA64F-NEXT: .cfi_def_cfa_offset 16
+; LA64F-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill
+; LA64F-NEXT: .cfi_offset 1, -8
+; LA64F-NEXT: bl %plt(fminimum_num)
+; LA64F-NEXT: ld.d $ra, $sp, 8 # 8-byte Folded Reload
+; LA64F-NEXT: addi.d $sp, $sp, 16
+; LA64F-NEXT: ret
+;
+; LA64D-LABEL: minimumnum_double_n1snan_arg:
+; LA64D: # %bb.0:
+; LA64D-NEXT: fmax.d $fa1, $fa1, $fa1
+; LA64D-NEXT: fmin.d $fa0, $fa0, $fa1
+; LA64D-NEXT: ret
+ %z = call double @llvm.minimumnum.f64(double %x, double %y)
+ ret double %z
+}
diff --git a/llvm/test/CodeGen/Mips/fp-maximumnum-minimumnum.ll b/llvm/test/CodeGen/Mips/fp-maximumnum-minimumnum.ll
index bc81966ca0f5c9..999fffbef88585 100644
--- a/llvm/test/CodeGen/Mips/fp-maximumnum-minimumnum.ll
+++ b/llvm/test/CodeGen/Mips/fp-maximumnum-minimumnum.ll
@@ -1,5 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc --mtriple=mipsisa32r6 < %s | FileCheck %s --check-prefix=MIPS32R6
+; RUN: llc --mtriple=mips64 < %s | FileCheck %s --check-prefix=MIPS64
declare float @llvm.maximumnum.f32(float, float)
declare double @llvm.maximumnum.f64(double, double)
@@ -13,6 +14,28 @@ define float @maximumnum_float(float %x, float %y) {
; MIPS32R6-NEXT: min.s $f1, $f12, $f12
; MIPS32R6-NEXT: jr $ra
; MIPS32R6-NEXT: max.s $f0, $f1, $f0
+;
+; MIPS64-LABEL: maximumnum_float:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.un.s $f12, $f12
+; MIPS64-NEXT: movt.s $f12, $f13, $fcc0
+; MIPS64-NEXT: c.un.s $f13, $f13
+; MIPS64-NEXT: movt.s $f13, $f12, $fcc0
+; MIPS64-NEXT: c.ule.s $f12, $f13
+; MIPS64-NEXT: mov.s $f0, $f13
+; MIPS64-NEXT: movf.s $f0, $f12, $fcc0
+; MIPS64-NEXT: add.s $f1, $f0, $f0
+; MIPS64-NEXT: c.un.s $f0, $f0
+; MIPS64-NEXT: movt.s $f0, $f1, $fcc0
+; MIPS64-NEXT: mfc1 $1, $f12
+; MIPS64-NEXT: mov.s $f1, $f0
+; MIPS64-NEXT: movz.s $f1, $f12, $1
+; MIPS64-NEXT: mfc1 $1, $f13
+; MIPS64-NEXT: mtc1 $zero, $f2
+; MIPS64-NEXT: movz.s $f1, $f13, $1
+; MIPS64-NEXT: c.eq.s $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.s $f0, $f1, $fcc0
%z = call float @llvm.maximumnum.f32(float %x, float %y)
ret float %z
}
@@ -24,6 +47,20 @@ define float @maximumnum_float_nsz(float %x, float %y) {
; MIPS32R6-NEXT: min.s $f1, $f12, $f12
; MIPS32R6-NEXT: jr $ra
; MIPS32R6-NEXT: max.s $f0, $f1, $f0
+;
+; MIPS64-LABEL: maximumnum_float_nsz:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: mov.s $f0, $f13
+; MIPS64-NEXT: c.un.s $f12, $f12
+; MIPS64-NEXT: movt.s $f12, $f13, $fcc0
+; MIPS64-NEXT: c.un.s $f13, $f13
+; MIPS64-NEXT: movt.s $f0, $f12, $fcc0
+; MIPS64-NEXT: c.ule.s $f12, $f0
+; MIPS64-NEXT: movf.s $f0, $f12, $fcc0
+; MIPS64-NEXT: add.s $f1, $f0, $f0
+; MIPS64-NEXT: c.un.s $f0, $f0
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.s $f0, $f1, $fcc0
%z = call nsz float @llvm.maximumnum.f32(float %x, float %y)
ret float %z
}
@@ -33,10 +70,132 @@ define float @maximumnum_float_nnan(float %x, float %y) {
; MIPS32R6: # %bb.0:
; MIPS32R6-NEXT: jr $ra
; MIPS32R6-NEXT: max.s $f0, $f12, $f14
+;
+; MIPS64-LABEL: maximumnum_float_nnan:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.ule.s $f12, $f13
+; MIPS64-NEXT: mov.s $f0, $f13
+; MIPS64-NEXT: movf.s $f0, $f12, $fcc0
+; MIPS64-NEXT: mfc1 $1, $f12
+; MIPS64-NEXT: mov.s $f1, $f0
+; MIPS64-NEXT: movz.s $f1, $f12, $1
+; MIPS64-NEXT: mfc1 $1, $f13
+; MIPS64-NEXT: movz.s $f1, $f13, $1
+; MIPS64-NEXT: mtc1 $zero, $f2
+; MIPS64-NEXT: c.eq.s $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.s $f0, $f1, $fcc0
%z = call nnan float @llvm.maximumnum.f32(float %x, float %y)
ret float %z
}
+define float @maximumnum_float_nnan_arg(float nofpclass(nan) %x, float nofpclass(nan) %y) {
+; MIPS32R6-LABEL: maximumnum_float_nnan_arg:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: max.s $f0, $f12, $f14
+;
+; MIPS64-LABEL: maximumnum_float_nnan_arg:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.ule.s $f12, $f13
+; MIPS64-NEXT: mov.s $f0, $f13
+; MIPS64-NEXT: movf.s $f0, $f12, $fcc0
+; MIPS64-NEXT: mfc1 $1, $f12
+; MIPS64-NEXT: mov.s $f1, $f0
+; MIPS64-NEXT: movz.s $f1, $f12, $1
+; MIPS64-NEXT: mfc1 $1, $f13
+; MIPS64-NEXT: movz.s $f1, $f13, $1
+; MIPS64-NEXT: mtc1 $zero, $f2
+; MIPS64-NEXT: c.eq.s $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.s $f0, $f1, $fcc0
+ %z = call float @llvm.maximumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+define float @maximumnum_float_n2nan_arg(float nofpclass(qnan snan) %x, float nofpclass(qnan snan) %y) {
+; MIPS32R6-LABEL: maximumnum_float_n2nan_arg:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: max.s $f0, $f12, $f14
+;
+; MIPS64-LABEL: maximumnum_float_n2nan_arg:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.ule.s $f12, $f13
+; MIPS64-NEXT: mov.s $f0, $f13
+; MIPS64-NEXT: movf.s $f0, $f12, $fcc0
+; MIPS64-NEXT: mfc1 $1, $f12
+; MIPS64-NEXT: mov.s $f1, $f0
+; MIPS64-NEXT: movz.s $f1, $f12, $1
+; MIPS64-NEXT: mfc1 $1, $f13
+; MIPS64-NEXT: movz.s $f1, $f13, $1
+; MIPS64-NEXT: mtc1 $zero, $f2
+; MIPS64-NEXT: c.eq.s $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.s $f0, $f1, $fcc0
+ %z = call float @llvm.maximumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+define float @maximumnum_float_nsnan_arg(float nofpclass(snan) %x, float nofpclass(snan) %y) {
+; MIPS32R6-LABEL: maximumnum_float_nsnan_arg:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: max.s $f0, $f12, $f14
+;
+; MIPS64-LABEL: maximumnum_float_nsnan_arg:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.un.s $f12, $f12
+; MIPS64-NEXT: movt.s $f12, $f13, $fcc0
+; MIPS64-NEXT: c.un.s $f13, $f13
+; MIPS64-NEXT: movt.s $f13, $f12, $fcc0
+; MIPS64-NEXT: c.ule.s $f12, $f13
+; MIPS64-NEXT: mov.s $f0, $f13
+; MIPS64-NEXT: movf.s $f0, $f12, $fcc0
+; MIPS64-NEXT: mfc1 $1, $f12
+; MIPS64-NEXT: mov.s $f1, $f0
+; MIPS64-NEXT: movz.s $f1, $f12, $1
+; MIPS64-NEXT: mfc1 $1, $f13
+; MIPS64-NEXT: movz.s $f1, $f13, $1
+; MIPS64-NEXT: mtc1 $zero, $f2
+; MIPS64-NEXT: c.eq.s $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.s $f0, $f1, $fcc0
+ %z = call float @llvm.maximumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+define float @maximumnum_float_n1snan_arg(float nofpclass(snan) %x, float %y) {
+; MIPS32R6-LABEL: maximumnum_float_n1snan_arg:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: min.s $f0, $f14, $f14
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: max.s $f0, $f12, $f0
+;
+; MIPS64-LABEL: maximumnum_float_n1snan_arg:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.un.s $f12, $f12
+; MIPS64-NEXT: movt.s $f12, $f13, $fcc0
+; MIPS64-NEXT: c.un.s $f13, $f13
+; MIPS64-NEXT: movt.s $f13, $f12, $fcc0
+; MIPS64-NEXT: c.ule.s $f12, $f13
+; MIPS64-NEXT: mov.s $f0, $f13
+; MIPS64-NEXT: movf.s $f0, $f12, $fcc0
+; MIPS64-NEXT: add.s $f1, $f0, $f0
+; MIPS64-NEXT: c.un.s $f0, $f0
+; MIPS64-NEXT: movt.s $f0, $f1, $fcc0
+; MIPS64-NEXT: mfc1 $1, $f12
+; MIPS64-NEXT: mov.s $f1, $f0
+; MIPS64-NEXT: movz.s $f1, $f12, $1
+; MIPS64-NEXT: mfc1 $1, $f13
+; MIPS64-NEXT: mtc1 $zero, $f2
+; MIPS64-NEXT: movz.s $f1, $f13, $1
+; MIPS64-NEXT: c.eq.s $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.s $f0, $f1, $fcc0
+ %z = call float @llvm.maximumnum.f32(float %x, float %y)
+ ret float %z
+}
define double @maximumnum_double(double %x, double %y) {
; MIPS32R6-LABEL: maximumnum_double:
@@ -45,6 +204,28 @@ define double @maximumnum_double(double %x, double %y) {
; MIPS32R6-NEXT: min.d $f1, $f12, $f12
; MIPS32R6-NEXT: jr $ra
; MIPS32R6-NEXT: max.d $f0, $f1, $f0
+;
+; MIPS64-LABEL: maximumnum_double:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.un.d $f12, $f12
+; MIPS64-NEXT: movt.d $f12, $f13, $fcc0
+; MIPS64-NEXT: c.un.d $f13, $f13
+; MIPS64-NEXT: movt.d $f13, $f12, $fcc0
+; MIPS64-NEXT: c.ule.d $f12, $f13
+; MIPS64-NEXT: mov.d $f0, $f13
+; MIPS64-NEXT: movf.d $f0, $f12, $fcc0
+; MIPS64-NEXT: add.d $f1, $f0, $f0
+; MIPS64-NEXT: c.un.d $f0, $f0
+; MIPS64-NEXT: movt.d $f0, $f1, $fcc0
+; MIPS64-NEXT: dmfc1 $1, $f12
+; MIPS64-NEXT: mov.d $f1, $f0
+; MIPS64-NEXT: movz.d $f1, $f12, $1
+; MIPS64-NEXT: dmfc1 $1, $f13
+; MIPS64-NEXT: movz.d $f1, $f13, $1
+; MIPS64-NEXT: dmtc1 $zero, $f2
+; MIPS64-NEXT: c.eq.d $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.d $f0, $f1, $fcc0
%z = call double @llvm.maximumnum.f64(double %x, double %y)
ret double %z
}
@@ -56,6 +237,20 @@ define double @maximumnum_double_nsz(double %x, double %y) {
; MIPS32R6-NEXT: min.d $f1, $f12, $f12
; MIPS32R6-NEXT: jr $ra
; MIPS32R6-NEXT: max.d $f0, $f1, $f0
+;
+; MIPS64-LABEL: maximumnum_double_nsz:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: mov.d $f0, $f13
+; MIPS64-NEXT: c.un.d $f12, $f12
+; MIPS64-NEXT: movt.d $f12, $f13, $fcc0
+; MIPS64-NEXT: c.un.d $f13, $f13
+; MIPS64-NEXT: movt.d $f0, $f12, $fcc0
+; MIPS64-NEXT: c.ule.d $f12, $f0
+; MIPS64-NEXT: movf.d $f0, $f12, $fcc0
+; MIPS64-NEXT: add.d $f1, $f0, $f0
+; MIPS64-NEXT: c.un.d $f0, $f0
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.d $f0, $f1, $fcc0
%z = call nsz double @llvm.maximumnum.f64(double %x, double %y)
ret double %z
}
@@ -65,10 +260,133 @@ define double @maximumnum_double_nnan(double %x, double %y) {
; MIPS32R6: # %bb.0:
; MIPS32R6-NEXT: jr $ra
; MIPS32R6-NEXT: max.d $f0, $f12, $f14
+;
+; MIPS64-LABEL: maximumnum_double_nnan:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.ule.d $f12, $f13
+; MIPS64-NEXT: mov.d $f0, $f13
+; MIPS64-NEXT: movf.d $f0, $f12, $fcc0
+; MIPS64-NEXT: dmfc1 $1, $f12
+; MIPS64-NEXT: mov.d $f1, $f0
+; MIPS64-NEXT: movz.d $f1, $f12, $1
+; MIPS64-NEXT: dmfc1 $1, $f13
+; MIPS64-NEXT: movz.d $f1, $f13, $1
+; MIPS64-NEXT: dmtc1 $zero, $f2
+; MIPS64-NEXT: c.eq.d $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.d $f0, $f1, $fcc0
%z = call nnan double @llvm.maximumnum.f64(double %x, double %y)
ret double %z
}
+define double @maximumnum_double_nnan_arg(double nofpclass(nan) %x, double nofpclass(nan) %y) {
+; MIPS32R6-LABEL: maximumnum_double_nnan_arg:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: max.d $f0, $f12, $f14
+;
+; MIPS64-LABEL: maximumnum_double_nnan_arg:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.ule.d $f12, $f13
+; MIPS64-NEXT: mov.d $f0, $f13
+; MIPS64-NEXT: movf.d $f0, $f12, $fcc0
+; MIPS64-NEXT: dmfc1 $1, $f12
+; MIPS64-NEXT: mov.d $f1, $f0
+; MIPS64-NEXT: movz.d $f1, $f12, $1
+; MIPS64-NEXT: dmfc1 $1, $f13
+; MIPS64-NEXT: movz.d $f1, $f13, $1
+; MIPS64-NEXT: dmtc1 $zero, $f2
+; MIPS64-NEXT: c.eq.d $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.d $f0, $f1, $fcc0
+ %z = call double @llvm.maximumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define double @maximumnum_double_n2nan_arg(double nofpclass(qnan snan) %x, double nofpclass(qnan snan) %y) {
+; MIPS32R6-LABEL: maximumnum_double_n2nan_arg:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: max.d $f0, $f12, $f14
+;
+; MIPS64-LABEL: maximumnum_double_n2nan_arg:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.ule.d $f12, $f13
+; MIPS64-NEXT: mov.d $f0, $f13
+; MIPS64-NEXT: movf.d $f0, $f12, $fcc0
+; MIPS64-NEXT: dmfc1 $1, $f12
+; MIPS64-NEXT: mov.d $f1, $f0
+; MIPS64-NEXT: movz.d $f1, $f12, $1
+; MIPS64-NEXT: dmfc1 $1, $f13
+; MIPS64-NEXT: movz.d $f1, $f13, $1
+; MIPS64-NEXT: dmtc1 $zero, $f2
+; MIPS64-NEXT: c.eq.d $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.d $f0, $f1, $fcc0
+ %z = call double @llvm.maximumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define double @maximumnum_double_nsnan_arg(double nofpclass(snan) %x, double nofpclass(snan) %y) {
+; MIPS32R6-LABEL: maximumnum_double_nsnan_arg:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: max.d $f0, $f12, $f14
+;
+; MIPS64-LABEL: maximumnum_double_nsnan_arg:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.un.d $f12, $f12
+; MIPS64-NEXT: movt.d $f12, $f13, $fcc0
+; MIPS64-NEXT: c.un.d $f13, $f13
+; MIPS64-NEXT: movt.d $f13, $f12, $fcc0
+; MIPS64-NEXT: c.ule.d $f12, $f13
+; MIPS64-NEXT: mov.d $f0, $f13
+; MIPS64-NEXT: movf.d $f0, $f12, $fcc0
+; MIPS64-NEXT: dmfc1 $1, $f12
+; MIPS64-NEXT: mov.d $f1, $f0
+; MIPS64-NEXT: movz.d $f1, $f12, $1
+; MIPS64-NEXT: dmfc1 $1, $f13
+; MIPS64-NEXT: movz.d $f1, $f13, $1
+; MIPS64-NEXT: dmtc1 $zero, $f2
+; MIPS64-NEXT: c.eq.d $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.d $f0, $f1, $fcc0
+ %z = call double @llvm.maximumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define double @maximumnum_double_n1snan_arg(double nofpclass(snan) %x, double %y) {
+; MIPS32R6-LABEL: maximumnum_double_n1snan_arg:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: min.d $f0, $f14, $f14
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: max.d $f0, $f12, $f0
+;
+; MIPS64-LABEL: maximumnum_double_n1snan_arg:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.un.d $f12, $f12
+; MIPS64-NEXT: movt.d $f12, $f13, $fcc0
+; MIPS64-NEXT: c.un.d $f13, $f13
+; MIPS64-NEXT: movt.d $f13, $f12, $fcc0
+; MIPS64-NEXT: c.ule.d $f12, $f13
+; MIPS64-NEXT: mov.d $f0, $f13
+; MIPS64-NEXT: movf.d $f0, $f12, $fcc0
+; MIPS64-NEXT: add.d $f1, $f0, $f0
+; MIPS64-NEXT: c.un.d $f0, $f0
+; MIPS64-NEXT: movt.d $f0, $f1, $fcc0
+; MIPS64-NEXT: dmfc1 $1, $f12
+; MIPS64-NEXT: mov.d $f1, $f0
+; MIPS64-NEXT: movz.d $f1, $f12, $1
+; MIPS64-NEXT: dmfc1 $1, $f13
+; MIPS64-NEXT: movz.d $f1, $f13, $1
+; MIPS64-NEXT: dmtc1 $zero, $f2
+; MIPS64-NEXT: c.eq.d $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.d $f0, $f1, $fcc0
+ %z = call double @llvm.maximumnum.f64(double %x, double %y)
+ ret double %z
+}
+
define float @minimumnum_float(float %x, float %y) {
; MIPS32R6-LABEL: minimumnum_float:
; MIPS32R6: # %bb.0:
@@ -76,6 +394,31 @@ define float @minimumnum_float(float %x, float %y) {
; MIPS32R6-NEXT: min.s $f1, $f12, $f12
; MIPS32R6-NEXT: jr $ra
; MIPS32R6-NEXT: min.s $f0, $f1, $f0
+;
+; MIPS64-LABEL: minimumnum_float:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.un.s $f12, $f12
+; MIPS64-NEXT: movt.s $f12, $f13, $fcc0
+; MIPS64-NEXT: c.un.s $f13, $f13
+; MIPS64-NEXT: movt.s $f13, $f12, $fcc0
+; MIPS64-NEXT: c.olt.s $f12, $f13
+; MIPS64-NEXT: mov.s $f0, $f13
+; MIPS64-NEXT: movt.s $f0, $f12, $fcc0
+; MIPS64-NEXT: add.s $f1, $f0, $f0
+; MIPS64-NEXT: c.un.s $f0, $f0
+; MIPS64-NEXT: movt.s $f0, $f1, $fcc0
+; MIPS64-NEXT: mfc1 $1, $f12
+; MIPS64-NEXT: lui $2, 32768
+; MIPS64-NEXT: xor $1, $1, $2
+; MIPS64-NEXT: mov.s $f1, $f0
+; MIPS64-NEXT: movz.s $f1, $f12, $1
+; MIPS64-NEXT: mfc1 $1, $f13
+; MIPS64-NEXT: xor $1, $1, $2
+; MIPS64-NEXT: mtc1 $zero, $f2
+; MIPS64-NEXT: movz.s $f1, $f13, $1
+; MIPS64-NEXT: c.eq.s $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.s $f0, $f1, $fcc0
%z = call float @llvm.minimumnum.f32(float %x, float %y)
ret float %z
}
@@ -87,6 +430,20 @@ define float @minimumnum_float_nsz(float %x, float %y) {
; MIPS32R6-NEXT: min.s $f1, $f12, $f12
; MIPS32R6-NEXT: jr $ra
; MIPS32R6-NEXT: min.s $f0, $f1, $f0
+;
+; MIPS64-LABEL: minimumnum_float_nsz:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: mov.s $f0, $f13
+; MIPS64-NEXT: c.un.s $f12, $f12
+; MIPS64-NEXT: movt.s $f12, $f13, $fcc0
+; MIPS64-NEXT: c.un.s $f13, $f13
+; MIPS64-NEXT: movt.s $f0, $f12, $fcc0
+; MIPS64-NEXT: c.olt.s $f12, $f0
+; MIPS64-NEXT: movt.s $f0, $f12, $fcc0
+; MIPS64-NEXT: add.s $f1, $f0, $f0
+; MIPS64-NEXT: c.un.s $f0, $f0
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.s $f0, $f1, $fcc0
%z = call nsz float @llvm.minimumnum.f32(float %x, float %y)
ret float %z
}
@@ -96,10 +453,148 @@ define float @minimumnum_float_nnan(float %x, float %y) {
; MIPS32R6: # %bb.0:
; MIPS32R6-NEXT: jr $ra
; MIPS32R6-NEXT: min.s $f0, $f12, $f14
+;
+; MIPS64-LABEL: minimumnum_float_nnan:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.olt.s $f12, $f13
+; MIPS64-NEXT: mov.s $f0, $f13
+; MIPS64-NEXT: movt.s $f0, $f12, $fcc0
+; MIPS64-NEXT: mfc1 $1, $f12
+; MIPS64-NEXT: lui $2, 32768
+; MIPS64-NEXT: xor $1, $1, $2
+; MIPS64-NEXT: mov.s $f1, $f0
+; MIPS64-NEXT: movz.s $f1, $f12, $1
+; MIPS64-NEXT: mfc1 $1, $f13
+; MIPS64-NEXT: xor $1, $1, $2
+; MIPS64-NEXT: movz.s $f1, $f13, $1
+; MIPS64-NEXT: mtc1 $zero, $f2
+; MIPS64-NEXT: c.eq.s $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.s $f0, $f1, $fcc0
%z = call nnan float @llvm.minimumnum.f32(float %x, float %y)
ret float %z
}
+define float @minimumnum_float_nnan_arg(float nofpclass(nan) %x, float nofpclass(nan) %y) {
+; MIPS32R6-LABEL: minimumnum_float_nnan_arg:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: min.s $f0, $f12, $f14
+;
+; MIPS64-LABEL: minimumnum_float_nnan_arg:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.olt.s $f12, $f13
+; MIPS64-NEXT: mov.s $f0, $f13
+; MIPS64-NEXT: movt.s $f0, $f12, $fcc0
+; MIPS64-NEXT: mfc1 $1, $f12
+; MIPS64-NEXT: lui $2, 32768
+; MIPS64-NEXT: xor $1, $1, $2
+; MIPS64-NEXT: mov.s $f1, $f0
+; MIPS64-NEXT: movz.s $f1, $f12, $1
+; MIPS64-NEXT: mfc1 $1, $f13
+; MIPS64-NEXT: xor $1, $1, $2
+; MIPS64-NEXT: movz.s $f1, $f13, $1
+; MIPS64-NEXT: mtc1 $zero, $f2
+; MIPS64-NEXT: c.eq.s $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.s $f0, $f1, $fcc0
+ %z = call float @llvm.minimumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+define float @minimumnum_float_n2nan_arg(float nofpclass(qnan snan) %x, float nofpclass(qnan snan) %y) {
+; MIPS32R6-LABEL: minimumnum_float_n2nan_arg:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: min.s $f0, $f12, $f14
+;
+; MIPS64-LABEL: minimumnum_float_n2nan_arg:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.olt.s $f12, $f13
+; MIPS64-NEXT: mov.s $f0, $f13
+; MIPS64-NEXT: movt.s $f0, $f12, $fcc0
+; MIPS64-NEXT: mfc1 $1, $f12
+; MIPS64-NEXT: lui $2, 32768
+; MIPS64-NEXT: xor $1, $1, $2
+; MIPS64-NEXT: mov.s $f1, $f0
+; MIPS64-NEXT: movz.s $f1, $f12, $1
+; MIPS64-NEXT: mfc1 $1, $f13
+; MIPS64-NEXT: xor $1, $1, $2
+; MIPS64-NEXT: movz.s $f1, $f13, $1
+; MIPS64-NEXT: mtc1 $zero, $f2
+; MIPS64-NEXT: c.eq.s $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.s $f0, $f1, $fcc0
+ %z = call float @llvm.minimumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+define float @minimumnum_float_nsnan_arg(float nofpclass(snan) %x, float nofpclass(snan) %y) {
+; MIPS32R6-LABEL: minimumnum_float_nsnan_arg:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: min.s $f0, $f12, $f14
+;
+; MIPS64-LABEL: minimumnum_float_nsnan_arg:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.un.s $f12, $f12
+; MIPS64-NEXT: movt.s $f12, $f13, $fcc0
+; MIPS64-NEXT: c.un.s $f13, $f13
+; MIPS64-NEXT: movt.s $f13, $f12, $fcc0
+; MIPS64-NEXT: c.olt.s $f12, $f13
+; MIPS64-NEXT: mov.s $f0, $f13
+; MIPS64-NEXT: movt.s $f0, $f12, $fcc0
+; MIPS64-NEXT: mfc1 $1, $f12
+; MIPS64-NEXT: lui $2, 32768
+; MIPS64-NEXT: xor $1, $1, $2
+; MIPS64-NEXT: mov.s $f1, $f0
+; MIPS64-NEXT: movz.s $f1, $f12, $1
+; MIPS64-NEXT: mfc1 $1, $f13
+; MIPS64-NEXT: xor $1, $1, $2
+; MIPS64-NEXT: movz.s $f1, $f13, $1
+; MIPS64-NEXT: mtc1 $zero, $f2
+; MIPS64-NEXT: c.eq.s $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.s $f0, $f1, $fcc0
+ %z = call float @llvm.minimumnum.f32(float %x, float %y)
+ ret float %z
+}
+
+define float @minimumnum_float_n1snan_arg(float nofpclass(snan) %x, float %y) {
+; MIPS32R6-LABEL: minimumnum_float_n1snan_arg:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: min.s $f0, $f14, $f14
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: min.s $f0, $f12, $f0
+;
+; MIPS64-LABEL: minimumnum_float_n1snan_arg:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.un.s $f12, $f12
+; MIPS64-NEXT: movt.s $f12, $f13, $fcc0
+; MIPS64-NEXT: c.un.s $f13, $f13
+; MIPS64-NEXT: movt.s $f13, $f12, $fcc0
+; MIPS64-NEXT: c.olt.s $f12, $f13
+; MIPS64-NEXT: mov.s $f0, $f13
+; MIPS64-NEXT: movt.s $f0, $f12, $fcc0
+; MIPS64-NEXT: add.s $f1, $f0, $f0
+; MIPS64-NEXT: c.un.s $f0, $f0
+; MIPS64-NEXT: movt.s $f0, $f1, $fcc0
+; MIPS64-NEXT: mfc1 $1, $f12
+; MIPS64-NEXT: lui $2, 32768
+; MIPS64-NEXT: xor $1, $1, $2
+; MIPS64-NEXT: mov.s $f1, $f0
+; MIPS64-NEXT: movz.s $f1, $f12, $1
+; MIPS64-NEXT: mfc1 $1, $f13
+; MIPS64-NEXT: xor $1, $1, $2
+; MIPS64-NEXT: mtc1 $zero, $f2
+; MIPS64-NEXT: movz.s $f1, $f13, $1
+; MIPS64-NEXT: c.eq.s $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.s $f0, $f1, $fcc0
+ %z = call float @llvm.minimumnum.f32(float %x, float %y)
+ ret float %z
+}
+
define double @minimumnum_double(double %x, double %y) {
; MIPS32R6-LABEL: minimumnum_double:
; MIPS32R6: # %bb.0:
@@ -107,6 +602,32 @@ define double @minimumnum_double(double %x, double %y) {
; MIPS32R6-NEXT: min.d $f1, $f12, $f12
; MIPS32R6-NEXT: jr $ra
; MIPS32R6-NEXT: min.d $f0, $f1, $f0
+;
+; MIPS64-LABEL: minimumnum_double:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.un.d $f12, $f12
+; MIPS64-NEXT: movt.d $f12, $f13, $fcc0
+; MIPS64-NEXT: c.un.d $f13, $f13
+; MIPS64-NEXT: movt.d $f13, $f12, $fcc0
+; MIPS64-NEXT: c.olt.d $f12, $f13
+; MIPS64-NEXT: mov.d $f0, $f13
+; MIPS64-NEXT: movt.d $f0, $f12, $fcc0
+; MIPS64-NEXT: add.d $f1, $f0, $f0
+; MIPS64-NEXT: c.un.d $f0, $f0
+; MIPS64-NEXT: movt.d $f0, $f1, $fcc0
+; MIPS64-NEXT: dmfc1 $1, $f12
+; MIPS64-NEXT: daddiu $2, $zero, 1
+; MIPS64-NEXT: dsll $2, $2, 63
+; MIPS64-NEXT: xor $1, $1, $2
+; MIPS64-NEXT: mov.d $f1, $f0
+; MIPS64-NEXT: movz.d $f1, $f12, $1
+; MIPS64-NEXT: dmfc1 $1, $f13
+; MIPS64-NEXT: xor $1, $1, $2
+; MIPS64-NEXT: movz.d $f1, $f13, $1
+; MIPS64-NEXT: dmtc1 $zero, $f2
+; MIPS64-NEXT: c.eq.d $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.d $f0, $f1, $fcc0
%z = call double @llvm.minimumnum.f64(double %x, double %y)
ret double %z
}
@@ -118,6 +639,20 @@ define double @minimumnum_double_nsz(double %x, double %y) {
; MIPS32R6-NEXT: min.d $f1, $f12, $f12
; MIPS32R6-NEXT: jr $ra
; MIPS32R6-NEXT: min.d $f0, $f1, $f0
+;
+; MIPS64-LABEL: minimumnum_double_nsz:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: mov.d $f0, $f13
+; MIPS64-NEXT: c.un.d $f12, $f12
+; MIPS64-NEXT: movt.d $f12, $f13, $fcc0
+; MIPS64-NEXT: c.un.d $f13, $f13
+; MIPS64-NEXT: movt.d $f0, $f12, $fcc0
+; MIPS64-NEXT: c.olt.d $f12, $f0
+; MIPS64-NEXT: movt.d $f0, $f12, $fcc0
+; MIPS64-NEXT: add.d $f1, $f0, $f0
+; MIPS64-NEXT: c.un.d $f0, $f0
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.d $f0, $f1, $fcc0
%z = call nsz double @llvm.minimumnum.f64(double %x, double %y)
ret double %z
}
@@ -127,6 +662,149 @@ define double @minimumnum_double_nnan(double %x, double %y) {
; MIPS32R6: # %bb.0:
; MIPS32R6-NEXT: jr $ra
; MIPS32R6-NEXT: min.d $f0, $f12, $f14
+;
+; MIPS64-LABEL: minimumnum_double_nnan:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.olt.d $f12, $f13
+; MIPS64-NEXT: mov.d $f0, $f13
+; MIPS64-NEXT: movt.d $f0, $f12, $fcc0
+; MIPS64-NEXT: daddiu $1, $zero, 1
+; MIPS64-NEXT: dsll $1, $1, 63
+; MIPS64-NEXT: dmfc1 $2, $f12
+; MIPS64-NEXT: xor $2, $2, $1
+; MIPS64-NEXT: mov.d $f1, $f0
+; MIPS64-NEXT: movz.d $f1, $f12, $2
+; MIPS64-NEXT: dmfc1 $2, $f13
+; MIPS64-NEXT: xor $1, $2, $1
+; MIPS64-NEXT: movz.d $f1, $f13, $1
+; MIPS64-NEXT: dmtc1 $zero, $f2
+; MIPS64-NEXT: c.eq.d $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.d $f0, $f1, $fcc0
%z = call nnan double @llvm.minimumnum.f64(double %x, double %y)
ret double %z
}
+
+define double @minimumnum_double_nnan_arg(double nofpclass(nan) %x, double nofpclass(nan) %y) {
+; MIPS32R6-LABEL: minimumnum_double_nnan_arg:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: min.d $f0, $f12, $f14
+;
+; MIPS64-LABEL: minimumnum_double_nnan_arg:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.olt.d $f12, $f13
+; MIPS64-NEXT: mov.d $f0, $f13
+; MIPS64-NEXT: movt.d $f0, $f12, $fcc0
+; MIPS64-NEXT: daddiu $1, $zero, 1
+; MIPS64-NEXT: dsll $1, $1, 63
+; MIPS64-NEXT: dmfc1 $2, $f12
+; MIPS64-NEXT: xor $2, $2, $1
+; MIPS64-NEXT: mov.d $f1, $f0
+; MIPS64-NEXT: movz.d $f1, $f12, $2
+; MIPS64-NEXT: dmfc1 $2, $f13
+; MIPS64-NEXT: xor $1, $2, $1
+; MIPS64-NEXT: movz.d $f1, $f13, $1
+; MIPS64-NEXT: dmtc1 $zero, $f2
+; MIPS64-NEXT: c.eq.d $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.d $f0, $f1, $fcc0
+ %z = call double @llvm.minimumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define double @minimumnum_double_n2nan_arg(double nofpclass(qnan snan) %x, double nofpclass(qnan snan) %y) {
+; MIPS32R6-LABEL: minimumnum_double_n2nan_arg:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: min.d $f0, $f12, $f14
+;
+; MIPS64-LABEL: minimumnum_double_n2nan_arg:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.olt.d $f12, $f13
+; MIPS64-NEXT: mov.d $f0, $f13
+; MIPS64-NEXT: movt.d $f0, $f12, $fcc0
+; MIPS64-NEXT: daddiu $1, $zero, 1
+; MIPS64-NEXT: dsll $1, $1, 63
+; MIPS64-NEXT: dmfc1 $2, $f12
+; MIPS64-NEXT: xor $2, $2, $1
+; MIPS64-NEXT: mov.d $f1, $f0
+; MIPS64-NEXT: movz.d $f1, $f12, $2
+; MIPS64-NEXT: dmfc1 $2, $f13
+; MIPS64-NEXT: xor $1, $2, $1
+; MIPS64-NEXT: movz.d $f1, $f13, $1
+; MIPS64-NEXT: dmtc1 $zero, $f2
+; MIPS64-NEXT: c.eq.d $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.d $f0, $f1, $fcc0
+ %z = call double @llvm.minimumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define double @minimumnum_double_nsnan_arg(double nofpclass(snan) %x, double nofpclass(snan) %y) {
+; MIPS32R6-LABEL: minimumnum_double_nsnan_arg:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: min.d $f0, $f12, $f14
+;
+; MIPS64-LABEL: minimumnum_double_nsnan_arg:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.un.d $f12, $f12
+; MIPS64-NEXT: movt.d $f12, $f13, $fcc0
+; MIPS64-NEXT: c.un.d $f13, $f13
+; MIPS64-NEXT: movt.d $f13, $f12, $fcc0
+; MIPS64-NEXT: c.olt.d $f12, $f13
+; MIPS64-NEXT: mov.d $f0, $f13
+; MIPS64-NEXT: movt.d $f0, $f12, $fcc0
+; MIPS64-NEXT: dmfc1 $1, $f12
+; MIPS64-NEXT: daddiu $2, $zero, 1
+; MIPS64-NEXT: dsll $2, $2, 63
+; MIPS64-NEXT: xor $1, $1, $2
+; MIPS64-NEXT: mov.d $f1, $f0
+; MIPS64-NEXT: movz.d $f1, $f12, $1
+; MIPS64-NEXT: dmfc1 $1, $f13
+; MIPS64-NEXT: xor $1, $1, $2
+; MIPS64-NEXT: movz.d $f1, $f13, $1
+; MIPS64-NEXT: dmtc1 $zero, $f2
+; MIPS64-NEXT: c.eq.d $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.d $f0, $f1, $fcc0
+ %z = call double @llvm.minimumnum.f64(double %x, double %y)
+ ret double %z
+}
+
+define double @minimumnum_double_n1snan_arg(double nofpclass(snan) %x, double %y) {
+; MIPS32R6-LABEL: minimumnum_double_n1snan_arg:
+; MIPS32R6: # %bb.0:
+; MIPS32R6-NEXT: min.d $f0, $f14, $f14
+; MIPS32R6-NEXT: jr $ra
+; MIPS32R6-NEXT: min.d $f0, $f12, $f0
+;
+; MIPS64-LABEL: minimumnum_double_n1snan_arg:
+; MIPS64: # %bb.0:
+; MIPS64-NEXT: c.un.d $f12, $f12
+; MIPS64-NEXT: movt.d $f12, $f13, $fcc0
+; MIPS64-NEXT: c.un.d $f13, $f13
+; MIPS64-NEXT: movt.d $f13, $f12, $fcc0
+; MIPS64-NEXT: c.olt.d $f12, $f13
+; MIPS64-NEXT: mov.d $f0, $f13
+; MIPS64-NEXT: movt.d $f0, $f12, $fcc0
+; MIPS64-NEXT: add.d $f1, $f0, $f0
+; MIPS64-NEXT: c.un.d $f0, $f0
+; MIPS64-NEXT: movt.d $f0, $f1, $fcc0
+; MIPS64-NEXT: dmfc1 $1, $f12
+; MIPS64-NEXT: daddiu $2, $zero, 1
+; MIPS64-NEXT: dsll $2, $2, 63
+; MIPS64-NEXT: xor $1, $1, $2
+; MIPS64-NEXT: mov.d $f1, $f0
+; MIPS64-NEXT: movz.d $f1, $f12, $1
+; MIPS64-NEXT: dmfc1 $1, $f13
+; MIPS64-NEXT: xor $1, $1, $2
+; MIPS64-NEXT: movz.d $f1, $f13, $1
+; MIPS64-NEXT: dmtc1 $zero, $f2
+; MIPS64-NEXT: c.eq.d $f0, $f2
+; MIPS64-NEXT: jr $ra
+; MIPS64-NEXT: movt.d $f0, $f1, $fcc0
+ %z = call double @llvm.minimumnum.f64(double %x, double %y)
+ ret double %z
+}
diff --git a/llvm/test/CodeGen/X86/fminimumnum-fmaximumnum.ll b/llvm/test/CodeGen/X86/fminimumnum-fmaximumnum.ll
new file mode 100644
index 00000000000000..38d996c432f20f
--- /dev/null
+++ b/llvm/test/CodeGen/X86/fminimumnum-fmaximumnum.ll
@@ -0,0 +1,1210 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+sse2 | FileCheck %s --check-prefixes=SSE2
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx | FileCheck %s --check-prefixes=AVX
+; RUN: llc < %s -mtriple=i686-unknown-unknown | FileCheck %s --check-prefixes=X86
+; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+avx | FileCheck %s --check-prefixes=X86AVX
+
+declare float @llvm.maximumnum.f32(float, float)
+declare double @llvm.maximumnum.f64(double, double)
+declare float @llvm.minimumnum.f32(float, float)
+declare double @llvm.minimumnum.f64(double, double)
+
+define dso_local float @maxf_nzero(float nofpclass(nzero snan) noundef %a, float nofpclass(nzero snan) noundef %b) local_unnamed_addr #0 {
+; SSE2-LABEL: maxf_nzero:
+; SSE2: # %bb.0: # %entry
+; SSE2-NEXT: movaps %xmm0, %xmm2
+; SSE2-NEXT: cmpunordss %xmm0, %xmm2
+; SSE2-NEXT: movaps %xmm2, %xmm3
+; SSE2-NEXT: andps %xmm1, %xmm3
+; SSE2-NEXT: andnps %xmm0, %xmm2
+; SSE2-NEXT: orps %xmm3, %xmm2
+; SSE2-NEXT: movaps %xmm1, %xmm3
+; SSE2-NEXT: cmpunordss %xmm1, %xmm3
+; SSE2-NEXT: movaps %xmm3, %xmm0
+; SSE2-NEXT: andps %xmm2, %xmm0
+; SSE2-NEXT: andnps %xmm1, %xmm3
+; SSE2-NEXT: orps %xmm0, %xmm3
+; SSE2-NEXT: movaps %xmm3, %xmm0
+; SSE2-NEXT: cmpltss %xmm2, %xmm0
+; SSE2-NEXT: andps %xmm0, %xmm2
+; SSE2-NEXT: andnps %xmm3, %xmm0
+; SSE2-NEXT: orps %xmm2, %xmm0
+; SSE2-NEXT: retq
+;
+; AVX-LABEL: maxf_nzero:
+; AVX: # %bb.0: # %entry
+; AVX-NEXT: vcmpunordss %xmm0, %xmm0, %xmm2
+; AVX-NEXT: vblendvps %xmm2, %xmm1, %xmm0, %xmm0
+; AVX-NEXT: vcmpunordss %xmm1, %xmm1, %xmm2
+; AVX-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm1
+; AVX-NEXT: vcmpltss %xmm0, %xmm1, %xmm2
+; AVX-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm0
+; AVX-NEXT: retq
+;
+; X86-LABEL: maxf_nzero:
+; X86: # %bb.0: # %entry
+; X86-NEXT: flds {{[0-9]+}}(%esp)
+; X86-NEXT: flds {{[0-9]+}}(%esp)
+; X86-NEXT: fucom %st(0)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: fld %st(1)
+; X86-NEXT: jp .LBB0_2
+; X86-NEXT: # %bb.1: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB0_2: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: fucom %st(0)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: fld %st(1)
+; X86-NEXT: jp .LBB0_4
+; X86-NEXT: # %bb.3: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB0_4: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: fucom %st(1)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: ja .LBB0_6
+; X86-NEXT: # %bb.5: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB0_6: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: retl
+;
+; X86AVX-LABEL: maxf_nzero:
+; X86AVX: # %bb.0: # %entry
+; X86AVX-NEXT: pushl %eax
+; X86AVX-NEXT: .cfi_def_cfa_offset 8
+; X86AVX-NEXT: vmovss {{.*#+}} xmm0 = mem[0],zero,zero,zero
+; X86AVX-NEXT: vmovss {{.*#+}} xmm1 = mem[0],zero,zero,zero
+; X86AVX-NEXT: vcmpunordss %xmm0, %xmm0, %xmm2
+; X86AVX-NEXT: vblendvps %xmm2, %xmm1, %xmm0, %xmm0
+; X86AVX-NEXT: vcmpunordss %xmm1, %xmm1, %xmm2
+; X86AVX-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm1
+; X86AVX-NEXT: vcmpltss %xmm0, %xmm1, %xmm2
+; X86AVX-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm0
+; X86AVX-NEXT: vmovss %xmm0, (%esp)
+; X86AVX-NEXT: flds (%esp)
+; X86AVX-NEXT: popl %eax
+; X86AVX-NEXT: .cfi_def_cfa_offset 4
+; X86AVX-NEXT: retl
+entry:
+ %cond = tail call float @llvm.maximumnum.f32(float %a, float %b)
+ ret float %cond
+}
+
+define dso_local float @maxf_pzero(float nofpclass(pzero snan) noundef %a, float nofpclass(pzero snan) noundef %b) local_unnamed_addr #0 {
+; SSE2-LABEL: maxf_pzero:
+; SSE2: # %bb.0: # %entry
+; SSE2-NEXT: movaps %xmm0, %xmm2
+; SSE2-NEXT: cmpunordss %xmm0, %xmm2
+; SSE2-NEXT: movaps %xmm2, %xmm3
+; SSE2-NEXT: andps %xmm1, %xmm3
+; SSE2-NEXT: andnps %xmm0, %xmm2
+; SSE2-NEXT: orps %xmm3, %xmm2
+; SSE2-NEXT: movaps %xmm1, %xmm3
+; SSE2-NEXT: cmpunordss %xmm1, %xmm3
+; SSE2-NEXT: movaps %xmm3, %xmm0
+; SSE2-NEXT: andps %xmm2, %xmm0
+; SSE2-NEXT: andnps %xmm1, %xmm3
+; SSE2-NEXT: orps %xmm0, %xmm3
+; SSE2-NEXT: movaps %xmm3, %xmm0
+; SSE2-NEXT: cmpltss %xmm2, %xmm0
+; SSE2-NEXT: andps %xmm0, %xmm2
+; SSE2-NEXT: andnps %xmm3, %xmm0
+; SSE2-NEXT: orps %xmm2, %xmm0
+; SSE2-NEXT: retq
+;
+; AVX-LABEL: maxf_pzero:
+; AVX: # %bb.0: # %entry
+; AVX-NEXT: vcmpunordss %xmm0, %xmm0, %xmm2
+; AVX-NEXT: vblendvps %xmm2, %xmm1, %xmm0, %xmm0
+; AVX-NEXT: vcmpunordss %xmm1, %xmm1, %xmm2
+; AVX-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm1
+; AVX-NEXT: vcmpltss %xmm0, %xmm1, %xmm2
+; AVX-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm0
+; AVX-NEXT: retq
+;
+; X86-LABEL: maxf_pzero:
+; X86: # %bb.0: # %entry
+; X86-NEXT: flds {{[0-9]+}}(%esp)
+; X86-NEXT: flds {{[0-9]+}}(%esp)
+; X86-NEXT: fucom %st(0)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: fld %st(1)
+; X86-NEXT: jp .LBB1_2
+; X86-NEXT: # %bb.1: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB1_2: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: fucom %st(0)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: fld %st(1)
+; X86-NEXT: jp .LBB1_4
+; X86-NEXT: # %bb.3: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB1_4: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: fucom %st(1)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: ja .LBB1_6
+; X86-NEXT: # %bb.5: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB1_6: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: retl
+;
+; X86AVX-LABEL: maxf_pzero:
+; X86AVX: # %bb.0: # %entry
+; X86AVX-NEXT: pushl %eax
+; X86AVX-NEXT: .cfi_def_cfa_offset 8
+; X86AVX-NEXT: vmovss {{.*#+}} xmm0 = mem[0],zero,zero,zero
+; X86AVX-NEXT: vmovss {{.*#+}} xmm1 = mem[0],zero,zero,zero
+; X86AVX-NEXT: vcmpunordss %xmm0, %xmm0, %xmm2
+; X86AVX-NEXT: vblendvps %xmm2, %xmm1, %xmm0, %xmm0
+; X86AVX-NEXT: vcmpunordss %xmm1, %xmm1, %xmm2
+; X86AVX-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm1
+; X86AVX-NEXT: vcmpltss %xmm0, %xmm1, %xmm2
+; X86AVX-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm0
+; X86AVX-NEXT: vmovss %xmm0, (%esp)
+; X86AVX-NEXT: flds (%esp)
+; X86AVX-NEXT: popl %eax
+; X86AVX-NEXT: .cfi_def_cfa_offset 4
+; X86AVX-NEXT: retl
+entry:
+ %cond = tail call float @llvm.maximumnum.f32(float %a, float %b)
+ ret float %cond
+}
+
+define dso_local float @maxf_zero(float nofpclass(zero snan) noundef %a, float nofpclass(zero snan) noundef %b) local_unnamed_addr #0 {
+; SSE2-LABEL: maxf_zero:
+; SSE2: # %bb.0: # %entry
+; SSE2-NEXT: movaps %xmm0, %xmm2
+; SSE2-NEXT: cmpunordss %xmm0, %xmm2
+; SSE2-NEXT: movaps %xmm2, %xmm3
+; SSE2-NEXT: andps %xmm1, %xmm3
+; SSE2-NEXT: andnps %xmm0, %xmm2
+; SSE2-NEXT: orps %xmm3, %xmm2
+; SSE2-NEXT: movaps %xmm1, %xmm3
+; SSE2-NEXT: cmpunordss %xmm1, %xmm3
+; SSE2-NEXT: movaps %xmm3, %xmm0
+; SSE2-NEXT: andps %xmm2, %xmm0
+; SSE2-NEXT: andnps %xmm1, %xmm3
+; SSE2-NEXT: orps %xmm0, %xmm3
+; SSE2-NEXT: movaps %xmm3, %xmm0
+; SSE2-NEXT: cmpltss %xmm2, %xmm0
+; SSE2-NEXT: andps %xmm0, %xmm2
+; SSE2-NEXT: andnps %xmm3, %xmm0
+; SSE2-NEXT: orps %xmm2, %xmm0
+; SSE2-NEXT: retq
+;
+; AVX-LABEL: maxf_zero:
+; AVX: # %bb.0: # %entry
+; AVX-NEXT: vcmpunordss %xmm0, %xmm0, %xmm2
+; AVX-NEXT: vblendvps %xmm2, %xmm1, %xmm0, %xmm0
+; AVX-NEXT: vcmpunordss %xmm1, %xmm1, %xmm2
+; AVX-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm1
+; AVX-NEXT: vcmpltss %xmm0, %xmm1, %xmm2
+; AVX-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm0
+; AVX-NEXT: retq
+;
+; X86-LABEL: maxf_zero:
+; X86: # %bb.0: # %entry
+; X86-NEXT: flds {{[0-9]+}}(%esp)
+; X86-NEXT: flds {{[0-9]+}}(%esp)
+; X86-NEXT: fucom %st(0)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: fld %st(1)
+; X86-NEXT: jp .LBB2_2
+; X86-NEXT: # %bb.1: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB2_2: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: fucom %st(0)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: fld %st(1)
+; X86-NEXT: jp .LBB2_4
+; X86-NEXT: # %bb.3: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB2_4: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: fucom %st(1)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: ja .LBB2_6
+; X86-NEXT: # %bb.5: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB2_6: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: retl
+;
+; X86AVX-LABEL: maxf_zero:
+; X86AVX: # %bb.0: # %entry
+; X86AVX-NEXT: pushl %eax
+; X86AVX-NEXT: .cfi_def_cfa_offset 8
+; X86AVX-NEXT: vmovss {{.*#+}} xmm0 = mem[0],zero,zero,zero
+; X86AVX-NEXT: vmovss {{.*#+}} xmm1 = mem[0],zero,zero,zero
+; X86AVX-NEXT: vcmpunordss %xmm0, %xmm0, %xmm2
+; X86AVX-NEXT: vblendvps %xmm2, %xmm1, %xmm0, %xmm0
+; X86AVX-NEXT: vcmpunordss %xmm1, %xmm1, %xmm2
+; X86AVX-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm1
+; X86AVX-NEXT: vcmpltss %xmm0, %xmm1, %xmm2
+; X86AVX-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm0
+; X86AVX-NEXT: vmovss %xmm0, (%esp)
+; X86AVX-NEXT: flds (%esp)
+; X86AVX-NEXT: popl %eax
+; X86AVX-NEXT: .cfi_def_cfa_offset 4
+; X86AVX-NEXT: retl
+entry:
+ %cond = tail call float @llvm.maximumnum.f32(float %a, float %b)
+ ret float %cond
+}
+
+define dso_local double @maxd_nzero(double nofpclass(nzero snan) noundef %a, double nofpclass(nzero snan) noundef %b) local_unnamed_addr #0 {
+; SSE2-LABEL: maxd_nzero:
+; SSE2: # %bb.0: # %entry
+; SSE2-NEXT: movapd %xmm0, %xmm2
+; SSE2-NEXT: cmpunordsd %xmm0, %xmm2
+; SSE2-NEXT: movapd %xmm2, %xmm3
+; SSE2-NEXT: andpd %xmm1, %xmm3
+; SSE2-NEXT: andnpd %xmm0, %xmm2
+; SSE2-NEXT: orpd %xmm3, %xmm2
+; SSE2-NEXT: movapd %xmm1, %xmm3
+; SSE2-NEXT: cmpunordsd %xmm1, %xmm3
+; SSE2-NEXT: movapd %xmm3, %xmm0
+; SSE2-NEXT: andpd %xmm2, %xmm0
+; SSE2-NEXT: andnpd %xmm1, %xmm3
+; SSE2-NEXT: orpd %xmm0, %xmm3
+; SSE2-NEXT: movapd %xmm3, %xmm0
+; SSE2-NEXT: cmpltsd %xmm2, %xmm0
+; SSE2-NEXT: andpd %xmm0, %xmm2
+; SSE2-NEXT: andnpd %xmm3, %xmm0
+; SSE2-NEXT: orpd %xmm2, %xmm0
+; SSE2-NEXT: retq
+;
+; AVX-LABEL: maxd_nzero:
+; AVX: # %bb.0: # %entry
+; AVX-NEXT: vcmpunordsd %xmm0, %xmm0, %xmm2
+; AVX-NEXT: vblendvpd %xmm2, %xmm1, %xmm0, %xmm0
+; AVX-NEXT: vcmpunordsd %xmm1, %xmm1, %xmm2
+; AVX-NEXT: vblendvpd %xmm2, %xmm0, %xmm1, %xmm1
+; AVX-NEXT: vcmpltsd %xmm0, %xmm1, %xmm2
+; AVX-NEXT: vblendvpd %xmm2, %xmm0, %xmm1, %xmm0
+; AVX-NEXT: retq
+;
+; X86-LABEL: maxd_nzero:
+; X86: # %bb.0: # %entry
+; X86-NEXT: fldl {{[0-9]+}}(%esp)
+; X86-NEXT: fldl {{[0-9]+}}(%esp)
+; X86-NEXT: fucom %st(0)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: fld %st(1)
+; X86-NEXT: jp .LBB3_2
+; X86-NEXT: # %bb.1: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB3_2: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: fucom %st(0)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: fld %st(1)
+; X86-NEXT: jp .LBB3_4
+; X86-NEXT: # %bb.3: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB3_4: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: fucom %st(1)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: ja .LBB3_6
+; X86-NEXT: # %bb.5: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB3_6: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: retl
+;
+; X86AVX-LABEL: maxd_nzero:
+; X86AVX: # %bb.0: # %entry
+; X86AVX-NEXT: pushl %ebp
+; X86AVX-NEXT: .cfi_def_cfa_offset 8
+; X86AVX-NEXT: .cfi_offset %ebp, -8
+; X86AVX-NEXT: movl %esp, %ebp
+; X86AVX-NEXT: .cfi_def_cfa_register %ebp
+; X86AVX-NEXT: andl $-8, %esp
+; X86AVX-NEXT: subl $8, %esp
+; X86AVX-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
+; X86AVX-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero
+; X86AVX-NEXT: vcmpunordsd %xmm0, %xmm0, %xmm2
+; X86AVX-NEXT: vblendvpd %xmm2, %xmm1, %xmm0, %xmm0
+; X86AVX-NEXT: vcmpunordsd %xmm1, %xmm1, %xmm2
+; X86AVX-NEXT: vblendvpd %xmm2, %xmm0, %xmm1, %xmm1
+; X86AVX-NEXT: vcmpltsd %xmm0, %xmm1, %xmm2
+; X86AVX-NEXT: vblendvpd %xmm2, %xmm0, %xmm1, %xmm0
+; X86AVX-NEXT: vmovlpd %xmm0, (%esp)
+; X86AVX-NEXT: fldl (%esp)
+; X86AVX-NEXT: movl %ebp, %esp
+; X86AVX-NEXT: popl %ebp
+; X86AVX-NEXT: .cfi_def_cfa %esp, 4
+; X86AVX-NEXT: retl
+entry:
+ %cond = tail call double @llvm.maximumnum.f64(double %a, double %b)
+ ret double %cond
+}
+
+define dso_local double @maxd_pzero(double nofpclass(pzero snan) noundef %a, double nofpclass(pzero snan) noundef %b) local_unnamed_addr #0 {
+; SSE2-LABEL: maxd_pzero:
+; SSE2: # %bb.0: # %entry
+; SSE2-NEXT: movapd %xmm0, %xmm2
+; SSE2-NEXT: cmpunordsd %xmm0, %xmm2
+; SSE2-NEXT: movapd %xmm2, %xmm3
+; SSE2-NEXT: andpd %xmm1, %xmm3
+; SSE2-NEXT: andnpd %xmm0, %xmm2
+; SSE2-NEXT: orpd %xmm3, %xmm2
+; SSE2-NEXT: movapd %xmm1, %xmm3
+; SSE2-NEXT: cmpunordsd %xmm1, %xmm3
+; SSE2-NEXT: movapd %xmm3, %xmm0
+; SSE2-NEXT: andpd %xmm2, %xmm0
+; SSE2-NEXT: andnpd %xmm1, %xmm3
+; SSE2-NEXT: orpd %xmm0, %xmm3
+; SSE2-NEXT: movapd %xmm3, %xmm0
+; SSE2-NEXT: cmpltsd %xmm2, %xmm0
+; SSE2-NEXT: andpd %xmm0, %xmm2
+; SSE2-NEXT: andnpd %xmm3, %xmm0
+; SSE2-NEXT: orpd %xmm2, %xmm0
+; SSE2-NEXT: retq
+;
+; AVX-LABEL: maxd_pzero:
+; AVX: # %bb.0: # %entry
+; AVX-NEXT: vcmpunordsd %xmm0, %xmm0, %xmm2
+; AVX-NEXT: vblendvpd %xmm2, %xmm1, %xmm0, %xmm0
+; AVX-NEXT: vcmpunordsd %xmm1, %xmm1, %xmm2
+; AVX-NEXT: vblendvpd %xmm2, %xmm0, %xmm1, %xmm1
+; AVX-NEXT: vcmpltsd %xmm0, %xmm1, %xmm2
+; AVX-NEXT: vblendvpd %xmm2, %xmm0, %xmm1, %xmm0
+; AVX-NEXT: retq
+;
+; X86-LABEL: maxd_pzero:
+; X86: # %bb.0: # %entry
+; X86-NEXT: fldl {{[0-9]+}}(%esp)
+; X86-NEXT: fldl {{[0-9]+}}(%esp)
+; X86-NEXT: fucom %st(0)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: fld %st(1)
+; X86-NEXT: jp .LBB4_2
+; X86-NEXT: # %bb.1: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB4_2: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: fucom %st(0)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: fld %st(1)
+; X86-NEXT: jp .LBB4_4
+; X86-NEXT: # %bb.3: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB4_4: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: fucom %st(1)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: ja .LBB4_6
+; X86-NEXT: # %bb.5: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB4_6: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: retl
+;
+; X86AVX-LABEL: maxd_pzero:
+; X86AVX: # %bb.0: # %entry
+; X86AVX-NEXT: pushl %ebp
+; X86AVX-NEXT: .cfi_def_cfa_offset 8
+; X86AVX-NEXT: .cfi_offset %ebp, -8
+; X86AVX-NEXT: movl %esp, %ebp
+; X86AVX-NEXT: .cfi_def_cfa_register %ebp
+; X86AVX-NEXT: andl $-8, %esp
+; X86AVX-NEXT: subl $8, %esp
+; X86AVX-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
+; X86AVX-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero
+; X86AVX-NEXT: vcmpunordsd %xmm0, %xmm0, %xmm2
+; X86AVX-NEXT: vblendvpd %xmm2, %xmm1, %xmm0, %xmm0
+; X86AVX-NEXT: vcmpunordsd %xmm1, %xmm1, %xmm2
+; X86AVX-NEXT: vblendvpd %xmm2, %xmm0, %xmm1, %xmm1
+; X86AVX-NEXT: vcmpltsd %xmm0, %xmm1, %xmm2
+; X86AVX-NEXT: vblendvpd %xmm2, %xmm0, %xmm1, %xmm0
+; X86AVX-NEXT: vmovlpd %xmm0, (%esp)
+; X86AVX-NEXT: fldl (%esp)
+; X86AVX-NEXT: movl %ebp, %esp
+; X86AVX-NEXT: popl %ebp
+; X86AVX-NEXT: .cfi_def_cfa %esp, 4
+; X86AVX-NEXT: retl
+entry:
+ %cond = tail call double @llvm.maximumnum.f64(double %a, double %b)
+ ret double %cond
+}
+
+define dso_local double @maxd_zero(double nofpclass(zero snan) noundef %a, double nofpclass(zero snan) noundef %b) local_unnamed_addr #0 {
+; SSE2-LABEL: maxd_zero:
+; SSE2: # %bb.0: # %entry
+; SSE2-NEXT: movapd %xmm0, %xmm2
+; SSE2-NEXT: cmpunordsd %xmm0, %xmm2
+; SSE2-NEXT: movapd %xmm2, %xmm3
+; SSE2-NEXT: andpd %xmm1, %xmm3
+; SSE2-NEXT: andnpd %xmm0, %xmm2
+; SSE2-NEXT: orpd %xmm3, %xmm2
+; SSE2-NEXT: movapd %xmm1, %xmm3
+; SSE2-NEXT: cmpunordsd %xmm1, %xmm3
+; SSE2-NEXT: movapd %xmm3, %xmm0
+; SSE2-NEXT: andpd %xmm2, %xmm0
+; SSE2-NEXT: andnpd %xmm1, %xmm3
+; SSE2-NEXT: orpd %xmm0, %xmm3
+; SSE2-NEXT: movapd %xmm3, %xmm0
+; SSE2-NEXT: cmpltsd %xmm2, %xmm0
+; SSE2-NEXT: andpd %xmm0, %xmm2
+; SSE2-NEXT: andnpd %xmm3, %xmm0
+; SSE2-NEXT: orpd %xmm2, %xmm0
+; SSE2-NEXT: retq
+;
+; AVX-LABEL: maxd_zero:
+; AVX: # %bb.0: # %entry
+; AVX-NEXT: vcmpunordsd %xmm0, %xmm0, %xmm2
+; AVX-NEXT: vblendvpd %xmm2, %xmm1, %xmm0, %xmm0
+; AVX-NEXT: vcmpunordsd %xmm1, %xmm1, %xmm2
+; AVX-NEXT: vblendvpd %xmm2, %xmm0, %xmm1, %xmm1
+; AVX-NEXT: vcmpltsd %xmm0, %xmm1, %xmm2
+; AVX-NEXT: vblendvpd %xmm2, %xmm0, %xmm1, %xmm0
+; AVX-NEXT: retq
+;
+; X86-LABEL: maxd_zero:
+; X86: # %bb.0: # %entry
+; X86-NEXT: fldl {{[0-9]+}}(%esp)
+; X86-NEXT: fldl {{[0-9]+}}(%esp)
+; X86-NEXT: fucom %st(0)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: fld %st(1)
+; X86-NEXT: jp .LBB5_2
+; X86-NEXT: # %bb.1: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB5_2: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: fucom %st(0)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: fld %st(1)
+; X86-NEXT: jp .LBB5_4
+; X86-NEXT: # %bb.3: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB5_4: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: fucom %st(1)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: ja .LBB5_6
+; X86-NEXT: # %bb.5: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB5_6: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: retl
+;
+; X86AVX-LABEL: maxd_zero:
+; X86AVX: # %bb.0: # %entry
+; X86AVX-NEXT: pushl %ebp
+; X86AVX-NEXT: .cfi_def_cfa_offset 8
+; X86AVX-NEXT: .cfi_offset %ebp, -8
+; X86AVX-NEXT: movl %esp, %ebp
+; X86AVX-NEXT: .cfi_def_cfa_register %ebp
+; X86AVX-NEXT: andl $-8, %esp
+; X86AVX-NEXT: subl $8, %esp
+; X86AVX-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
+; X86AVX-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero
+; X86AVX-NEXT: vcmpunordsd %xmm0, %xmm0, %xmm2
+; X86AVX-NEXT: vblendvpd %xmm2, %xmm1, %xmm0, %xmm0
+; X86AVX-NEXT: vcmpunordsd %xmm1, %xmm1, %xmm2
+; X86AVX-NEXT: vblendvpd %xmm2, %xmm0, %xmm1, %xmm1
+; X86AVX-NEXT: vcmpltsd %xmm0, %xmm1, %xmm2
+; X86AVX-NEXT: vblendvpd %xmm2, %xmm0, %xmm1, %xmm0
+; X86AVX-NEXT: vmovlpd %xmm0, (%esp)
+; X86AVX-NEXT: fldl (%esp)
+; X86AVX-NEXT: movl %ebp, %esp
+; X86AVX-NEXT: popl %ebp
+; X86AVX-NEXT: .cfi_def_cfa %esp, 4
+; X86AVX-NEXT: retl
+entry:
+ %cond = tail call double @llvm.maximumnum.f64(double %a, double %b)
+ ret double %cond
+}
+
+define dso_local float @minf_nzero(float nofpclass(nzero snan) noundef %a, float nofpclass(nzero snan) noundef %b) local_unnamed_addr #0 {
+; SSE2-LABEL: minf_nzero:
+; SSE2: # %bb.0: # %entry
+; SSE2-NEXT: movaps %xmm0, %xmm2
+; SSE2-NEXT: cmpunordss %xmm0, %xmm2
+; SSE2-NEXT: movaps %xmm2, %xmm3
+; SSE2-NEXT: andps %xmm1, %xmm3
+; SSE2-NEXT: andnps %xmm0, %xmm2
+; SSE2-NEXT: orps %xmm3, %xmm2
+; SSE2-NEXT: movaps %xmm1, %xmm3
+; SSE2-NEXT: cmpunordss %xmm1, %xmm3
+; SSE2-NEXT: movaps %xmm3, %xmm0
+; SSE2-NEXT: andps %xmm2, %xmm0
+; SSE2-NEXT: andnps %xmm1, %xmm3
+; SSE2-NEXT: orps %xmm0, %xmm3
+; SSE2-NEXT: movaps %xmm2, %xmm0
+; SSE2-NEXT: cmpltss %xmm3, %xmm0
+; SSE2-NEXT: andps %xmm0, %xmm2
+; SSE2-NEXT: andnps %xmm3, %xmm0
+; SSE2-NEXT: orps %xmm2, %xmm0
+; SSE2-NEXT: retq
+;
+; AVX-LABEL: minf_nzero:
+; AVX: # %bb.0: # %entry
+; AVX-NEXT: vcmpunordss %xmm0, %xmm0, %xmm2
+; AVX-NEXT: vblendvps %xmm2, %xmm1, %xmm0, %xmm0
+; AVX-NEXT: vcmpunordss %xmm1, %xmm1, %xmm2
+; AVX-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm1
+; AVX-NEXT: vcmpltss %xmm1, %xmm0, %xmm2
+; AVX-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm0
+; AVX-NEXT: retq
+;
+; X86-LABEL: minf_nzero:
+; X86: # %bb.0: # %entry
+; X86-NEXT: flds {{[0-9]+}}(%esp)
+; X86-NEXT: flds {{[0-9]+}}(%esp)
+; X86-NEXT: fucom %st(0)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: fld %st(1)
+; X86-NEXT: jp .LBB6_2
+; X86-NEXT: # %bb.1: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB6_2: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: fucom %st(0)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: fld %st(1)
+; X86-NEXT: jp .LBB6_4
+; X86-NEXT: # %bb.3: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB6_4: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: fucom %st(1)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: jb .LBB6_6
+; X86-NEXT: # %bb.5: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB6_6: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: retl
+;
+; X86AVX-LABEL: minf_nzero:
+; X86AVX: # %bb.0: # %entry
+; X86AVX-NEXT: pushl %eax
+; X86AVX-NEXT: .cfi_def_cfa_offset 8
+; X86AVX-NEXT: vmovss {{.*#+}} xmm0 = mem[0],zero,zero,zero
+; X86AVX-NEXT: vmovss {{.*#+}} xmm1 = mem[0],zero,zero,zero
+; X86AVX-NEXT: vcmpunordss %xmm0, %xmm0, %xmm2
+; X86AVX-NEXT: vblendvps %xmm2, %xmm1, %xmm0, %xmm0
+; X86AVX-NEXT: vcmpunordss %xmm1, %xmm1, %xmm2
+; X86AVX-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm1
+; X86AVX-NEXT: vcmpltss %xmm1, %xmm0, %xmm2
+; X86AVX-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm0
+; X86AVX-NEXT: vmovss %xmm0, (%esp)
+; X86AVX-NEXT: flds (%esp)
+; X86AVX-NEXT: popl %eax
+; X86AVX-NEXT: .cfi_def_cfa_offset 4
+; X86AVX-NEXT: retl
+entry:
+ %cond = tail call float @llvm.minimumnum.f32(float %a, float %b)
+ ret float %cond
+}
+
+define dso_local float @minf_pzero(float nofpclass(pzero snan) noundef %a, float nofpclass(pzero snan) noundef %b) local_unnamed_addr #0 {
+; SSE2-LABEL: minf_pzero:
+; SSE2: # %bb.0: # %entry
+; SSE2-NEXT: movaps %xmm0, %xmm2
+; SSE2-NEXT: cmpunordss %xmm0, %xmm2
+; SSE2-NEXT: movaps %xmm2, %xmm3
+; SSE2-NEXT: andps %xmm1, %xmm3
+; SSE2-NEXT: andnps %xmm0, %xmm2
+; SSE2-NEXT: orps %xmm3, %xmm2
+; SSE2-NEXT: movaps %xmm1, %xmm3
+; SSE2-NEXT: cmpunordss %xmm1, %xmm3
+; SSE2-NEXT: movaps %xmm3, %xmm0
+; SSE2-NEXT: andps %xmm2, %xmm0
+; SSE2-NEXT: andnps %xmm1, %xmm3
+; SSE2-NEXT: orps %xmm0, %xmm3
+; SSE2-NEXT: movaps %xmm2, %xmm0
+; SSE2-NEXT: cmpltss %xmm3, %xmm0
+; SSE2-NEXT: andps %xmm0, %xmm2
+; SSE2-NEXT: andnps %xmm3, %xmm0
+; SSE2-NEXT: orps %xmm2, %xmm0
+; SSE2-NEXT: retq
+;
+; AVX-LABEL: minf_pzero:
+; AVX: # %bb.0: # %entry
+; AVX-NEXT: vcmpunordss %xmm0, %xmm0, %xmm2
+; AVX-NEXT: vblendvps %xmm2, %xmm1, %xmm0, %xmm0
+; AVX-NEXT: vcmpunordss %xmm1, %xmm1, %xmm2
+; AVX-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm1
+; AVX-NEXT: vcmpltss %xmm1, %xmm0, %xmm2
+; AVX-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm0
+; AVX-NEXT: retq
+;
+; X86-LABEL: minf_pzero:
+; X86: # %bb.0: # %entry
+; X86-NEXT: flds {{[0-9]+}}(%esp)
+; X86-NEXT: flds {{[0-9]+}}(%esp)
+; X86-NEXT: fucom %st(0)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: fld %st(1)
+; X86-NEXT: jp .LBB7_2
+; X86-NEXT: # %bb.1: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB7_2: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: fucom %st(0)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: fld %st(1)
+; X86-NEXT: jp .LBB7_4
+; X86-NEXT: # %bb.3: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB7_4: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: fucom %st(1)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: jb .LBB7_6
+; X86-NEXT: # %bb.5: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB7_6: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: retl
+;
+; X86AVX-LABEL: minf_pzero:
+; X86AVX: # %bb.0: # %entry
+; X86AVX-NEXT: pushl %eax
+; X86AVX-NEXT: .cfi_def_cfa_offset 8
+; X86AVX-NEXT: vmovss {{.*#+}} xmm0 = mem[0],zero,zero,zero
+; X86AVX-NEXT: vmovss {{.*#+}} xmm1 = mem[0],zero,zero,zero
+; X86AVX-NEXT: vcmpunordss %xmm0, %xmm0, %xmm2
+; X86AVX-NEXT: vblendvps %xmm2, %xmm1, %xmm0, %xmm0
+; X86AVX-NEXT: vcmpunordss %xmm1, %xmm1, %xmm2
+; X86AVX-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm1
+; X86AVX-NEXT: vcmpltss %xmm1, %xmm0, %xmm2
+; X86AVX-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm0
+; X86AVX-NEXT: vmovss %xmm0, (%esp)
+; X86AVX-NEXT: flds (%esp)
+; X86AVX-NEXT: popl %eax
+; X86AVX-NEXT: .cfi_def_cfa_offset 4
+; X86AVX-NEXT: retl
+entry:
+ %cond = tail call float @llvm.minimumnum.f32(float %a, float %b)
+ ret float %cond
+}
+
+define dso_local float @minf_zero(float nofpclass(zero snan) noundef %a, float nofpclass(zero snan) noundef %b) local_unnamed_addr #0 {
+; SSE2-LABEL: minf_zero:
+; SSE2: # %bb.0: # %entry
+; SSE2-NEXT: movaps %xmm0, %xmm2
+; SSE2-NEXT: cmpunordss %xmm0, %xmm2
+; SSE2-NEXT: movaps %xmm2, %xmm3
+; SSE2-NEXT: andps %xmm1, %xmm3
+; SSE2-NEXT: andnps %xmm0, %xmm2
+; SSE2-NEXT: orps %xmm3, %xmm2
+; SSE2-NEXT: movaps %xmm1, %xmm3
+; SSE2-NEXT: cmpunordss %xmm1, %xmm3
+; SSE2-NEXT: movaps %xmm3, %xmm0
+; SSE2-NEXT: andps %xmm2, %xmm0
+; SSE2-NEXT: andnps %xmm1, %xmm3
+; SSE2-NEXT: orps %xmm0, %xmm3
+; SSE2-NEXT: movaps %xmm2, %xmm0
+; SSE2-NEXT: cmpltss %xmm3, %xmm0
+; SSE2-NEXT: andps %xmm0, %xmm2
+; SSE2-NEXT: andnps %xmm3, %xmm0
+; SSE2-NEXT: orps %xmm2, %xmm0
+; SSE2-NEXT: retq
+;
+; AVX-LABEL: minf_zero:
+; AVX: # %bb.0: # %entry
+; AVX-NEXT: vcmpunordss %xmm0, %xmm0, %xmm2
+; AVX-NEXT: vblendvps %xmm2, %xmm1, %xmm0, %xmm0
+; AVX-NEXT: vcmpunordss %xmm1, %xmm1, %xmm2
+; AVX-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm1
+; AVX-NEXT: vcmpltss %xmm1, %xmm0, %xmm2
+; AVX-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm0
+; AVX-NEXT: retq
+;
+; X86-LABEL: minf_zero:
+; X86: # %bb.0: # %entry
+; X86-NEXT: flds {{[0-9]+}}(%esp)
+; X86-NEXT: flds {{[0-9]+}}(%esp)
+; X86-NEXT: fucom %st(0)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: fld %st(1)
+; X86-NEXT: jp .LBB8_2
+; X86-NEXT: # %bb.1: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB8_2: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: fucom %st(0)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: fld %st(1)
+; X86-NEXT: jp .LBB8_4
+; X86-NEXT: # %bb.3: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB8_4: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: fucom %st(1)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: jb .LBB8_6
+; X86-NEXT: # %bb.5: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB8_6: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: retl
+;
+; X86AVX-LABEL: minf_zero:
+; X86AVX: # %bb.0: # %entry
+; X86AVX-NEXT: pushl %eax
+; X86AVX-NEXT: .cfi_def_cfa_offset 8
+; X86AVX-NEXT: vmovss {{.*#+}} xmm0 = mem[0],zero,zero,zero
+; X86AVX-NEXT: vmovss {{.*#+}} xmm1 = mem[0],zero,zero,zero
+; X86AVX-NEXT: vcmpunordss %xmm0, %xmm0, %xmm2
+; X86AVX-NEXT: vblendvps %xmm2, %xmm1, %xmm0, %xmm0
+; X86AVX-NEXT: vcmpunordss %xmm1, %xmm1, %xmm2
+; X86AVX-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm1
+; X86AVX-NEXT: vcmpltss %xmm1, %xmm0, %xmm2
+; X86AVX-NEXT: vblendvps %xmm2, %xmm0, %xmm1, %xmm0
+; X86AVX-NEXT: vmovss %xmm0, (%esp)
+; X86AVX-NEXT: flds (%esp)
+; X86AVX-NEXT: popl %eax
+; X86AVX-NEXT: .cfi_def_cfa_offset 4
+; X86AVX-NEXT: retl
+entry:
+ %cond = tail call float @llvm.minimumnum.f32(float %a, float %b)
+ ret float %cond
+}
+
+define dso_local double @mind_nzero(double nofpclass(nzero snan) noundef %a, double nofpclass(nzero snan) noundef %b) local_unnamed_addr #0 {
+; SSE2-LABEL: mind_nzero:
+; SSE2: # %bb.0: # %entry
+; SSE2-NEXT: movapd %xmm0, %xmm2
+; SSE2-NEXT: cmpunordsd %xmm0, %xmm2
+; SSE2-NEXT: movapd %xmm2, %xmm3
+; SSE2-NEXT: andpd %xmm1, %xmm3
+; SSE2-NEXT: andnpd %xmm0, %xmm2
+; SSE2-NEXT: orpd %xmm3, %xmm2
+; SSE2-NEXT: movapd %xmm1, %xmm3
+; SSE2-NEXT: cmpunordsd %xmm1, %xmm3
+; SSE2-NEXT: movapd %xmm3, %xmm0
+; SSE2-NEXT: andpd %xmm2, %xmm0
+; SSE2-NEXT: andnpd %xmm1, %xmm3
+; SSE2-NEXT: orpd %xmm0, %xmm3
+; SSE2-NEXT: movapd %xmm2, %xmm0
+; SSE2-NEXT: cmpltsd %xmm3, %xmm0
+; SSE2-NEXT: andpd %xmm0, %xmm2
+; SSE2-NEXT: andnpd %xmm3, %xmm0
+; SSE2-NEXT: orpd %xmm2, %xmm0
+; SSE2-NEXT: retq
+;
+; AVX-LABEL: mind_nzero:
+; AVX: # %bb.0: # %entry
+; AVX-NEXT: vcmpunordsd %xmm0, %xmm0, %xmm2
+; AVX-NEXT: vblendvpd %xmm2, %xmm1, %xmm0, %xmm0
+; AVX-NEXT: vcmpunordsd %xmm1, %xmm1, %xmm2
+; AVX-NEXT: vblendvpd %xmm2, %xmm0, %xmm1, %xmm1
+; AVX-NEXT: vcmpltsd %xmm1, %xmm0, %xmm2
+; AVX-NEXT: vblendvpd %xmm2, %xmm0, %xmm1, %xmm0
+; AVX-NEXT: retq
+;
+; X86-LABEL: mind_nzero:
+; X86: # %bb.0: # %entry
+; X86-NEXT: fldl {{[0-9]+}}(%esp)
+; X86-NEXT: fldl {{[0-9]+}}(%esp)
+; X86-NEXT: fucom %st(0)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: fld %st(1)
+; X86-NEXT: jp .LBB9_2
+; X86-NEXT: # %bb.1: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB9_2: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: fucom %st(0)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: fld %st(1)
+; X86-NEXT: jp .LBB9_4
+; X86-NEXT: # %bb.3: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB9_4: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: fucom %st(1)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: jb .LBB9_6
+; X86-NEXT: # %bb.5: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB9_6: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: retl
+;
+; X86AVX-LABEL: mind_nzero:
+; X86AVX: # %bb.0: # %entry
+; X86AVX-NEXT: pushl %ebp
+; X86AVX-NEXT: .cfi_def_cfa_offset 8
+; X86AVX-NEXT: .cfi_offset %ebp, -8
+; X86AVX-NEXT: movl %esp, %ebp
+; X86AVX-NEXT: .cfi_def_cfa_register %ebp
+; X86AVX-NEXT: andl $-8, %esp
+; X86AVX-NEXT: subl $8, %esp
+; X86AVX-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
+; X86AVX-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero
+; X86AVX-NEXT: vcmpunordsd %xmm0, %xmm0, %xmm2
+; X86AVX-NEXT: vblendvpd %xmm2, %xmm1, %xmm0, %xmm0
+; X86AVX-NEXT: vcmpunordsd %xmm1, %xmm1, %xmm2
+; X86AVX-NEXT: vblendvpd %xmm2, %xmm0, %xmm1, %xmm1
+; X86AVX-NEXT: vcmpltsd %xmm1, %xmm0, %xmm2
+; X86AVX-NEXT: vblendvpd %xmm2, %xmm0, %xmm1, %xmm0
+; X86AVX-NEXT: vmovlpd %xmm0, (%esp)
+; X86AVX-NEXT: fldl (%esp)
+; X86AVX-NEXT: movl %ebp, %esp
+; X86AVX-NEXT: popl %ebp
+; X86AVX-NEXT: .cfi_def_cfa %esp, 4
+; X86AVX-NEXT: retl
+entry:
+ %cond = tail call double @llvm.minimumnum.f64(double %a, double %b)
+ ret double %cond
+}
+
+define dso_local double @mind_pzero(double nofpclass(pzero snan) noundef %a, double nofpclass(pzero snan) noundef %b) local_unnamed_addr #0 {
+; SSE2-LABEL: mind_pzero:
+; SSE2: # %bb.0: # %entry
+; SSE2-NEXT: movapd %xmm0, %xmm2
+; SSE2-NEXT: cmpunordsd %xmm0, %xmm2
+; SSE2-NEXT: movapd %xmm2, %xmm3
+; SSE2-NEXT: andpd %xmm1, %xmm3
+; SSE2-NEXT: andnpd %xmm0, %xmm2
+; SSE2-NEXT: orpd %xmm3, %xmm2
+; SSE2-NEXT: movapd %xmm1, %xmm3
+; SSE2-NEXT: cmpunordsd %xmm1, %xmm3
+; SSE2-NEXT: movapd %xmm3, %xmm0
+; SSE2-NEXT: andpd %xmm2, %xmm0
+; SSE2-NEXT: andnpd %xmm1, %xmm3
+; SSE2-NEXT: orpd %xmm0, %xmm3
+; SSE2-NEXT: movapd %xmm2, %xmm0
+; SSE2-NEXT: cmpltsd %xmm3, %xmm0
+; SSE2-NEXT: andpd %xmm0, %xmm2
+; SSE2-NEXT: andnpd %xmm3, %xmm0
+; SSE2-NEXT: orpd %xmm2, %xmm0
+; SSE2-NEXT: retq
+;
+; AVX-LABEL: mind_pzero:
+; AVX: # %bb.0: # %entry
+; AVX-NEXT: vcmpunordsd %xmm0, %xmm0, %xmm2
+; AVX-NEXT: vblendvpd %xmm2, %xmm1, %xmm0, %xmm0
+; AVX-NEXT: vcmpunordsd %xmm1, %xmm1, %xmm2
+; AVX-NEXT: vblendvpd %xmm2, %xmm0, %xmm1, %xmm1
+; AVX-NEXT: vcmpltsd %xmm1, %xmm0, %xmm2
+; AVX-NEXT: vblendvpd %xmm2, %xmm0, %xmm1, %xmm0
+; AVX-NEXT: retq
+;
+; X86-LABEL: mind_pzero:
+; X86: # %bb.0: # %entry
+; X86-NEXT: fldl {{[0-9]+}}(%esp)
+; X86-NEXT: fldl {{[0-9]+}}(%esp)
+; X86-NEXT: fucom %st(0)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: fld %st(1)
+; X86-NEXT: jp .LBB10_2
+; X86-NEXT: # %bb.1: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB10_2: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: fucom %st(0)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: fld %st(1)
+; X86-NEXT: jp .LBB10_4
+; X86-NEXT: # %bb.3: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB10_4: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: fucom %st(1)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: jb .LBB10_6
+; X86-NEXT: # %bb.5: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB10_6: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: retl
+;
+; X86AVX-LABEL: mind_pzero:
+; X86AVX: # %bb.0: # %entry
+; X86AVX-NEXT: pushl %ebp
+; X86AVX-NEXT: .cfi_def_cfa_offset 8
+; X86AVX-NEXT: .cfi_offset %ebp, -8
+; X86AVX-NEXT: movl %esp, %ebp
+; X86AVX-NEXT: .cfi_def_cfa_register %ebp
+; X86AVX-NEXT: andl $-8, %esp
+; X86AVX-NEXT: subl $8, %esp
+; X86AVX-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
+; X86AVX-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero
+; X86AVX-NEXT: vcmpunordsd %xmm0, %xmm0, %xmm2
+; X86AVX-NEXT: vblendvpd %xmm2, %xmm1, %xmm0, %xmm0
+; X86AVX-NEXT: vcmpunordsd %xmm1, %xmm1, %xmm2
+; X86AVX-NEXT: vblendvpd %xmm2, %xmm0, %xmm1, %xmm1
+; X86AVX-NEXT: vcmpltsd %xmm1, %xmm0, %xmm2
+; X86AVX-NEXT: vblendvpd %xmm2, %xmm0, %xmm1, %xmm0
+; X86AVX-NEXT: vmovlpd %xmm0, (%esp)
+; X86AVX-NEXT: fldl (%esp)
+; X86AVX-NEXT: movl %ebp, %esp
+; X86AVX-NEXT: popl %ebp
+; X86AVX-NEXT: .cfi_def_cfa %esp, 4
+; X86AVX-NEXT: retl
+entry:
+ %cond = tail call double @llvm.minimumnum.f64(double %a, double %b)
+ ret double %cond
+}
+
+define dso_local double @mind_zero(double nofpclass(zero snan) noundef %a, double nofpclass(zero snan) noundef %b) local_unnamed_addr #0 {
+; SSE2-LABEL: mind_zero:
+; SSE2: # %bb.0: # %entry
+; SSE2-NEXT: movapd %xmm0, %xmm2
+; SSE2-NEXT: cmpunordsd %xmm0, %xmm2
+; SSE2-NEXT: movapd %xmm2, %xmm3
+; SSE2-NEXT: andpd %xmm1, %xmm3
+; SSE2-NEXT: andnpd %xmm0, %xmm2
+; SSE2-NEXT: orpd %xmm3, %xmm2
+; SSE2-NEXT: movapd %xmm1, %xmm3
+; SSE2-NEXT: cmpunordsd %xmm1, %xmm3
+; SSE2-NEXT: movapd %xmm3, %xmm0
+; SSE2-NEXT: andpd %xmm2, %xmm0
+; SSE2-NEXT: andnpd %xmm1, %xmm3
+; SSE2-NEXT: orpd %xmm0, %xmm3
+; SSE2-NEXT: movapd %xmm2, %xmm0
+; SSE2-NEXT: cmpltsd %xmm3, %xmm0
+; SSE2-NEXT: andpd %xmm0, %xmm2
+; SSE2-NEXT: andnpd %xmm3, %xmm0
+; SSE2-NEXT: orpd %xmm2, %xmm0
+; SSE2-NEXT: retq
+;
+; AVX-LABEL: mind_zero:
+; AVX: # %bb.0: # %entry
+; AVX-NEXT: vcmpunordsd %xmm0, %xmm0, %xmm2
+; AVX-NEXT: vblendvpd %xmm2, %xmm1, %xmm0, %xmm0
+; AVX-NEXT: vcmpunordsd %xmm1, %xmm1, %xmm2
+; AVX-NEXT: vblendvpd %xmm2, %xmm0, %xmm1, %xmm1
+; AVX-NEXT: vcmpltsd %xmm1, %xmm0, %xmm2
+; AVX-NEXT: vblendvpd %xmm2, %xmm0, %xmm1, %xmm0
+; AVX-NEXT: retq
+;
+; X86-LABEL: mind_zero:
+; X86: # %bb.0: # %entry
+; X86-NEXT: fldl {{[0-9]+}}(%esp)
+; X86-NEXT: fldl {{[0-9]+}}(%esp)
+; X86-NEXT: fucom %st(0)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: fld %st(1)
+; X86-NEXT: jp .LBB11_2
+; X86-NEXT: # %bb.1: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB11_2: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: fucom %st(0)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: fld %st(1)
+; X86-NEXT: jp .LBB11_4
+; X86-NEXT: # %bb.3: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB11_4: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: fucom %st(1)
+; X86-NEXT: fnstsw %ax
+; X86-NEXT: # kill: def $ah killed $ah killed $ax
+; X86-NEXT: sahf
+; X86-NEXT: jb .LBB11_6
+; X86-NEXT: # %bb.5: # %entry
+; X86-NEXT: fstp %st(0)
+; X86-NEXT: fldz
+; X86-NEXT: fxch %st(1)
+; X86-NEXT: .LBB11_6: # %entry
+; X86-NEXT: fstp %st(1)
+; X86-NEXT: retl
+;
+; X86AVX-LABEL: mind_zero:
+; X86AVX: # %bb.0: # %entry
+; X86AVX-NEXT: pushl %ebp
+; X86AVX-NEXT: .cfi_def_cfa_offset 8
+; X86AVX-NEXT: .cfi_offset %ebp, -8
+; X86AVX-NEXT: movl %esp, %ebp
+; X86AVX-NEXT: .cfi_def_cfa_register %ebp
+; X86AVX-NEXT: andl $-8, %esp
+; X86AVX-NEXT: subl $8, %esp
+; X86AVX-NEXT: vmovsd {{.*#+}} xmm0 = mem[0],zero
+; X86AVX-NEXT: vmovsd {{.*#+}} xmm1 = mem[0],zero
+; X86AVX-NEXT: vcmpunordsd %xmm0, %xmm0, %xmm2
+; X86AVX-NEXT: vblendvpd %xmm2, %xmm1, %xmm0, %xmm0
+; X86AVX-NEXT: vcmpunordsd %xmm1, %xmm1, %xmm2
+; X86AVX-NEXT: vblendvpd %xmm2, %xmm0, %xmm1, %xmm1
+; X86AVX-NEXT: vcmpltsd %xmm1, %xmm0, %xmm2
+; X86AVX-NEXT: vblendvpd %xmm2, %xmm0, %xmm1, %xmm0
+; X86AVX-NEXT: vmovlpd %xmm0, (%esp)
+; X86AVX-NEXT: fldl (%esp)
+; X86AVX-NEXT: movl %ebp, %esp
+; X86AVX-NEXT: popl %ebp
+; X86AVX-NEXT: .cfi_def_cfa %esp, 4
+; X86AVX-NEXT: retl
+entry:
+ %cond = tail call double @llvm.minimumnum.f64(double %a, double %b)
+ ret double %cond
+}
More information about the llvm-commits
mailing list