[llvm] Intrinsic: Fix minnum and introduce minimumnum (PR #93373)
via llvm-commits
llvm-commits at lists.llvm.org
Sat May 25 00:42:55 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-support
@llvm/pr-subscribers-backend-x86
@llvm/pr-subscribers-backend-aarch64
Author: YunQiang Su (wzssyqa)
<details>
<summary>Changes</summary>
Currently, on different platform, the behaivor of llvm.minnum is different if one operand is sNaN.
When we compute sNaN vs NUM
ARM/AArch64 follow the IEEE754-2008's minNUM: return qNaN.
LIBCALL: returns qNaN.
RV/X86/Hexagon follow the IEEE754-2019's minimumNumber: return NUM.
MIPS/LoongArch/Generic: return NUM.
So, let's introduce `llvm.minmumnum/llvm.maximumnum`, which always follow IEEE754-2019's minimumNumber/maximumNumber.
Since `llvm.minnum` shares the same name with IEEE754-2008's minNUM, and currently, it is used for fmin(3), we should ask all ports to switch the behavior to minNUM.
Fixes: #<!-- -->93033
---
Patch is 117.02 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/93373.diff
60 Files Affected:
- (modified) llvm/include/llvm/ADT/APFloat.h (+24-4)
- (modified) llvm/include/llvm/Analysis/IVDescriptors.h (+4-1)
- (modified) llvm/include/llvm/Analysis/TargetLibraryInfo.def (+67-1)
- (modified) llvm/include/llvm/Analysis/ValueTracking.h (+4)
- (modified) llvm/include/llvm/CodeGen/BasicTTIImpl.h (+10)
- (modified) llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h (+2)
- (modified) llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h (+12)
- (modified) llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h (+1)
- (modified) llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h (+36)
- (modified) llvm/include/llvm/CodeGen/GlobalISel/Utils.h (+4)
- (modified) llvm/include/llvm/CodeGen/ISDOpcodes.h (+12)
- (modified) llvm/include/llvm/CodeGen/TargetLowering.h (+7)
- (modified) llvm/include/llvm/IR/ConstrainedOps.def (+2)
- (modified) llvm/include/llvm/IR/IRBuilder.h (+10)
- (modified) llvm/include/llvm/IR/IntrinsicInst.h (+2)
- (modified) llvm/include/llvm/IR/Intrinsics.td (+40)
- (modified) llvm/include/llvm/IR/RuntimeLibcalls.def (+20)
- (modified) llvm/include/llvm/IR/VPIntrinsics.def (+22)
- (modified) llvm/include/llvm/Support/TargetOpcodes.def (+6)
- (modified) llvm/include/llvm/Target/GenericOpcodes.td (+19)
- (modified) llvm/include/llvm/Target/GlobalISel/Combine.td (+3-3)
- (modified) llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td (+4)
- (modified) llvm/include/llvm/Target/TargetSelectionDAG.td (+18)
- (modified) llvm/lib/Analysis/ConstantFolding.cpp (+8)
- (modified) llvm/lib/Analysis/IVDescriptors.cpp (+4)
- (modified) llvm/lib/Analysis/InstructionSimplify.cpp (+15-2)
- (modified) llvm/lib/Analysis/ValueTracking.cpp (+17-7)
- (modified) llvm/lib/Analysis/VectorUtils.cpp (+2)
- (modified) llvm/lib/CodeGen/ExpandVectorPredication.cpp (+19-1)
- (modified) llvm/lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp (+2)
- (modified) llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp (+2)
- (modified) llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp (+8)
- (modified) llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp (+56-2)
- (modified) llvm/lib/CodeGen/GlobalISel/Utils.cpp (+18)
- (modified) llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (+8-3)
- (modified) llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp (+46-3)
- (modified) llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp (+103-1)
- (modified) llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h (+8)
- (modified) llvm/lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp (+13)
- (modified) llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp (+14-8)
- (modified) llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp (+17-3)
- (modified) llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (+38)
- (modified) llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp (+6)
- (modified) llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp (+120-20)
- (modified) llvm/lib/CodeGen/TargetLoweringBase.cpp (+1)
- (modified) llvm/lib/Target/AArch64/AArch64ISelLowering.cpp (+1-1)
- (modified) llvm/lib/Target/AArch64/AArch64InstrInfo.td (+8)
- (modified) llvm/lib/Target/Hexagon/HexagonISelLowering.cpp (+5-1)
- (modified) llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp (+6)
- (modified) llvm/lib/Target/Hexagon/HexagonPatterns.td (+4)
- (modified) llvm/lib/Target/Hexagon/HexagonPatternsHVX.td (+8)
- (modified) llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp (+1-1)
- (modified) llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp (+3-1)
- (modified) llvm/lib/Target/RISCV/RISCVISelLowering.cpp (+19-8)
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfoD.td (+2)
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfoF.td (+2)
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfoVSDPatterns.td (+2)
- (modified) llvm/lib/Target/X86/X86ISelLowering.cpp (+9-1)
- (modified) llvm/lib/Target/X86/X86TargetTransformInfo.cpp (+9-2)
- (modified) llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp (+4)
``````````diff
diff --git a/llvm/include/llvm/ADT/APFloat.h b/llvm/include/llvm/ADT/APFloat.h
index deb74cb2fdeb1..69dcb3d5f2634 100644
--- a/llvm/include/llvm/ADT/APFloat.h
+++ b/llvm/include/llvm/ADT/APFloat.h
@@ -1422,9 +1422,19 @@ inline APFloat maxnum(const APFloat &A, const APFloat &B) {
LLVM_READONLY
inline APFloat minimum(const APFloat &A, const APFloat &B) {
if (A.isNaN())
- return A;
+ return A.makeQuiet();
if (B.isNaN())
- return B;
+ return B.makeQuiet();
+ if (A.isZero() && B.isZero() && (A.isNegative() != B.isNegative()))
+ return A.isNegative() ? A : B;
+ return B < A ? B : A;
+}
+LLVM_READONLY
+inline APFloat minimumnum(const APFloat &A, const APFloat &B) {
+ if (A.isNaN())
+ return B.isNaN() ? B.makeQuiet() : B;
+ if (B.isNaN())
+ return A;
if (A.isZero() && B.isZero() && (A.isNegative() != B.isNegative()))
return A.isNegative() ? A : B;
return B < A ? B : A;
@@ -1435,9 +1445,19 @@ inline APFloat minimum(const APFloat &A, const APFloat &B) {
LLVM_READONLY
inline APFloat maximum(const APFloat &A, const APFloat &B) {
if (A.isNaN())
- return A;
+ return A.makeQuiet();
if (B.isNaN())
- return B;
+ return B.makeQuiet();
+ if (A.isZero() && B.isZero() && (A.isNegative() != B.isNegative()))
+ return A.isNegative() ? B : A;
+ return A < B ? B : A;
+}
+LLVM_READONLY
+inline APFloat maximumnum(const APFloat &A, const APFloat &B) {
+ if (A.isNaN())
+ return B.isNaN() ? B.makeQuiet() : B;
+ if (B.isNaN())
+ return A;
if (A.isZero() && B.isZero() && (A.isNegative() != B.isNegative()))
return A.isNegative() ? B : A;
return A < B ? B : A;
diff --git a/llvm/include/llvm/Analysis/IVDescriptors.h b/llvm/include/llvm/Analysis/IVDescriptors.h
index 5c7b613ac48c4..cba3e568daca4 100644
--- a/llvm/include/llvm/Analysis/IVDescriptors.h
+++ b/llvm/include/llvm/Analysis/IVDescriptors.h
@@ -48,6 +48,8 @@ enum class RecurKind {
FMax, ///< FP max implemented in terms of select(cmp()).
FMinimum, ///< FP min with llvm.minimum semantics
FMaximum, ///< FP max with llvm.maximum semantics
+ FMinimumnum, ///< FP min with llvm.minimumnum semantics
+ FMaximumnum, ///< FP max with llvm.maximumnum semantics
FMulAdd, ///< Sum of float products with llvm.fmuladd(a * b + sum).
IAnyOf, ///< Any_of reduction with select(icmp(),x,y) where one of (x,y) is
///< loop invariant, and both x and y are integer type.
@@ -226,7 +228,8 @@ class RecurrenceDescriptor {
/// Returns true if the recurrence kind is a floating-point min/max kind.
static bool isFPMinMaxRecurrenceKind(RecurKind Kind) {
return Kind == RecurKind::FMin || Kind == RecurKind::FMax ||
- Kind == RecurKind::FMinimum || Kind == RecurKind::FMaximum;
+ Kind == RecurKind::FMinimum || Kind == RecurKind::FMaximum ||
+ Kind == RecurKind::FMinimumnum || Kind == RecurKind::FMaximumnum;
}
/// Returns true if the recurrence kind is any min/max kind.
diff --git a/llvm/include/llvm/Analysis/TargetLibraryInfo.def b/llvm/include/llvm/Analysis/TargetLibraryInfo.def
index 717693a7cf63c..d91891a852618 100644
--- a/llvm/include/llvm/Analysis/TargetLibraryInfo.def
+++ b/llvm/include/llvm/Analysis/TargetLibraryInfo.def
@@ -1314,7 +1314,7 @@ TLI_DEFINE_ENUM_INTERNAL(flsll)
TLI_DEFINE_STRING_INTERNAL("flsll")
TLI_DEFINE_SIG_INTERNAL(Int, LLong)
-// Calls to fmax and fmin library functions expand to the llvm.maxnnum and
+// Calls to fmax and fmin library functions expand to the llvm.maxnum and
// llvm.minnum intrinsics with the correct parameter types for the arguments
// (all types must match).
/// double fmax(double x, double y);
@@ -1347,6 +1347,72 @@ TLI_DEFINE_ENUM_INTERNAL(fminl)
TLI_DEFINE_STRING_INTERNAL("fminl")
TLI_DEFINE_SIG_INTERNAL(Floating, Same, Same)
+// Calls to fmaximum and fminimum library functions expand to the llvm.maximum and
+// llvm.minimum intrinsics with the correct parameter types for the arguments
+// (all types must match).
+/// double fmaximum(double x, double y);
+TLI_DEFINE_ENUM_INTERNAL(fmaximum)
+TLI_DEFINE_STRING_INTERNAL("fmaximum")
+TLI_DEFINE_SIG_INTERNAL(Floating, Same, Same)
+
+/// float fmaximumf(float x, float y);
+TLI_DEFINE_ENUM_INTERNAL(fmaximumf)
+TLI_DEFINE_STRING_INTERNAL("fmaximumf")
+TLI_DEFINE_SIG_INTERNAL(Floating, Same, Same)
+
+/// long double fmaximuml(long double x, long double y);
+TLI_DEFINE_ENUM_INTERNAL(fmaximuml)
+TLI_DEFINE_STRING_INTERNAL("fmaximuml")
+TLI_DEFINE_SIG_INTERNAL(Floating, Same, Same)
+
+/// double fminimum(double x, double y);
+TLI_DEFINE_ENUM_INTERNAL(fminimum)
+TLI_DEFINE_STRING_INTERNAL("fminimum")
+TLI_DEFINE_SIG_INTERNAL(Floating, Same, Same)
+
+/// float fminimumf(float x, float y);
+TLI_DEFINE_ENUM_INTERNAL(fminimumf)
+TLI_DEFINE_STRING_INTERNAL("fminimumf")
+TLI_DEFINE_SIG_INTERNAL(Floating, Same, Same)
+
+/// long double fminimuml(long double x, long double y);
+TLI_DEFINE_ENUM_INTERNAL(fminimuml)
+TLI_DEFINE_STRING_INTERNAL("fminimuml")
+TLI_DEFINE_SIG_INTERNAL(Floating, Same, Same)
+
+// Calls to fmaximum_num and fminimum_num library functions expand to the llvm.maximumnum and
+// llvm.minimumnum intrinsics with the correct parameter types for the arguments
+// (all types must match).
+/// double fmaximum_num(double x, double y);
+TLI_DEFINE_ENUM_INTERNAL(fmaximum_num)
+TLI_DEFINE_STRING_INTERNAL("fmaximum_num")
+TLI_DEFINE_SIG_INTERNAL(Floating, Same, Same)
+
+/// float fmaximum_numf(float x, float y);
+TLI_DEFINE_ENUM_INTERNAL(fmaximum_numf)
+TLI_DEFINE_STRING_INTERNAL("fmaximum_numf")
+TLI_DEFINE_SIG_INTERNAL(Floating, Same, Same)
+
+/// long double fmaximum_numl(long double x, long double y);
+TLI_DEFINE_ENUM_INTERNAL(fmaximum_numl)
+TLI_DEFINE_STRING_INTERNAL("fmaximum_numl")
+TLI_DEFINE_SIG_INTERNAL(Floating, Same, Same)
+
+/// double fminimum_num(double x, double y);
+TLI_DEFINE_ENUM_INTERNAL(fminimum_num)
+TLI_DEFINE_STRING_INTERNAL("fminimum_num")
+TLI_DEFINE_SIG_INTERNAL(Floating, Same, Same)
+
+/// float fminimum_numf(float x, float y);
+TLI_DEFINE_ENUM_INTERNAL(fminimum_numf)
+TLI_DEFINE_STRING_INTERNAL("fminimum_numf")
+TLI_DEFINE_SIG_INTERNAL(Floating, Same, Same)
+
+/// long double fminimum_numl(long double x, long double y);
+TLI_DEFINE_ENUM_INTERNAL(fminimum_numl)
+TLI_DEFINE_STRING_INTERNAL("fminimum_numl")
+TLI_DEFINE_SIG_INTERNAL(Floating, Same, Same)
+
/// double fmod(double x, double y);
TLI_DEFINE_ENUM_INTERNAL(fmod)
TLI_DEFINE_STRING_INTERNAL("fmod")
diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h
index 0584b7e29f67b..c8aaa9d75c119 100644
--- a/llvm/include/llvm/Analysis/ValueTracking.h
+++ b/llvm/include/llvm/Analysis/ValueTracking.h
@@ -1065,6 +1065,10 @@ enum SelectPatternFlavor {
SPF_UMAX, /// Unsigned maximum
SPF_FMINNUM, /// Floating point minnum
SPF_FMAXNUM, /// Floating point maxnum
+ SPF_FMINIMUM,/// Floating point minnum
+ SPF_FMAXIMUM,/// Floating point maxnum
+ SPF_FMINIMUMNUM, /// Floating point minnum
+ SPF_FMAXIMUMNUM, /// Floating point maxnum
SPF_ABS, /// Absolute value
SPF_NABS /// Negated absolute value
};
diff --git a/llvm/include/llvm/CodeGen/BasicTTIImpl.h b/llvm/include/llvm/CodeGen/BasicTTIImpl.h
index 2091432d4fe27..167cc2d1755a5 100644
--- a/llvm/include/llvm/CodeGen/BasicTTIImpl.h
+++ b/llvm/include/llvm/CodeGen/BasicTTIImpl.h
@@ -1686,6 +1686,8 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
case Intrinsic::vector_reduce_fmin:
case Intrinsic::vector_reduce_fmaximum:
case Intrinsic::vector_reduce_fminimum:
+ case Intrinsic::vector_reduce_fmaximumnum:
+ case Intrinsic::vector_reduce_fminimumnum:
case Intrinsic::vector_reduce_umax:
case Intrinsic::vector_reduce_umin: {
IntrinsicCostAttributes Attrs(IID, RetTy, Args[0]->getType(), FMF, I, 1);
@@ -2009,6 +2011,12 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
case Intrinsic::maximum:
ISD = ISD::FMAXIMUM;
break;
+ case Intrinsic::minimumnum:
+ ISD = ISD::FMINIMUMNUM;
+ break;
+ case Intrinsic::maximumnum:
+ ISD = ISD::FMAXIMUMNUM;
+ break;
case Intrinsic::copysign:
ISD = ISD::FCOPYSIGN;
break;
@@ -2090,6 +2098,8 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
case Intrinsic::vector_reduce_fmin:
case Intrinsic::vector_reduce_fmaximum:
case Intrinsic::vector_reduce_fminimum:
+ case Intrinsic::vector_reduce_fmaximumnum:
+ case Intrinsic::vector_reduce_fminimumnum:
return thisT()->getMinMaxReductionCost(getMinMaxReductionIntrinsicOp(IID),
VecOpTy, ICA.getFlags(), CostKind);
case Intrinsic::abs: {
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
index 2111e82e1a99d..c6fe31b3cd4fe 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
@@ -947,8 +947,10 @@ class CombinerHelper {
///
/// * G_FMAXNUM
/// * G_FMAXIMUM
+ /// * G_FMAXIMUMNUM
/// * G_FMINNUM
/// * G_FMINIMUM
+ /// * G_FMINIMUMNUM
///
/// Helper function for matchFPSelectToMinMax.
unsigned getFPMinMaxOpcForSelect(CmpInst::Predicate Pred, LLT DstTy,
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
index 2b3efc3b609f0..47535559e77f1 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
@@ -551,6 +551,8 @@ class GVecReduce : public GenericMachineInstr {
case TargetOpcode::G_VECREDUCE_FMIN:
case TargetOpcode::G_VECREDUCE_FMAXIMUM:
case TargetOpcode::G_VECREDUCE_FMINIMUM:
+ case TargetOpcode::G_VECREDUCE_FMAXIMUMNUM:
+ case TargetOpcode::G_VECREDUCE_FMINIMUMNUM:
case TargetOpcode::G_VECREDUCE_ADD:
case TargetOpcode::G_VECREDUCE_MUL:
case TargetOpcode::G_VECREDUCE_AND:
@@ -589,6 +591,12 @@ class GVecReduce : public GenericMachineInstr {
case TargetOpcode::G_VECREDUCE_FMINIMUM:
ScalarOpc = TargetOpcode::G_FMINIMUM;
break;
+ case TargetOpcode::G_VECREDUCE_FMAXIMUMNUM:
+ ScalarOpc = TargetOpcode::G_FMAXIMUMNUM;
+ break;
+ case TargetOpcode::G_VECREDUCE_FMINIMUMNUM:
+ ScalarOpc = TargetOpcode::G_FMINIMUMNUM;
+ break;
case TargetOpcode::G_VECREDUCE_ADD:
ScalarOpc = TargetOpcode::G_ADD;
break;
@@ -669,6 +677,8 @@ class GBinOp : public GenericMachineInstr {
case TargetOpcode::G_FMAXNUM_IEEE:
case TargetOpcode::G_FMINIMUM:
case TargetOpcode::G_FMAXIMUM:
+ case TargetOpcode::G_FMINIMUMNUM:
+ case TargetOpcode::G_FMAXIMUMNUM:
case TargetOpcode::G_FADD:
case TargetOpcode::G_FSUB:
case TargetOpcode::G_FMUL:
@@ -719,6 +729,8 @@ class GFBinOp : public GBinOp {
case TargetOpcode::G_FMAXNUM_IEEE:
case TargetOpcode::G_FMINIMUM:
case TargetOpcode::G_FMAXIMUM:
+ case TargetOpcode::G_FMINIMUMNUM:
+ case TargetOpcode::G_FMAXIMUMNUM:
case TargetOpcode::G_FADD:
case TargetOpcode::G_FSUB:
case TargetOpcode::G_FMUL:
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
index 284f434fbb9b0..8ce6b44c7e1c6 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
@@ -403,6 +403,7 @@ class LegalizerHelper {
LegalizeResult lowerMinMax(MachineInstr &MI);
LegalizeResult lowerFCopySign(MachineInstr &MI);
LegalizeResult lowerFMinNumMaxNum(MachineInstr &MI);
+ LegalizeResult lowerFMinimumNumMaximumNum(MachineInstr &MI);
LegalizeResult lowerFMad(MachineInstr &MI);
LegalizeResult lowerIntrinsicRound(MachineInstr &MI);
LegalizeResult lowerFFloor(MachineInstr &MI);
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
index 92e05ee858a75..96cc0f738d258 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
@@ -1723,6 +1723,30 @@ class MachineIRBuilder {
return buildInstr(TargetOpcode::G_FMAXNUM_IEEE, {Dst}, {Src0, Src1}, Flags);
}
+ MachineInstrBuilder
+ buildFMinimum(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1,
+ std::optional<unsigned> Flags = std::nullopt) {
+ return buildInstr(TargetOpcode::G_FMINIMUM, {Dst}, {Src0, Src1}, Flags);
+ }
+
+ MachineInstrBuilder
+ buildFMaximum(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1,
+ std::optional<unsigned> Flags = std::nullopt) {
+ return buildInstr(TargetOpcode::G_FMAXIMUM, {Dst}, {Src0, Src1}, Flags);
+ }
+
+ MachineInstrBuilder
+ buildFMinimumNUM(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1,
+ std::optional<unsigned> Flags = std::nullopt) {
+ return buildInstr(TargetOpcode::G_FMINIMUMNUM, {Dst}, {Src0, Src1}, Flags);
+ }
+
+ MachineInstrBuilder
+ buildFMaximumNUM(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1,
+ std::optional<unsigned> Flags = std::nullopt) {
+ return buildInstr(TargetOpcode::G_FMAXIMUMNUM, {Dst}, {Src0, Src1}, Flags);
+ }
+
MachineInstrBuilder buildShl(const DstOp &Dst, const SrcOp &Src0,
const SrcOp &Src1,
std::optional<unsigned> Flags = std::nullopt) {
@@ -2074,6 +2098,18 @@ class MachineIRBuilder {
return buildInstr(TargetOpcode::G_VECREDUCE_FMINIMUM, {Dst}, {Src});
}
+ /// Build and insert \p Res = G_VECREDUCE_FMAXIMUMNUM \p Src
+ MachineInstrBuilder buildVecReduceFMaximumnum(const DstOp &Dst,
+ const SrcOp &Src) {
+ return buildInstr(TargetOpcode::G_VECREDUCE_FMAXIMUMNUM, {Dst}, {Src});
+ }
+
+ /// Build and insert \p Res = G_VECREDUCE_FMINIMUMNUM \p Src
+ MachineInstrBuilder buildVecReduceFMinimumnum(const DstOp &Dst,
+ const SrcOp &Src) {
+ return buildInstr(TargetOpcode::G_VECREDUCE_FMINIMUMNUM, {Dst}, {Src});
+ }
+
/// Build and insert \p Res = G_VECREDUCE_ADD \p Src
MachineInstrBuilder buildVecReduceAdd(const DstOp &Dst, const SrcOp &Src) {
return buildInstr(TargetOpcode::G_VECREDUCE_ADD, {Dst}, {Src});
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/Utils.h b/llvm/include/llvm/CodeGen/GlobalISel/Utils.h
index 70421a518ab72..c26f8ffd839e7 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/Utils.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/Utils.h
@@ -60,6 +60,8 @@ class APFloat;
case TargetOpcode::G_VECREDUCE_FMIN: \
case TargetOpcode::G_VECREDUCE_FMAXIMUM: \
case TargetOpcode::G_VECREDUCE_FMINIMUM: \
+ case TargetOpcode::G_VECREDUCE_FMAXIMUMNUM: \
+ case TargetOpcode::G_VECREDUCE_FMINIMUMNUM: \
case TargetOpcode::G_VECREDUCE_ADD: \
case TargetOpcode::G_VECREDUCE_MUL: \
case TargetOpcode::G_VECREDUCE_AND: \
@@ -77,6 +79,8 @@ class APFloat;
case TargetOpcode::G_VECREDUCE_FMIN: \
case TargetOpcode::G_VECREDUCE_FMAXIMUM: \
case TargetOpcode::G_VECREDUCE_FMINIMUM: \
+ case TargetOpcode::G_VECREDUCE_FMAXIMUMNUM: \
+ case TargetOpcode::G_VECREDUCE_FMINIMUMNUM: \
case TargetOpcode::G_VECREDUCE_ADD: \
case TargetOpcode::G_VECREDUCE_MUL: \
case TargetOpcode::G_VECREDUCE_AND: \
diff --git a/llvm/include/llvm/CodeGen/ISDOpcodes.h b/llvm/include/llvm/CodeGen/ISDOpcodes.h
index d8af97957e48e..910728e38c1b1 100644
--- a/llvm/include/llvm/CodeGen/ISDOpcodes.h
+++ b/llvm/include/llvm/CodeGen/ISDOpcodes.h
@@ -435,6 +435,8 @@ enum NodeType {
STRICT_LLRINT,
STRICT_FMAXIMUM,
STRICT_FMINIMUM,
+ STRICT_FMAXIMUMNUM,
+ STRICT_FMINIMUMNUM,
/// STRICT_FP_TO_[US]INT - Convert a floating point value to a signed or
/// unsigned integer. These have the same semantics as fptosi and fptoui
@@ -991,6 +993,12 @@ enum NodeType {
FMINIMUM,
FMAXIMUM,
+ /// FMINIMUMNUM/FMAXIMUMNUM - minimum/maximum that also treat -0.0
+ /// as less than 0.0. While FMINNUM_IEEE/FMAXNUM_IEEE follow IEEE 754-2008
+ /// semantics, FMINIMUM/FMAXIMUM follow IEEE 754-2019 semantics.
+ FMINIMUMNUM,
+ FMAXIMUMNUM,
+
/// FSINCOS - Compute both fsin and fcos as a single operation.
FSINCOS,
@@ -1365,6 +1373,10 @@ enum NodeType {
/// llvm.minimum and llvm.maximum semantics.
VECREDUCE_FMAXIMUM,
VECREDUCE_FMINIMUM,
+ /// FMINIMUMNUM/FMAXIMUMNUM nodes doesn't propatate NaNs and signed zeroes using the
+ /// llvm.minimumnum and llvm.maximumnum semantics.
+ VECREDUCE_FMAXIMUMNUM,
+ VECREDUCE_FMINIMUMNUM,
/// Integer reductions may have a result type larger than the vector element
/// type. However, the reduction is performed using the vector element type
/// and the value in the top bits is unspecified.
diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index 50a8c7eb75af5..c92eb86c08a48 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -2908,6 +2908,8 @@ class TargetLoweringBase {
case ISD::FMAXNUM_IEEE:
case ISD::FMINIMUM:
case ISD::FMAXIMUM:
+ case ISD::FMINIMUMNUM:
+ case ISD::FMAXIMUMNUM:
case ISD::AVGFLOORS:
case ISD::AVGFLOORU:
case ISD::AVGCEILS:
@@ -5116,6 +5118,8 @@ class TargetLowering : public TargetLoweringBase {
/// through to the default expansion/soften to libcall, we might introduce a
/// link-time dependency on libm into a file that originally did not have one.
SDValue createSelectForFMINNUM_FMAXNUM(SDNode *Node, SelectionDAG &DAG) const;
+ SDValue createSelectForFMINIMUM_FMAXIMUM(SDNode *Node, SelectionDAG &DAG) const;
+ SDValue createSelectForFMINIMUMNUM_FMAXIMUMNUM(SDNode *Node, SelectionDAG &DAG) const;
/// Return a reciprocal estimate value for the input operand.
/// \p Enabled is a ReciprocalEstimate enum with value either 'Unspecified' or
@@ -5247,6 +5251,9 @@ class TargetLowering : public TargetLoweringBase {
/// Expand fminimum/fmaximum into multiple comparison with selects.
SDValue expandFMINIMUM_FMAXIMUM(SDNode *N, SelectionDAG &DAG) const;
+ /// Expand fminimumnum/fmaximumnum into multiple comparison with selects.
+ SDValue expandFMINIMUMNUM_FMAXIMUMNUM(SDNode *N, SelectionDAG &DAG) const;
+
/// Expand FP_TO_[US]INT_SAT into FP_TO_[US]INT and selects or min/max.
/// \param N Node to expand
/// \returns The expansion result
diff --git a/llvm/include/llvm/IR/ConstrainedOps.def b/llvm/include/llvm/IR/ConstrainedOps.def
index 41aa44de957f9..361a050cd2355 100644
--- a/llvm/include/llvm/IR/ConstrainedOps.def
+++ b/llvm/include/llvm/IR/ConstrainedOps.def
@@ -86,6 +86,8 @@ DAG_FUNCTION(maxnum, 2, 0, experimental_constrained_maxnum, FMAXNUM
DAG_FUNCTION(minnum, 2, 0, experimental_constrained_minnum, FMINNUM)
DAG_FUNCTION(maximum, 2, 0, experimental_constrained_maximum, FMAXIMUM)
DAG_FUNCTION(minimum, 2, 0, experimental_constrained_minimum, FMINIMUM)
+DAG_FUNCTION(maximumnum, 2, 0, experimental_constrained_maximumnum, FMAXIMUMNUM)
+DAG_FUNCTION(minimumnum, 2, 0, experimental_constrained_minimumnum, FMINIMUMNUM)
DAG_FUNCTION(nearbyint, 1, 1, experimental_constrained_nearbyint, FNEARBYINT)
DAG_FUNCTION(pow, 2, 1, experimental_constrained_pow, FPOW)
DAG_FUNCTION(powi, 2, 1, experimental_constrained_powi, FPOWI)
diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h
index 40a9cf507248a..34394c6478d16 100644
--- a/llvm/include/llvm/IR/IRBuilder.h
+++ b/llvm/include/llvm/IR/IRBuilder.h
@@ -1018,6 +1018,16 @@ class IRBuilderBase {
...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/93373
More information about the llvm-commits
mailing list