[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